Files
octopus-workflow/core/rules/session-scope-guard.md
T

6.5 KiB

Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。

Session Scope Guard (mandatory)

Enforcement layer: precheck-mechanized (injection-budget batch-2, [org-internal #3667]) — pre-flight sources 1-3 below live in the repo's session-conflicts script, source 4 in the claim script's compare-and-swap. This file is the normative definition, NOT part of any agents_md injection whitelist since 2026-08-29 — do not re-add; the checks run at claim time regardless.

Standalone and ticket-seeded sessions run without a pipeline around them — no plan, no reviewer keeping them inside their work item. When such a session hits a test failure NOT caused by its own change ([org-internal [org-internal #1803]], via [org-internal #1753]/org-internal #1744), it tends to fix the foreign failure in place (drifting off-task), and sessions seeded for the same issue collide on the same shared flaky test.

Iron Law: if a test fails and it was NOT caused by your change, you MUST classify → file → continue. Do NOT fix it in place — unless that test IS your task.

The classify → file → continue protocol

  1. Classify — rerun the failing test on the base commit / last-green: fails there too → baseline failure (BF); intermittent across runs → flaky test (FT); fails only with your change → your regression — fix it now.
  2. File — register every BF/FT as an issue in the ticket backend labeled baseline-failure or flaky-test with a BF-NNN / FT-NNN id, per the testing rule. Deduplicate against an existing BF/FT issue (comment your run evidence instead of filing a twin).
  3. Continue — return to your assigned task; cite the BF/FT issue number in your report / PR body so the next session sees it is owned.

A foreign failure does not block your task, but the task is NOT done until the failure is filed — an un-filed BF/FT is a process gap. Filing is the whole job: the fix belongs to whoever owns that test, not to you.

One task, one owner — check before you start

Before starting work on an issue or code area, you MUST verify no other session already owns it. The pre-flight check spans four sources — (1) live sessions referencing #N, (2) a workflow branch already covering #N (worktrees, local branches, remote workflow/* refs), (3) an open PR referencing #N, (4) assignee + claim comment naming another owner. A hit on ANY source → the ticket is already owned: ABORT (or, for a DEAD claim, take over via the mechanized channel below; otherwise coordinate on the issue), never silently start a second owner.

Mechanized ([org-internal #3667]): the repo's session-conflicts script (<session-conflicts-cmd> <ticket>) scans sources 1-3 in one read-only pass (exit 4 = conflict, matching the claim script; source 1 fail-opens visibly when the app API is down — the backend hard guard [org-internal #1989] backstops); source 4 IS the claim script's compare-and-swap. Dead-claim takeover is mechanized in the claim script (see below); manual recipes: the headless-session-ops skill's ticket-recipe reference §0.

Dead-claim takeover ([org-internal #3668]). A claim whose session is gone (404 on the app API) and whose branch was never pushed is a DEAD claim — the [org-internal #3419] shape. Do NOT hand-edit the dead claim comment (the retired admin workaround — unauditable); run the claim script's takeover subcommand (<claim-takeover-cmd> <ticket> <branch> --session-id <id>) instead. Evidence rule (the claim script's header is normative): a competing claim is dead iff its named branch is ABSENT on the remote AND (its session 404s OR the comment is at least CLAIM_TAKEOVER_STALE_DAYS old — age >= the threshold, default 3d). Evidence holds → one atomic takeover: assignee re-set + a **claim** comment carrying supersedes-claim #<id> markers and the inline evidence (auditable chain, nothing edited) + branch push, with post-posting race re-verification. Evidence fails (session alive, branch pushed = completed claim, or fresh claim with unknown liveness) → exit 10, zero mutation — coordinate on the issue or salvage the worktree instead. A valid claim is never superseded.

Claim-first (atomic 3-step claim). The FIRST action when starting ticket-driven work is to claim the ticket — one atomic action of THREE steps, valid ONLY when all complete: (1) set the issue assignee to the working account, (2) post a claim comment naming the workflow branch and session id, (3) push the workflow branch to remote (even an empty commit — a purely local branch is invisible to other sessions, [org-internal [org-internal #2280]/[org-internal #2282]]). Use the repo's claim wrappers (staged-transaction claim script; exit codes and CAS semantics in its header; non-zero = NOT claimed) and the provision wrapper (adds the worktree + Tier-1 runs scaffold). The manual 3-step is the fallback where the scripts are unavailable, same re-verification.

Merge-time equivalence check. Before merging, scan the remote main branch's recent commits for #<ticket> — surfacing an equivalent implementation already on main before the merge rejection.

Merge-time review gate ([org-internal #2345]). pipeline/review-code is a required status: merge needs it green OR the route-based exemption (Kind/* close routes skip review-code — posted by the repo's review-gate-exemption script). Read the commit-status endpoint for the PR SHA: success + review not required (route: description → route exemption, proceed; success otherwise → proceed; missing / error / pending / other → BLOCK — a missing status never approves.

Epic ownership table. Multi-chunk parallel Epics keep a chunk → session/account ownership table on the parent issue — consult it and claim your chunk before starting.

Two sessions owning the same issue or code area is never faster — it is the exact collision this rule prevents. If a collision HAS happened, follow the failure-path playbook at the ownership-collision runbook (Tier-2 reference page, reachable via the ticket backend).

Scope

Applies semantically to every session — pipeline subagents (Producer / Verifier / Reviewer / Tool) and standalone/ticket-seeded sessions alike; for subagents, "your task" is the delegated prompt's scope, and classify → file → continue applies unchanged. Filing rides the testing rule; launch-time owner checks live in the headless-session-ops skill (which points here). This file stays the normative definition — read on demand.