---
name: session-memory-contract
description: "Canonical operational contract for Agent Orchestra session-state survival and handoffs. Use when discovering where plan, design, review, startup, calibration, tracking, or plugin state belongs. DO NOT USE FOR: designing new storage mechanisms or writing rationale docs (use design-exploration or documentation-finalization)."
---

<!-- markdownlint-disable-file MD013 -->

# Session Memory Contract

Operational source of truth for Agent Orchestra session-state shapes, survival labels, canonical read/write mechanisms, and cross-tool fungibility. This skill documents the mechanisms already used by the repo; it does not create a new persistence layer.

## When to Use

- When a skill, agent, command, or script reads or writes plan, design, review, startup, calibration, tracking, or plugin-release state.
- When documenting whether state survives compaction, conversation end, worktree switches, or a Copilot-to-Claude handoff.
- When replacing vague `session memory` wording with a row-specific survival label and canonical mechanism.
- When deciding whether a local cache must be reconciled against a durable GitHub marker.

## Survival Vocabulary

Use these labels exactly when documenting a state shape.

| Label                 | Meaning                                                                                                                                                                                                            |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `per-dispatch`        | Survives only the current prompt, subagent dispatch, command invocation, or tool call.                                                                                                                             |
| `within-conversation` | Survives while the current chat conversation and its session memory remain available, including VS Code compaction when `/memories/session/` is preserved. It is not a cross-conversation or cross-tool guarantee. |
| `within-worktree`     | Survives in local files tied to the checked-out worktree and machine. It is available to tools that share that checkout, but not to a fresh clone or remote/cloud agent unless separately committed or copied.     |
| `durable`             | Survives conversation end and tool/model handoff through GitHub issues, PR comments, PR bodies, issue bodies, or committed repository files.                                                                       |
| `per-process`         | Special value for PID-keyed temp files. Use only when a state file is intentionally scoped to one process lifetime rather than to a conversation or worktree.                                                      |

**Surface-naming requirement**: when survival depends on the execution surface, write the label as `{base}:{surface}`. Examples: `within-conversation:inline`, `within-conversation:subagent`, `within-conversation:hooks`, or `within-worktree:hooks`. The base must still be one of `per-dispatch`, `within-conversation`, `within-worktree`, or `durable`; `per-process` remains a special value for PID-keyed temp files.

Use these cross-tool fungibility values in the table and in citations: `yes`, `no`, `partial - {trigger or limitation}`, or `n/a`.

## Contract Rules

1. **Per-shape read precedence**: follow the lookup chain named by the row for that exact state shape. Do not apply a plan-cache lookup chain to design, review, startup, calibration, or tracking state just because both mention session memory.
2. **Write precedence**: write only through the row's canonical owner and mechanism. Do not mirror local caches into durable GitHub comments unless the row explicitly says that path owns the durable write.
3. **Honest gaps**: if a surface has no write mechanism, no durable equivalent, or only a best-effort fallback, say that directly and continue through the documented fail-open or recovery path.
4. **No-new-mechanism rule**: this contract records current mechanisms. Do not introduce a new persistence mechanism, Claude-only session store, or automatic sync path while citing this skill.
5. **Survival-label rule**: state-owning docs must carry a nearby survival label and cite the owning contract row. Generic namespace traversal is exempt when it only says to list or inspect a namespace such as `/memories/session/` or `.copilot-tracking/` and does not prescribe a concrete state shape or write.
6. **Cache-vs-durable conflict rule**: durable GitHub or committed sources win over stale local caches, but a provably fresher in-conversation cache is the source for the next durable write. For example, mid-flight plan progress annotations in the active cache must not be discarded just because the durable artifact has not been updated yet. Local caches may be recreated from durable sources when they are stale, and D9 comparisons normalize transport-only formatting drift before deciding whether a durable marker changed.

## Canonical State Rows

| ID     | Shape                           | Survival                                                                                                               | Copilot canonical mechanism                                                                                                                                                                                                                    | Claude canonical mechanism                                                                                                                                                                                                          | Cross-tool fungibility                                                                                                                                                                  | Citation/delegation notes                                                                                                                                                                                                                                                                                                                                                    |
| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SMC-01 | single-issue plan cache         | `within-conversation`; `durable` only after an explicit handoff marker write                                           | Persist and update `/memories/session/plan-issue-{ID}.md` with `vscode/memory`; D9 writes `<!-- plan-issue-{ID} -->` only on Pause/Stop when needed.                                                                                           | `/plan` and `/orchestrate` use GitHub issue comments with `<!-- plan-issue-{ID} -->` plus parent dispatch context, persisted via `skills/session-memory-contract/scripts/persist-marker.ps1` (family `plan-issue`, issue #893 — the ONLY documented write path, never a hand-composed `gh issue comment`; that rule buys a single audited writer, **not** protection from `updated_at` advancement — see [handoff-markers.md](references/handoff-markers.md) § What the write-path rule buys); Claude has no separate `vscode/memory` cache.                                                                    | `partial - same-session cache is not cross-tool; durable marker handoff is cross-tool. #379 follow-up/cross-link needed for the partial path.`                                          | Citations: [Issue-Planner](../../agents/Issue-Planner.agent.md), [Code-Conductor](../../agents/Code-Conductor.agent.md), [Claude guide](../../CLAUDE.md). Pending #384 (<!-- pending-384 -->). Update this row when #384 resolves: revise the cache/marker split if plan-storage ownership changes.                                                                          |
| SMC-02 | bundled plan cache              | `within-conversation`; `durable` only through per-issue handoff marker writes                                          | Persist `/memories/session/plan-bundle-{primary}-{secondary1}-{secondaryN}.md`; Code-Conductor reads bundle plans before single-issue plans and writes per-issue `<!-- plan-issue-{ID} -->` markers only on bundle D9 Pause/Stop when needed.  | `/orchestrate` carries bundle context to `code-conductor`; durable resume reads each issue's GitHub markers rather than a Claude-local bundle cache.                                                                                | `partial - local bundle cache is not fungible; per-issue durable markers are. #379 follow-up/cross-link needed for the bundle handoff path.`                                            | Citations: [Code-Conductor multi-issue flow](../../agents/Code-Conductor.agent.md), [/orchestrate](../../commands/orchestrate.md). Pending #384 (<!-- pending-384 -->). Update this row when #384 resolves: revise bundled-plan storage and marker rules if the plan-storage contract changes.                                                                               |
| SMC-03 | design cache                    | `within-conversation`; design source is `durable` in the issue body or an explicit design handoff marker               | Cache `/memories/session/design-issue-{ID}.md` from the current design snapshot; Solution-Designer persists design details to the issue body, and D9 may write `<!-- design-issue-{ID} -->` when needed.                                       | Prefer parent context, then latest `<!-- design-issue-{ID} -->` issue comment, then issue body; Claude does not require a local design cache.                                                                                       | `yes - authoritative issue body and durable design marker are cross-tool; the session cache is only an optimization.`                                                                   | Citations: [.github/copilot-instructions](../../.github/copilot-instructions.md), [Code-Conductor](../../agents/Code-Conductor.agent.md), [code-conductor shell](../../agents/code-conductor.md). Pending #384 (<!-- pending-384 -->). Update this row when #384 resolves: revise design-cache and durable-design precedence if the plan/design handoff contract changes.    |
| SMC-05 | pre-PR review-state             | `within-conversation`                                                                                                  | Persist branch-keyed local review state to `/memories/session/review-state-{ID}.md` with review mode and prosecution/defense/judgment booleans before PR creation when the branch exposes an issue ID.                                         | No durable Claude-local equivalent before PR creation; review commands may consume the same branch-keyed shape only when the active conversation has the session-memory file available, otherwise re-enter missing review stages.   | `partial - pre-PR review-state is branch-keyed session state and not a durable cross-tool artifact. #379 follow-up/cross-link needed for any cross-tool pre-PR resume story.`           | Citations: [review-state persistence](../validation-methodology/references/review-state-persistence.md), [review reconciliation](../validation-methodology/references/review-reconciliation.md).                                                                                                                                                                             |
| SMC-06 | post-PR review-state resume     | `durable`; session memory is a final fallback                                                                          | Resume review completion from the durable review comment first, then PR-body `<!-- pipeline-metrics -->`, then `/memories/session/review-state-{ID}.md`.                                                                                       | Same durable PR comment and PR-body lookup; session memory is optional fallback only when the surface has it.                                                                                                                       | `yes - durable PR artifacts are cross-tool and latest durable evidence wins.`                                                                                                           | Citations: [review-state persistence](../validation-methodology/references/review-state-persistence.md), [review reconciliation](../validation-methodology/references/review-reconciliation.md), [pipeline metrics schema](../calibration-pipeline/references/metrics-schema.md).                                                                                            |
| SMC-07 | run-once startup-check marker   | `within-conversation:hooks`; inline surfaces may have an honest gap                                                    | Write `/memories/session/session-startup-check-complete.md` after the automatic startup detector runs; fail open if session memory cannot be read or written.                                                                                  | Hook-driven Claude startup shares the run-once intent, but inline/headless command paths may lack a reliable session-memory write surface and must say so.                                                                          | `partial - hook path is bounded to the conversation, inline/headless gaps are not fungible. #379 follow-up/cross-link needed for cross-surface startup semantics.`                      | Citations: [session-startup](../session-startup/SKILL.md), [README hook note](../../README.md), [CUSTOMIZATION startup note](../../CUSTOMIZATION.md).                                                                                                                                                                                                                        |
| SMC-08 | phase-completion markers        | `durable`                                                                                                              | Use GitHub issue comments such as `<!-- experience-owner-complete-{ID} -->`, `<!-- design-phase-complete-{ID} -->`, `<!-- plan-issue-{ID} -->`, and `<!-- design-issue-{ID} -->` for smart resume and D9 durable handoff.                      | Same GitHub markers, persisted via `skills/session-memory-contract/scripts/persist-marker.ps1` (issue #893; `design-issue-{ID}` excepted — a legacy Copilot session-memory concept with no active Claude-side writer); `/orchestrate` checks them before dispatching Code-Conductor.                                                                                                                                                  | `yes - GitHub markers are the shared cross-tool resume surface.`                                                                                                                        | Citations: [Code-Conductor smart resume](../../agents/Code-Conductor.agent.md), [/orchestrate](../../commands/orchestrate.md), [CLAUDE handoffs](../../CLAUDE.md).                                                                                                                                                                                                           |
| SMC-09 | calibration snapshots           | `per-dispatch`; durable only after inclusion in PR-body metrics                                                        | Capture aggregate-review output and prosecution-depth decisions during the review cycle; PR bodies persist the selected summary through `<!-- pipeline-metrics -->` when a PR is created.                                                      | Same scripts and PR-body metrics are available when Claude runs the workflow, but raw command output is not a shared state store.                                                                                                   | `partial - raw snapshots are per-dispatch; PR-body metrics are durable. #379 follow-up/cross-link needed for raw calibration snapshot handoff expectations.`                            | Citations: [review reconciliation](../validation-methodology/references/review-reconciliation.md), [pipeline metrics schema](../calibration-pipeline/references/metrics-schema.md), [aggregate-review-scores](../calibration-pipeline/scripts/aggregate-review-scores.ps1).                                                                                                  |
| SMC-10 | per-finding calibration cache   | `within-worktree`                                                                                                      | Write per-finding entries and re-activation events to `.copilot-tracking/calibration/review-data.json` through `write-calibration-entry.ps1` or backfill tooling.                                                                              | Same local worktree file when Claude is operating in the same checkout; otherwise reconstruct from PR-body pipeline metrics or skip local optimization.                                                                             | `partial - same-worktree cache is reusable across Copilot and Claude; PR-body metrics are required for durable or fresh-checkout handoff.`                                              | Citations: [calibration-pipeline](../calibration-pipeline/SKILL.md), [write-calibration-entry core](../calibration-pipeline/scripts/write-calibration-entry-core.ps1), [tracking-format](../tracking-format/SKILL.md).                                                                                                                                                       |
| SMC-11 | cross-PR calibration state      | `within-worktree`                                                                                                      | Aggregate scripts update derived state in `.copilot-tracking/calibration/review-data.json`, including prosecution depth, re-activation events, complexity history, and proposal tracking.                                                      | Same local calibration file and scripts when the worktree is shared; otherwise use GitHub PR bodies as the durable raw source and rebuild.                                                                                          | `partial - same-worktree derived state is reusable across Copilot and Claude; GitHub PR metrics are the durable rebuild source for fresh checkouts.`                                    | Citations: [aggregate-review-scores](../calibration-pipeline/scripts/aggregate-review-scores.ps1), [create-improvement-issue core](../calibration-pipeline/scripts/create-improvement-issue-core.ps1), [pipeline metrics schema](../calibration-pipeline/references/metrics-schema.md).                                                                                      |
| SMC-12 | plugin release-hygiene decision | `within-worktree:hooks`; `within-conversation:hooks` when the hook payload provides `session_id`                       | Store the scoped decision in `.claude/.state/release-hygiene-{slug}.json`; Copilot normally keys by branch slug when no session ID exists.                                                                                                     | Store the same decision file through the Claude PostToolUse hook, preferring `session_id` and falling back to branch slug or session fallback.                                                                                      | `partial - both surfaces use the same state-file shape, but keying can diverge (session_id versus branch slug); silence is shared only when both resolve the same key.`                 | Citations: [plugin-release-hygiene](../plugin-release-hygiene/SKILL.md), [Copilot platform note](../plugin-release-hygiene/platforms/copilot.md), [Claude platform note](../plugin-release-hygiene/platforms/claude.md).                                                                                                                                                     |
| SMC-13 | .copilot-tracking/ artifacts    | `within-worktree`                                                                                                      | Store local research, specification, archived tracking, and calibration artifacts under `.copilot-tracking/`; do not use this directory for session-memory plan files.                                                                         | Claude shells may write the same local research/spec artifacts when running in the shared checkout; cloud or fresh-branch agents cannot read them unless they are copied or committed elsewhere.                                    | `partial - same-worktree artifacts are reusable; use GitHub issues or committed docs for durable fresh-checkout or cross-agent handoff.`                                                | Citations: [tracking-format](../tracking-format/SKILL.md), [Research-Agent](../../agents/Research-Agent.agent.md), [Specification](../../agents/Specification.agent.md), [session cleanup detector](../session-startup/scripts/session-cleanup-detector-core.ps1).                                                                                                           |
| SMC-14 | subagent-env-handshake state    | `per-dispatch`                                                                                                         | `n/a`; Copilot subagent dispatch does not use this Claude environment-handshake carrier.                                                                                                                                                       | Prepend a `<!-- subagent-env-handshake v1 -->` prompt block with parent HEAD, branch, cwd, dirty fingerprint, workspace mode, and timestamp; the subagent verifies live state before tree-grounded claims.                          | `n/a`                                                                                                                                                                                   | Delegated/informational note: this row delegates the schema and match/mismatch/error behavior to [subagent-env-handshake](../subagent-env-handshake/SKILL.md); the state is prompt-carried and intentionally not persisted.                                                                                                                                                  |
| SMC-15 | rate-limit deferred work state  | `within-conversation`                                                                                                  | When a rate-limited subagent call defers remaining work and `vscode/memory` is available, write `/memories/session/rate-limit-deferred-{scope}.md` with deferred findings/work items, interrupted phase/step, and resume point.                | Claude surfaces that can read/write `/memories/session` may use the same bounded payload; inline/no-write Claude cannot persist it and must carry deferred items in visible conversation or handoff text instead.                   | `partial - same-conversation/session-memory payload is not cross-tool or cross-session; durable plan/PR/issue context can restart the phase but does not preserve the pending payload.` | Citations: [parallel-execution error handling](../parallel-execution/references/error-handling.md), [code review D38 rationale](../../Documents/Design/code-review.md), and [session-memory contract rationale](../../Documents/Design/session-memory-contract.md). This row catalogs a bounded state shape only; it is not a durable fallback or new persistence mechanism. |
| SMC-16 | review-judge-produced sentinel  | `durable`                                                                                                              | Copilot judge runs post `<!-- review-judge-produced-{PR} -->` as a PR comment immediately after the judge ruling finalizes and before pipeline-metrics persistence. Idempotency: check `gh pr view {PR} --json comments` before writing; skip if already present. | Claude judge runs persist the same sentinel via `skills/session-memory-contract/scripts/persist-marker.ps1` (family `review-judge-produced`, issue #893 — the ONLY documented write path, never a hand-composed `gh pr comment`), whose own post-new idempotency comparison supersedes the separate presence check. The sentinel is separate from the `judge-rulings` YAML comment and must be written first (ordering: sentinel → judge-rulings). | `yes - both Copilot and Claude judge runs write this sentinel; Code-Conductor reads it via the warn-only hook synthesis path to detect "review completed but credit not yet written."` | Citations: [review-judgment skill](../review-judgment/SKILL.md), [frame-credit-ledger-core.ps1](../../.github/scripts/lib/frame-credit-ledger-core.ps1) (`Test-ReviewSentinelPresent`, `Resolve-NotPersistedSynthesis`). Governed by this row (SMC-16). |
| SMC-17 | credit-input deferred-emission marker | `durable`                                                                                                         | Pipeline-entry agents (Experience-Owner, Solution-Designer, Issue-Planner) and Code-Conductor (for the `orchestration` port) write `<!-- credit-input-{port}-{ID} -->` as an issue comment immediately after posting their completion marker. Payload: a single `yaml` fenced block carrying `{ port, adapter, evidence }` matching the corresponding `Build-*CreditRow` parameter list. | Same GitHub issue-comment write, persisted via `skills/session-memory-contract/scripts/persist-marker.ps1` (family `credit-input`, issue #893 — the ONLY documented write path, never a hand-composed `gh issue comment`). Code-Conductor reads these markers at PR-creation time by scanning `gh issue view {ID} --json comments --paginate`, parses the YAML payload, calls the matching `Build-*CreditRow`, and emits the credit row into the PR body's pipeline-metrics `credits[]` block. Read-after-write retry: up to 3 times with 1s exponential backoff if the credit-input marker is absent after the paired completion marker for the same port is present (e.g., `<!-- experience-owner-complete-{ID} -->` for `experience`, `<!-- design-phase-complete-{ID} -->` for `design`, `<!-- plan-issue-{ID} -->` for `plan`, `<!-- engagement-record-orchestration-{ID} -->` for `orchestration`). | `yes - GitHub issue-comment is the shared cross-tool durable artifact; Code-Conductor on both platforms harvests the same comment thread via gh CLI.` | Citations: [frame-credit-ledger-core.ps1](../../.github/scripts/lib/frame-credit-ledger-core.ps1) (`Invoke-CreditInputHarvest`), [Code-Conductor](../../agents/Code-Conductor.agent.md), [CLAUDE.md cross-tool markers](../../CLAUDE.md). Governed by this row (SMC-17). Port set: `experience`, `design`, `plan`, `orchestration`. Payload survival: `durable`; retry state: `within-conversation`. |
| SMC-18 | cost-collection install-prompt suppression key | `session` (`within-conversation`; survives Copilot compaction when `/memories/session/` is preserved) | Write any non-empty value to `/memories/session/cost-collection-install-prompt-{repo-cwd}` via `vscode/memory` after the user responds to the prompt; check the key with `vscode/memory view` before each specialist dispatch and skip the prompt if set. Failure path on `vscode/memory` unavailable: fall back to one-prompt-per-session (no suppression — the prompt may fire on every dispatch within the session, but the workflow is not blocked). | `n/a` — Claude orchestration skips the Copilot cost-collection pre-flight entirely; this key is never read or written by Claude paths. | `n/a — Copilot-only by design D9` | Citations: [Code-Conductor Hub Execution Workflow item 3](../../agents/Code-Conductor.agent.md), [copilot-cost-collection skill](../copilot-cost-collection/SKILL.md). Key shape: `cost-collection-install-prompt-{repo-cwd}` where `{repo-cwd}` is the absolute workspace root path. Governed by this row (SMC-18). Added in issue #514 Step 6. |
| SMC-19 | design finding-dispositions marker payload | `durable` | Store `finding_dispositions:` only inside the `<!-- design-phase-complete-{ID} -->` issue-comment marker. Shape: a single `yaml` fenced block with `schema_version: 1`, `passes_run`, and `entries[]` carrying `finding_id`, `pass`, `disposition`, `classification`, `disposition_rationale`, optional `artifact_citation`, and optional `also_flagged_by`. Copilot resume reads the SMC-08 design completion marker and preserves the block when updating the marker. | Same GitHub issue-comment marker and YAML shape. Claude resume reads the SMC-08 design completion marker and preserves the block when updating the marker. Do not mirror this payload into `<!-- credit-input-{port}-{ID} -->` markers. | `yes - the GitHub issue-comment marker is the shared durable resume surface, and the same payload shape is read by both platforms.` | Citations: [solution-authoring disposition gate](../solution-authoring/SKILL.md), [design disposition audit tests](../../.github/scripts/Tests/design-disposition-audit.Tests.ps1), [phase-completion markers row](#canonical-state-rows) SMC-08. Governed by this row (SMC-19). Payload survival: `durable`; cross-tool fungibility: `yes`. |
| SMC-20 | engagement-record marker payload | `durable`             | Upstream agents (Experience-Owner, Solution-Designer, and Issue-Planner) write `<!-- engagement-record-{phase}-{ID} -->` as an issue comment alongside their phase-completion marker. Payload: single yaml fenced block with `schema_version: 2`, `phase`, `capture_session`, `load_bearing_decisions[]`. Entries whose `decision_id` carries the `followup-` prefix are the Filing Approval Gate's durable records (safe-operations §2e) riding this family additively — per-item drop/modify records (#837) plus the batch-scoped ruling record (#1012); they are read by `Merge-FollowupRecords`, which unions them across every prior marker rather than latest-wins-per-phase, and a write that adds one must carry the phase's other `load_bearing_decisions` forward or orphan them. Multiple markers per `(phase, issue)` are allowed; `latest-createdAt` wins on read. Note: the `orchestration` phase uses `schema_version: 3` and is written by Code-Conductor (not an upstream agent) immediately after scope-classification resolves. Note (#974): the `experience` phase has a second writer that is likewise not an upstream agent — the open-for-work conversation (`skills/open-for-work/SKILL.md`), which records its worth-it, affirmation-gate, and brief-approval decisions at `schema_version: 2`. Because this family is `post-new` with latest-createdAt-wins, that conversation must write one cumulative marker rather than one per checkpoint, or the earlier decision is orphaned and gate reconciliation warns on it forever. | Same GitHub issue-comment write, persisted via `skills/session-memory-contract/scripts/persist-marker.ps1` (family `engagement-record`, issue #893 — the ONLY documented write path for the `experience`/`design`/`plan`/`orchestration` phases, never a hand-composed `gh issue comment`; the `review` phase is a known v1 registry gap — PR-keyed but the family declares an issue surface — and stays hand-authored via `gh pr comment` until closed). Resume read via `Read-EngagementRecords` from `.github/scripts/lib/frame-engagement-record-core.ps1` — consumed by `solution-authoring`'s `same-decision-resume` skip rule at upstream phase re-entry. Helper uses `powershell-yaml`; `gh` query preserves `createdAt`. | `yes - GitHub issue-comment is the shared cross-tool durable artifact; both platforms read via the same helper.` | Citations: [engagement-record-emission](../engagement-record-emission/SKILL.md), [solution-authoring same-decision-resume](../solution-authoring/SKILL.md), [frame-engagement-record-core.ps1](../../.github/scripts/lib/frame-engagement-record-core.ps1) (Read-EngagementRecords). Governed by this row (SMC-20). Port set: `experience`, `design`, `plan`, `orchestration`, `review`. Note: the `review` phase is PR-keyed; it uses `-PullRequestNumber` on the read helper and writes to PR comments rather than issue comments. Governed by SMC-23. Write path active per #576; read path active per #575. Payload survival: `durable`; cross-tool fungibility: `yes`. |
| SMC-21 | gate-decision event log (L0 tokens + L1 events) | `within-conversation` (session memory: `memories/session/gate-events-{key}.jsonl`); fallback `within-worktree` (`.copilot-tracking/gate-events.jsonl`) | Agents emit L0 gate-decision tokens at each classification-gate decision point (solution-authoring gate); the PostToolUse hook appends L1 corroboration events. The L2 reconciliation validator (`gate-reconciliation-core.ps1`) reads this log at review time. Schema: `skills/solution-authoring/schemas/gate-decision-token.schema.json`. Key derivation: `Resolve-GateSessionKey` in `skills/solution-authoring/scripts/gate-event-logger-hook.ps1` (session_id → branch-slug → sha fallback). | L0 tokens: agent-written (no separate cross-tool contract — tokens are emitted by the active agent on either platform using the same schema). L1 events: hook-written via PostToolUse on Claude (`AskUserQuestion`) and conditionally on Copilot (`vscode/askQuestions` — platform-confirmed in issue #617 s1). The log path and key-resolution strategy are shared. | partial — L0 tokens are platform-neutral; L1 hook events depend on PostToolUse support for the structured-question tool on each platform (L1 hook on Claude: designed for `AskUserQuestion` (PostToolUse); empirical confirmation pending (spike artifact not produced in #617 s1); conditional for Copilot per `vscode/askQuestions` per #617 s1). | Citations: [gate-decision-token schema](../solution-authoring/schemas/gate-decision-token.schema.json), [gate-event-logger-hook.ps1](../solution-authoring/scripts/gate-event-logger-hook.ps1), [gate-reconciliation-core.ps1](../../.github/scripts/lib/gate-reconciliation-core.ps1), issue #617. Governed by this row (SMC-21). Added in issue #617. |
| SMC-22 | reference pre-flight run-once marker | `within-conversation:hooks`; inline/headless path may lack a reliable session-memory write surface — fail open (run the loader) if the marker cannot be read | Write the `(issue, conversation)` body-hash-based skip key after the first reference pre-flight injection for a given `(issue, conversation)` pair; on a second prompt for the same issue in the same conversation, skip re-injection unless the issue-body hash has changed (two-phase check: Phase-1 loads prior marker state — no short-circuit, gh fetch follows unconditionally; Phase-2 compares stored `body_hash` against freshly fetched hash and skips only when equal). "Conversation" is realized as `session_id` from the hook payload; when `session_id` is absent the hook falls back to `'unknown'`, which means all prompts without a session ID share one marker file (known `'unknown'`-session collision caveat). The run-once gate is implemented in `reference-preflight-hook.ps1` via the Claude `UserPromptSubmit` hook. | `n/a` — Copilot does not use the `UserPromptSubmit` hook for reference pre-flight; the hook path is Claude-only. Copilot surfaces rely on the `upstream-onboarding` skill's Project Reference Loading step to invoke the loader directly. | `n/a — Claude-only hook path by design` | Citations: [project-references SKILL.md §Sentinel](../project-references/SKILL.md) (defines the canonical `<!-- refs-injected-{issue} -->` sentinel grammar); [upstream-onboarding SKILL.md](../upstream-onboarding/SKILL.md) (sentinel-detect/defer step). Honest gap: the inline/headless path may have no reliable session-memory write surface; the hook must fail open and run the loader rather than silently skipping injection. This row documents the run-once marker contract only — it does not introduce a new persistence mechanism (no-new-mechanism rule, Rule 4). Governed by this row (SMC-22). Added in issue #647. |
| SMC-23 | review-phase engagement-record + review-dispositions marker pair | `durable` | Write `<!-- engagement-record-review-{PR} -->` and `<!-- review-dispositions-{PR} -->` as PR comments after the judge verdict resolves. Payload: engagement-record uses `schema_version: 4`, `phase: review`, PR-keyed (not issue-keyed). review-dispositions payload uses `schema_version: 4`, `passes_run`, `entries[]` with `stable_finding_key` (one entry per finding, routine and load-bearing); v2 added per-entry `severity`, `ac_cross_check`, and `stage`; v3 added per-entry `reviewer_source`; v4 adds per-entry `internal_match` and the PR-level `external_sources_reconciled` field — see `skills/review-judgment/SKILL.md § Post-Judge Disposition Gate § Persistence — Ordering` for the authoritative field contract. Multiple markers per PR allowed; latest-createdAt wins on read. | `review-dispositions-{PR}` is persisted via `skills/session-memory-contract/scripts/persist-marker.ps1` (family `review-dispositions`, issue #893 — the ONLY documented write path, never a hand-composed `gh pr comment`); `engagement-record-review-{PR}` is a known v1 registry gap (PR-keyed, but the `engagement-record` family declares an issue surface) and stays a hand-composed `gh pr comment` write until closed. Resume read for engagement-record via `Read-EngagementRecords -PullRequestNumber {PR} -Phase review`; resume read for dispositions via dedicated review-dispositions validator (see S4). | `yes - GitHub PR comment is the shared durable cross-tool artifact; both platforms read via the same helper and PR comment thread.` | Citations: [engagement-record-emission](../engagement-record-emission/SKILL.md) (amended #655 S3), [frame-engagement-record-core.ps1](../../.github/scripts/lib/frame-engagement-record-core.ps1) (PR-aware path, #655 S2), [solution-authoring disposition gate](../solution-authoring/SKILL.md), [review-judgment Post-Judge Disposition Gate](../review-judgment/SKILL.md). Governed by this row (SMC-23). Added in #655 S3. Payload survival: `durable`; cross-tool fungibility: `yes`. |
| SMC-24 | proposed-followups headless-queue marker | `durable` | The Filing Approval Gate (safe-operations §2e) writes `<!-- proposed-followups-{PR\|ISSUE} -->` as a PR or issue comment through `find-or-upsert-comment.ps1` (`Write-ProposedFollowupsComment` in `.github/scripts/lib/followup-gate-core.ps1`) when no interactive surface is available for the maintainer-approval decision. Payload: a fenced YAML block of proposed follow-up issues. Marker head transitions `proposed` → `claimed` → `consumed`. | Same script and marker; the Claude gate path calls the identical `find-or-upsert-comment.ps1` primitive and `Write-ProposedFollowupsComment` helper, so there is no separate Claude-only write path. | `yes - the PowerShell helper and GitHub PR/issue comment are shared cross-tool; both platforms read and write the same marker.` | Citations: [safe-operations Filing Approval Gate §2e](../safe-operations/SKILL.md), [followup-gate-core.ps1](../../.github/scripts/lib/followup-gate-core.ps1) (`Write-ProposedFollowupsComment`), [handoff-markers](references/handoff-markers.md). Consumed by the next gate-capable session touching the same PR/issue (per the design's DD6). Governed by this row (SMC-24). Added in issue #837. Payload survival: `durable`; cross-tool fungibility: `yes`. |

**Applies to every row above that names `persist-marker.ps1` or `persist-phase-ledger.ps1` as the ONLY documented write path.** That rule buys a **single audited writer** — one place where the family registry, payload hygiene, validator adapters and burst ordering are enforced. It does **not** buy protection from `updated_at` advancement. Whether a given write advances anything depends on the family's **write shape**, not on the primitive: an `upsert` family's write replaces the target comment's whole body and advances `updated_at` on every family sitting beside it, exactly as a hand-composed call would, while a `post-new` family's write POSTs a fresh comment and advances nothing. `updated_at` never moves backwards. Before replacing a comment's whole body, read [handoff-markers.md](references/handoff-markers.md) § What the write-path rule buys, which carries the shape split and lists who derives meaning from that field and which of them a touch would break.

## Gotchas

| Trigger                                        | Gotcha                                                                                                                                         | Fix                                                                                                                                                      |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Treating a local cache as if it were a handoff | A Copilot `/memories/session/` file can survive compaction but still disappear at conversation end or be invisible to Claude and cloud agents. | Check the owning SMC row. If cross-tool resume is required, use the row's durable marker or document the honest gap instead of inventing a mirror store. |

| Trigger                                           | Gotcha                                                                                                             | Fix                                                                                                                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Adding a new state shape without a survival label | Later docs cannot tell whether the state survives dispatch, conversation end, worktree changes, or GitHub handoff. | Add a nearby `Survival: {label}; contract: SMC-XX` callout in the state-owning file, or add a new contract row in this skill if the shape is genuinely new. |

## References

- [references/handoff-markers.md](references/handoff-markers.md) — cross-tool handoff marker catalog; all active and retired GitHub comment marker families with SMC citations
- [references/conductor-session-handoff.md](references/conductor-session-handoff.md) — Code-Conductor long-session context management and user-handoff escalation patterns
