Repository navigation
Description
Finding
PR #468's spec (§6.2, specs/2026-10-25-subsession-model-governance.md:272) states: "Session.fork creates a child whose parent is the source session." The implementation does the opposite, and the difference silently removes governance from a whole subtree:
packages/core/src/session/projector.ts(~:160-172): the forked session is inserted withparent_id: null(fork_session_idrecords the source instead), copying only the source's ownsubagent_policy.- The one-time fork check in
packages/core/src/session.tsvalidates only the copied model at the fork instant, against the source as parent.
Consequences, all reachable by forking a child session (POST /api/session/:id/fork):
- The fork is top-level, so
switchAgent/switchModelskip governance entirely — both guard onsession.parentID(packages/core/src/session/session.ts, child-only checks added by PRs feat(core): subsession model governance #468/fix(core): run the governance check on switchAgent for child sessions #486). The fork can be switched to any excluded model unchecked. - The fork's own children are governed only by the copied policy: the governance (and depth) walks follow
parentIDonly and never traversefork_session_id, so every ancestor policy above the source — e.g. the primary session'smodels/excludedModels— silently drops out of the subtree.
Forking a governed child therefore launders it out of its ancestor policies: same agent, same model, same history — minus the restrictions.
Evidence
Verified on current main ffbc856: projector insert (parent_id: null, fork_session_id: event.data.parentID, subagent_policy: parent.subagent_policy), spec §6.2 text, the fork-time check in packages/core/src/session.ts, and the parentID guards in packages/core/src/session/session.ts. Existing fork governance tests (packages/core/test/session-governance.test.ts:167/186) cover forking a session whose own policy excludes its model, and policy copying — not forking a child out from under a grandparent's policy.
Acceptance criteria
- Forking a child session does not escape ancestor governance: either the fork stays linked into the governance chain (its switches and its descendants' creation are checked against the source's ancestors' policies as well as the copied policy), or the escape is an explicitly documented, spec-amended decision with the fork-time check applying the full ancestor chain.
- A regression test forks a grandchild under a primary policy that excludes its model and shows the fork cannot be switched to — or launched with children on — the excluded model (or documents the accepted behavior if the design decision goes the other way).
Filed by the pr-diff-review job, 2026-10-26 run (addendum 3: governance reviewer final report reconciled and re-verified by the parent; this corrects the run's first-pass fork disposition, which had verified only the fork-time check).
Activity
dezren39 commentedon Oct 26, 2026
Intake review
Still live: verified by the filer on current main
ffbc8562f2(filed 2026-10-26, pr-diff-review): the fork projector still insertsparent_id: null. No open PR addresses fork governance. Acceptance criteria were already present, so the body is unchanged.Related: PR #468 (governance, spec §6.2 states the opposite of the implementation); PR #486 (child-only switch checks the fork escapes); sibling governance holes from the same review: #506, #507, #508.
Notes / risks: this is a governance escape, not just a spec mismatch — forking a governed child drops every ancestor policy above the source for the fork and its whole descendant subtree. Priority set to high for that reason. The criteria allow either linking the fork into the chain or a documented spec amendment; the silent status quo is the one unacceptable outcome.
Suggested approach: walk the governance chain through
fork_session_idwhenparentIDis null on a fork (or set the fork's parent linkage for governance purposes), and add the grandchild-fork regression test from the criteria.Labels normalized by the fleet monitor: kind/bug, source/pr-diff-review, status/needs-triage, priority/high, effort/m, meta/enriched.
dezren39 commentedon Oct 27, 2026
🤖 Agent note · state: triaged (verified still present)
Verified on current main f1e0c58 (fresh read of the sandbox clone, fast-forwarded this run):
packages/core/src/session/projector.ts(~:158-172) — the fork insert still writesparent_id: nullwithfork_session_id: event.data.parentID, copying only the source session's ownsubagent_policy,agent, andmodel. Ancestor policies above the source still drop out of the forked subtree, and the fork's own switches still skip the child-only governance guards.Conclusion: NOT fixed upstream, no open PR touches projector.ts. Remains a valid priority/high fix; left in needs-triage for a queue/sweep fix run (effort/m, not a trivial self-solve). Related: #507 (same PR #468 governance family).
dezren39 commentedon Oct 28, 2026
State: triaged (verified still present) + fix routed
Agent: issue sweep (issue-sweep-rotating)
Session/ID: issue-sweep-rotating run 2026-10-28 16:24 CDT
Found via: sweep triage — priority/high unqueued item in the backlog
Task: re-verify on current main and route the fix (previous triages confirmed but never enqueued a fix packet)
Expectation: effort/m fix via queue task 2725 (packet-505-fix.json, repo-health-opencode-pilot)
Verified on current main 0b51b19 (fresh sandbox read): packages/core/src/session/projector.ts:160-161 still inserts the fork with
parent_id: nullandfork_session_id: event.data.parentID; the governance ancestor walk in model-governance.ts follows parentID only. Bug live, unchanged since the 2026-10-27 verification on f1e0c58. Packet pins the governance-link shape (spec 6.2 already decided) and the grandchild-fork regression test; the "document the escape" alternative was not routed.dezren39 commentedon Oct 28, 2026
Progress (task 2725): PR #775 opened — #775
Implemented the governance-link shape (the issue's option (a); projection untouched — forks still insert with
parent_id: null):model-governance.ts: theassertAllowedancestor walk followsparentID ?? fork.sessionID, so policies above the source bind the fork and its descendants.session/session.ts:switchAgent/switchModelgate on that governance parent, so a fork's own switches are checked against its source's chain; genuinely top-level sessions stay unchecked.subagent-depth.ts: the depth walk follows the same link (a fork hop counts as one level).session-governance.test.ts: forking a grandchild under a grandparenttest/haiku-only policy — the fork cannot switch to or launch children ontest/opus, and can launch ontest/haiku.Task 2725 is parked awaiting CI on PR #775; on green it merges and closes this issue.
dezren39 commentedon Oct 28, 2026
Triage confirmation — 2026-10-28 (queue task 2733)
Packet numbering correction: queue task 2733 was enqueued as "triage #511", but its body, evidence, and context refs describe this issue, #505. #511 is an unrelated, already-merged PR ("apply Selection segment rules in v1 model migration", fixes #503) — verified via the GitHub API, search, and the web page on 2026-10-28. Nothing about #511 needs triage. The triage below is for #505, the issue the packet actually describes.
Confirmed still live: #505 is OPEN; the fork-governance hole it describes is not fixed on current main (
5e77693704) — the fix exists only on the unmerged PR branch below. Not a duplicate of #507 (model-less child checked vs run model; fix in flight as PR #776) or of closed siblings #506/#508 — distinct mechanism: fork projection setsparent_id: null, so governance walks that followparentIDonly miss every ancestor policy above the fork's source, and the fork's own switchAgent/switchModel take the top-level gate.Priority confirmed:
priority/highis correct — this is a governance escape for a fork and its whole descendant subtree, not a spec nit.Fix already in flight — no new fix task needed: PR #775 "fix(core): govern forks as children of their source session" (
Fixes #505, branchqueue/2725-505-fork-governance, mergeable, CI pending at triage time) is bound to queue task 2725, which holds this issue'squeue/parked+work/assignedlabels. Enqueuing another fix task would duplicate task 2725.Status label:
status/needs-triage→status/in-progressto match the in-flight fix.agent-note:v1 · agent: repo-queue-worker-shift-opencode-b · task: 2733 · issue: #505 · action: triage-confirmed
dezren39 commentedon Oct 28, 2026
Merged: PR #775 (merge commit a9452a1) — forks are now governed as children of their source session; session-governance suite 8/8 on the laptop including the new grandchild-fork regression. CI note: unit (linux/windows) failed only on two TUI permission-focus tests ('permission layers leave the focused peer's Enter and navigation alone until activated', 'permission rejection text keeps its draft and regains focus when its scope resumes') that fail identically on unrelated PR #776 — a pre-existing main issue, log-verified, not caused by this change. All other checks green (typecheck, build x2, nix-eval, affected packages).
agent-note:v1 · agent: repo-queue-worker-shift-opencode-b · task: 2725 · issue: #505 · action: merged · pr: #775