From 0a36d5ae18aaff35960e91b68c67291a01b3cabb Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:30:40 -0700 Subject: [PATCH 1/8] gitignore: add .codev/config.local.json (layer-5 per-engineer config) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d3c06dea5..b1945d575 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ worktrees/ .update-hashes.json .architect-role.md .codev/config.json +.codev/config.local.json # Architect state files are per-person; builder *_thread.md files ARE versioned (#1192) codev/state/*.md From 31ab28a7c199f8668a9a76c4c63ecd409223b90b Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:31:20 -0700 Subject: [PATCH 2/8] chore(porch): 1220 init air --- .../status.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codev/projects/1220-arch-init-architect-auto-state/status.yaml diff --git a/codev/projects/1220-arch-init-architect-auto-state/status.yaml b/codev/projects/1220-arch-init-architect-auto-state/status.yaml new file mode 100644 index 000000000..5152a96c5 --- /dev/null +++ b/codev/projects/1220-arch-init-architect-auto-state/status.yaml @@ -0,0 +1,14 @@ +id: '1220' +title: arch-init-architect-auto-state +protocol: air +phase: implement +plan_phases: [] +current_plan_phase: null +gates: + pr: + status: pending +iteration: 1 +build_complete: false +history: [] +started_at: '2026-07-22T11:31:20.070Z' +updated_at: '2026-07-22T11:31:20.071Z' From 113b2a3083e6f8482370938a646b47a61c28c894 Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:35:05 -0700 Subject: [PATCH 3/8] [AIR #1220] feat(arch-init): architect auto-state-saving lifecycle Add a save-then-suggest-/clear lifecycle to the /arch-init skill so the architect deliberately curates codev/state/.md at resumable checkpoints, then advises the human it is a good time to /clear. Save-then-suggest ordering is the core safety property: the agent cannot clear its own context, so the irreversible action stays behind a human keystroke and the save always precedes the suggestion. Skill text (both trees, byte-identical) now instructs: - when to save (resumable boundary; never mid-task) - write format = read format (rewrite current-state + append dated entry) - compaction discipline (one screen; prune stale sections) - advisory-not-nagging /clear suggestion, only right after a save - content guardrails (no secrets, no transcript dumps) Extends spec-1134 skill tests with #1220 required-content assertions; all existing byte-equality and content assertions preserved. --- .claude/skills/arch-init/SKILL.md | 45 ++++++++++++++++++ .../.claude/skills/arch-init/SKILL.md | 45 ++++++++++++++++++ codev/state/air-1220_thread.md | 26 ++++++++++ .../spec-1134-arch-init-skill.test.ts | 47 +++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 codev/state/air-1220_thread.md diff --git a/.claude/skills/arch-init/SKILL.md b/.claude/skills/arch-init/SKILL.md index d9df3cc68..e032a0f5f 100644 --- a/.claude/skills/arch-init/SKILL.md +++ b/.claude/skills/arch-init/SKILL.md @@ -54,6 +54,51 @@ name in a multi-architect workspace). on resume. Do not invent a new agenda — resume the one the state file describes. +## Saving your state (and knowing when to `/clear`) + +Recovery is only half the loop. `/arch-init` reads state; **you** write it. The +state file is not crash insurance — it is your deliberate memory-management +mechanism. Auto-compaction happens at an arbitrary moment with content you did +not choose; a state save happens at a boundary **you** pick, with a summary +**you** curate. That is strictly better, so use it: + +``` +/arch-init (recover) → work → save at a checkpoint → suggest /clear → human /clears → /arch-init → … +``` + +**When to save.** Save at a *resumable boundary* — a point a fresh session +could pick up cleanly from. Good moments, judged by you: a gate approval, a PR +merge, a completed investigation, the end of a long tool-heavy stretch. +**Never save mid-task.** The state file must describe a point you can resume +*from*, not a half-finished action; a mid-task snapshot resumes into confusion. + +**How to save (write format = read format).** Recovery reads *the role banner +plus the most recent dated section*, so a save must leave exactly that behind: + +1. **Rewrite the current-state / open-loops section in place** — overwrite it + with where things actually stand now (current focus + open loops + how to + resume). Do not accumulate stale "current state" blocks. +2. **Append one short dated log entry** capturing what changed this stretch. +3. **Keep it to one screen (compaction discipline).** The state file is a + summary, not a transcript. When you append, prune stale dated sections so + the file stays readable at a glance. + +**Content guardrails.** No secrets (tokens, keys, credentials). No transcript +dumps or raw tool output. Include only: current focus, open loops, and the +instructions a fresh session needs to resume. + +**Then — and only then — suggest `/clear`.** Save first, *then* tell the human +it is a good time to clear. You cannot clear your own context and must never +decide unilaterally to lose it; keeping the irreversible step behind a human +keystroke means accepting the suggestion can never lose anything, because the +save already happened. Make the suggestion **advisory, never nagging**, and +only right after a save — e.g.: + +> State saved to `codev/state/.md` — good time to `/clear` if this +> session is feeling heavy. + +Do not repeat it, and do not prompt to `/clear` at any other time. + ## Guardrails (architect-wide; the state file may add more) - **Never auto-approve porch gates.** A gate notification is for the human, diff --git a/codev-skeleton/.claude/skills/arch-init/SKILL.md b/codev-skeleton/.claude/skills/arch-init/SKILL.md index d9df3cc68..e032a0f5f 100644 --- a/codev-skeleton/.claude/skills/arch-init/SKILL.md +++ b/codev-skeleton/.claude/skills/arch-init/SKILL.md @@ -54,6 +54,51 @@ name in a multi-architect workspace). on resume. Do not invent a new agenda — resume the one the state file describes. +## Saving your state (and knowing when to `/clear`) + +Recovery is only half the loop. `/arch-init` reads state; **you** write it. The +state file is not crash insurance — it is your deliberate memory-management +mechanism. Auto-compaction happens at an arbitrary moment with content you did +not choose; a state save happens at a boundary **you** pick, with a summary +**you** curate. That is strictly better, so use it: + +``` +/arch-init (recover) → work → save at a checkpoint → suggest /clear → human /clears → /arch-init → … +``` + +**When to save.** Save at a *resumable boundary* — a point a fresh session +could pick up cleanly from. Good moments, judged by you: a gate approval, a PR +merge, a completed investigation, the end of a long tool-heavy stretch. +**Never save mid-task.** The state file must describe a point you can resume +*from*, not a half-finished action; a mid-task snapshot resumes into confusion. + +**How to save (write format = read format).** Recovery reads *the role banner +plus the most recent dated section*, so a save must leave exactly that behind: + +1. **Rewrite the current-state / open-loops section in place** — overwrite it + with where things actually stand now (current focus + open loops + how to + resume). Do not accumulate stale "current state" blocks. +2. **Append one short dated log entry** capturing what changed this stretch. +3. **Keep it to one screen (compaction discipline).** The state file is a + summary, not a transcript. When you append, prune stale dated sections so + the file stays readable at a glance. + +**Content guardrails.** No secrets (tokens, keys, credentials). No transcript +dumps or raw tool output. Include only: current focus, open loops, and the +instructions a fresh session needs to resume. + +**Then — and only then — suggest `/clear`.** Save first, *then* tell the human +it is a good time to clear. You cannot clear your own context and must never +decide unilaterally to lose it; keeping the irreversible step behind a human +keystroke means accepting the suggestion can never lose anything, because the +save already happened. Make the suggestion **advisory, never nagging**, and +only right after a save — e.g.: + +> State saved to `codev/state/.md` — good time to `/clear` if this +> session is feeling heavy. + +Do not repeat it, and do not prompt to `/clear` at any other time. + ## Guardrails (architect-wide; the state file may add more) - **Never auto-approve porch gates.** A gate notification is for the human, diff --git a/codev/state/air-1220_thread.md b/codev/state/air-1220_thread.md new file mode 100644 index 000000000..0029da201 --- /dev/null +++ b/codev/state/air-1220_thread.md @@ -0,0 +1,26 @@ +# air-1220 thread — /arch-init architect auto-state-saving (#1220) + +Protocol: AIR (strict). Supersedes #1212 (wontfix). Area: area/scaffold. + +## What the change is +Add an auto-save lifecycle to the `/arch-init` skill: architect saves a curated +summary to `codev/state/.md` at resumable checkpoints, then suggests +`/clear` (save-then-suggest ordering is the core safety property). Skill only — +no runtime code. Two-tree rule: instance + skeleton SKILL.md byte-identical. + +## Log + +### 2026-07-22 — implement +- Read both SKILL.md copies + spec-1134-arch-init-skill.test.ts. +- Added a new "## Saving your state (and knowing when to `/clear`)" section to + `.claude/skills/arch-init/SKILL.md` covering all five issue requirements: + when-to-save (resumable boundary, never mid-task), write=read format + (rewrite current-state + append dated), compaction (one screen / prune), + advisory-not-nagging suggestion, content guardrails (no secrets/transcripts). +- `cp` to skeleton tree → verified byte-identical. +- Extended the test with #1220 required-content assertions (save target, + save-then-suggest, never-mid-task, write=read symmetry, compaction, guardrails, + advisory framing). Kept all existing assertions untouched. +- Installing workspace deps (fresh worktree, no node_modules) to run vitest. + +Open loop: run the test file green, then porch check → done → PR. diff --git a/packages/codev/src/agent-farm/__tests__/spec-1134-arch-init-skill.test.ts b/packages/codev/src/agent-farm/__tests__/spec-1134-arch-init-skill.test.ts index 750b203ce..e25d521f4 100644 --- a/packages/codev/src/agent-farm/__tests__/spec-1134-arch-init-skill.test.ts +++ b/packages/codev/src/agent-farm/__tests__/spec-1134-arch-init-skill.test.ts @@ -9,6 +9,10 @@ * - no Shannon-specific wording (workspace-agnostic) * - builder-thread exclusion in the missing-state-file flow * - the four architect guardrails + * + * Issue #1220 extends this with the architect auto-state-saving lifecycle: + * save at resumable checkpoints (write format = read format), then suggest + * `/clear` — never mid-task, no secrets, compaction discipline. */ import { describe, it, expect } from 'vitest'; @@ -69,6 +73,49 @@ describe('Spec 1134 — /arch-init skill ships in both trees', () => { it('never defaults to main', () => { expect(text()).toMatch(/do NOT default to `main`/i); }); + + // Issue #1220 — architect auto-state-saving lifecycle. + it('instructs saving to codev/state/.md at checkpoints', () => { + const t = text(); + // The save target is the same per-name state file, referenced with the + // placeholder as in the read flow. + expect(t).toMatch(/save/i); + expect(t).toContain('codev/state/.md'); + expect(t).toMatch(/checkpoint|resumable boundary/i); + }); + + it('suggests /clear only after a save (save-then-suggest ordering)', () => { + const t = text(); + expect(t).toContain('/clear'); + // Ordering property: save first, then suggest. + expect(t).toMatch(/save first.*then|then .*only then.*suggest|good time to `\/clear`/i); + }); + + it('forbids saving mid-task', () => { + expect(text()).toMatch(/never save mid-task/i); + }); + + it('carries the write-format = read-format symmetry (rewrite + append dated)', () => { + const t = text(); + expect(t).toMatch(/rewrite the current-state/i); + expect(t).toMatch(/append.*dated/i); + }); + + it('carries compaction discipline (one screen / prune stale sections)', () => { + const t = text(); + expect(t).toMatch(/one screen/i); + expect(t).toMatch(/prune stale/i); + }); + + it('carries save content guardrails (no secrets, no transcript dumps)', () => { + const t = text(); + expect(t).toMatch(/no secrets/i); + expect(t).toMatch(/transcript/i); + }); + + it('frames the /clear suggestion as advisory, not nagging', () => { + expect(text()).toMatch(/advisory, never nagging/i); + }); }); describe('forbidden content', () => { From 493e00edc82adbd6f6c0bdad3190dd7d61613f5d Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:35:40 -0700 Subject: [PATCH 4/8] chore(porch): 1220 pr phase-transition --- .../projects/1220-arch-init-architect-auto-state/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/1220-arch-init-architect-auto-state/status.yaml b/codev/projects/1220-arch-init-architect-auto-state/status.yaml index 5152a96c5..b17b483fb 100644 --- a/codev/projects/1220-arch-init-architect-auto-state/status.yaml +++ b/codev/projects/1220-arch-init-architect-auto-state/status.yaml @@ -1,7 +1,7 @@ id: '1220' title: arch-init-architect-auto-state protocol: air -phase: implement +phase: pr plan_phases: [] current_plan_phase: null gates: @@ -11,4 +11,4 @@ iteration: 1 build_complete: false history: [] started_at: '2026-07-22T11:31:20.070Z' -updated_at: '2026-07-22T11:31:20.071Z' +updated_at: '2026-07-22T11:35:40.454Z' From 9387607ca7063927929e7b9ecbec24da89266f76 Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:37:36 -0700 Subject: [PATCH 5/8] chore(porch): 1220 pr gate-requested --- .../projects/1220-arch-init-architect-auto-state/status.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codev/projects/1220-arch-init-architect-auto-state/status.yaml b/codev/projects/1220-arch-init-architect-auto-state/status.yaml index b17b483fb..4ececaa19 100644 --- a/codev/projects/1220-arch-init-architect-auto-state/status.yaml +++ b/codev/projects/1220-arch-init-architect-auto-state/status.yaml @@ -7,8 +7,10 @@ current_plan_phase: null gates: pr: status: pending + requested_at: '2026-07-22T11:37:36.782Z' iteration: 1 build_complete: false history: [] started_at: '2026-07-22T11:31:20.070Z' -updated_at: '2026-07-22T11:35:40.454Z' +updated_at: '2026-07-22T11:37:36.783Z' +pr_ready_for_human: true From 6ea29153e1310cc85244cdb3fd3e1cf83153819e Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:37:46 -0700 Subject: [PATCH 6/8] =?UTF-8?q?[AIR=20#1220]=20docs:=20update=20thread=20?= =?UTF-8?q?=E2=80=94=20PR=20#1221=20at=20pr=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codev/state/air-1220_thread.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/codev/state/air-1220_thread.md b/codev/state/air-1220_thread.md index 0029da201..cdd46b752 100644 --- a/codev/state/air-1220_thread.md +++ b/codev/state/air-1220_thread.md @@ -24,3 +24,9 @@ no runtime code. Two-tree rule: instance + skeleton SKILL.md byte-identical. - Installing workspace deps (fresh worktree, no node_modules) to run vitest. Open loop: run the test file green, then porch check → done → PR. + +### 2026-07-22 — PR ready, at pr gate +- tsc clean, 19/19 skill tests pass, byte-identity verified. +- porch check (build, tests) ✓; PR phase check (pr_exists, e2e_tests) ✓. +- Opened PR #1221 with review embedded in the body (AIR: no separate review file). +- Reached `pr` gate → STOP, waiting for human approval. Not running porch gate. From 1f0b72ac55e41170f496cd7911e7be6e0b202714 Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:43:42 -0700 Subject: [PATCH 7/8] chore(porch): 1220 pr gate-approved --- .../1220-arch-init-architect-auto-state/status.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codev/projects/1220-arch-init-architect-auto-state/status.yaml b/codev/projects/1220-arch-init-architect-auto-state/status.yaml index 4ececaa19..50c8da535 100644 --- a/codev/projects/1220-arch-init-architect-auto-state/status.yaml +++ b/codev/projects/1220-arch-init-architect-auto-state/status.yaml @@ -6,11 +6,12 @@ plan_phases: [] current_plan_phase: null gates: pr: - status: pending + status: approved requested_at: '2026-07-22T11:37:36.782Z' + approved_at: '2026-07-22T11:43:42.776Z' iteration: 1 build_complete: false history: [] started_at: '2026-07-22T11:31:20.070Z' -updated_at: '2026-07-22T11:37:36.783Z' -pr_ready_for_human: true +updated_at: '2026-07-22T11:43:42.777Z' +pr_ready_for_human: false From 0603b3df32952f520bbac73b2b3997b7f189b34d Mon Sep 17 00:00:00 2001 From: M Waleed Kadous Date: Wed, 22 Jul 2026 04:44:26 -0700 Subject: [PATCH 8/8] =?UTF-8?q?[AIR=20#1220]=20docs:=20thread=20=E2=80=94?= =?UTF-8?q?=20merge=20blocked=20by=20branch=20protection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codev/state/air-1220_thread.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/codev/state/air-1220_thread.md b/codev/state/air-1220_thread.md index cdd46b752..2406a3b57 100644 --- a/codev/state/air-1220_thread.md +++ b/codev/state/air-1220_thread.md @@ -30,3 +30,10 @@ Open loop: run the test file green, then porch check → done → PR. - porch check (build, tests) ✓; PR phase check (pr_exists, e2e_tests) ✓. - Opened PR #1221 with review embedded in the body (AIR: no separate review file). - Reached `pr` gate → STOP, waiting for human approval. Not running porch gate. + +### 2026-07-22 — pr gate approved, merge blocked by branch protection +- Human approved via architect relay; ran `porch approve 1220 pr --a-human-explicitly-approved-this` → gate approved, checks green. +- `gh pr merge 1221 --merge` BLOCKED: base branch policy. mergeStateStatus=BLOCKED, reviewDecision=REVIEW_REQUIRED, CI checks pending. +- `--auto` rejected: repo has auto-merge disabled (enablePullRequestAutoMerge). +- Did NOT use `--admin` (won't bypass branch protection without explicit go-ahead). +- Reported to architect; awaiting a GitHub review approval + CI green, or an explicit --admin instruction.