Design, plan, fact-check report, and athanor implementation report for the adept discovery and tiered knowledge folders feature. Also captures the harness behavior investigation as an open goal.
11 KiB
Plan: Adept discovery and tiered knowledge folders
Design: designs/2026-09-18-adept-discovery.md
Date: 2026-09-18
Decisions
Q1: Journal relocation — worth the churn?
Decision: Move journals to journal/ subfolder. No existing adept folders exist in this repo, so there is zero churn here. The design's lazy migration path (next adept into a legacy folder does the git mv) is sound for other projects. The clean ls benefit is real and permanent; the migration cost is one-time and bounded.
Q2: Doc vocabulary — fixed or free?
Decision: Suggested vocabulary, free additions, index rule enforces discoverability. A fixed vocabulary would be over-prescriptive for domains that don't map cleanly to key-files / conventions / architecture / gotchas. The index rule ("if it is not listed in CLAUDE.md, it does not exist") is the enforcement mechanism — it makes free naming safe. The _template/CLAUDE.md should list the suggested names as comments so a founding adept sees the vocabulary without being constrained by it.
Q3: ## Adepts in journal — grepping enough, or add a counter?
Decision: Grepping is enough. A counter is exactly the hand-maintained metadata the design principle forbids. The ## Adepts section in the journal provides a grep-friendly surface (grep -l 'auth —' journals/). If someone ever wants counts, a one-liner over journal files derives them.
Q4: roster.sh location — skill folder vs. Justfile recipe
Decision: Skill folder (${CLAUDE_SKILL_DIR}/roster.sh). This avoids a Justfile dependency that the design otherwise does not introduce. The Justfile in this repo is currently unstaged and minimal. Adding a just adepts recipe would couple a plugin-internal concern to the consuming project's build tool. The skill folder is the natural home — spire:project already uses the same ${CLAUDE_SKILL_DIR} mechanism for cat.
Q5: Parallel sessions — acceptable conflict risk?
Decision: Acceptable for now; document the worktree in handoff.md. The conflict surface is handoff.md, which is short and human-resolvable. The adept should record its worktree/branch in handoff.md's frontmatter branch: field (already in the design). Rare enough that engineering a lock or merge protocol would be premature.
Implementation Phases
Phase 1 — New spire:adepts skill (the roster)
Dependencies: None. Foundational new component.
1.1 Create plugins/spire/skills/adepts/SKILL.md
Content per design §D. Frontmatter:
---
name: adepts
description: Lists the adept domains in the workpad — what each covers, when it was last active, its status. Loaded by Igor at boot; any agent may invoke it for a fresh listing.
allowed-tools: Bash(bash:*)
---
Body: the shell-injection line !`bash "${CLAUDE_SKILL_DIR}/roster.sh"` followed by the empty-roster comment.
1.2 Create plugins/spire/skills/adepts/roster.sh
Implement the script from design §D. Key implementation details:
- Workpad resolution:
WORKPAD_FOLDERenv var →just workpad-folder 2>/dev/null→docs/workpad→.workpad. Also grep.claude/spire/project.mdfor theWorkpad:line as fallback for the external-tickets-folder case. - Iterate
"$WP"/adepts/*/, skip_template. - Parse frontmatter from each domain's
CLAUDE.mdusingsed(extract lines between opening and closing---). - Derive
newestandsessionsfromjournal/filenames (also check the domain root for legacyYYYY-MM-DD-HH-journal-*files for backward compatibility with unmigrated folders). - Output one
- **slug** — summary ...line per domain. - Make the script executable (
chmod +x).
Verification
bash plugins/spire/skills/adepts/roster.shin a repo with noadepts/folder produces the "none" fallback line.- Frontmatter parsing handles values with colons, and files with no frontmatter produce empty output (not errors).
Phase 2 — Update agents/adept.md (tiered layout + handoff protocol)
Dependencies: None (parallel with Phase 1).
2.1 Rewrite domain folder structure section
Replace current ## Domain folder structure (lines 62-66) with new layout from design §A (showing journal/ subfolder, handoff.md, knowledge docs).
2.2 Split genesis into founding and successor protocols
Replace current ## Genesis section (lines 18-31) with two subsections:
- Successor genesis (design §E): nine numbered steps — read
adepts/CLAUDE.md, read domainCLAUDE.md(index), readhandoff.md, run drift check, read Must-read docs, read only named journal entries, verify-and-correct if drift found, write genesis journal, rewritehandoff.md. - Founding genesis (design §E): copy
_template/CLAUDE.mdand_template/handoff.md, fill frontmatter during orientation, create at minimumkey-files.md, writehandoff.mdbefore first consultation withverified-at= current HEAD, write genesis journal entry.
2.3 Add handoff.md duties
New section ## Handoff after genesis: rolling, overwritten, short (≤40 lines). Written early, refreshed after significant consultations. Frontmatter fields: updated, session, branch, verified-at. The drift check mechanism.
2.4 Update consultation section
Add after existing point 5: refresh handoff.md after state-changing consultations; use Skill("spire:adepts") for sibling discovery; update index when adding docs.
2.5 Add index maintenance rules
CLAUDE.md stays under ~60 lines. Tiers are conditional (state the condition). Docs split at ~200 lines. Siblings introspected on demand, not preloaded. Every root file must appear in the index.
2.6 Update end-of-life and knowledge tiers
Make "wrap up" concrete (refresh handoff, closing journal). Add four-tier table from design §A.
Verification
- No reference to flat
YYYY-MM-DD-HH-journal-<topic>.mdat root level remains. - Both founding and successor genesis protocols present as distinct subsections.
handoff.mdmentioned with overwrite-not-append rule.
Phase 3 — Update skills/igor/SKILL.md (roster integration + spawning)
Dependencies: Phase 1 (skill must exist to be referenced).
3.1 Rewrite ## Adepts section
Remove "Check the workpad's adepts/ folder before spawning." Replace with: roster is loaded by spire:adepts at boot; Igor does not read adept folders directly. Two brief shapes (successor vs. founding). Roster matching uses the gravity-well rule. Shell-disabled fallback: Haiku subagent runs roster.sh.
3.2 Update session start steps
After creating journal: seed ## Adepts from roster rows relevant to topic. May name a matching adept in the greeting.
3.3 Add wrap-up step for adepts
In session lifecycle wrap-up: SendMessage each live adept to close, wait via ListAgents, journal final state per adept.
Verification
- No reference to "Check the workpad's
adepts/folder" remains. - Both brief shapes present. Fallback documented.
Phase 4 — Update agents/igor.md (add skill)
Dependencies: Phase 1.
Add spire:adepts to skills: list after spire:workpad.
Phase 5 — Update journal template
Dependencies: None (parallel with other phases).
Add ## Adepts section between ## Log and ## Artifacts in skills/igor/references/journal-template.md.
Phase 6 — Update skills/init/SKILL.md (new templates)
Dependencies: Phases 1-2 (references the new layout).
- Rewrite Phase 4
adepts/CLAUDE.mdcontent to match design §G. - Rewrite
_template/CLAUDE.mdto be an index template with frontmatter and tiered reading list. - Add
_template/handoff.mdtemplate. - Update Phase 7 commit file list.
Phase 7 — Update supporting files
Dependencies: None (logically last).
skills/workpad/SKILL.md: addadepts/to optional-folders list.skills/igor/references/project.md: updateAdepts:line to reference roster.skills/curator/SKILL.md: add scope note distinguishing knowledge docs (curator targets) from handoff/journal (not targets).
Commit Strategy
Commit 1 — ✨ Add spire:adepts roster skill
plugins/spire/skills/adepts/SKILL.md,plugins/spire/skills/adepts/roster.sh
Commit 2 — 🤖 Update adept agent for tiered layout and handoff protocol
plugins/spire/agents/adept.md
Commit 3 — 🤖 Wire Igor to use adept roster for discovery and spawning
plugins/spire/skills/igor/SKILL.md,plugins/spire/agents/igor.md,plugins/spire/skills/igor/references/journal-template.md
Commit 4 — 🤖 Update init templates and supporting files for adept discovery
plugins/spire/skills/init/SKILL.md,plugins/spire/skills/workpad/SKILL.md,plugins/spire/skills/igor/references/project.md,plugins/spire/skills/curator/SKILL.md
Fact-Check Items
From the design (questions 6-10)
FC-1 (Q6): Nested CLAUDE.md auto-loading — does the harness load <dir>/CLAUDE.md when a subagent reads files under <dir> via Read? Underpins the "keep CLAUDE.md short" length pressure.
FC-2 (Q7): Skill shell injection with a script path — does !`bash "${CLAUDE_SKILL_DIR}/roster.sh"` work with allowed-tools: Bash(bash:*)? Does ${CLAUDE_SKILL_DIR} resolve for plugin skills at agent-startup preload time? Behavior under disableSkillShellExecution?
FC-3 (Q8): Workpad resolution in the script — does the resolution chain cover the external-tickets-folder case?
FC-4 (Q9): Skill("spire:adepts") from a subagent — can an adept invoke a plugin skill on demand?
FC-5 (Q10): git log with glob pathspecs — does git log --oneline <sha>..HEAD -- src/middleware/auth* work correctly, or does shell expansion interfere? Should the handoff template quote the paths?
Additional items from planning
FC-6: sed frontmatter parsing robustness — handles values with colons? Multiline arrays? Files with no frontmatter?
FC-7: ls vs. find for journal enumeration — behavior when journal/ doesn't exist? Does 2>/dev/null on ls swallow both arguments' output?
FC-8: CLAUDE_SKILL_DIR for the adepts skill — resolves to plugins/spire/skills/adepts/ (or cached equivalent), not the invoking skill's directory?
Design Adjustments (from planner)
roster.shshould grep.claude/spire/project.mdfor the workpad path as an additional fallback for the external-tickets-folder case.- Keep
covers:parsing out ofroster.sh— it's consumed by the drift check inhandoff.md, not by the roster. The roster only needssummary,status, andrelated. - Phase parallelism: Phases 1, 2, and 5 have no dependencies and can be worked in parallel. Phase 3 depends on Phase 1. Phase 6 depends on Phase 2.
Risks and Mitigations
roster.shfragility — shell parsing of YAML frontmatter withsedis brittle. Mitigation: only extract four single-line fields; "unmigrated" fallback for unparseable frontmatter; convention note that frontmatter values must be single-line.handoff.mdoverwrite breaks git merge — parallel sessions in same domain. Mitigation: accepted (Q5); rare, short file,branch:field helps resolution.- Large change surface — many files change across the plugin. Mitigation: commit strategy isolates additive roster skill from behavior changes; each commit independently verifiable.
- Backward compatibility — existing adept folders see "unmigrated" in roster. Mitigation: by design; lazy migration via next adept spawn.