ADR-9837 — `/plan-start` is a plugin skill that loads ONE project; a start hook keeps it across `/clear`, resume and compaction
Mirrored from the fleet knowledge base: wi/decisions/ADR-9837-plan-start-loads-one-project.md
Updated
Mirrored verbatim from
utopia-models/knowledgewi/decisions/ADR-9837-plan-start-loads-one-project.mdby the allowlisted publish pipeline. Edit it there, not here.
artifact_type: adr
adr_id: ADR-9837
adr_status: accepted
status: active
decision_date: 2026-10-23
supersedes:
superseded_by:
issue: 9837
subprocess: process
references:
- wi/work/specs/plan-405-session-context-wiring/spec.md
- wi/decisions/ADR-9836-a-project-free-shared-floor.md
- _process/steps/plan-start-frame.md
- _infra/scripts/project-census.py
- utopia-models/fleet-plugins (fleet-doctrine skills/plan-start, scripts/project-session.sh)ADR-9837 — /plan-start is a plugin skill that loads ONE project; a start hook keeps it across /clear, resume and compaction
Context
P1 (ADR-9836) made the always-on text project-free. Something must now put ONE project's text into a planning
session and keep it there. Before this, /plan-start was a brain-agent skill (agent box only) that read
_process/steps/{1-brief,2-loop,3-file}.md in full — 86,350 B of frame, with the portfolio context arriving only
as a one-shot Read of <portfolio>/README.md (dmv-research's alone is 45 KB; net's 125 KB) that did not survive
compaction. sessionstart-standing.sh re-injected only the [standing:…] line, keyed on a plan binding.
Re-measured on Claude Code 2.1.302 (cloud@novaserver, 2026-10-23), throwaway plugin via --plugin-dir:
disable-model-invocation: trueon a PLUGIN skill: the Skill tool refuses it (Skill xprobe cannot be used with Skill tool due to disable-model-invocation) and a typed/xproberuns it. The old loader's note (2026-08-14: the flag "does not stop the Skill tool") is no longer true.${CLAUDE_SESSION_ID},${CLAUDE_PLUGIN_ROOT}and$ARGUMENTSare substituted in a plugin skill body.- A same-named project/user skill SHADOWS a plugin skill on the bare
/name(typed/xprobereturned the local copy). So the brain-agentskills/plan-startmust go, or/plan-startnever reaches the plugin. - SessionStart fires with
source=startup,resume,compactandclearunderclaude -p, and/clearin a resumed-psession mints a new session id in the same process.
Options considered
- Do nothing — keep the 86 KB frame and the README read. Rejected: the project text is not scoped (the README read is optional and lost at compaction) and the frame is 3.5× the spec's budget for it.
- Keep the brain-agent skill, slim it — Rejected: a brain skill reaches one box (
skills-layer), and the start hook and state file it depends on ship in the plugin anyway; two delivery paths for one mechanism. !shell injection inside SKILL.md — Rejected: it runs before the three answers exist, and (per the 2026-10-22 experiments) needs--add-dirto read files outside the working directory.- Integrate existing: the plugin's SessionStart + a plugin skill + a script, modelled on
sessionstart-standing.sh's pid adoption — CHOSEN.
Decision
- fleet-doctrine 0.93.0 ships
skills/plan-start/SKILL.md(disable-model-invocation: true). It asks mode → project → recipe (AskUserQuestion, the same fixed card), or takes them as three arguments, then runsscripts/project-session.sh load <mode> <project> <recipe> --session ${CLAUDE_SESSION_ID}. project-session.sh loadwrites~/.claude/state/plan-issue/<session_id>(project, mode, recipe, claude_pid, cwd, opened_at — merged, so P4's keys survive), runsmode-set.shso the per-turn injector keeps working side by side, and prints: the start line · the STANDING block ·<project>/context.md· the recipe · the project's capability rows (capabilities.sh --inject --project) · the comms digest forcleaningonly ·_process/steps/plan-start-frame.md.project-session.sh startis one SessionStart hook, matcherstartup|resume|clear|compact. It prints[session] project=… mode=… recipe=… issue=…and re-injects<project>/context.md, or[session] NO PROJECTand nothing else. Onclearit MOVES the newest state file whoseclaude_pidis this process and which is newer than the process. Every fire is a line in~/.claude/state/plan-issue.log.- Capability rows belong to a project by id (
dmv-*/dmvresearch/clkk·cleaning-*/utopiacleans·net-*/resume;wigets the unclaimed rows). The map'sproject:field is the Infisical project, not ours. - The project canary is the context file's own H1, so
project-census.pyneeds no marker written into the six context files. sessionstart-standing.sh, the plan binding and the old step files stay (side by side, per the spec). The brain-agentskills/plan-startis deleted (it would shadow the plugin skill).
The frame, and which corrections it carries
_process/steps/plan-start-frame.md (17,398 B) replaces reading 1-brief.md + 2-loop.md (66,720 B) at
/plan-start. Kept, with their evidence: architect-only; bypassPermissions; one-argument mode-set.sh and the
retired forms; interactive is the whole name; monitor is the recipe's field; the interactive PASS/FLOOR/TEST
(one hard lock per pass, a wrong pass is a pass, approving remarks end nothing, his word ends the loop not the
step); --portfolio mandatory (171/190 measurement, PLAN-191 wrong-portfolio); plan-new is synchronous, read the
entry back; header lines, no pipes; artifact at the TOP (13/65 → 68/130 measurements) and artifact:none; the
template not prose, one mode variant, SVG width, one script; component-doc current state and "no subagent
establishes current state"; lane agent dispatchable but not swept; ask before researching; no acceptance at
step 1; converting into existing machinery; recalling vs reading; research lands then the card (PLAN-397); both
exit options and the click read by the hook (ADR-6932, PLAN-225); neither exit advances the step; the
three-things report; the artifact iterates in place; ### P1 · headings and zero ≠ zero phases; write at the
source, registry copy authoritative (240-document measurement); never hand-write the entry, never
backlog task create, unbound plan has no identity; five steps, COMMIT absent, every step derived; Executed vs
step 5; a week names a subject; Cycle/Week UI-only; park at birth (PLAN-142); repair rule.
Moved out of the injected frame, not retired — each still in its step file, read on demand: the Q1/Q2/Q3
wording and card rules (now the SKILL.md body, which asks them); the plan-new.sh --portfolio exact-match table
and the net/talent/cleaning/raw slug notes (1-brief.md; project-session.sh normalises the spellings);
the README-is-not-re-attached note (superseded: the start hook re-injects context.md); the per-portfolio
loader-skill deletion history; the WIN subprocess appendix and catalogue snapshot (the recipes command reads
the directory live); the OCC-column harvest internals (plan-registry.ts line refs); the resume half of
2-loop.md — SETTLED, TRAPS, VERIFICATION and the four-source research (/plan-continue's frame, unchanged).
Retired: none.
Consequences
- A planning session carries one project's context (≤3 KB) plus one recipe and a 17 KB frame instead of 86 KB.
/plan-startis identical on every box that runs fleet-doctrine ≥ 0.93.0; the Architect's box needs the brain-agent deletion pulled, or its old skill keeps winning the bare name.- P4 fills
issue,repo,item_node_id,loop,last_stamp_epochin the same file; the start line already printsissue=.
ADR-9836 — The Architect's always-on layer is a project-free floor; project text is `<project>/context.md`
Mirrored from the fleet knowledge base: wi/decisions/ADR-9836-a-project-free-shared-floor.md
ADR-9838 — Docs follow code through claude-code-action on PRs and a close-out Stop hook, from one map
Mirrored from the fleet knowledge base: wi/decisions/ADR-9838-docs-follow-code-through-claude-code-action-and-a-close-out-hook.md