Cleaned classification — gap splits into 4 buckets:


Bash

cd C:/Users/decid/Documents/projects/rebno
rm -f trace-tmp.json trace-err.txt 2>/dev/null
# how many distinct files carry parse_error/undeclared (the doc-edit surface)?
traceable-reqs check --json 2>/dev/null > /c/Users/decid/AppData/Local/Temp/tr.json
node -e "
const fs=require('fs');
const j=JSON.parse(fs.readFileSync('C:/Users/decid/AppData/Local/Temp/tr.json','utf8'));
const f=j.findings||[];
const docfiles=new Set();
for(const x of f){if(x.code==='parse_error'||x.code==='undeclared_id'){if(x.file)docfiles.add(x.file);}}
console.log('distinct files needing tag edits:', docfiles.size);
// split live vs archived
let live=0,arch=0;
for(const p of docfiles){if(p.includes('v1.0-phases'))arch++;else live++;}
console.log('  archived (v1.0-phases):',arch,' live/current:',live);
"
rm -f /c/Users/decid/AppData/Local/Temp/tr.json

Count doc-edit surface


distinct files needing tag edits: 0
  archived (v1.0-phases): 0  live/current: 0


JSON omits file field for these. Pull locations from human output.


cd C:/Users/decid/Documents/projects/rebno
traceable-reqs check 2>/dev/null | grep -oE "(parse_error|undeclared_id) [A-Za-z0-9-]+ [^ ]+\.md" | awk '{print $3}' | sed 's/:[0-9]*$//' | sort -u > /c/Users/decid/AppData/Local/Temp/files.txt
echo "distinct files w/ tag findings:"; wc -l < /c/Users/decid/AppData/Local/Temp/files.txt
echo "--- live (non-archived) ---"
grep -v "v1.0-phases" /c/Users/decid/AppData/Local/Temp/files.txt
echo "--- archived count ---"
grep -c "v1.0-phases" /c/Users/decid/AppData/Local/Temp/files.txt

Extract finding file paths from human output


distinct files w/ tag findings:
16
--- live (non-archived) ---
.planning/phases/07-workflow-smoke-convention-locks/07-06-SUMMARY.md
.planning/phases/07-workflow-smoke-convention-locks/07-CONTEXT.md
.planning/phases/07-workflow-smoke-convention-locks/07-PATTERNS.md
.planning/phases/07-workflow-smoke-convention-locks/07-RESEARCH.md
--- archived count ---
12


Determine default new level size for Gridvania


16 files carry the 137 tag findings (4 live phase-7 docs + 12 archived v1.0). Quick-probe why v1.0 reqs lost doc evidence.


cd C:/Users/decid/Documents/projects/rebno
echo "=== REQ-EXT-01 doc tag anywhere? ==="
grep -rn "doc->REQ-EXT-01\]" --include="*.md" . 2>/dev/null | head -5
echo "=== bare EXT-01 form? ==="
grep -rn "doc->EXT-01\]" --include="*.md" . 2>/dev/null | head -5
echo "=== manifest EXT-01 stages ==="
grep -A2 'id = "REQ-EXT-01"' traceable-reqs.toml
echo "=== scan roots in manifest ==="
grep -A6 "\[scan\]" traceable-reqs.toml 2>/dev/null || grep -iE "roots|scan" traceable-reqs.toml | head

Probe v1.0 req evidence loss


=== REQ-EXT-01 doc tag anywhere? ===
=== bare EXT-01 form? ===
=== manifest EXT-01 stages ===
id = "REQ-EXT-01"
title = "Extract client GML scripts to one-file-per-script tree"

=== scan roots in manifest ===
[scan]
roots = [
  "docs",
  "decomp/wiki",
  "tools",
  "scripts",
  ".planning",


Phase 7 Wave 1: 5 ADR/req plans

07-01..07-05 — ADRs 0009-0012 + HYG-02 stages tighten

Phase 7 Wave 2: lint scripts

07-06 — tools/scripts lint files + HYG-01 tag

Phase 7 Wave 3: preflight wiring

07-07 — package.json + LOCAL-DEPLOY.md MANDATORY section

Phase 7 Wave 4: operator smoke gate

07-08 — operator authors synth 8000x6400 LDtk world, PASS/FAIL verdict (autonomous:false)

Phase 7 verify+complete

code-review, regression, verify_phase_goal, update_roadmap


Root cause found — bigger than placeholders:

**REQ-EXT-01 has zero doc tags AND no `required_stages` line** (defaults to `["doc"]`). Same for the other 27 v1.0 reqs. traceable-reqs was adopted mid-v1.0 (commit ee722b2), reqs seeded with implicit `doc` stage, but **most v1.0 reqs were never doc-tagged** — the CI hard-gate was deferred (CLAUDE.md says so), GH Actions died, so nothing ever enforced coverage. The 72 `missing_stage` findings are v1.0's un-enforced trace debt, **not a Phase-7 regression.**

This maps directly onto spt-core **Rule 5 (activation, not premature failure):** reqs stay `required_stages = []` until the *active* milestone delivers them. The correct model:

| Bucket | Count | Action |
|---|---|---|
| Phase-7 reqs (MAP-02, MAP-15, HYG-01, HYG-02) | 4 | Keep activated — tagged + green |
| Future v1.1 (MAP-01, 03–14, 16 → phases 8–12) | ~14 | Deactivate `[]`; each phase re-activates its own |
| v1.0 closed milestone (EXT, SDOC, AST, CDOC, CLI, SRV, DEP) | ~28 | Deactivate `[]` — validated at tag `v1.0`, functional gate was the milestone gate, retro-tagging archived docs = busywork |
| Parity backlog (PAR-01..08) | 8 | Deactivate `[]` — v1.2+ |
| Illustrative/placeholder tags (REQ-X, REQ-XX-NN, REQ-SRV-XX…) in 16 docs | 137 | Angle-bracket `[<stage>->REQ-X]` (now works on v0.1.1) |

Plus from code review: WR-04 LOCAL-DEPLOY.md self-contradiction (fix).

This is a proper gap-closure phase (manifest surgery ~50 reqs + 16 doc files + adopt a TRACEABILITY.md contract like spt-core). Two decisions before I proceed:


AskUserQuestion

Question: v1.0 closed-milestone reqs (EXT/SDOC/AST/CDOC/CLI/SRV/DEP, ~28) never got doc tags in v1.0. Deactivate or retro-tag?

Choices:
Set required_stages=[] — validated at tag v1.0, functional gate WAS the milestone gate. Matches your 'deactivate not remove' directive + spt-core activation model. Recommended.
Add [doc->REQ-EXT-01] etc. to the 12 archived v1.0 phase docs so they stay activated+green. Full historical trace, but ~28 reqs of busywork with no forward value.
Deactivate reqs whose evidence is genuinely gone; retro-tag any where the doc tag exists in bare form (just needs REQ- prefix). Per-req judgment by gap planner.

Question: How to execute this cleanup?

Choices:
/gsd:plan-phase 7 --gaps → reviewed atomic plans + SUMMARY, then /gsd:execute-phase 7 --gaps-only. Clean GSD trace. Recommended for manifest surgery of this size.
I do it directly this session: manifest edits + angle-bracket docs + LOCAL-DEPLOY fix + TRACEABILITY.md, commit atomically, re-verify. Faster, less ceremony.


Your questions have been answered: "v1.0 closed-milestone reqs (EXT/SDOC/AST/CDOC/CLI/SRV/DEP, ~28) never got doc tags in v1.0. Deactivate or retro-tag?"="Deactivate [] (spt-core Rule 5)", "How to execute this cleanup?"="Formal gap-closure plan". You can now continue with these answers in mind.

Question: v1.0 closed-milestone reqs (EXT/SDOC/AST/CDOC/CLI/SRV/DEP, ~28) never got doc tags in v1.0. Deactivate or retro-tag?

Choices:
Set required_stages=[] — validated at tag v1.0, functional gate WAS the milestone gate. Matches your 'deactivate not remove' directive + spt-core activation model. Recommended.
Add [doc->REQ-EXT-01] etc. to the 12 archived v1.0 phase docs so they stay activated+green. Full historical trace, but ~28 reqs of busywork with no forward value.
Deactivate reqs whose evidence is genuinely gone; retro-tag any where the doc tag exists in bare form (just needs REQ- prefix). Per-req judgment by gap planner.

Question: How to execute this cleanup?

Choices:
/gsd:plan-phase 7 --gaps → reviewed atomic plans + SUMMARY, then /gsd:execute-phase 7 --gaps-only. Clean GSD trace. Recommended for manifest surgery of this size.
I do it directly this session: manifest edits + angle-bracket docs + LOCAL-DEPLOY fix + TRACEABILITY.md, commit atomically, re-verify. Faster, less ceremony.


Decisions locked: v1.0 reqs → deactivate `[]`; formal gap-closure plan. Phase 7 stays `gaps_found` (not complete). I'll persist the decisions + analysis so the gap-planner (fresh context) inherits them, then route.


Bash

cd C:/Users/decid/Documents/projects/rebno
echo "=== VERIFICATION.md gap section ==="
sed -n '/## Gap/,/## /p' .planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md 2>/dev/null | head -40
echo "=== tail ==="
tail -25 .planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md

Read VERIFICATION gap section


=== VERIFICATION.md gap section ===
### Gaps Summary

The phase delivered the core mission — four convention-lock ADRs, the LDtk version pin, the three lint/check scripts (one functional, two pre-wired stubs), HYG-01 tag, preflight chain composition, MANDATORY section in LOCAL-DEPLOY.md, and an operator-PASS smoke test on the synthetic 8000×6400 3×3 GridVania world with screenshot evidence and three v1.2 watchpoints documented. Phases 8+ inherit a stable convention surface and can begin authoring `.ldtk` content without ambiguity.

The single gap is the **HYG-02 scope interpretation conflict**: the as-shipped forward-lock-only design (lint-no-req-placeholders.mjs blocks NEW placeholders via an allowlist) conflicts with the literal text of ROADMAP SC #4 ("zero findings"), REQUIREMENTS.md line 76 ("cleaned from Phase 04 + 06.4 docs"), and Plan 07-07 acceptance criterion #6 (`pnpm preflight exits 0` on green state). 209 `[must]` undeclared_id findings remain in `pnpm trace:check`, all confined to archived `.planning/milestones/v1.0-phases/` and this phase's own planning docs. The cascade effect: `pnpm preflight` currently exits 1, leaving the new MANDATORY deploy gate non-actionable as written.

This is a single root cause with three observable symptoms (SC #2 PARTIAL, SC #4 FAILED, internal LOCAL-DEPLOY.md contradiction) — closing the underlying scope decision resolves all three. The decision belongs to the operator; the verifier surfaces the path options under the `human_verification` block.

---

_Verified: 2026-05-24_
_Verifier: Claude (gsd-verifier, Opus 4.7 1M context)_
=== tail ===
### Human Verification Required

#### 1. HYG-02 retroactive-vs-forward-lock scope adjudication

**Test:** Operator picks one of three resolution paths for the HYG-02 trace:check gap (see `gaps[].missing` list):
   - (a) Retroactively clean placeholders from archived v1.0 docs + Phase 7 planning docs;
   - (b) Extend traceable-reqs.toml with a documented scan-allowlist (matches the operator-trust posture of lint-no-req-placeholders.mjs);
   - (c) Amend ROADMAP SC #4 + REQUIREMENTS.md HYG-02 wording + Plan 07-07 acceptance criterion #6 to match the as-shipped forward-lock-only interpretation, and extend LOCAL-DEPLOY.md's existing `## Pre-flight` known-debt language into the new MANDATORY section.

**Expected:** Operator decision documented. A follow-up plan (or amendment commit) implements the chosen path. After implementation, `pnpm preflight` exits 0 on green state, and `docs/deploy/LOCAL-DEPLOY.md` reads consistently across both pre-flight sections.

**Why human:** Scope/policy decision, not a code defect. The shipped artifacts work correctly; the verifier cannot pick the hygiene-budget vs documentation-consistency tradeoff without operator preference. Plan 07-08 SUMMARY explicitly raised this for adjudication.

### Gaps Summary

The phase delivered the core mission — four convention-lock ADRs, the LDtk version pin, the three lint/check scripts (one functional, two pre-wired stubs), HYG-01 tag, preflight chain composition, MANDATORY section in LOCAL-DEPLOY.md, and an operator-PASS smoke test on the synthetic 8000×6400 3×3 GridVania world with screenshot evidence and three v1.2 watchpoints documented. Phases 8+ inherit a stable convention surface and can begin authoring `.ldtk` content without ambiguity.

The single gap is the **HYG-02 scope interpretation conflict**: the as-shipped forward-lock-only design (lint-no-req-placeholders.mjs blocks NEW placeholders via an allowlist) conflicts with the literal text of ROADMAP SC #4 ("zero findings"), REQUIREMENTS.md line 76 ("cleaned from Phase 04 + 06.4 docs"), and Plan 07-07 acceptance criterion #6 (`pnpm preflight exits 0` on green state). 209 `[must]` undeclared_id findings remain in `pnpm trace:check`, all confined to archived `.planning/milestones/v1.0-phases/` and this phase's own planning docs. The cascade effect: `pnpm preflight` currently exits 1, leaving the new MANDATORY deploy gate non-actionable as written.

This is a single root cause with three observable symptoms (SC #2 PARTIAL, SC #4 FAILED, internal LOCAL-DEPLOY.md contradiction) — closing the underlying scope decision resolves all three. The decision belongs to the operator; the verifier surfaces the path options under the `human_verification` block.

---

_Verified: 2026-05-24_
_Verifier: Claude (gsd-verifier, Opus 4.7 1M context)_


Now write the gap-closure decisions doc the planner inherits.


Write

---
phase: 07-workflow-smoke-convention-locks
type: gap-decisions
status: ready-for-gap-plan
created: 2026-06-03
source: 07-VERIFICATION.md (gaps_found, 4/5 must-haves)
operator_decisions: locked 2026-06-03
---

# Phase 7 Gap-Closure Decisions

Operator-adjudicated resolution for the single verification gap (HYG-02 scope
conflict + its trace:check cascade). These decisions are LOCKED — the gap-closure
planner should plan TO them, not re-litigate.

## Root cause (corrected from VERIFICATION.md)

VERIFICATION.md framed the gap as "HYG-02 forward-lock-only vs literal cleanup."
Deeper investigation (2026-06-03) found the real root cause is broader:

**traceable-reqs was adopted mid-v1.0 (commit ee722b2) but its CI hard-gate was
never enforced** (GH Actions storage died; CLAUDE.md documents the gate as
deferred). Result: most v1.0 reqs were seeded into the manifest with the implicit
default `required_stages = ["doc"]` but **never actually doc-tagged**. The 209
`pnpm trace:check` findings break down as:

| Code | Count | Nature |
|---|---|---|
| `missing_stage` | 72 | Reqs activated (implicit `["doc"]`) with zero doc evidence — v1.0 trace debt + not-yet-built v1.1 phases + parity backlog |
| `parse_error` | 94 | Malformed illustrative tags in tagging-contract docs (e.g. `[stage->REQ-ID]` example prose) |
| `undeclared_id` | 43 | Placeholder example IDs (`REQ-X`, `REQ-XX-NN`, `REQ-SRV-XX`, `REQ-CLI-XX`, `REQ-DEP-NN`, `REQ-ID`) used illustratively in docs |

This is **not a Phase-7 regression** — Phase 7's own 4 reqs (MAP-02, MAP-15,
HYG-01, HYG-02) are correctly tagged and green.

## Convention adopted: spt-core Rule 5 (activation, not premature failure)

Source: `../spt-core/docs/TRACEABILITY.md` Rule 5 —
> "Every requirement starts `required_stages = []` (inactive) so `check` stays
> green pre-code. A milestone activates the requirements it delivers by setting
> their real `required_stages`. Deferred items stay `[]` until promoted."

traceable-reqs measures the **active milestone's delivery**, not archived history.
Closed-milestone reqs were gated by their functional milestone gate (v1.0 validated
at tag `v1.0` / commit `1f6073e`), not by trace coverage.

## Tooling prerequisite — DONE

traceable-reqs upgraded **v0.1.0 → v0.1.1** globally (2026-06-03). v0.1.1 adds
angle-bracket-ignore: `[<stage>->REQ-X]` is treated as illustration, not live
evidence (verified empirically — v0.1.0 flagged it `parse_error`; v0.1.1 emits
no finding). Backup of v0.1.0 at
`C:/Users/decid/AppData/Local/Programs/traceable-reqs/traceable-reqs.0.1.0.bak.exe`.
This is the enabler for the illustrative-tag fix below.

## Locked decisions (operator, 2026-06-03)

### D-1 — Manifest req activation buckets

Edit `traceable-reqs.toml`. Set explicit `required_stages` per bucket:

| Bucket | Req IDs | required_stages |
|---|---|---|
| **Phase-7 delivered (active)** | REQ-MAP-02, REQ-MAP-15, REQ-HYG-01, REQ-HYG-02 | keep as-is (activated + green) |
| **Future v1.1 (phases 8–12)** | REQ-MAP-01, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 16 | `[]` — each phase re-activates its own at plan time |
| **v1.0 closed milestone** | REQ-EXT-01..08, REQ-SDOC-01..06, REQ-AST-02..04, REQ-CDOC-02..03, REQ-CLI-05, REQ-SRV-02, 05, 06, 07, 08, 09, 10, 11 (+ any other v1.0 req currently defaulting to `["doc"]` without evidence) | `[]` — validated at tag v1.0; deactivate, do NOT remove |
| **Parity backlog (v1.2+)** | REQ-PAR-01..08 | `[]` |

**Decision basis:** operator chose "Deactivate [] (spt-core Rule 5)" over
retro-tagging. Rationale: v1.0 functional gate was the milestone gate;
retro-tagging ~28 archived reqs = busywork with no forward value.

**IMPORTANT — deactivate, NOT remove.** Every req row stays in the manifest with
its id + title intact; only `required_stages` changes to `[]`. This preserves the
registry so a future milestone can re-activate (or a v1.2 parity push can promote
PAR-* without re-deriving them).

Note: any req CURRENTLY activated for `impl`/`unit` with real evidence (e.g. v1.0
SRV reqs that DID get impl/unit tags, or DEP reqs with CI tags) must be checked
before blanket-deactivating — only deactivate reqs whose required stages are
genuinely uncovered. Cross-check each missing_stage finding against existing tags
before zeroing. (The 72 missing_stage list in 07-VERIFICATION.md `gaps[]` is the
authoritative target set.)

### D-2 — Illustrative/placeholder tags → angle-bracket form

For the 137 parse_error + undeclared_id findings across these 16 files:
- 4 live: `07-CONTEXT.md`, `07-PATTERNS.md`, `07-RESEARCH.md`, `07-06-SUMMARY.md`
- 12 archived under `.planning/milestones/v1.0-phases/`

Convert each ILLUSTRATIVE tag (example prose showing the tagging grammar, not real
evidence) to the angle-bracket form `[<stage>->REQ-ID]` per spt-core TRACEABILITY.md
"Tag examples" convention. v0.1.1 ignores these.

Per-occurrence judgment required: distinguish a genuine illustration (keep, angle-
bracket it) from an accidental real-looking tag that should point at a declared
req (fix the id). Most will be illustrations.

### D-3 — LOCAL-DEPLOY.md contradiction (code-review WR-04)

`docs/deploy/LOCAL-DEPLOY.md` `## Pre-flight` (known-legacy-debt: review & continue)
contradicts `## Preflight gate (MANDATORY)` (MUST exit 0). After D-1+D-2 land,
`pnpm preflight` exits 0 on green state, so the MANDATORY section becomes
actionable. Reconcile the two sections: the MANDATORY gate is authoritative;
the older Pre-flight known-debt language should defer to it (or be removed).

### D-4 — Adopt a TRACEABILITY.md contract (recommended, mirror spt-core)

Create `docs/TRACEABILITY.md` (or extend CLAUDE.md trace section) documenting the
activation-not-premature-failure rule so this debt does not silently re-accumulate.
Model on `../spt-core/docs/TRACEABILITY.md`. At minimum codify: reqs start `[]`,
milestone activates its own, tag in the same change as evidence, illustrative tags
use `[<stage>->...]`.

## Exit criteria for the gap-closure plan

- `pnpm trace:check` exits 0 (zero `[must]` findings)
- `pnpm preflight` exits 0 end-to-end
- `docs/deploy/LOCAL-DEPLOY.md` reads consistently (no Pre-flight vs MANDATORY conflict)
- Phase-7's 4 reqs remain activated + green (no accidental deactivation)
- Every manifest req row preserved (deactivation = `required_stages=[]`, never deletion)
- Re-run `/gsd:verify-work 7` (or re-verify) → `passed`

## Out of scope (carry forward, do not fix here)

- Code-review WR-01 (`lint-atlas-hash.mjs` `_smoke` substring vs path-segment match)
  — Phase 8 activation watchpoint, not blocking now.
- WR-02 (allowlist prefix-trust posture) — documented behavior; revisit if abused.
- WR-03 (symlink handling in lint-atlas-hash) — Phase 8.
- WR-05 (check-conversion-regression no forcing function) — Phase 9.


File created successfully at: C:\Users\decid\Documents\projects\rebno\.planning\phases\07-workflow-smoke-convention-locks\07-GAP-DECISIONS.md (file state is current in your context — no need to Read it back)

---
phase: 07-workflow-smoke-convention-locks
type: gap-decisions
status: ready-for-gap-plan
created: 2026-06-03
source: 07-VERIFICATION.md (gaps_found, 4/5 must-haves)
operator_decisions: locked 2026-06-03
---

# Phase 7 Gap-Closure Decisions

Operator-adjudicated resolution for the single verification gap (HYG-02 scope
conflict + its trace:check cascade). These decisions are LOCKED — the gap-closure
planner should plan TO them, not re-litigate.

## Root cause (corrected from VERIFICATION.md)

VERIFICATION.md framed the gap as "HYG-02 forward-lock-only vs literal cleanup."
Deeper investigation (2026-06-03) found the real root cause is broader:

**traceable-reqs was adopted mid-v1.0 (commit ee722b2) but its CI hard-gate was
never enforced** (GH Actions storage died; CLAUDE.md documents the gate as
deferred). Result: most v1.0 reqs were seeded into the manifest with the implicit
default `required_stages = ["doc"]` but **never actually doc-tagged**. The 209
`pnpm trace:check` findings break down as:

| Code | Count | Nature |
|---|---|---|
| `missing_stage` | 72 | Reqs activated (implicit `["doc"]`) with zero doc evidence — v1.0 trace debt + not-yet-built v1.1 phases + parity backlog |
| `parse_error` | 94 | Malformed illustrative tags in tagging-contract docs (e.g. `[stage->REQ-ID]` example prose) |
| `undeclared_id` | 43 | Placeholder example IDs (`REQ-X`, `REQ-XX-NN`, `REQ-SRV-XX`, `REQ-CLI-XX`, `REQ-DEP-NN`, `REQ-ID`) used illustratively in docs |

This is **not a Phase-7 regression** — Phase 7's own 4 reqs (MAP-02, MAP-15,
HYG-01, HYG-02) are correctly tagged and green.

## Convention adopted: spt-core Rule 5 (activation, not premature failure)

Source: `../spt-core/docs/TRACEABILITY.md` Rule 5 —
> "Every requirement starts `required_stages = []` (inactive) so `check` stays
> green pre-code. A milestone activates the requirements it delivers by setting
> their real `required_stages`. Deferred items stay `[]` until promoted."

traceable-reqs measures the **active milestone's delivery**, not archived history.
Closed-milestone reqs were gated by their functional milestone gate (v1.0 validated
at tag `v1.0` / commit `1f6073e`), not by trace coverage.

## Tooling prerequisite — DONE

traceable-reqs upgraded **v0.1.0 → v0.1.1** globally (2026-06-03). v0.1.1 adds
angle-bracket-ignore: `[<stage>->REQ-X]` is treated as illustration, not live
evidence (verified empirically — v0.1.0 flagged it `parse_error`; v0.1.1 emits
no finding). Backup of v0.1.0 at
`C:/Users/decid/AppData/Local/Programs/traceable-reqs/traceable-reqs.0.1.0.bak.exe`.
This is the enabler for the illustrative-tag fix below.

## Locked decisions (operator, 2026-06-03)

### D-1 — Manifest req activation buckets

Edit `traceable-reqs.toml`. Set explicit `required_stages` per bucket:

| Bucket | Req IDs | required_stages |
|---|---|---|
| **Phase-7 delivered (active)** | REQ-MAP-02, REQ-MAP-15, REQ-HYG-01, REQ-HYG-02 | keep as-is (activated + green) |
| **Future v1.1 (phases 8–12)** | REQ-MAP-01, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 16 | `[]` — each phase re-activates its own at plan time |
| **v1.0 closed milestone** | REQ-EXT-01..08, REQ-SDOC-01..06, REQ-AST-02..04, REQ-CDOC-02..03, REQ-CLI-05, REQ-SRV-02, 05, 06, 07, 08, 09, 10, 11 (+ any other v1.0 req currently defaulting to `["doc"]` without evidence) | `[]` — validated at tag v1.0; deactivate, do NOT remove |
| **Parity backlog (v1.2+)** | REQ-PAR-01..08 | `[]` |

**Decision basis:** operator chose "Deactivate [] (spt-core Rule 5)" over
retro-tagging. Rationale: v1.0 functional gate was the milestone gate;
retro-tagging ~28 archived reqs = busywork with no forward value.

**IMPORTANT — deactivate, NOT remove.** Every req row stays in the manifest with
its id + title intact; only `required_stages` changes to `[]`. This preserves the
registry so a future milestone can re-activate (or a v1.2 parity push can promote
PAR-* without re-deriving them).

Note: any req CURRENTLY activated for `impl`/`unit` with real evidence (e.g. v1.0
SRV reqs that DID get impl/unit tags, or DEP reqs with CI tags) must be checked
before blanket-deactivating — only deactivate reqs whose required stages are
genuinely uncovered. Cross-check each missing_stage finding against existing tags
before zeroing. (The 72 missing_stage list in 07-VERIFICATION.md `gaps[]` is the
authoritative target set.)

### D-2 — Illustrative/placeholder tags → angle-bracket form

For the 137 parse_error + undeclared_id findings across these 16 files:
- 4 live: `07-CONTEXT.md`, `07-PATTERNS.md`, `07-RESEARCH.md`, `07-06-SUMMARY.md`
- 12 archived under `.planning/milestones/v1.0-phases/`

Convert each ILLUSTRATIVE tag (example prose showing the tagging grammar, not real
evidence) to the angle-bracket form `[<stage>->REQ-ID]` per spt-core TRACEABILITY.md
"Tag examples" convention. v0.1.1 ignores these.

Per-occurrence judgment required: distinguish a genuine illustration (keep, angle-
bracket it) from an accidental real-looking tag that should point at a declared
req (fix the id). Most will be illustrations.

### D-3 — LOCAL-DEPLOY.md contradiction (code-review WR-04)

`docs/deploy/LOCAL-DEPLOY.md` `## Pre-flight` (known-legacy-debt: review & continue)
contradicts `## Preflight gate (MANDATORY)` (MUST exit 0). After D-1+D-2 land,
`pnpm preflight` exits 0 on green state, so the MANDATORY section becomes
actionable. Reconcile the two sections: the MANDATORY gate is authoritative;
the older Pre-flight known-debt language should defer to it (or be removed).

### D-4 — Adopt a TRACEABILITY.md contract (recommended, mirror spt-core)

Create `docs/TRACEABILITY.md` (or extend CLAUDE.md trace section) documenting the
activation-not-premature-failure rule so this debt does not silently re-accumulate.
Model on `../spt-core/docs/TRACEABILITY.md`. At minimum codify: reqs start `[]`,
milestone activates its own, tag in the same change as evidence, illustrative tags
use `[<stage>->...]`.

## Exit criteria for the gap-closure plan

- `pnpm trace:check` exits 0 (zero `[must]` findings)
- `pnpm preflight` exits 0 end-to-end
- `docs/deploy/LOCAL-DEPLOY.md` reads consistently (no Pre-flight vs MANDATORY conflict)
- Phase-7's 4 reqs remain activated + green (no accidental deactivation)
- Every manifest req row preserved (deactivation = `required_stages=[]`, never deletion)
- Re-run `/gsd:verify-work 7` (or re-verify) → `passed`

## Out of scope (carry forward, do not fix here)

- Code-review WR-01 (`lint-atlas-hash.mjs` `_smoke` substring vs path-segment match)
  — Phase 8 activation watchpoint, not blocking now.
- WR-02 (allowlist prefix-trust posture) — documented behavior; revisit if abused.
- WR-03 (symlink handling in lint-atlas-hash) — Phase 8.
- WR-05 (check-conversion-regression no forcing function) — Phase 9.


Bash

cd C:/Users/decid/Documents/projects/rebno
git add .planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md .planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md .planning/phases/07-workflow-smoke-convention-locks/07-REVIEW.md
git status --short | head

Stage gap decisions + verification + review


warning: in the working copy of '.planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.planning/phases/07-workflow-smoke-convention-locks/07-REVIEW.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md', LF will be replaced by CRLF the next time Git touches it
A  .planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md
A  .planning/phases/07-workflow-smoke-convention-locks/07-REVIEW.md
A  .planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md
?? docs/LEGACY_FEATURE_REFERENCE.md


cd C:/Users/decid/Documents/projects/rebno
gsd-sdk query commit "docs(phase-07): verification gaps_found + locked gap-closure decisions

Phase 7 execution complete (8/8 plans), code review clean (0 critical),
but verification = gaps_found (4/5 must-haves). Single root cause:
traceable-reqs adopted mid-v1.0 with CI gate never enforced -> 209 trace:check
findings (72 missing_stage v1.0 trace debt + 137 illustrative-tag parse/undeclared).
NOT a Phase-7 regression.

Operator decisions locked (07-GAP-DECISIONS.md):
- Adopt spt-core Rule 5 (activation-not-premature-failure): deactivate
  required_stages=[] for v1.0-closed + future-v1.1 + parity-backlog reqs;
  keep Phase-7's 4 reqs activated. Deactivate, never remove.
- Angle-bracket illustrative tags [<stage>->REQ-X] (enabled by traceable-reqs
  v0.1.1 upgrade, done globally this session).
- Fix LOCAL-DEPLOY.md Pre-flight vs MANDATORY contradiction (code-review WR-04).
- Adopt docs/TRACEABILITY.md contract mirroring spt-core.

Next: /gsd:plan-phase 7 --gaps -> /gsd:execute-phase 7 --gaps-only." --files .planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md .planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md .planning/phases/07-workflow-smoke-convention-locks/07-REVIEW.md 2>&1 | tail -6

Commit gap decisions + verification artifacts


  "files": [
    ".planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md",
    ".planning/phases/07-workflow-smoke-convention-locks/07-REVIEW.md",
    ".planning/phases/07-workflow-smoke-convention-locks/07-VERIFICATION.md"
  ]
}


Updated task #5 status


TaskCreate

Phase 7 gap-closure: trace debt + manifest activation

Per 07-GAP-DECISIONS.md: deactivate v1.0/future/parity reqs to [], angle-bracket 137 illustrative tags, fix LOCAL-DEPLOY contradiction, adopt TRACEABILITY.md, re-verify. Route: /gsd:plan-phase 7 --gaps


Task #6 created successfully: Phase 7 gap-closure: trace debt + manifest activation


Phase 7 work complete + handed off cleanly. Final status:

## ✓ Phase 7 executed — verification: gaps_found (4/5)

**Shipped (8/8 plans):** ADRs 0009–0012, LDtk pin 1.5.3, 3 lint scripts, preflight chain, LOCAL-DEPLOY MANDATORY section, operator smoke-test PASS (3×3 GridVania, your UAT).

**Code review:** 0 critical, 5 warn (non-blocking).

**Gap:** 1 root cause — traceable-reqs adopted mid-v1.0, CI gate never enforced → 209 trace:check findings (v1.0 trace debt + illustrative tags), NOT a Phase-7 regression. Decisions locked in `07-GAP-DECISIONS.md`:
- spt-core Rule 5: deactivate `[]` v1.0-closed + future-v1.1 + parity reqs; keep Phase-7's 4 active
- angle-bracket 137 illustrative tags (traceable-reqs **v0.1.1 installed globally** this session — enables `[<stage>->REQ-X]` ignore)
- fix LOCAL-DEPLOY contradiction (WR-04)
- adopt `docs/TRACEABILITY.md` contract

**Phase NOT marked complete** — gap-closure pending.

---
## ▶ Next

`/clear` then:

`/gsd:plan-phase 7 --gaps` ← reads 07-GAP-DECISIONS.md, produces gap plans
then `/gsd:execute-phase 7 --gaps-only`

Also: `cat .planning/phases/07-workflow-smoke-convention-locks/07-GAP-DECISIONS.md` — full decision record.

Tooling note: v0.1.0 binary backed up at `traceable-reqs.0.1.0.bak.exe`; v0.1.1 also benefits spt-core (same global binary).


<command-message>spt:live</command-message>
<command-name>/spt:live</command-name>


Base directory for this skill: C:\Users\decid\.claude\plugins\cache\cplugs\spt\1.11.25\skills\live

# /spt:live

All commands use `$OWL` and `$LIVE` env vars, auto-injected by the plugin's SessionStart hook. If commands fail with "command not found", restart the Claude Code session so the SessionStart hook re-runs.

> **Output format:** Status messages (ANSI-colored) go to **stderr**. Live agent output is orange. Agents parse `TAG:value` tokens.

> **Identity auto-detection:** For messaging commands (send, ring, commune, signoff, etc.), your identity is auto-detected from your session. Pass your ID explicitly only if auto-detection fails. Startup commands (`start`, `revive`) always require an explicit ID.

Starting a live agent session is a single background task. From then on, the live agent id becomes your name. You have a "Psyche" companion agent. Relative to Psyche, you are referred to as "Self".

## Messaging Command Reference

All three commands read the message body from **stdin** (pipe or heredoc).

```bash
# send -- fire-and-forget to a target (use when you have an active session)
$OWL send <target> <<'EOF'
message body
EOF

# send --reply-to -- respond to whoever messaged you
$OWL send --reply-to <sender> <<'EOF'
response body
EOF

# ring -- send and wait for reply (alias: ask)
$OWL ring <target> <<'EOF'
message body
EOF
```

If auto-detection fails, pass your ID explicitly: `$OWL send <target> <your-id>`, `$OWL send --reply-to <sender> <your-id>`, `$OWL ring <target> <your-id>`.

**When to use which:**
- **`send`**: Fire-and-forget message to a target.
- **`send --reply-to`**: You received a message and want to respond. `from` is auto-set from the original sender.
- **`ring`**: Send and wait for reply. Creates a temporary perch if you have no listener.

## Auto-resume (--auto, SessionStart auto-pick, casual triggers)

Three entry paths converge here. They share ONE dispatch table and ONE uniform AUTO-07 confirmation hop:

1. **Bare `--auto` flag**: user invoked `/spt:live --auto` (no positional id). Run `$LIVE pick-spec` to get pick JSON.
2. **SessionStart `<spt-live-auto-pick>` XML block** present in your context: parse the inner JSON as the pick-spec result; do NOT re-invoke `$LIVE pick-spec` (the JSON is already provided).
3. **Casual-language trigger** (the 8 AUTO-RESUME phrases in this skill's description frontmatter, e.g. "continue live work", "resume live agent"): treat as the bare `--auto` path — run `$LIVE pick-spec` to get pick JSON.

> The AUTO-02 next-work surfacing in Step 3 below ALSO runs at the end of the standard `/spt:live <id>` flow (after `$LIVE psyche-download <id>` in Step 2 retrieves context), not just under --auto. This keeps the "what's next" pane as a one-stop surface independent of entry path.

### Step 1 (Auto-resume): Get pick JSON

If no `<spt-live-auto-pick>` XML block is already in your context with the pick JSON, run:

```bash
$LIVE pick-spec
```

Parse the JSON; dispatch on the `kind` field per Step 2 below.

### Step 2 (Auto-resume): Dispatch on `kind`

**AUTO-07 (uniform confirmation rule):** EVERY successful Auto-resume launch — including `kind:"auto"` — fires an `AskUserQuestion` BEFORE any `$LIVE start` invocation. Dispatcher false-positives (e.g., a phrase like "let me continue the live demo" routing here unintentionally) get a clean Cancel exit, never a silent agent launch.

- **`kind:"auto"`** — exactly one offline agent in this repo's history.
  - Fire `AskUserQuestion` with:
    - `header`: `"Resume agent"`
    - `question`: `"Resume <id>?"` (substitute `<id>` from JSON)
    - `options`: a single option `label: "Resume <id>"`, `description: "Continue this agent's prior session"`
    - `body_addendum`: `"Auto-resume: <id> is the only offline agent in this repo."`
  - On `Resume <id>` selected: `$LIVE start <id>`.
  - On Cancel (no option chosen): exit silently. Do NOT loop into the normal ID Recollection Step 2 — the user explicitly declined the most-recent agent.

- **`kind:"pick"`** — 2+ offline agents. `options[0]` is the most-recently-active per Phase 31 D-12 sort order (`last_active desc, then id asc`).
  - Fire `AskUserQuestion` with:
    - `header`: `"Resume agent"`
    - `question`: `"Resume <options[0].label>?"` (substitute the label of `options[0]`)
    - `options`: two options — `label: "Resume <options[0].label>"` (description: `"Continue the most-recently-active agent"`) AND `label: "Pick a different agent"` (description: `"Show the full picker"`)
    - `body_addendum`: `"Auto-resume offers the most-recently-active agent. Choose 'Pick a different agent' for the full list."`
  - On `Resume <options[0].label>`: `$LIVE start <options[0].label>`.
  - On `Pick a different agent`: fall through to the normal [ID Recollection Step 2](#step-2-dispatch-on-kind) `kind:"pick"` dispatch (existing flow). Emit a `AUTO_FALLTHROUGH:pick-deferred` stderr breadcrumb for diagnosis: `echo "AUTO_FALLTHROUGH:pick-deferred" >&2`.
  - On Cancel (no option chosen): exit silently.

- **`kind:"prompt-new"`** — 0 known agents. D-09 no-op enhancement: fall through to the normal [ID Recollection Step 2](#step-2-dispatch-on-kind) `kind:"prompt-new"` dispatch (which already wires FRESH-01 first-commune via the existing flow). Emit a stderr breadcrumb: `echo "AUTO_FALLTHROUGH:prompt-new" >&2`. No AUTO-07 confirmation here — the existing `kind:"prompt-new"` `AskUserQuestion` IS the confirmation; double-prompting would be noise.

- **`kind:"all-live"`** — every known agent is currently live. D-09 no-op enhancement: fall through to the normal [ID Recollection Step 2](#step-2-dispatch-on-kind) `kind:"all-live"` dispatch (Fork-each `AskUserQuestion`). Emit a stderr breadcrumb: `echo "AUTO_FALLTHROUGH:all-live" >&2`. No AUTO-07 confirmation here — the existing all-live dispatch IS the confirmation.

The `AUTO_FALLTHROUGH:{kind}` stderr lines are debug breadcrumbs only — not user-visible; they aid post-hoc diagnosis of which arm fell through.

### Step 3 (Auto-resume, post-start): AUTO-02 next-work surfacing

ONLY if `$LIVE start <id>` succeeded above (NOT on Cancel, NOT on fall-through to normal flow), run:

```bash
$LIVE psyche-download <id>
```

> **Output truncation.** If the Bash tool reports `Output too large (N KB)` and saves the full result to a `tool-results/<id>.txt` file, use the `Read` tool on that saved path to access the full content. Do NOT re-run `psyche-download` to grep/awk out sections — repeated invocations re-download the same context, waste tokens, and may duplicate `## Pending Commune` sections in `live_context.md` per the §"Drop file lifecycle" contract below.

Then surface the "next body of work" to the user. Scan the psyche-download stdout line-by-line for the FIRST line that prefix-matches any of these three exact H2 markers (case-sensitive, prefix match — `## Current Focus (gen 45)` qualifies):

- `## Current Focus`
- `## Next Up`
- `## Next Steps`

**If a match is found**: extract the section starting at the matched line through (but NOT including) the next line that starts with `## ` at column 0, or to EOF if no such line exists. Print the extracted section verbatim to the user under a "Next body of work" heading.

**If no match is found**: synthesize a 1-2 sentence "Here's where we left off; next step looks like X" summary from the psyche-download output (read the whole download, distill the most-recent commitments + pending threads) and print the synthesis under the same heading.

The structured-marker scan comes first; Claude synthesis is the fallback. Last-commune content is explicitly NOT used for this surface — it's too noisy and often stale relative to the agent's current intent.

## Step 1: Start in background

```bash
$LIVE start <id> [--period <seconds>] [--pulse-psyche]
```

> **8-minute default period** Period defines how often a context summary is generated in the background via "echo communes". Pass `--period <seconds>` (minimum 60) to override the cadence; `--period 0` is accepted as an explicit no-cadence opt-out.

The start command:

1. **Launches your Psyche** as an external process
2. **Enters your poll loop** inline -- emitting one `<EVENT>` envelope line per message delivery
3. Reports the Psyche's session name and generation number

### Invocation (Monitor)

Invoke `$LIVE start <id>` via the Monitor tool with:
- `command: "$LIVE start <id>"`
- `persistent: true`
- `description: "« spt event »"`

`$LIVE start` enters the poll loop inline; the stream stays alive across messages and emits one `<EVENT type="msg|alarm|echo_commune|init_signoff" ...>body</EVENT>` line per delivery. See [On message arrival](#on-message-arrival) for the full envelope-type catalog.

## Step 2: Retrieve Psyche context

After launching the background start task:

```bash
$LIVE psyche-download <id>
```

> **Output truncation.** If the Bash tool reports `Output too large (N KB)` and saves the full result to a `tool-results/<id>.txt` file, use the `Read` tool on that saved path to access the full content.

Pass the same `<id>` you used in `$LIVE start`. Auto-detection may fail during startup before the perch is fully registered.

- If content is current, no action needed.
- If context has information you lack, absorb it.
- If stale or missing recent work, send a commune to update Psyche.
- If `psyche-download`'s stderr contains the literal substring `NO-CONTEXT:<id>`, enter the **first-commune flow** below before doing anything else with this agent. This is the FRESH-02 trigger; the same flow is reached from the `kind:"prompt-new"` arm under [ID Recollection Step 2](#step-2-dispatch-on-kind) (FRESH-01). One unified surface, two trigger paths.

### First-commune flow (FRESH-01 / FRESH-02 / FRESH-03)

When the trigger fires (NO-CONTEXT on `psyche-download`, OR pick-spec returned `kind:"prompt-new"` and the user picked an id):

**Announce first** (before synthesizing): emit `Fresh live agent. Preparing for init.` to the user as a plain one-line message (no formatting, no code fence). The `{first commune summary}` synthesis below reads session memory + `README.md` + `CLAUDE.md` + `.planning/STATE.md` and takes several seconds — without this announcement the user sees a silent dead pause between trigger and the AskUserQuestion. Then synthesize the summary and fire the AskUserQuestion below.

Fire a SINGLE `AskUserQuestion` with these fields:

- **header**: `First commune`
- **question**: `Here is a summary of my first context as live agent <agent_id>. Anything I should add, or proceed to init?` (substitute `<agent_id>` from context)
- **options**: exactly one option — `label: "Proceed to init"`, `description: "Start the agent now with the summary above as initial context"`
- **body_addendum**: the `{first commune summary}` string you synthesize per the next bullet.

Note: `AskUserQuestion`'s native free-text "Other" input captures additions.

**Synthesizing `{first commune summary}`**: compose a 4–8 sentence summary combining two sources, in order:

1. **Primary** — this Claude Code session's conversation memory: read your own session context and surface what the user and you have done so far. This IS the agent's first context. (Per Phase 33 CONTEXT D-01.)
2. **Secondary** — a brief project snapshot: read `README.md`, `CLAUDE.md`, and `.planning/STATE.md` (treat any missing file silently — no error to the user). Distill current project state and progress.

The same synthesis path is used regardless of trigger (Phase 33 D-02 — FRESH-01 and FRESH-02 are not differentiated).

**Handling the response**:

- **"Proceed to init"** Run `$LIVE start <id>` (or, if Step 1 already ran, proceed in-flow). If there is any native-Other free-text addition, synthesize the user's free-text into the summary. Then — after start succeeds — use the **Write tool** to create `.claude/<id>-commune.md` with the augmented summary as its body. This is the canonical first-commune path (see `/spt:commune`): Psyche absorbs the file, which is then deleted on successful ingest.
- **Cancel** (no option chosen): exit silently — matches the existing `kind:"prompt-new"` cancel semantics; do not re-prompt.

### Drift detection (Phase 23 v1.8)

`$LIVE psyche-download <id>` may emit a `<psyche-stamp/>` block (5 fields) and ALWAYS emits a `<current/>` block (live stamp values plus `commits_since` and `commits_unpulled` deltas). When `<current project>` equals `<psyche-stamp project>` AND any of `branch` / `head_sha` / `machine` differ, an HTML-comment ATTENTION SELF directive is appended instructing you to fire `AskUserQuestion`.

The directive text emitted:

```text
<!-- ATTENTION SELF: this project has advanced since your last commune/signoff.
Compare <psyche-stamp/> against <current/> above.
Fire AskUserQuestion with:
  header: "Project drift"
  question: "This project has advanced since my involvement. Should I catch up?"
  multiSelect: true
  options:
    - "Observe new commits"
    - "Skip for now"
    - "Don't ask again"
-->
```

When you see this comment, fire `AskUserQuestion` with the header / question / multiSelect / options exactly as quoted, then dispatch on the user's selection(s):

- **`Observe new commits`** → run `git log <psyche-stamp head_sha>..HEAD` to surface what changed to the user. No system action; no marker write; no commune fire.
- **`Skip for now`** → no-op. The directive will re-appear on the next `$LIVE psyche-download` if drift still applies.
- **`Don't ask again`** → invoke the write-side suppression subcommand:
  ```bash
  $LIVE suppress-drift <self_id> <project>
  ```
  where `<self_id>` is your own owl ID and `<project>` is the value from the `<current project="...">` attribute. Subsequent psyche-downloads for the same `(self_id, project)` pair will skip the directive.

**Cross-project resume (D-10):** when `<current project>` differs from `<psyche-stamp project>`, the ATTENTION SELF directive is NOT emitted (silent by design). You should still NOTICE the project mismatch by reading the two blocks, but do not prompt the user.

## On message arrival

Follow the same message handling protocol as `/spt:ready`. Messages arrive on TWO orthogonal paths:

1. **Parse the envelope.**
   - stdout carries a single `<EVENT>` line per delivery. Four shapes:
     - `<EVENT type="msg" from="<sender-id>">body</EVENT>` — regular message; `from` attribute = sender ID.
     - `<EVENT type="alarm" target-time="<ISO-8601>" current-time="<ISO-8601>">body</EVENT>` — self-originated timed alarm.
     - `<EVENT type="echo_commune" from="<self-id>-psyche" timestamp="<ISO-8601>" note="<descriptor>">body</EVENT>` — auto-fired echo-commune brief from your Psyche, emitted after a SessionStart-triggered `/clear` or `/compact` cycle. `note` carries the trigger source. Body is your context summary wrapped in a two-slice envelope: `<live-context>...</live-context>` plus (when the Psyche resolved a tracked project) `<project-context>...</project-context>`. After `<br>`-split and HTML-unescape per `/spt:ready` body-parsing rules, the two slices form a single SessionStart resume brief — absorb both as one continuous context.
     - Body parsing: split on literal `<br>` to recover newlines, then HTML-unescape each fragment (`<` → `<`, `>` → `>`, `"` → `"`, `&` → `&` **last**, to avoid double-decoding).
   - **Hook path (orthogonal)**: when you are busy mid-tool-call, PreToolUse injects `<owl_messages>...</owl_messages>` XML into your tool context. Read the `from` attribute as sender ID. Same handling.
2. **Reply** via `$OWL send --reply-to <sender-id>`.

### Handling the `<spt-psyche-sync-prompt>` envelope

When an `<owl_messages>` injection or an `<EVENT type="msg">` body contains a `<spt-psyche-sync-prompt>` element (delivered actively to your perch on `$LIVE start`/`revive` and on a `/clear`|`/compact` boundary), it carries a self-contained `<instructions>` element. **That `<instructions>` element is authoritative** — follow it exactly, the same way you treat the `<instructions>` inside a `<spt-version-changelog>` envelope.

The instructions direct you to render an `AskUserQuestion` with EXACTLY these three options (labels verbatim, do not paraphrase):

- **`Enable now`** → run `/psyche-sync-setup` to configure the private GitHub repo and enable cross-machine Psyche context sync.
- **`No, never`** → the sync is marked declined; you will not be re-prompted. Acknowledge briefly and continue. (The decline is recorded automatically by the sync state machine — no manual settings edit needed.)
- **`Remind me in 12h`** → defer the offer. Acknowledge briefly and continue. (The 12h cooldown is recorded automatically.)

This handler is always loaded with the skill — it is belt-and-suspenders. The embedded `<instructions>` element already carries the full directive, but this section guarantees an always-present handler so the envelope is actioned even independent of the embedded text. Do NOT reply to the `psyche-sync-prompt` pseudo-sender — it is an informational hook origin, not a real perch.

---

## ID Recollection (no-arg `/spt:live`)

When the user says `/spt:live` with **no ID**, run the auto-pick flow.

### Step 1: Ask the picker for a spec

```bash
$LIVE pick-spec
```

This emits a single JSON object on stdout. Parse it and dispatch on the `kind` field.

### Step 2: Dispatch on `kind`

- **`kind: "auto"`** — exactly one offline agent in this repo's history. Run:
  ```bash
  $LIVE start <id>
  ```
  where `<id>` is the JSON's `id` field. Tell the user: *"Auto-launching `<id>` (only known agent in this repo)."*

- **`kind: "pick"`** — 2+ offline agents. Fire `AskUserQuestion` using the JSON's `header`, `question`, `options`, and `body_addendum` fields verbatim. Do NOT add an explicit "Other" option — `AskUserQuestion` already provides a native free-text "Other" input; an extra option duplicates it.

- **`kind: "prompt-new"`** — 0 offline agents. Same `AskUserQuestion` pattern, but the `options` are starter role-name suggestions and `body_addendum` lists the full starter pool. `AskUserQuestion`'s native free-text is used; do not add an explicit "Other" option.
  - **FRESH-01: first-commune before start.** When the user picks a new id (whether from a starter option or by typing into native Other), **BEFORE** running `$LIVE start <id>`, fire the [first-commune flow](#first-commune-flow-fresh-01--fresh-02--fresh-03) — the same single `AskUserQuestion` shape (header / question / options / body_addendum) defined under Step 2's NO-CONTEXT bullet. Use the FRESH-03 verbatim template, synthesize `{first commune summary}` per the D-01 source priority, and only on `Proceed to init` proceed with `$LIVE start <chosen-id>`. On cancel: silent exit (matches existing `kind:"prompt-new"` cancel semantics).

- **`kind: "all-live"`** — every known agent in this repo is currently live. Fire `AskUserQuestion` using the JSON's `header`, `question`, and `options` fields verbatim. There is NO `body_addendum` on this kind. Each option's `label` is `Fork <id>` (exactly one space after `Fork`).
  - **Fork `<id>` selected**: strip the leading `Fork ` prefix (exactly 5 characters including the trailing space) to recover `<id>`. Prompt the user as plain text for the new agent id, then run `$LIVE fork <id> <new-id>`. Mirrors the existing D8 fork flow in Step 3.
  - **Free-text typed into the native Other field**: route through `$LIVE pick-spec --resolve <name>` and dispatch via the Step 3 resolve table below (`in_this_repo_history` / `live` / `other_repos`) — same path as the free-text Other under `kind:"pick"`. Preserves the cross-repo collision guard.
  - **Cancel**: terminate silently. Do NOT loop back into `pick-spec`. This is distinct from the forced-picker rule (Cancel-from-D7 / D8 / D9 in the Step 3 Cancel-handling block) — `all-live` Cancel is a clean exit signal, not a re-pick.

### Step 3: Handle the user's choice

- **If the user picked one of the listed options** (`label` from the JSON), run:
  ```bash
  $LIVE start <picked-label>
  ```

- **If the user typed a name into the free-text field**, resolve it first:
  ```bash
  $LIVE pick-spec --resolve <name>
  ```
  The output JSON has fields `in_this_repo_history`, `live`, and `other_repos` (an array of repo basenames). Dispatch:

  | in_this_repo_history | live | other_repos | Action |
  |---|---|---|---|
  | true | false | (any) | **Silent reuse**: `$LIVE start <name>` |
  | false | false | empty | **Fresh init**: `$LIVE start <name>` |
  | false | false | non-empty | **Confirm reuse**: fire `AskUserQuestion`. Construct the body from the template `"Agent {name} exists in other repos: {repos}. Reuse it here?"`, where `{name}` is the resolved name (substituted) and `{repos}` is every string in the JSON `other_repos` array joined with `, ` (substituted, no omission). Options: `Reuse here` / `Cancel`. On `Reuse here` run `$LIVE start <name>`; on `Cancel` see Cancel handling below. |
  | true | true | (any) | **Offer fork**: fire `AskUserQuestion` with options `Fork to new agent` / `Cancel`. On `Fork to new agent`, prompt the user for a new id, then run `$LIVE fork <name> <new-id>`. On `Cancel`, see Cancel handling below. |
  | false | true | non-empty | **Refuse + re-pick**: follow Cancel handling below to fire `AskUserQuestion` (forced presentation, all three kinds covered). Before firing, prepend to the constructed `body_addendum` the template-substituted warning `"⚠ {name} is already live in {repos} — pick something else.\n\n"`, where `{name}` is the rejected name and `{repos}` is the JSON `other_repos` array joined with `, `. Do NOT skip the `AskUserQuestion` fire even if `pick-spec` returns `kind:"auto"` or `kind:"prompt-new"`. |

  If the resolve JSON has an `error` field (invalid id format), tell the user the name is invalid and re-prompt.

### Cancel handling (after D7 confirm or D8 fork dialog)

When the user picks **Cancel** in any post-resolve `AskUserQuestion`, do NOT loop back into `pick-spec` directly. The Cancel is a signal that the user wants to choose a different agent. Re-invoke the picker with **forced presentation**:

1. Run `$LIVE pick-spec` again to get fresh JSON.
2. **Always fire `AskUserQuestion`, regardless of the returned `kind`.** Do NOT auto-launch even if `kind:"auto"` is returned (the user just rejected that single historical agent — auto-launching it again is exactly the bug this rule fixes). Construct the `AskUserQuestion` payload per the `kind`:
   - **`kind:"pick"`** — use JSON's `header`, `question`, `options`, `body_addendum` verbatim (same as Step 2 normal path).
   - **`kind:"prompt-new"`** — use JSON's `header`, `question`, `options` (starter roles), `body_addendum` verbatim (same as Step 2 normal path).
   - **`kind:"auto"`** — synthesize an `AskUserQuestion` manually:
     - `header`: `"Choose live agent"`
     - `question`: `"Which agent should /spt:live use?"`
     - `options`: a single option whose `label` is the JSON's `id` field
     - `body_addendum`: `"Known agent in this repo:\n- <id>\n\nOr type a different name using Other."` (substitute `<id>` from JSON)
     - Do NOT run `$LIVE start <id>` until the user explicitly selects that option in the `AskUserQuestion`.
3. Process the user's choice via Step 3 dispatch as usual.

**Forced picker rule:** Cancel-from-D7, Cancel-from-D8, and Refuse-D9 all share the same re-entry path — they re-fire `AskUserQuestion` and never auto-launch.

### Notes

- The explicit-id path (`/spt:live <id>`) bypasses this flow entirely and behaves exactly as documented in Step 1 above.

---

## Edge Cases

- **Duplicate `/spt:live`**: Rejects with `COLLISION`. Check `/spt:list-agents` first, or use `/spt:revive`.
- **Psyche process dies**: Use `/spt:revive` to restart.
- **Psyche spawn failure**: Start command logs error but continues. Listener poll runs without your Psyche.
- **INSIGHT messages from Psyche**: `INSIGHT ({timestamp}): {observation}` -- high-priority observation about your work. Psyche only sends INSIGHTs for contradictions between stated intentions and actions, forgotten commitments, reasoning gaps, or extended time without progress. Read carefully and adjust if warranted. If the INSIGHT seems incorrect or confused, reply to clarify so you and your Psyche stay on the same page.

---

## Live Agent Best Practices

### Stay idle for fastest delivery

Messages arrive fastest when you are **idle** (not executing a tool call) -- the background poll delivers them instantly. When you are busy, messages still arrive via the PreToolUse hook but with slight delay (next tool call boundary).

- **Always launch Agent tool calls with `run_in_background: true`** when you have an active perch. Foreground agents block your poll loop entirely -- no messages can be delivered until the agent finishes.
- **Launch work as background tasks** (`run_in_background: true`) when results aren't immediately needed or when the task may take longer than a few seconds to finish.
- **Go idle after launching.** The idle gap is when poll-path messages get delivered instantly.
- **Batch independent work into parallel background tasks** rather than sequential foreground calls.

### Check background tasks first

When your poll interjects with a new message, **before processing it**:
1. Check if other background tasks have completed.
2. Read completed task output (especially `« spt event »` polls from subagents).
3. Then process the new message.

- **Read background task output directly — no `sleep` prefix.** To inspect a completed or in-progress background task, call the Read tool on its output file. Do NOT chain `sleep N && <read>`: the Bash tool blocks sleeps ≥2s chained before other commands, and background-task stdout is flushed promptly, so a plain Read picks up whatever has been written.


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


Bash

Get live agent pick spec


Error: Exit code 127
/usr/bin/bash: line 4: C:/Users/decid/.claude/plugins/cache/cplugs/spt/1.10.15/owl.exe: No such file or directory


[Request interrupted by user]


<command-message>spt:signoff</command-message>
<command-name>/spt:signoff</command-name>
<command-args>rebbie --- write an offline signoff</command-args>


Base directory for this skill: C:\Users\decid\.claude\plugins\cache\cplugs\spt\1.11.25\skills\signoff

# /spt:signoff

All commands use `$LIVE` env var, auto-injected by the plugin's SessionStart hook. If commands fail with "command not found", restart the Claude Code session so the SessionStart hook re-runs.

> **Identity auto-detection:** Your identity is auto-detected from your session. Pass your ID explicitly only if auto-detection fails.

## Flow

1. **Download Psyche's *current* context** — it shifts during the session as background echo communes fire. Re-download right before composing; the gen-N snapshot you read at session start is already stale:
   ```bash
   $LIVE psyche-download <your-id>
   ```

   > **Output truncation.** If the Bash tool reports `Output too large (N KB)` and saves the full result to a `tool-results/<id>.txt` file, use the `Read` tool on that saved path to access the full content.

2. **Diff your knowledge against this fresh download** — only *what's missing from it* belongs in the FINAL COMMUNE body (work completed, decisions made, intentions formed). Anything already absorbed is not.

3. **Sign off** -- use the **Write tool** to create
   `.claude/{your-id}-signoff.md`. Do not use Bash/heredoc -- Write is the
   canonical path: no shell escaping, no `EOF` collision risk, and Write
   auto-creates the `.claude/` parent directory.

   - **Plain signoff** (no final commune body): Write the file with an empty
     string as its contents.
   - **Signoff with a FINAL COMMUNE body**: Write the file with the final
     commune body as its contents — the body MUST be wrapped in the same
     two-slice envelope as a regular commune (see `## Two-slice body shape`
	 below, or `/spt:commune` for the full teaching).

	 Your live agent listener detects the file, notifies your Psyche wrapper,
	 prints `STOP:{your-id} (signoff dropped)`, and exits cleanly. The Psyche
	 wrapper independently consumes the file and tears itself down.

   **Offline path (no live listener):** If no session is currently live for
   your agent, the dropped `.claude/{your-id}-signoff.md` simply persists on
   disk. The next time anyone runs `$LIVE psyche-download <your-id>`, that
   signoff body reflected under a `## Pending Signoff (written {mtime})`
   header. This is the way to record post-session-end context updates.

## Two-slice body shape (Phase 25 D-10/D-11)

When the FINAL-COMMUNE body is non-empty (the second sub-bullet of Step 3 above), it follows the same Phase 25 D-10/D-11 two-slice envelope contract as a regular commune body:

- **In a tracked project** (detected via the `project="..."` attribute on the `<current ... />` tag at the top of `$LIVE psyche-download` output): emit `<live-context>...</live-context>` plus either `<project-context>...</project-context>` (with content) or `<project-context></project-context>` (empty body — "in-project but quiet" signal per D-25.1-02).
- **Outside any tracked project** (no payload at all from `psyche-download` — no `<current/>` tag, no `project="..."` attribute): emit ONLY `<live-context>...</live-context>`. Do NOT emit an empty `<project-context>` envelope.
- **Plain signoff** (empty file body, first sub-bullet of Step 3): the two-slice contract does NOT apply — the file is literally empty.

See `/spt:commune` → `## Two-slice body shape (Phase 25 D-10/D-11)` for the full teaching with three worked examples. See `psyche.md` §`<output_envelope>` for the canonical per-slice content taxonomy. See `psyche.md` §`<absorption>` (25.3-02) for the inbound-merge + re-emit rules — Psyche absorbs and re-emits these envelopes; on the FINAL_COMMUNE the wrapper's last Psyche session emits the two-slice body for the same routing pass.

**Routing: emit this envelope; SPT routes it to disk (Phase 25.3-02).** You write the two-slice body in the signoff file; the wrapper feeds it through Psyche's final session, and SPT (the Rust runtime) routes each emitted slice to its destination file. The `<live-context>` body lands at `agents/{your-id}/live_context.md`. The `<project-context>` body lands at `projects/<resolved_project>/{your-id}.md`, where `<resolved_project>` is resolved BY SPT via Self's perch `info.json` `cwd` field (25.3-01 Defect B2 fix). You do NOT name the project (Option A no-name shape locked); you do NOT know the filesystem path. NOT "Psyche writes the file." NOT "the agent persists to the project file." You emit; SPT routes.

**Signoff vs Stop:**
- **`/spt:signoff`** -- Graceful: INIT_SIGNOFF (with optional final commune) to Psyche first. Use for normal session end.
- **`/spt:force-stop`** -- Force: kills immediately. Use when unresponsive or need immediate kill.

## Envelope shape (Phase 23 v1.8)

As of v1.8 Phase 23, the init_signoff envelope carries a 5-field stamp (`machine`, `project`, `branch`, `head_sha`, `head_subject`) alongside `timestamp`.

```xml
<EVENT type="init_signoff" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="claude_skill_owl" branch="main" head_sha="abc123..." head_subject="subject line">Signoff initiated by Self...</EVENT>
```

With an optional final-commune body (when the signoff drop file is non-empty):

```xml
<EVENT type="init_signoff" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="claude_skill_owl" branch="main" head_sha="abc123..." head_subject="subject line">FINAL COMMUNE: ...body... | Signoff initiated by Self...</EVENT>
```

Outside a git repo (D-11), `branch`, `head_sha`, and `head_subject` are omitted entirely. The wrapper-side `type="init_signoff"` predicate is matched case-insensitively and ignores unknown attrs, so the new stamp fields are forward-compatible with older receivers. For drift detection on resume, see the `live` skill.

The `body` placeholder in the INIT_SIGNOFF examples above (when a FINAL COMMUNE is present) is the two-slice body — see `## Two-slice body shape (Phase 25 D-10/D-11)` above; the Phase 23 EVENT envelope and the Phase 25 two-slice body nest, with EVENT wrapping the two-slice body. `$LIVE signoff` composes the EVENT envelope automatically — you NEVER write `<EVENT>` tags.

ARGUMENTS: rebbie --- write an offline signoff


<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>


<command-name>/reload-plugins</command-name>
            <command-message>reload-plugins</command-message>
            <command-args></command-args>


<local-command-stdout>Reloaded: 6 plugins · 0 skills · 39 agents · 9 hooks · 1 plugin MCP server · 1 plugin LSP server</local-command-stdout>