Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .claude/skills/arch-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<name>.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,
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
45 changes: 45 additions & 0 deletions codev-skeleton/.claude/skills/arch-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<name>.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,
Expand Down
17 changes: 17 additions & 0 deletions codev/projects/1220-arch-init-architect-auto-state/status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
id: '1220'
title: arch-init-architect-auto-state
protocol: air
phase: pr
plan_phases: []
current_plan_phase: null
gates:
pr:
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:43:42.777Z'
pr_ready_for_human: false
39 changes: 39 additions & 0 deletions codev/state/air-1220_thread.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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/<name>.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.

### 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.

### 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.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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/<name>.md at checkpoints', () => {
const t = text();
// The save target is the same per-name state file, referenced with the
// <name> placeholder as in the read flow.
expect(t).toMatch(/save/i);
expect(t).toContain('codev/state/<name>.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', () => {
Expand Down
Loading