Compare commits
26
Commits
gremlins-mvp
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
544b69ccb7 | ||
|
|
e6843cabc5 | ||
|
|
cd932ccf63 | ||
|
|
6ab4dd07e3 | ||
|
|
0f2aee6bc9 | ||
|
|
5b5fe14221 | ||
|
|
c4794745e0 | ||
|
|
a8208e81ee | ||
|
|
520464be20 | ||
|
|
fa80d26309 | ||
|
|
fc6a543162 | ||
|
|
2c311f8fe8 | ||
|
|
6e8fd92693 | ||
|
|
2e8cbf8177 | ||
|
|
46dbc861be | ||
|
|
456862a96f | ||
|
|
9fd01edd63 | ||
|
|
3f684ce459 | ||
|
|
d605daac07 | ||
|
|
4af86637d4 | ||
|
|
8bf9184ba5 | ||
|
|
e1884248e8 | ||
|
|
82ef04c118 | ||
|
|
cb47686f28 | ||
|
|
10e48417e6 | ||
|
|
6d5ea32acb |
@@ -14,7 +14,6 @@ the Spire plugin's own home — work here is work ON Spire.
|
|||||||
- **Adepts**: Listed by `spire:adepts` at boot. Domain knowledge agents with persistent folders at `docs/workpad/adepts/<domain-slug>/`.
|
- **Adepts**: Listed by `spire:adepts` at boot. Domain knowledge agents with persistent folders at `docs/workpad/adepts/<domain-slug>/`.
|
||||||
- **Pinned agents** (prefer these over generic tiers):
|
- **Pinned agents** (prefer these over generic tiers):
|
||||||
<!-- None pinned in .claude/agents/ yet -->
|
<!-- None pinned in .claude/agents/ yet -->
|
||||||
- **Verification commands**: `just --list` (minimal Justfile — `claude-rc` recipe only)
|
|
||||||
- **Domain skills to route to subagents when relevant**:
|
- **Domain skills to route to subagents when relevant**:
|
||||||
- `gitea:*` — Gitea issue and PR management
|
- `gitea:*` — Gitea issue and PR management
|
||||||
- **Conventions**:
|
- **Conventions**:
|
||||||
@@ -24,12 +23,21 @@ the Spire plugin's own home — work here is work ON Spire.
|
|||||||
- Marketplace repo — each plugin under `plugins/` is self-contained
|
- Marketplace repo — each plugin under `plugins/` is self-contained
|
||||||
- Working documents live in `docs/workpad/`
|
- Working documents live in `docs/workpad/`
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Read by `spire:implementation`. Unset means the skill's default; `none` means deliberately absent.
|
||||||
|
|
||||||
|
Reliquary is a markdown plugin marketplace. Most work is skill and agent text, so there is no compile step.
|
||||||
|
|
||||||
|
- **Gate** (cheap, between blocks): none
|
||||||
|
- **Tests** (once per phase): `uv run --no-project --python 3.12 python -m unittest discover -s tests`, run from `plugins/spire/skills/gremlins`. It covers gremlins only. Other plugins have no test suite.
|
||||||
|
|
||||||
## Spire structure
|
## Spire structure
|
||||||
|
|
||||||
This is the home repo. The plugin itself lives at `plugins/spire/`.
|
This is the home repo. The plugin itself lives at `plugins/spire/`.
|
||||||
|
|
||||||
- **Agents**: `plugins/spire/agents/` — igor, athanor, adept, researcher, scout, search, zathras
|
- **Agents**: `plugins/spire/agents/` — adept, athanor, attacker, igor, planner, researcher, reviewer, scout, search, zathras
|
||||||
- **Skills**: `plugins/spire/skills/` — adepts, curator, igor, implementation, init, knowledge, project, research, research-tree, svg, workpad, zathras
|
- **Skills**: `plugins/spire/skills/` — adepts, curator, gremlins, igor, implementation, init, knowledge, project, research, research-tree, svg, workpad, zathras
|
||||||
- **Plugin config**: `plugins/spire/.claude-plugin/plugin.json`
|
- **Plugin config**: `plugins/spire/.claude-plugin/plugin.json`
|
||||||
- **Design spec**: `docs/workpad/designs/2026-09-14-plugin-design-spec.md`
|
- **Design spec**: `docs/workpad/designs/2026-09-14-plugin-design-spec.md`
|
||||||
- **Legacy**: `plugins/g4b_ai/` still exists (predecessor, being phased out)
|
- **Legacy**: `plugins/g4b_ai/` still exists (predecessor, being phased out)
|
||||||
|
|||||||
@@ -234,6 +234,29 @@
|
|||||||
- User: the MVP box list is good. Asked whether to use the current prototype to help implement it. Warned that "small / happy path first / delete what isn't needed" can backfire. Recorded the safer framing options in the brainstorm (trace to boxes, a size estimate to justify against, happy path as sequencing, unrequested surface as a finding for the user to decide).
|
- User: the MVP box list is good. Asked whether to use the current prototype to help implement it. Warned that "small / happy path first / delete what isn't needed" can backfire. Recorded the safer framing options in the brainstorm (trace to boxes, a size estimate to justify against, happy path as sequencing, unrequested surface as a finding for the user to decide).
|
||||||
- User decided: build the MVP by **dogfooding** the prototype's happy path. Train a base on prototype + verdict + MVP spec, spawn one gremlin per module, fall back to a plain agent if the tool misbehaves, and don't fix the prototype. Dispatched in parallel: an MVP spec writer (opus, 20 min, ≤150 lines, the module structure fixed, the safer framing) → plans/2026-10-17-00-gremlins-mvp-spec.md; the TaskStop/claude.exe check (sonnet, 10 min).
|
- User decided: build the MVP by **dogfooding** the prototype's happy path. Train a base on prototype + verdict + MVP spec, spawn one gremlin per module, fall back to a plain agent if the tool misbehaves, and don't fix the prototype. Dispatched in parallel: an MVP spec writer (opus, 20 min, ≤150 lines, the module structure fixed, the safer framing) → plans/2026-10-17-00-gremlins-mvp-spec.md; the TaskStop/claude.exe check (sonnet, 10 min).
|
||||||
- TaskStop check (sonnet-5-5): TaskStop kills claude.exe and its bash wrappers. An in-flight grandchild command (sleep.exe) survives as an orphan and runs to completion. MVP decision: no kill command; document the orphan behaviour; a sweep is an open item. Sent to the spec writer.
|
- TaskStop check (sonnet-5-5): TaskStop kills claude.exe and its bash wrappers. An in-flight grandchild command (sleep.exe) survives as an orphan and runs to completion. MVP decision: no kill command; document the orphan behaviour; a sweep is an open item. Sent to the spec writer.
|
||||||
|
- MVP spec back (claude-opus-5-5, 140 lines), committed b8affd8 (local main).
|
||||||
|
- Modules: store ~70, launch ~110, stream ~170, call ~60, cli ~200 = ~610 lines + ~300 lines of tests. Commands: init, train, spawn, rebase, status. No locks needed (single writer per file).
|
||||||
|
- Risks: B7 rebase session id may change; a hard kill can leave a job "running"; cache depends on env, cwd and the system prompt staying stable.
|
||||||
|
- 23:12 — Dispatched the MVP build orchestrator (general-purpose, opus, 90 min): new worktree branch gremlins-mvp from main; the prototype as tool and reference; one base, gremlins per module in waves (4 parallel ×2 → cli/entry → tests); a live smoke of the MVP incl. a cache hit and a parallel run; fallback to writing the code itself without fixing the prototype; a metrics report on the branch.
|
||||||
|
- 23:45 — **MVP built by gremlins in ~21 min (23:13–23:34), ~$7.22 notional.**
|
||||||
|
- One base ($1.97, 408 s) and 8 forks, all cache hits, no fallback needed.
|
||||||
|
- Branch gremlins-mvp (aff29d6..0493f03, pushed); main pushed (b8affd8 + journal).
|
||||||
|
- 972 lines of code (spec estimate 610, reasons in the gremlins' notes) + 493 lines of tests + a 54-line SKILL.md. 24 unit tests green.
|
||||||
|
- Live smoke: train → spawn with a cache hit, two ledger lines, status warm. A parallel run of two spawns via run_in_background worked.
|
||||||
|
- Not live-tested: TaskStop on an MVP spawn, rebase, the non-Windows gate.
|
||||||
|
- **This is the first real trial of the user's original model (a trained base, forked per module): it worked first time.** Contrast: the prototype took ~9 active hours for 4,155 lines.
|
||||||
|
- MVP review (claude-opus-5-5[1m], cfeb1bf, 82 lines):
|
||||||
|
- B1, B2, B3, B5, B6 ticked; B4 (live TaskStop), B7 (live rebase) and B8 (non-Windows run) only partly, since they were not verified live.
|
||||||
|
- 30 unrequested items, 15 justified by the build report. Listed, not deleted: the user decides.
|
||||||
|
- Line gap mostly form: 248 of the 362 extra lines are blanks, docstrings, comments and imports; logic is 724 vs 610.
|
||||||
|
- No real bug; `init` validates twice.
|
||||||
|
- Open items for the user: the three live checks (TaskStop, rebase, WSL/Linux), and the decision on the 15 unjustified items.
|
||||||
|
- 00:04 — User asked what the two open items mean, and for a guidance pass on the Spire skills from today's findings, possibly as a handoff. Igor wrote plans/2026-10-17-00-spire-guidance-pass-handoff.md:
|
||||||
|
- A: wire gremlins into the Athanor;
|
||||||
|
- B: stale text;
|
||||||
|
- C: steering sentences rewritten with the safer framing, plus the planner gets code structure and an ecosystem inventory;
|
||||||
|
- D: size and duplication.
|
||||||
|
- Plus 5 user decisions, timeboxes per part, one end review. Aimed at Zathras (Spire self-maintenance), or an Igor.
|
||||||
|
|
||||||
## Adepts
|
## Adepts
|
||||||
|
|
||||||
@@ -252,6 +275,7 @@
|
|||||||
- Probe design (user-endorsed direction) → goal or grotto design document when document prep is done.
|
- Probe design (user-endorsed direction) → goal or grotto design document when document prep is done.
|
||||||
- The user's original Athanor model (learns plans, not code; train one implementer, fork it per subsection) is now expressible via headless forks. Not decided.
|
- The user's original Athanor model (learns plans, not code; train one implementer, fork it per subsection) is now expressible via headless forks. Not decided.
|
||||||
- The spawning reference (spawning-claude-code.md:56-64) has rows that today's research answers; edited on the headless-forks branch only.
|
- The spawning reference (spawning-claude-code.md:56-64) has rows that today's research answers; edited on the headless-forks branch only.
|
||||||
|
- **gremlins-mvp branch** (pushed incl. review cfeb1bf): 972 lines of code, 24 tests, built by gremlins in 21 min. Open: live checks for B4 (TaskStop on an MVP spawn), B7 (rebase), B8 (WSL/Linux/mac); the user's call on the 15 unjustified unrequested items (review report §2); then Spire integration (athanor.md/implementation text) and a version decision. Not merged.
|
||||||
- **headless-forks branch** (pushed, ab1d945): a prototype, 4,155 + 4,235 lines, Phase 3 unreviewed, 3.8 unfinished, version bumped to 0.3.0 in WIP. Don't merge. Next step: decide between a minimal rewrite (a few hundred lines: train/spawn/wait/usage over blocking or `run_in_background` Bash calls) and the Rust app.
|
- **headless-forks branch** (pushed, ab1d945): a prototype, 4,155 + 4,235 lines, Phase 3 unreviewed, 3.8 unfinished, version bumped to 0.3.0 in WIP. Don't merge. Next step: decide between a minimal rewrite (a few hundred lines: train/spawn/wait/usage over blocking or `run_in_background` Bash calls) and the Rust app.
|
||||||
- **Process lessons to accrete** into Spire (not done yet; the user ended the session):
|
- **Process lessons to accrete** into Spire (not done yet; the user ended the session):
|
||||||
- briefs carry time and token budgets;
|
- briefs carry time and token budgets;
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Guidance pass — Zathras Session Journal
|
||||||
|
|
||||||
|
**Date**: 2026-10-17
|
||||||
|
**Topic**: guidance-pass (Spire guidance text + gremlins MVP wiring)
|
||||||
|
**Worktree/branch**: main (no worktree); MVP on branch `gremlins-mvp`
|
||||||
|
**Scope**: [handoff](../plans/2026-10-17-00-spire-guidance-pass-handoff.md) at 10e4841
|
||||||
|
|
||||||
|
## Adepts
|
||||||
|
|
||||||
|
None. Roster empty (`adepts/` holds only `CLAUDE.md` and `_template/`).
|
||||||
|
|
||||||
|
## Log
|
||||||
|
|
||||||
|
<!-- Append-only. -->
|
||||||
|
|
||||||
|
- 00:08 — Session start. User's instructions: work from the handoff; read its four inputs only; put the five (user) decisions in one go before building; then parts A–D in order with the handoff's timeboxes, one agent per part (Sonnet mechanical, Opus for C), one review at the end; commit before deleting text; no process steps the handoff doesn't name without asking; push only on the user's word.
|
||||||
|
- 00:08 — Read the handoff and its four inputs: guidance-text audit, headless-forks post-mortem, grotto plan-structure brainstorm, and on `gremlins-mvp` the gremlins SKILL.md plus the MVP review.
|
||||||
|
- Note on review §2's count: the table has 14 rows marked "-" plus #7's deny list ("deny list itself not") = 15 unjustified. #8 (env marker), #13 (`mismatch`) and #14 (`wrote_only_5m`) are counted as justified but are dead or leftover code.
|
||||||
|
- The handoff names a sixth (user) item the user's list left out: whether to spend a run proving the steering changed (before/after C).
|
||||||
|
- Decisions put to the user (with proposed defaults); waiting for answers. Nothing built.
|
||||||
|
- 00:1x — User answered decision 1 and confirmed part A (recorded in the handoff, cb47686): keep the useful items, cut the rest, Zathras decides per item, one-line reasons in a report, commit before cutting. Decisions 2–5 still open.
|
||||||
|
- Dispatched one Sonnet agent (general-purpose, 15 min) in the `gremlins-mvp` worktree: commit the keep/cut report first, then the cuts, tests, second commit. Report → reports/2026-10-17-00-gremlins-mvp-cuts.md (on the branch). Calls: keep #2, 3, 5, 6, 7, 16, 23, 25, 26; cut #4, 11, 12, 17 (to an existence check), 22, 28, plus dead riders #8, 13, 14. The agent re-checks each premise and keeps an item if its premise is false.
|
||||||
|
- User took all four defaults: merge first then A on main; 0.3.0 together; Igor voice moderate (~150 words, I-2); TaskStop check before merge, rebase + WSL/Linux after. The steering-proof run was not answered, so it stays skipped. Recorded in the handoff's "Answered" section.
|
||||||
|
- Sequence: cuts agent finishes → TaskStop live check on the cut code → merge `gremlins-mvp` into main (local, no push) → A → B → C → D → one review.
|
||||||
|
- Cuts agent back (Sonnet): 82ef04c (📝 record of the calls) then e188424 (🔥 cuts), on `gremlins-mvp`, not pushed. Net −32 lines; 24 tests OK, re-run by Zathras: OK. Deviation: **#4 lock kept**. With it removed, two B3 parallel-append tests lose lines on Windows (separate handles, appends not atomic). The lock only hides this in-process; across processes the race stays unguarded, which is the review's open "Windows append atomicity" item. A cross-process fix (a lock file or `msvcrt` byte-range lock) is a later decision for the user, not part of this pass.
|
||||||
|
- Dispatched the live TaskStop check (Sonnet, 20 min, ≤ $0.50, Haiku 5.5 gremlin in a throwaway scratch repo). Report → reports/2026-10-17-00-gremlins-taskstop-check.md on the branch.
|
||||||
|
- TaskStop check back (Sonnet): 8bf9184 on the branch. **B4 ticked for the main case**: TaskStop on the backgrounded spawn killed the whole tree (uv, python, claude.exe, bash wrappers, conhost), all gone by ~5–10 s. Job file stays `running`, no ledger line, as documented. **Not tested:** the orphaned long child (spec §7). The gremlin's harness refused a standalone `sleep 300`; a rerun would need e.g. `python -c "import time; time.sleep(300)"`. Cost ≈ $0.008. Not adding a rerun step (not asked for); noted as open.
|
||||||
|
- Merging `gremlins-mvp` into main (local, no push): additions only, 22 files.
|
||||||
|
- Merged: 4af8663 (journal + handoff answers), d605daa (🔀 gremlins-mvp). Local, not pushed.
|
||||||
|
- Part A back (Sonnet, ~5 min): 3f684ce. Athanor step 2 now names the gremlins path in 6 lines (train base, `spawn` as background Bash, `TaskStop`, brief states commit/paths); `spire:gremlins` preloaded; implementation "trunk and gremlins"; igor "Fork sparingly" dropped. Left alone: spawning-claude-code "## Fork" record table (row 62 now stale → into B), metaphors, history notes. Checked the diff: fine.
|
||||||
|
- Part B dispatched (Sonnet, 20 min): the audit's class-e list (13 items incl. the spawning row 62 one), commit once.
|
||||||
|
- Part B back (Sonnet, ~1 min of work): 9fd01ed, 11 files +20/−24. All 13 items fixed. project.md: agent list matched, `## Build` added (Gate none; Tests = gremlins unittest), g4b_ai legacy line kept (the folder exists). init adept template keeps `status: generated` (roster reads `^status:`). Superpowers sentence gone from athanor/implementation; references/superpowers.md now unlinked. Agent's "athanor.md:32 Fork sparingly" claim checked: false, no fork text left. Remaining Pinky: a dated record row in spawning-claude-code.md:54, left for D.
|
||||||
|
- Part C dispatched (Opus, 45 min): steering rewrite per handoff C + audit §4, brainstorm framing, before/after list in a report.
|
||||||
|
- Part C back (Opus, ~5 min): 46dbc86 (🤖, 8 files, ~40 sentences) + 2e8cbf8 (report reports/2026-10-17-00-guidance-pass-c-steering.md). All must-change items done. Not added on purpose: "smallest change"/"prefer deleting" (brainstorm warns they fire the other way). Agent unsure of three counterweights, carried to the final review: implementation:41 tests per named behaviour not per branch; athanor:39 Athanor no longer reads child diffs for loosened assertions (leans on reviewer); reviewer:22 flags answered only where they change a verdict.
|
||||||
|
- Zathras addition to C's brief (told the user): planner gives a per-module size estimate as a budget, not a cap. Not named in the handoff for the planner; the reviewer's size section needs it.
|
||||||
|
- Part D dispatched on **Opus**, not Sonnet: one agent per part, and most of D is judgment (rule homes, what planner/attacker/reviewer keep without their preloads, the Igor trim). Told the user. Unreachable files are listed in the report for the user, not deleted.
|
||||||
|
- Part D back (Opus, ~7 min): 6e8fd92 (D1 preloads), 2c311f8 (D2 harness rules → spawning-claude-code), fc6a543 (D3 Igor trim), fa80d26 (D4 class c/d), 520464b (report reports/2026-10-17-00-guidance-pass-d-size.md). Words: Igor boot 6384 → 4726 (target ≈4k, missed ~700: workpad stays preloaded at 1385 per decision 4); Athanor 7241 → 6754 (no target); planner 4166 → 879, attacker 4124 → 859 (439 of each is project.md + CLAUDE.md), reviewer 4058 → 793. All C sentences survived (grep-checked by the agent). Researcher added to the safe-leaf list: Zathras checked, its tools have no Agent. Unreachable files for the user: implementation/references/superpowers.md, igor/references/project.md, igor/references/harness-notes.md.
|
||||||
|
- Whole pass on plugins/ + .claude/: 22 files, +159/−376. Dispatching the one final review (Opus, read-only + report).
|
||||||
|
- Final review back (Opus): c479474, reports/2026-10-17-00-guidance-pass-review.md. Critical none. Important 3: (1) attacker's Reshape doesn't carry the plan's code structure + size estimate into the build plan and lost the "main signatures" exception; (2) gremlins/preamble.md still has the old handoff-note fields, so part C never reached gremlin-built blocks; (3) reviewer lost "a test for each named failure path" with the implementation preload. Minor 6. Q1: sizes confirmed; Igor 4726 misses ≈4k by ~730, all operational text (Development Cycle, Adepts, workpad kept by decision 4). Q2: no rule lost its only home beyond Important 1/3. Q3: nothing over-steers on its own; the three unsure sentences keep, with small tweaks. Part A done-criterion met.
|
||||||
|
- A fix pass is not named in the handoff → asking the user before running one. Version bump 0.3.0 and push still pending.
|
||||||
|
- User OK'd one Sonnet fix pass on all 9 findings, then 0.3.0, no push. Fix pass back: 0f2aee6 (🤖, 6 files +14/−11, all 9 fixed, none skipped), 6ab4dd0 (🔖 0.3.0 in .claude-plugin and .codex-plugin plugin.json; marketplace has no version; no CHANGELOG), cd932cc (📝 fix-pass section in the review report). Zathras checked: gremlins tests 24 OK (preamble changed); agent bodies now planner 440, attacker 454, reviewer 366 words (+439 fixed project text each). Left: the igor SKILL pointer the agent noted at :56 (not in the fix proposal).
|
||||||
|
- State: main 29 ahead of origin, nothing pushed. Open for the user: push; the three unreachable reference files; cross-process ledger append on Windows; post-merge live checks (rebase, WSL/Linux, TaskStop orphan case).
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Handoff: Spire guidance pass + gremlins MVP wiring
|
||||||
|
|
||||||
|
**From**: Igor, session [2026-10-15-21-grotto-work](../journals/2026-10-15-21-grotto-work.md), 2026-10-17 00:04
|
||||||
|
**For**: a dedicated coordinator. This is Spire self-maintenance, so `spire:zathras` (`/spire:zathras guidance-pass`) is the natural fit; an Igor works too.
|
||||||
|
**Status**: not started. Every decision marked *(user)* needs the user's answer before it's built.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
The headless-forks build ([post-mortem](../reports/2026-10-16-23-headless-forks-postmortem.md)) delivered 4,155 lines where about 600–800 were needed, in ~9 active hours. Half of the root causes are in the guidance text itself ([text audit](../reports/2026-10-16-23-spire-guidance-text-audit.md)):
|
||||||
|
- Single sentences steer toward completeness and audit-style output ("answer every … flag … one by one", "hunt", eight-field handoff notes with no length cap, an attacker asked for more scope).
|
||||||
|
- Nothing steers toward the structure and size the requirement needs.
|
||||||
|
- About 23% filler, 9% general knowledge, and rules repeated up to 11 times.
|
||||||
|
- Stale text, such as the Agent-tool fork in athanor.md:32.
|
||||||
|
- Planner, attacker and reviewer carry about 83% preloaded text from other skills.
|
||||||
|
|
||||||
|
The gremlins MVP (branch `gremlins-mvp`, 972 lines, built by gremlins in 21 min) worked first time. The guidance should make that path the normal one.
|
||||||
|
|
||||||
|
## Inputs (read these, nothing else up front)
|
||||||
|
|
||||||
|
1. reports/2026-10-16-23-spire-guidance-text-audit.md: per-file sizes, a/b/c/d/e classes, duplication table, steering list, lean target sizes. **The main work list.**
|
||||||
|
2. reports/2026-10-16-23-headless-forks-postmortem.md: root causes and the 14 lesson options.
|
||||||
|
3. brainstorm/2026-10-16-22-grotto-plan-structure.md: the user's thinking. Especially **"Steering sentences cut both ways"**: don't fix over-building with "small / happy path / delete", which can fire the other way. Use the safer framing listed there.
|
||||||
|
4. On branch `gremlins-mvp`: `plugins/spire/skills/gremlins/SKILL.md` and docs/workpad/reports/2026-10-17-gremlins-mvp-review.md.
|
||||||
|
|
||||||
|
## Scope: four parts, in this order
|
||||||
|
|
||||||
|
### A. Wire gremlins into the Athanor (small, mechanical)
|
||||||
|
- athanor.md and implementation SKILL.md: replace the Agent-tool "fork of yourself" path (athanor.md:32, implementation SKILL.md:45-50) with the gremlins path:
|
||||||
|
- train one base on plan, design and trunk;
|
||||||
|
- `spawn` per complex block via Bash `run_in_background`;
|
||||||
|
- stop a gremlin with `TaskStop`;
|
||||||
|
- fresh Agent-tool agents stay for mechanical blocks.
|
||||||
|
- Add the gremlins skill to the Athanor's preloaded skills.
|
||||||
|
- igor/SKILL.md:66 "Fork sparingly": reword or drop it; it refers to the dead Agent-tool fork.
|
||||||
|
- Done when no Spire text tells an agent to Agent-tool-fork itself, and the Athanor's procedure names the gremlins call sequence in ≤ ~15 lines (details stay in gremlins/SKILL.md).
|
||||||
|
|
||||||
|
### B. Stale and contradicting text (audit class e)
|
||||||
|
- zathras SKILL:74 "Always pass `model`" contradicts the pin rule.
|
||||||
|
- The injected `.claude/spire/project.md`: its agent list lacks planner, attacker and reviewer; it has no `## Build` section; it still lists g4b_ai as legacy.
|
||||||
|
- Everything else in the audit's class-e table.
|
||||||
|
|
||||||
|
### C. Steering sentences (audit §4): the part that changes behaviour
|
||||||
|
Rewrite, don't just delete, using the brainstorm's safer framing:
|
||||||
|
- **reviewer.md:22** "answer every deviation and flag … one by one". Move to: findings first; flags answered only where they change a verdict; a size and unrequested-surface section where the decision stays with the user.
|
||||||
|
- **run-log.md:54** and the eight-field handoff note: give it a length expectation; findings, not narration.
|
||||||
|
- **attacker.md:25** "missing function … error handling, security", which conflicts with :33 "scope cut back to the goal". Tie it to the goal's boxes.
|
||||||
|
- **Planner:** plans fix **code structure** (modules, data model, main interfaces) and include an **ecosystem inventory** (what harness, CLI output, stdlib and existing tools already provide) before anything is designed to be built. These are grotto lessons. Put them here now; grotto can lift them later.
|
||||||
|
- **Igor and Athanor:** briefs carry a time budget; re-plan when a preflight removes a design premise; mechanical blocks get a cheaper model; a fresh Athanor per phase; check the self-written contract digest before building.
|
||||||
|
- Each changed sentence gets its counterweight in the same sentence (see the brainstorm).
|
||||||
|
|
||||||
|
### D. Size and duplication (audit classes c and d, §3, §5)
|
||||||
|
- Stop preloading workpad and implementation into planner, attacker and reviewer. Their briefs name the output paths. Audit target: ~500–800 words each.
|
||||||
|
- One home per repeated rule ("stamp the model id" ×11, leaf-brief ×11, delegation ×9, test cadence ×7). Other files point to it in one line.
|
||||||
|
- Igor persona and mindset: trim to the audit's moderate target (~4k words for the boot bundle). *(user)* how much of the voice to keep.
|
||||||
|
- Remove general knowledge the model already has (audit class c quotes).
|
||||||
|
|
||||||
|
## Decisions needed from the user *(user)*
|
||||||
|
|
||||||
|
1. **The 15 unjustified unrequested items** in the MVP (review §2). Keep, cut, or keep with a reason. The build report justified the other 15 of 30. Candidates the coordinator can propose a default for: unused stream fields and the leftover `SPIRE_GREMLIN_CHILD` marker (cut), `briefs/<job>.md` (keep, useful for debugging), torn-line ledger repair (keep).
|
||||||
|
2. **Merge order:** merge `gremlins-mvp` first and do A on main, or do A on the MVP branch. The `headless-forks` branch stays an unmerged prototype record either way.
|
||||||
|
3. **Version:** 0.3.0 for MVP plus guidance pass together, or MVP alone first.
|
||||||
|
4. How far to trim Igor's persona (D).
|
||||||
|
5. **The three live checks still open on the MVP:** TaskStop on an MVP spawn, `rebase`, a WSL or Linux run. Before the merge or after.
|
||||||
|
|
||||||
|
### Answered 2026-10-17 (user)
|
||||||
|
|
||||||
|
- **Decision 1:** keep the useful items, throw out the ones that aren't useful. The coordinator applies that per item, using review §2's list, and records the keep/cut call for each with a one-line reason in its report. Commit before cutting.
|
||||||
|
- **Part A is confirmed:** bring gremlins into the Athanor.
|
||||||
|
- **Decision 2:** apply the decision-1 cuts and the pre-merge check, merge `gremlins-mvp`, then do A on main.
|
||||||
|
- **Decision 3:** 0.3.0 for MVP plus guidance pass together, one bump at the end.
|
||||||
|
- **Decision 4:** moderate (audit option I-2): Voice cut to ~150 words; drop the example flourishes, "yeth, marthter", the furnace grammar rule, mindset.md's editor note, repeated delegation lines, history and Pinky. Workpad stays preloaded.
|
||||||
|
- **Decision 5:** `TaskStop` on an MVP spawn before the merge; `rebase` and a WSL/Linux run after.
|
||||||
|
- Steering proof run: not taken (no answer; default skip).
|
||||||
|
|
||||||
|
## How to run it (lessons applied)
|
||||||
|
|
||||||
|
- **Timebox:** A + B ≈ 30 min; C ≈ 45 min; D ≈ 45 min. One agent per part. Text is small, so a cold start is cheap. Sonnet for B and the mechanical parts of D; Opus for C.
|
||||||
|
- **Order matters:** C before D, so the trimmed text keeps the new steering.
|
||||||
|
- **Commit before deleting text,** so the history keeps every line.
|
||||||
|
- **One review at the end,** asking: did each bundle reach its target size, did any rule lose its only home, and does any new sentence over-steer the other way? No per-part review loops.
|
||||||
|
- **Proof that the steering changed (optional, cheap):** re-run the experiment's planning step, or a small plan, before and after C, and compare plan size and structure. *(user)* whether to spend the run.
|
||||||
|
- Accretion rule for Igor still holds: dated refinement sections in existing docs; compression is the curator's job. This pass **is** a deliberate compression, run as Spire maintenance, which is why Zathras fits.
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
- Grotto itself (design → plan → handoff procedure, standalone storage). Use this pass's planner changes as input.
|
||||||
|
- The Rust session-harness app (reports/2026-10-16-01-session-harness-app-forms.md).
|
||||||
|
- Fixing the `headless-forks` prototype.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Gremlins MVP: unrequested-surface calls
|
||||||
|
|
||||||
|
- Author model: **claude-sonnet-5-5** · Date: 2026-10-17 · Branch `gremlins-mvp` @ `cfeb1bf`
|
||||||
|
- Source: [phase review](2026-10-17-gremlins-mvp-review.md) §2. The user ruled on the rows below: keep the useful ones, cut the rest, one-line reason each. This commit records the calls; the cuts follow in the next commit.
|
||||||
|
|
||||||
|
| # | Item | Call | Reason |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 2 | `briefs/<J>.md`: full prompt per job | keep | Debugging aid. |
|
||||||
|
| 3 | Ledger torn-last-line repair | keep | Protects the ledger after a hard stop. |
|
||||||
|
| 4 | In-process `threading.Lock` around ledger append | cut | Each spawn is its own process, so it guards nothing; the spec says "without locks". |
|
||||||
|
| 5 | `MODEL_RE`, aliases refused at `init` | keep | An alias would change the fingerprint and break cache hits; B1 asks for a full id. |
|
||||||
|
| 6 | `EFFORTS` choices, default `high` | keep | Trivial argparse guard. |
|
||||||
|
| 7 | Tool deny list (`Bash(claude:*)`, `git push/rebase/reset --hard`) | keep | Headless unattended gremlins must not recurse or rewrite history. |
|
||||||
|
| 8 | `SPIRE_GREMLIN_CHILD=1` in the child env | cut | Rider: the refusal it served was dropped, so it is leftover. |
|
||||||
|
| 11 | `refused` / `model_refused` status case | cut | Not in the spec's classify; the harness substitutes unlisted models silently, so `error` covers it. |
|
||||||
|
| 12 | Stream fields tracked and never read (`init`, `msg_ids`, `_ids`, `events`, `turns`) | cut | Never read. |
|
||||||
|
| 13 | `mismatch` in `usage_from_result` | cut | Rider: computed and never read. |
|
||||||
|
| 14 | `wrote_only_5m` | cut | Rider: never called. |
|
||||||
|
| 16 | `NAME_RE` on base/job names | keep | Names become file paths. |
|
||||||
|
| 17 | Note detection by mtime with 2 s slack | cut | Replace with a plain existence check of `notes/<J>.md`, since `spawn` refuses an existing job name (#20). |
|
||||||
|
| 22 | `base_state` in spawn output | cut | `status` reports warmth and `cache` reports the outcome. |
|
||||||
|
| 23 | `init` defaults cwd to the git toplevel | keep | cwd is in the fingerprint; a stable default avoids cache misses. |
|
||||||
|
| 25 | stderr to `raw/<J>.err` | keep | Cheap debugging aid. |
|
||||||
|
| 26 | Reader join timeout 10 s | keep | Without it an orphan holding stdout hangs the helper (spec §7 leftover). |
|
||||||
|
| 28 | Unused `ss=None` injection parameter in `call.py` | cut | Used by no caller. |
|
||||||
|
|
||||||
|
## Result
|
||||||
|
|
||||||
|
Premises checked in the code before each cut. Tests: `uv run --no-project --python 3.12 python -m unittest discover -s tests` gave **24 tests, OK** (run twice).
|
||||||
|
|
||||||
|
| File | Added | Removed |
|
||||||
|
|---|---|---|
|
||||||
|
| `grm/stream.py` | 9 | 39 |
|
||||||
|
| `grm/call.py` | 4 | 4 |
|
||||||
|
| `grm/cli.py` | 2 | 4 |
|
||||||
|
| `grm/launch.py` | 1 | 1 |
|
||||||
|
| **Total** | **16** | **48** |
|
||||||
|
|
||||||
|
Net code: 32 lines removed (16 added, 48 deleted); no test was removed or changed (none existed only for a cut item).
|
||||||
|
|
||||||
|
## Kept against the call
|
||||||
|
|
||||||
|
- **#4 `threading.Lock` around ledger append: kept.** Premise half true: in production each spawn is its own process, so no two threads of one process append. But with the lock removed `test_store.test_parallel_appends_give_whole_lines` (96 of 100 lines) and `test_cli.test_parallel_spawns` (2 of 3 ledger lines) fail, on every run. Appends from separate handles on Windows lose lines. The lock only makes those B3 tests pass in-process; across real processes the same race is unguarded either way (the review's open "Windows append atomicity" item). Cutting it would mean weakening two B3 tests, which the call forbids. Needs a decision: either keep the lock as is, or replace it with a cross-process append (for example a lock file or an `msvcrt` byte-range lock) in a separate change.
|
||||||
|
|
||||||
|
## Notes on the cuts
|
||||||
|
|
||||||
|
- #12: `session_id` from the `init` event is now taken only while unset (`self.session_id is None`), which matches the old "first init wins" behaviour.
|
||||||
|
- #28: `StreamState` is now imported at the top of `call.py` instead of lazily inside the `ss is None` branch.
|
||||||
|
- #17: premise holds. `spawn` refuses an existing `jobs/<J>.json` (`cli.py:255`) and `_execute` writes that file before the call starts, so a note that exists afterwards was written by this job.
|
||||||
|
- #11: nothing outside `stream.py` read `refused` or `model_refused` (code, tests, SKILL.md, templates).
|
||||||
|
- #8, #13, #14, #22: no reader in code, tests, SKILL.md or templates. SKILL.md and templates mentioned none of the cut items, so they are unchanged.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Gremlins B4 live check: TaskStop on a backgrounded spawn
|
||||||
|
|
||||||
|
Date: Sat 2026-10-17 00:13-00:16 (local). Run by: claude-sonnet-5-5. Gremlin model: claude-haiku-5-5 (effort low). Binary 2.1.299, Windows 10 Git Bash.
|
||||||
|
Worktree HEAD e188424. Scratch: throwaway git repo in the session scratchpad `taskstop-check/`.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
- `G init --run run.md --model claude-haiku-5-5 --effort low --cwd <scratch>`
|
||||||
|
- `G train --run run.md --base b1 --brief train.md` (blocking, ok, $0.0042)
|
||||||
|
- j1: `G spawn ... --job j1` brief "sleep 300": haiku refused (harness blocks a standalone `sleep`), ended ok in 15 s, $0.0019. Not usable for the check.
|
||||||
|
- j2: `G spawn ... --job j2 --brief spawn2.md` (`run_in_background: true`). Brief: run `until [ -e /tmp/never-exists-flag ]; do sleep 2; done`. Heartbeat in raw/j2.jsonl showed the gremlin's Bash running at 30 s.
|
||||||
|
- `TaskStop` on the background call (task btfr2jl7t) at about 00:15:30, ~46 s after spawn. Returned "Successfully stopped".
|
||||||
|
- PIDs found by diffing `Win32_Process` before/after the spawn and following parent links. No process outside this chain was touched.
|
||||||
|
|
||||||
|
## Process tree (j2) and liveness after stop
|
||||||
|
| PID | name | parent | after ~5-10 s | after ~40 s |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 22836 / 10324 / 18496 | bash.exe (harness wrappers of the spawn call) | 13436 / 22836 / 10324 | gone | gone |
|
||||||
|
| 1464 | uv.exe | 18496 | gone | gone |
|
||||||
|
| 36336 -> 22192 | python.exe (gremlins.py, 2 procs) | 1464 / 36336 | gone | gone |
|
||||||
|
| 19200 | claude.exe (gremlin, = child_pid in j2.json) | 22192 | gone | gone |
|
||||||
|
| 19580 -> 35212 | bash.exe (gremlin's Bash tool wrappers, 35212 ran the loop) | 19200 / 19580 | gone | gone |
|
||||||
|
| 25392 | conhost.exe | 35212 | gone | gone |
|
||||||
|
| sleep.exe (transient, `sleep 2`, MSYS-forked parent) | - | - | none found | none found |
|
||||||
|
|
||||||
|
No `sleep.exe` and no process with the gremlin's command line existed at either check. Nothing to clean up; no kill issued by me.
|
||||||
|
|
||||||
|
## State after the stop (`run-gremlins/`)
|
||||||
|
- `jobs/j2.json`: `status: running`, `ended: null`, `child_pid: 19200`, no note, no cost. Matches the documented hard-stop behaviour.
|
||||||
|
- `ledger.jsonl`: 2 lines (b1-train, j1). No j2 line. Matches the documented behaviour.
|
||||||
|
- `notes/`: only j1.md; the gremlin wrote no note.
|
||||||
|
|
||||||
|
## Cost
|
||||||
|
About $0.008 total (train 0.0042, j1 0.0019, j2 unrecorded, estimated <= 0.002).
|
||||||
|
|
||||||
|
## Verdict
|
||||||
|
B4 ticked for the claude process and all bash/python/uv wrappers: TaskStop killed the whole tree on Windows Git Bash. Not exercised: the spec §7 orphan case, a long single child (the loop's `sleep 2` children were too short-lived and the loop's bash died with the tree); a `sleep 300` brief is refused by the gremlin's own harness, so that case needs a different long command (for example `python -c "import time; time.sleep(300)"`).
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Guidance pass C: steering sentences
|
||||||
|
|
||||||
|
- **Date**: Sat Oct 17 00:24:15 WEDT 2026
|
||||||
|
- **Model**: claude-opus-5-5
|
||||||
|
- **Scope**: handoff [part C](../plans/2026-10-17-00-spire-guidance-pass-handoff.md), audit §4, framing from the brainstorm's "Steering sentences cut both ways"
|
||||||
|
- **Commit**: 46dbc86 (skill and agent text). Line numbers are after that commit. Paths are relative to `plugins/spire/`.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
| file:line | before | after | counterweight |
|
||||||
|
|---|---|---|---|
|
||||||
|
| agents/reviewer.md:22 | "Answer **every** deviation and flag … one by one" | "Read every flag …; answer one … only where it changes a finding or a verdict" | every flag is still read |
|
||||||
|
| agents/reviewer.md:23 | "Hunt **weakened checks** … tests that cannot fail" | "Check the phase's diff for weakened checks (… deleted tests) …; each one you find is a finding" | the check stays mandatory; its scope is the diff |
|
||||||
|
| agents/reviewer.md:24 | "List what was built that the plan did not ask for. On record only" | short "Size and unrequested surface" section, one line each; "You list; Igor and the user decide" | an unplanned addition may be good; the reviewer never removes |
|
||||||
|
| agents/reviewer.md:27 | "Grade findings Critical, Important or Minor …" | "Findings come first … Name the gates and tests you ran in one line; do not list what you checked and found fine" | evidence of what ran stays |
|
||||||
|
| agents/reviewer.md:38 | "and the unplanned additions" | "and the size and unrequested-surface lines" | (follows :24) |
|
||||||
|
| skills/implementation/SKILL.md:54 | "answers every deviation and flag … one by one. It looks specifically for weakened checks" | "reads every flag …, answering one only where it changes a finding or a verdict. In the phase's diff it looks for …" | same as reviewer :22–23 |
|
||||||
|
| skills/implementation/SKILL.md:55 | "It lists what was built that the plan did not ask for" | "short size and unrequested surface section … The reviewer lists; Igor and the user decide" | same as reviewer :24 |
|
||||||
|
| skills/implementation/SKILL.md:26 | "consumers of changed semantics … (… callers in other crates)" | "+ every direct reader or caller of what the change touches, and further only where the changed meaning is passed on" | every direct consumer still covered |
|
||||||
|
| skills/implementation/SKILL.md:34 | "A plan holds decisions, contracts, invariants and the scope fence" | "+ the code structure … (… the main signatures)" | code still only where its form is the decision |
|
||||||
|
| skills/implementation/SKILL.md:41 | (missing: tests per block) | "a test for each behaviour and failure path the plan names, not one per branch, and never cut a test a plan box needs to save size" | named failure paths get tests; size never cuts one |
|
||||||
|
| skills/implementation/SKILL.md:62 | "If you cannot write the failing test, keep investigating" | "investigate further; if it still will not reproduce …, fix on the evidence you have and say so in the handoff note" | still investigates; the gap is recorded |
|
||||||
|
| skills/implementation/SKILL.md:63 | "Explore before you focus. Look one or two layers up …" | "… when the cause is not plain: … and stop exploring once you can name the cause" | exploring stays the default for unclear bugs |
|
||||||
|
| skills/implementation/references/run-log.md:34 | (no length expectation) | "A few lines per block: findings, not narration. 'none' is the normal answer …" | "a real deviation or doubt is never left out" |
|
||||||
|
| run-log.md:41 | "Done: … in a few lines" | "in one or two lines" | (inside the :34 rule) |
|
||||||
|
| run-log.md:42 | "Deviations from plan: <what, and why>" | "+ including size well over the plan's estimate" | size budget gets explained, not obeyed |
|
||||||
|
| run-log.md:43 | "Flagged for review: <anything the reviewer should look at …>" | "<a point you are unsure of …> — or 'none'" | an unsure point is still flagged |
|
||||||
|
| run-log.md:56 | "Flags for the reviewer: every deviation and every … line above, one per bullet" | "the deviations and flags from the block notes above, one line each … or 'none'" | nothing from the notes is dropped |
|
||||||
|
| run-log.md:57 | "Not run / untested: <anything the tests do not cover>" | "<behaviour the plan names that no test or gate ran> — or 'none'" | named behaviour gaps still listed |
|
||||||
|
| agents/attacker.md:23 | "Consumers of changed semantics …: other readers, stats, migrations, callers …" | "every direct reader or caller of what the change touches (…), and further only where the changed meaning is passed on" | every direct consumer still covered |
|
||||||
|
| agents/attacker.md:25 | "Missing function: …, error handling, security" | "something a goal box needs that the plan does not deliver, … or the error handling and security that box implies" | error handling and security stay in scope where a box implies them |
|
||||||
|
| agents/attacker.md:26 | (new) | "A function no box needs is not missing: propose it under the open decisions with a one-line reason" | proposed, not silently dropped |
|
||||||
|
| agents/attacker.md:34 | "Scope cut back to the goal." | "… each block traces to a box, and cutting never removes a failure path or a test a box names" | cutting is bounded |
|
||||||
|
| agents/planner.md:23 | (new) ecosystem inventory | "what the harness, CLI output, the stdlib and the project's existing tools already provide … build only what the boxes need and the inventory does not cover" | "a one-line reason where a listed tool falls short" |
|
||||||
|
| agents/planner.md:24 | (new) code structure | "modules, the data model, the main interfaces (signatures …, no bodies) and where the special cases live" | "no more than the boxes need" |
|
||||||
|
| agents/planner.md:25 | (new) size estimate | "per module, in lines: a budget the builder explains deviations from in the run log" | "not a cap that justifies dropping a failure path or a test" |
|
||||||
|
| agents/planner.md:29 | "Phases that each end in a testable state; … steps with a completion criterion each" | "+ happy path end to end before the failure paths the boxes name (order, not priority); a step no box needs carries a one-line reason" | failure paths still built; extra steps allowed with a reason |
|
||||||
|
| agents/planner.md:32 | "(a schema, a wire format, a state machine)" | "+ the signatures in the code structure" | bodies still left to the builder |
|
||||||
|
| agents/athanor.md:32 | (missing: digest check) | "If you write a contract digest …, check it once against the plan and the code before any block builds on it" | "a gap that needs a design decision goes back to Igor, not into the digest" |
|
||||||
|
| agents/athanor.md:33 | "A mechanical or distant block goes to a fresh Agent-tool agent" | "+ on a cheaper model (Sonnet, or Haiku for a scripted transform)" | "unless the block needs design judgment" |
|
||||||
|
| agents/athanor.md:39 | "read the fix's diff for loosened assertions or deleted checks before you report green" | "report green only from your own test run, and if a fix changed a test, name it in the phase close" | changed tests reach the reviewer |
|
||||||
|
| agents/athanor.md:40 | "phase close with every deviation and flag listed for the reviewer" | "One short handoff note per block …; 'none' is a normal answer" | "a real deviation is never left out" |
|
||||||
|
| agents/athanor.md:45 | "When Igor resumes you for the next phase, start again at intake" | "The next phase goes to a fresh Athanor, which starts at intake from the run log and trunk notes you leave behind" | state carries over through the files |
|
||||||
|
| agents/athanor.md:52 | (missing: time budget) | "Every block brief carries a time budget" | "never a skipped gate or test" |
|
||||||
|
| agents/athanor.md:59 | (missing: re-plan) | "A broken premise stops the phase … hand back for a re-plan instead of documenting it" | a detail-level surprise stays a default plus flag |
|
||||||
|
| agents/athanor.md:75 | "room left for the fix pass and the next phase" | "room left for the fix pass" | (follows :45) |
|
||||||
|
| skills/igor/SKILL.md:61 | "**Best over fastest.** … finishing well, not finishing first" | "**Right over fast.** … finishing well means what the goal asks for, built and checked, not more" | "built and checked" |
|
||||||
|
| skills/igor/SKILL.md:90 | (missing: time budget) | "Every Athanor brief carries a time budget for the phase: an estimate it reports against" | "never a reason to skip a gate or a test" |
|
||||||
|
| skills/igor/SKILL.md:98 | "it answers every handoff flag, hunts weakened checks …" | "reads every handoff flag and answers one only where it changes a verdict, checks the phase's diff …, lists size and unrequested surface for you and the user to decide" | same as reviewer |
|
||||||
|
| skills/igor/SKILL.md:105 | "Approach is wrong … back to design" | "+ includes a preflight or block that removed a premise the design rests on: re-plan instead of documenting it" | "a result that only shifts a detail stays a flag" |
|
||||||
|
| skills/igor/SKILL.md:111 | "Between phases, and for the fix pass, Igor resumes the same Athanor" | "For the fix pass, … resumes the same Athanor … Each new phase gets a fresh Athanor started from the run log and trunk notes" | the fix pass keeps the builder's context |
|
||||||
|
| skills/research-tree/SKILL.md:41 | "List every sub-topic …, even ones that feel redundant" | "List the sub-topics the question needs answered, including ones you are unsure about; merge or drop the redundant ones" | unsure topics still listed |
|
||||||
|
|
||||||
|
## §4 items left alone
|
||||||
|
|
||||||
|
- igor SKILL:92 stamp-check and its 11 repeats: part D.
|
||||||
|
- igor SKILL:186 wrap-up (adept handoffs, accretion, graduation): runs once per session and is Igor's guard against forgetting; part D can trim the wording.
|
||||||
|
- adept.md:61/81 handoff refresh after state-changing consultations: capped at ~40 lines, a few lines per refresh, and it is what survives an abrupt end.
|
||||||
|
- adept "Don't guess" search dispatches: cheap, and it prevents stale priors.
|
||||||
|
- Missing "smallest change that meets the goal" / "prefer deleting to adding": deliberately not added. The brainstorm warns that these fire the other way. Tracing to boxes plus the size budget covers them.
|
||||||
|
- Missing size caps for plans, build plans, journals: not added as caps. The per-module size estimate, short handoff notes and a short review section are the budget instead.
|
||||||
|
- implementation:58 and igor:109 "extra reviews need a stated reason": already balanced.
|
||||||
|
- run-log.md trunk notes "every consumer of a changed semantic": already bounded by "a page".
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Guidance pass D: size and duplication
|
||||||
|
|
||||||
|
- **Date**: Sat Oct 17 00:32:32 WEDT 2026
|
||||||
|
- **Model**: claude-opus-5-5
|
||||||
|
- **Scope**: handoff [part D](../plans/2026-10-17-00-spire-guidance-pass-handoff.md), decision 4 (audit option I-2), audit §1/§2/§3/§5
|
||||||
|
- **Commits**: 6e8fd92 (D1 agents), 2c311f8 (D2 harness homes), fc6a543 (D3 Igor), fa80d26 (D4 class c/d). Paths below are relative to `plugins/spire/`.
|
||||||
|
|
||||||
|
## Bundle sizes (`wc -w`, audit §1 definitions, at 2e8cbf8 → now)
|
||||||
|
|
||||||
|
| Bundle | Before | After | Target | |
|
||||||
|
|---|---:|---:|---:|---|
|
||||||
|
| Igor boot (igor.md, SKILL, mindset, adepts, workpad, journal-template, project + project.md, repo CLAUDE.md) | 6384 | 4726 | ≈ 4000 | missed by ~700 |
|
||||||
|
| Athanor start (athanor.md, workpad, implementation, gremlins, spawning, run-log, project, CLAUDE.md) | 7241 | 6754 | none set | |
|
||||||
|
| Planner (planner.md, project, CLAUDE.md) | 4166 | 879 | 500–800 | ~80 over |
|
||||||
|
| Attacker | 4124 | 859 | 500–800 | ~60 over |
|
||||||
|
| Reviewer | 4058 | 793 | 500–800 | met |
|
||||||
|
|
||||||
|
Igor: workpad stays preloaded (1385 words after trims) and project + project.md + CLAUDE.md are 439, so the 4k target leaves ~1.6k for igor SKILL + mindset; they are now 2425 + 184, and what is left is mostly class a (cycle, decision tree, queuing, adepts, rules). Planner/attacker: 439 of each bundle is project.md + repo CLAUDE.md; the bodies are part C text.
|
||||||
|
|
||||||
|
## Rule → home
|
||||||
|
|
||||||
|
| Rule | Home | Points to it / keeps one line (agent follows it) | Dropped from |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Stamp the model id | `spawning-claude-code.md` rules of thumb | planner, attacker, reviewer (one line each, own output); run-log.md:9 (adds "unknown, not a guess"); implementation "Spawning" pointer; athanor Dispatching pointer | implementation:53, :68; athanor:50; model-tiers:39 |
|
||||||
|
| Check the stamp | igor SKILL `**Models.**` | — | model-tiers |
|
||||||
|
| Pinned → omit `model`, unpinned → alias, no Fable | `spawning-claude-code.md` | igor SKILL `**Models.**` (Igor dispatches); zathras:74 one line; athanor pointer | model-tiers:35–40, athanor:50 |
|
||||||
|
| Leaf briefs "do this yourself" | `spawning-claude-code.md` | igor Rules `**Harness.**`; zathras:74; athanor pointer; implementation pointer; model-tiers sub-delegation guard | planner, attacker, reviewer (no Agent tool); search.md paragraph |
|
||||||
|
| Igor delegates / work vs conversation | igor SKILL Core Directive | lifecycle step 2 "classify per the Core Directive"; zathras keeps its own (does not load igor) | Voice bullet, Role section, Mindset "Stay available" and "Do X means delegate X" (merged into Core Directive), mindset.md voice lines |
|
||||||
|
| Gate between blocks, tests once | implementation "Building a phase" | athanor steps 3–4 (its procedure); attacker one line (new, since it no longer loads implementation); igor stage (5) | — (init and the project template explain the config fields; kept) |
|
||||||
|
| Notifications = turn ending | `spawning-claude-code.md` | igor Rules `**Harness.**` | — |
|
||||||
|
| Delegation table | igor SKILL `## Delegation` | zathras:63 now points there; model-tiers.md keeps only the write-capability and sub-delegation guards | model-tiers table + rules of thumb |
|
||||||
|
| Fix pass / re-check | implementation "Phase review" | reviewer Re-check gets one line (it lost the preload) | — |
|
||||||
|
|
||||||
|
## Removed text by class (rough words)
|
||||||
|
|
||||||
|
- **Persona (≈ 650)**: igor Voice 300 → 81 (dropped "yeth, marthter", four example flourishes, furnace grammar rule, "Delegate whenever possible" bullet); "forge… let it cook" Athanor flourish; mindset.md "The enemy" (dup of SKILL intro), provenance line, "five voice lines… Protect them in any rewrite"; zathras "Not Zathras the great leader…" and four example lines; plugin CLAUDE.md "wizard's private workshop".
|
||||||
|
- **Class d (≈ 900)**: delegation repeats in igor (×5) and Role section; "184 of 184" history in igor's model rule; "It is what pays for dropping per-task review" (igor, implementation:30 paragraph); "Separation keeps review honest"; model-tiers duplicate table and rules (~520); two extra adept spawn templates (now one + two variant lines); "core problem this solves" (research); spawning:51 alias argument; Pinky aside in spawning:54 (record fact kept); models.md withdrawn 4.6/Opus-5 notes; leaf lines in planner/attacker/reviewer; search.md "You do not have the Agent tool…" and scout/researcher equivalents.
|
||||||
|
- **Class c (≈ 700)**: tool lists in search, scout, researcher; "Start narrow", "Read strategically", "Use Glob…"; "Synthesize, don't summarize", "clear headings", "Lead with the answer"; research WebFetch/WebSearch explanation; workpad textbook doc-kind distinctions (kept the routing rules), intro, lifecycles and "does not cover" compressed; research-tree topological-layering sentence; igor "Fearlessness means flagging misconceptions" (kept "emotional outbursts don't change your dedication" as **Steady**).
|
||||||
|
|
||||||
|
## Part C sentences moved
|
||||||
|
|
||||||
|
- igor SKILL stage (6) "reads every handoff flag and answers one only where it changes a verdict, checks the phase's diff for weakened checks and tests that cannot fail" → its home `agents/reviewer.md` (already there word for word). Igor keeps "lists size and unrequested surface for you and the user to decide" and a pointer. All other part C sentences are unchanged in place (grep-checked).
|
||||||
|
- `implementation:63` "Explore before you focus" is an audit class-c quote but part C rewrote it with a stopping rule; kept.
|
||||||
|
|
||||||
|
## Unreachable files (user decides)
|
||||||
|
|
||||||
|
- `skills/implementation/references/superpowers.md` (461 words, unlinked)
|
||||||
|
- `skills/igor/references/project.md` (351, blank template, unreachable via `spire:project`)
|
||||||
|
- `skills/igor/references/harness-notes.md` (107, moved-stub; still repeats leaf/notification rules)
|
||||||
|
|
||||||
|
## Unsure
|
||||||
|
|
||||||
|
- model-tiers sub-delegation guard: the old text said researcher "may have the Agent tool"; its frontmatter has none, so I listed it (and planner/attacker/reviewer) as safe leaves. A factual fix, not a new rule, but check it.
|
||||||
|
- Igor delegation home: the Core Directive now says it is the rule's home and nothing below overrides it, replacing "if any instruction below seems to conflict with delegation, delegation wins". Same meaning, shorter.
|
||||||
|
- The igor stage (6) move landed in D4 (fa80d26), not D3.
|
||||||
|
- `README.md:32` still says "Put it in the oven." (not loaded by agents; left).
|
||||||
|
- The Athanor bundle was not a target; only its stamp/leaf/model lines became one pointer.
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Guidance pass review (parts A–D)
|
||||||
|
|
||||||
|
- **Date**: Sat Oct 17 00:37:25 WEDT 2026
|
||||||
|
- **Model**: claude-opus-5-5
|
||||||
|
- **Scope**: `git diff d605daa HEAD -- plugins/ .claude/` (22 files), against the [handoff](../plans/2026-10-17-00-spire-guidance-pass-handoff.md)'s three review questions. Paths are relative to `plugins/spire/`.
|
||||||
|
- **Checks run**: `wc -w` on every bundle file; read the full diff and the current planner/attacker/reviewer/athanor/igor/implementation/workpad/zathras text; grepped every part C sentence, every audit class-e item, "fork", the old handoff fields; resolved every `skills:` entry and every file path in added lines.
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
No Critical findings.
|
||||||
|
|
||||||
|
**Important**
|
||||||
|
|
||||||
|
1. `agents/attacker.md:28-34`: the attacker no longer preloads implementation, whose :32 said a plan holds "the code structure … the main signatures". The Reshape list never says to carry the planner's code structure and size estimate into the build plan. Its :32 "code only where its exact form is the decision" leaves out the signatures exception, so the attacker may strip them. The reviewer (`reviewer.md:22`) and the run log (`run-log.md:42`) then measure size against an estimate that may not exist in the build plan. **Fix:** add a Reshape bullet: "carry over the plan's code structure (signatures included) and per-module size estimate, adjusted where the attack changes them."
|
||||||
|
2. `skills/gremlins/preamble.md:16,18`: the gremlin handoff template still has the pre-C fields "Done: in a few lines" and "Flagged for review: <anything the reviewer should look at>". It has no "findings, not narration" and no "'none' is the normal answer". Complex blocks, the main build path, never get the part C rewrite of `run-log.md:34,41-43`. **Fix:** copy the run-log.md handoff note (the :34 sentence plus the :41-43 fields) into the preamble.
|
||||||
|
3. `agents/reviewer.md:18-23`: the counterweight to implementation:39 ("a test for each behaviour and failure path the plan names … never cut a test a plan box needs") has no checker. The reviewer lost that text with the implementation preload. Its diff check catches weakened or deleted tests, but not a named failure path that never got a test. **Fix:** add a Review bullet: "a behaviour or failure path the plan names with no test is a finding."
|
||||||
|
|
||||||
|
**Minor**
|
||||||
|
|
||||||
|
4. `skills/implementation/references/spawning-claude-code.md:17`: "Igor may `SendMessage` … the Athanor between phases" contradicts part C (`igor/SKILL.md:90`, `athanor.md:45`: a fresh Athanor per phase), and this file is now the declared home of harness rules. **Fix:** "(the Athanor for the fix pass, an adept)".
|
||||||
|
5. `spawning-claude-code.md:62,64`: the Fork table still says "the Athanor as trunk can fork it" and "check … before relying on trunk and forks". These are descriptive, not an instruction, but they point at the dead path. **Fix:** add a row "not used by Spire since 2026-10-16; trunk + gremlins replaces it", or drop the trunk mention.
|
||||||
|
6. `agents/attacker.md:31`: the per-block owner model comes from "defaults from `spire:project` `## Build`". Reliquary's `## Build` sets none, and the attacker no longer sees implementation:47 (gremlin for complex blocks, fresh Sonnet/Haiku for mechanical ones). The Athanor re-routes at :33, so the effect is small. **Fix:** add one clause naming the two owner kinds.
|
||||||
|
7. `skills/zathras/SKILL.md:56,63`: it points to `skills/igor/SKILL.md`, which Zathras never loads. Its own table has no planner/attacker/reviewer rows, yet :63 assumes "an attacked, reshaped plan". The no-Fable rule is also absent at :67. This is not a regression: the earlier pointer went to the equally unloaded model-tiers.md. **Fix:** add the three pinned cycle agents to Zathras's table, and add "never Fable" to :67.
|
||||||
|
8. `agents/athanor.md:39`: "if a fix changed a test, name it". A test changed by a child inside a block, not in a fallout fix, is not covered. The reviewer's whole-diff check catches it. **Fix:** "if any block or fix changed or deleted an existing test, name it in the phase close."
|
||||||
|
9. `agents/reviewer.md:20`: "Read every flag" does not require checking it, so a flagged doubt can be read and left uninvestigated. **Fix:** "Check every flag …; report one only where it changes a finding or a verdict."
|
||||||
|
|
||||||
|
## 1. Bundle sizes
|
||||||
|
|
||||||
|
Confirmed exactly: Igor 4726, Athanor 6754, planner 879, attacker 859, reviewer 793.
|
||||||
|
- **Igor: missed by ~730.** Fixed parts: workpad 1385 (kept preloaded per decision 4), project + project.md + CLAUDE.md 439, igor.md + adepts + journal-template 293. That leaves igor SKILL at 2425 and mindset at 184. The largest remaining blocks are the Development Cycle with its decision tree and queuing (igor SKILL:71-92, ~600), workpad Ticket context (:46-66, ~350) and Adepts (igor:94-110, ~270). All of these are class a, so the remaining gap is a scope choice (workpad preload, cycle detail), not filler.
|
||||||
|
- **Planner +79, attacker +59: met in substance.** 439 of each bundle is fixed project text, and the bodies are 382 and 367 words without frontmatter. The overage is part C's added bullets (inventory, structure, size) plus D's cadence line in the attacker. Reviewer met.
|
||||||
|
- Athanor: no target. Implementation SKILL grew 1395 → 1446 and athanor.md 980 → 1156 (part C and gremlins).
|
||||||
|
|
||||||
|
## 2. Rules that lost their only home
|
||||||
|
|
||||||
|
None lost outright. Every §3 rule still has its home stating it, and each dispatcher (Igor, Athanor via the mandated spawning read, Zathras) still loads a file stating the stamp, pin and leaf rules. Planner, attacker and reviewer each keep: output path from the brief (Igor:77 names `plans/`/`reports/`, and Igor loads workpad), stamp, separation, Critical/Important/Minor, fix pass and re-check (reviewer:29), gate/test cadence (attacker:31) and the full attack checklist (attacker:19-24). Their leaf lines went, but none of the three has the Agent tool. What they lost and still need is findings 1, 3 and 6. All part B fixes and all part C sentences are still present, the reviewer stage-6 sentence now living in `reviewer.md`. The exception is the gremlin copy of the handoff note (finding 2), which part C never reached.
|
||||||
|
|
||||||
|
## 3. Over-steering
|
||||||
|
|
||||||
|
No new sentence licenses under-building on its own. Each carries its counterweight, and the size estimate is a budget, not a cap. Verdicts on the C author's three:
|
||||||
|
- **"a test for each behaviour and failure path the plan names, not one per branch"**: keep. It is safe only if the plan names failure paths (planner:27 requires that) and someone checks coverage. The check is missing after D (finding 3).
|
||||||
|
- **Athanor reports green only from its own run and names changed tests**: keep. Weakened-check detection now rests on the reviewer's diff check, which is mandatory and covers the whole phase. Widen the naming to child changes (finding 8).
|
||||||
|
- **Reviewer answers a flag only where it changes a verdict**: keep. The residual risk is that "read" can mean skimming a doubt the builder raised; change it to "check" (finding 9).
|
||||||
|
|
||||||
|
D trims that changed meaning were checked: implementation's "what pays for dropping per-task review", the "Do this yourself" lines in tool-less agents, and the researcher/search/scout prohibitions now enforced by their tool lists. None weakens a test, a review or error handling.
|
||||||
|
|
||||||
|
Part A done-criterion: met. No Spire text tells an agent to fork itself through the Agent tool (only the spawning claims table, finding 5). The gremlins sequence is `athanor.md:33-37` (5 lines), and `spire:gremlins` is preloaded. All `skills:` entries and the referenced paths resolve.
|
||||||
|
|
||||||
|
## Fix pass
|
||||||
|
|
||||||
|
Commits: fixes `0f2aee6`, version bump `6ab4dd0` (Spire 0.3.0 in `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json`; no CHANGELOG exists, the marketplace manifest carries no version).
|
||||||
|
|
||||||
|
1. Fixed: attacker Reshape bullet carries over code structure (signatures) and size estimate.
|
||||||
|
2. Fixed: gremlin `preamble.md` handoff note now matches `run-log.md` (findings not narration, "none" is normal, Done/Deviations/Flagged fields).
|
||||||
|
3. Fixed: reviewer bullet "a behaviour or failure path the plan names with no test is a finding".
|
||||||
|
4. Fixed: `spawning-claude-code.md` rule of thumb now says the Athanor for the fix pass, an adept.
|
||||||
|
5. Fixed: Fork table notes Spire has not used the Agent-tool fork since 2026-10-16 (trunk + gremlins replaces it); trunk mention dropped from the preflight row.
|
||||||
|
6. Fixed: attacker owner clause names the two owner kinds (gremlin for complex, fresh Sonnet or Haiku for mechanical).
|
||||||
|
7. Fixed: Zathras table gains a planner/attacker/reviewer row; "never Fable unless the user asks" added to the model rule.
|
||||||
|
8. Fixed: Athanor names any test a block or fix changed or deleted.
|
||||||
|
9. Fixed: reviewer "Check every flag"; report one only where it changes a finding or a verdict.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Gremlins post-merge live checks (B7, B4, B8)
|
||||||
|
|
||||||
|
Date: Sat 2026-10-17 00:58-01:05 (local). Run by claude-sonnet-5-5. Gremlin model: claude-haiku-5-5 (effort low). Binary 2.1.299, Windows 10 Git Bash. `main` @ e6843ca (Spire 0.3.0). Scratch: throwaway git repo + run log in the session scratchpad `pm/`. `G` = `uv run --script plugins/spire/skills/gremlins/gremlins.py`.
|
||||||
|
|
||||||
|
## 1. B7 `rebase` live
|
||||||
|
Commands: `G init --run run.md --model claude-haiku-5-5 --effort low --cwd repo`; `G train --base b1`; commit `add sub` in repo (4a14b1b -> 93e419d); `G rebase --base b1 --brief rebase.md`; `G spawn --job s1`, then `--job s2`.
|
||||||
|
|
||||||
|
| Call | status | session | cache | cost | cumulative | delta |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| b1-train | ok | 57dde9a1 | - | 0.003195 | 0.003195 | 0.003195 |
|
||||||
|
| b1-rebase1 | ok | 57dde9a1 (unchanged) | hit | 0.000816 | 0.004011 | 0.000816 |
|
||||||
|
| s1 (fork of rebased b1) | ok | c7997b70 | hit | 0.001339 | 0.005350 | 0.001339 |
|
||||||
|
| s2 (fork of rebased b1) | ok | 6eb566c4 | hit | 0.001437 | 0.005448 | 0.001437 |
|
||||||
|
|
||||||
|
- The plain resume keeps the same session id; `bases/b1.json` got `commit` 93e419d, one `rebases[]` entry (from_commit 4a14b1b), `cost_cumulative_usd` 0.00401097.
|
||||||
|
- The rebase answered from the new `calc.py` (saw `sub` and the commit): the delta header worked.
|
||||||
|
- Cost delta adds up: 0.003195 + 0.000816 = 0.004011 = the base's stored cumulative (0.00401097, the sum of its `modelUsage` costUSD), so the basis after a plain resume is right (open assumption closed). Forks use the base's 0.004011 as their basis (s2 is not added on top of s1), as designed.
|
||||||
|
- Cost: $0.0068. **Verdict B7: ticked.**
|
||||||
|
|
||||||
|
## 2. B4 orphan case (long single child)
|
||||||
|
- First try (job `long`, brief `python -c "import time; time.sleep(300)"`): ended ok in 10 s, gremlin's shell has no `python` (exit 127, `python: command not found`). Not usable.
|
||||||
|
- Retry with the absolute interpreter (`.../uv/python/cpython-3.13.1-windows-x86_64-none/python.exe -c "import time; time.sleep(300)"`), job `long2` then `long3`, each `run_in_background: true`. Process table (`Win32_Process`) snapshotted before the spawn and at ~35 s; the tree below is from `long3`, the live sleeper is the leaf. `TaskStop` at 01:02:19 returned "Successfully stopped". `long2` was stopped the same way; its ~5 s reading was lost to a scripting error of mine (only ~35 s read: all gone).
|
||||||
|
|
||||||
|
| PID | name | role | ~5 s after stop | ~30 s after stop |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 6168 / 12152 / 37052 | bash.exe | harness wrappers of the spawn call | gone | gone |
|
||||||
|
| 31532 | uv.exe | `uv run --script` | gone | gone |
|
||||||
|
| 38504 -> 38140 | python.exe x2 | gremlins.py | gone | gone |
|
||||||
|
| 37772 | claude.exe | gremlin (= child_pid) | gone | gone |
|
||||||
|
| 7216 -> 12540 -> 28456 | bash.exe x3 | gremlin's Bash tool wrappers | gone | gone |
|
||||||
|
| 12920 | conhost.exe | console of the Bash tool | gone | gone |
|
||||||
|
| 38816 | python.exe | the 300 s sleeper (in flight) | gone | gone |
|
||||||
|
|
||||||
|
- No process survived; no kill issued by me. The sleeper was alive at ~35 s after spawn and gone 5 s after the stop.
|
||||||
|
- State after the stop: `jobs/long3.json` `status: running`, `ended: null`; ledger has no line for `long2` or `long3` (5 lines: train, rebase1, s1, s2, long). Matches SKILL.md "Stopping a gremlin".
|
||||||
|
- The spec §7 "orphan can survive" case did **not** occur on Windows Git Bash: SKILL.md's "known leftover" sentence is not reproduced here (still possible on other platforms).
|
||||||
|
- Cost: ~$0.0045 (`long` 0.001506; `long2`/`long3` unrecorded, est. <= 0.0015 each). **Verdict B4: ticked** (Windows Git Bash; the in-flight child dies with the tree).
|
||||||
|
|
||||||
|
## 3. B8 non-Windows
|
||||||
|
- `wsl -l -v`: Ubuntu-20.04 (WSL2, Python 3.10.12, uv present, git present); no `claude` binary and no `~/.claude` in it.
|
||||||
|
- `cd plugins/spire/skills/gremlins && uv run --no-project --python 3.12 python -m unittest discover -s tests` in WSL (`uname`: Linux 6.18 x86_64): **24 tests, OK, 5.6 s** (same count as the Windows gate). `git status` clean afterwards (`PYTHONDONTWRITEBYTECODE=1`).
|
||||||
|
- Live `train` + `spawn` in WSL: **not run**. Claude Code is not installed or signed in inside WSL; installing it is setup, which the brief forbade. Running the Windows `claude.exe` via interop would not test Linux.
|
||||||
|
- Cost: $0. **Verdict B8: partly** (unit tests on Linux pass; the live Linux run is still open: needs `claude` installed and logged in inside WSL).
|
||||||
|
|
||||||
|
## Totals
|
||||||
|
Spend about $0.011 (limit $1). Repo untouched except this report. Scratch repo and run state left in the scratchpad `pm/`. No processes of mine left running.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "spire",
|
"name": "spire",
|
||||||
"version": "0.2.2",
|
"version": "0.3.0",
|
||||||
"description": "Spire — an agent orchestration system for structured development. Session coordination (Igor), domain knowledge (adepts), dispatching (athanor), workpad, research, and implementation governance. Knowledge navigation via the separate tome plugin (opt-in).",
|
"description": "Spire — an agent orchestration system for structured development. Session coordination (Igor), domain knowledge (adepts), dispatching (athanor), workpad, research, and implementation governance. Knowledge navigation via the separate tome plugin (opt-in).",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Gabor Körber",
|
"name": "Gabor Körber",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "spire",
|
"name": "spire",
|
||||||
"version": "0.2.2",
|
"version": "0.3.0",
|
||||||
"description": "Spire — an agent orchestration system for structured development. Session coordination (Igor), domain knowledge (adepts), dispatching (athanor), workpad, research, and implementation governance. Knowledge navigation via the separate tome plugin (opt-in).",
|
"description": "Spire — an agent orchestration system for structured development. Session coordination (Igor), domain knowledge (adepts), dispatching (athanor), workpad, research, and implementation governance. Knowledge navigation via the separate tome plugin (opt-in).",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Gabor Körber",
|
"name": "Gabor Körber",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Spire is an agent orchestration plugin — a wizard's private workshop where knowledge accumulates, work gets dispatched, and the system maintains itself. See README.md for component overview.
|
Spire is an agent orchestration plugin: work gets dispatched, knowledge accumulates, and the system maintains itself. See README.md for component overview.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ skills:
|
|||||||
- spire:project
|
- spire:project
|
||||||
- spire:workpad
|
- spire:workpad
|
||||||
- spire:implementation
|
- spire:implementation
|
||||||
|
- spire:gremlins
|
||||||
---
|
---
|
||||||
|
|
||||||
You are the **Athanor** — the alchemist's slow furnace. You ARE the oven; plans go into you and forged implementations come out. Igor (or the user) loads you with a build plan, closes the door, and waits. You do not talk to the user, you do not surface partial results, you do not ask mid-run; if the brief is unworkable, say so once at the end. You run your own subagents via the Agent (Task) tool. "Fire up the Athanor" and "into the Athanor with it" mean you.
|
You are the **Athanor** — the alchemist's slow furnace. You ARE the oven; plans go into you and forged implementations come out. Igor (or the user) loads you with a build plan, closes the door, and waits. You do not talk to the user, you do not surface partial results, you do not ask mid-run; if the brief is unworkable, say so once at the end. You run your own subagents via the Agent (Task) tool. "Fire up the Athanor" and "into the Athanor with it" mean you.
|
||||||
@@ -28,28 +29,33 @@ The `spire:implementation` skill is how you work. Its references hold the run-lo
|
|||||||
|
|
||||||
The plan you receive has already been attacked and reshaped into phases and blocks. Each turn you build one phase and hand back.
|
The plan you receive has already been attacked and reshaped into phases and blocks. Each turn you build one phase and hand back.
|
||||||
|
|
||||||
1. **Intake.** Read the build plan, the run log so far, and the code the phase touches. That reading is your trunk. Check you are on the branch the brief names; stop if not. Write short trunk notes next to the run log so fresh agents, and a successor Athanor, can start from them.
|
1. **Intake.** Read the build plan, the run log so far, and the code the phase touches. That reading is your trunk. Check you are on the branch the brief names; stop if not. Write short trunk notes next to the run log so fresh agents, and a successor Athanor, can start from them. If you write a contract digest for points the plan left open, check it once against the plan and the code before any block builds on it; a gap that needs a design decision goes back to Igor, not into the digest.
|
||||||
2. **Build the blocks** in the plan's order, in the foreground. Each block goes to its owner. A complex block in the area you just read can go to a fork of yourself (it inherits your model and, assumed, your context). A mechanical or distant block goes to a fresh agent that reads the trunk notes. Fork behaviour is partly unverified; see the spawning reference.
|
2. **Build the blocks** in the plan's order, in the foreground. Each block goes to its owner. A mechanical or distant block goes to a fresh Agent-tool agent that reads the trunk notes, on a cheaper model (Sonnet, or Haiku for a scripted transform) unless the block needs design judgment. A complex block in the area you read goes to a gremlin (`spire:gremlins` has the commands):
|
||||||
|
- Train one base on the plan, the design and the trunk (the code the build touches).
|
||||||
|
- Start one gremlin per complex block with `spawn`, as a Bash call with `run_in_background: true`. Read its result from the completion notice.
|
||||||
|
- Stop a gremlin with `TaskStop` on its background Bash call.
|
||||||
|
- Each brief says whether the gremlin commits and which paths it may touch.
|
||||||
3. **Gate between blocks.** The cheap check the plan or project config names (compile, typecheck). Not a review.
|
3. **Gate between blocks.** The cheap check the plan or project config names (compile, typecheck). Not a review.
|
||||||
4. **Tests once**, at phase end. Fix the fallout in that last block. A child's "tests pass" is a claim: read the fix's diff for loosened assertions or deleted checks before you report green.
|
4. **Tests once**, at phase end. Fix the fallout in that last block. A child's "tests pass" is a claim: report green only from your own test run, and if any block or fix changed or deleted an existing test, name it in the phase close and leave judging it to the reviewer.
|
||||||
5. **Run log.** One handoff note per block, then the phase close with every deviation and flag listed for the reviewer.
|
5. **Run log.** One short handoff note per block, then the phase close with the deviations and flags for the reviewer; "none" is a normal answer, and a real deviation is never left out.
|
||||||
6. **Hand back.** Igor dispatches the phase review.
|
6. **Hand back.** Igor dispatches the phase review.
|
||||||
|
|
||||||
The plan sets block size and owner model as defaults. You may deviate (split a block, change an owner, add a check) when the work calls for it; log the reason in the run log.
|
The plan sets block size and owner model as defaults. You may deviate (split a block, change an owner, add a check) when the work calls for it; log the reason in the run log.
|
||||||
|
|
||||||
When Igor resumes you with review findings: one fix pass over all of them, commits, a note in the run log, hand back. When Igor resumes you for the next phase, start again at intake for that phase.
|
When Igor resumes you with review findings: one fix pass over all of them, commits, a note in the run log, hand back. The next phase goes to a fresh Athanor, which starts at intake from the run log and trunk notes you leave behind.
|
||||||
|
|
||||||
## Dispatching
|
## Dispatching
|
||||||
|
|
||||||
- Sequential work runs in the foreground. Do not resume your children with `SendMessage`; their completion would go to the session root and you would stall. Dispatch a fresh foreground agent instead.
|
- Sequential work runs in the foreground. Do not resume your children with `SendMessage`; their completion would go to the session root and you would stall. Dispatch a fresh foreground agent instead.
|
||||||
- Pinned agents: omit `model`. Unpinned agents: pass the owner's alias. Every agent stamps its model id in its handoff note.
|
- Model pins, model-id stamps and leaf briefs follow the rules of thumb in `spawning-claude-code.md`; read them before your first dispatch.
|
||||||
- Leaf briefs say "do this yourself; do not dispatch further agents."
|
- Every block brief carries a time budget; an overrun gets a line in the handoff note, never a skipped gate or test.
|
||||||
- If a plugin agent type is missing, use `general-purpose` with the agent's body in the brief.
|
- If a plugin agent type is missing, use `general-purpose` with the agent's body in the brief.
|
||||||
|
|
||||||
## Keepers
|
## Keepers
|
||||||
|
|
||||||
- **You do not plan, attack plans, or review your own output.** Plans come in finished. Phase review is done by a fresh reviewer that Igor dispatches.
|
- **You do not plan, attack plans, or review your own output.** Plans come in finished. Phase review is done by a fresh reviewer that Igor dispatches.
|
||||||
- **Closed door.** Undecided points get the conservative default, flagged in the handoff note. Never block on the user.
|
- **Closed door.** Undecided points get the conservative default, flagged in the handoff note. Never block on the user.
|
||||||
|
- **A broken premise stops the phase.** When a preflight or a block shows that a premise the design rests on is false, hand back for a re-plan instead of documenting it and building on; a result that only shifts a detail gets the conservative default and a flag.
|
||||||
- **Goals are read-only.** Never write, modify, or delete anything in the workpad `goals/` folder — only the user and Igor author goals. Your outputs go to `reports/`, `research/`, `plans/`.
|
- **Goals are read-only.** Never write, modify, or delete anything in the workpad `goals/` folder — only the user and Igor author goals. Your outputs go to `reports/`, `research/`, `plans/`.
|
||||||
- **Agents write their own reports.** Every subagent gets an explicit output file path in the workpad. You read the finished files; you are not a copy-paste bottleneck.
|
- **Agents write their own reports.** Every subagent gets an explicit output file path in the workpad. You read the finished files; you are not a copy-paste bottleneck.
|
||||||
- **Stay in your lane.** Work only within the brief's scope and the branch or worktree the brief and project config name. Stage per project config (default: explicit paths). Never open pull requests; push if instructed, never force-push.
|
- **Stay in your lane.** Work only within the brief's scope and the branch or worktree the brief and project config name. Stage per project config (default: explicit paths). Never open pull requests; push if instructed, never force-push.
|
||||||
@@ -57,7 +63,7 @@ When Igor resumes you with review findings: one fix pass over all of them, commi
|
|||||||
|
|
||||||
## Tools, not the loop
|
## Tools, not the loop
|
||||||
|
|
||||||
Use what the harness and the project give you: a fail-first test inside a block, a look one layer up before fixing a stubborn failure, evidence before you claim a gate or test result, parallel agents only for genuinely independent blocks. Superpowers is not part of the loop; if a brief asks for it, `spire:implementation` `references/superpowers.md` says which of its rules the lean rules override.
|
Use what the harness and the project give you: a fail-first test inside a block, a look one layer up before fixing a stubborn failure, evidence before you claim a gate or test result, parallel agents only for genuinely independent blocks.
|
||||||
|
|
||||||
## Non-build briefs
|
## Non-build briefs
|
||||||
|
|
||||||
@@ -65,4 +71,4 @@ Research cascades and broad audits are allowed: decompose the brief, fan out, sy
|
|||||||
|
|
||||||
## Deliverable
|
## Deliverable
|
||||||
|
|
||||||
Your final message is a report to your dispatcher, not the user: phase built or not, run log and trunk notes paths, commits, gate and test results, the flags for the reviewer, deviations from the plan, and whether you have room left for the fix pass and the next phase.
|
Your final message is a report to your dispatcher, not the user: phase built or not, run log and trunk notes paths, commits, gate and test results, the flags for the reviewer, deviations from the plan, and whether you have room left for the fix pass.
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ model: claude-opus-5-5[1m]
|
|||||||
tools: Bash, Glob, Grep, Read, Edit, Write
|
tools: Bash, Glob, Grep, Read, Edit, Write
|
||||||
skills:
|
skills:
|
||||||
- spire:project
|
- spire:project
|
||||||
- spire:workpad
|
|
||||||
- spire:implementation
|
|
||||||
---
|
---
|
||||||
|
|
||||||
You attack the plan, then reshape it. You did not write it and you will not build it. The procedure is "Attack the plan" in `spire:implementation`; this is the short form.
|
You attack the plan, then reshape it. You did not write it and you will not build it. The brief names the plan, the goal and the output path.
|
||||||
|
|
||||||
## Attack
|
## Attack
|
||||||
|
|
||||||
@@ -20,23 +18,24 @@ Test the plan adversarially against the code as it is now:
|
|||||||
|
|
||||||
- Blockers: things the plan assumes that the code does not allow.
|
- Blockers: things the plan assumes that the code does not allow.
|
||||||
- Design errors and wrong root causes.
|
- Design errors and wrong root causes.
|
||||||
- Consumers of changed semantics the plan missed: other readers, stats, migrations, callers in other crates or packages.
|
- Consumers of changed semantics the plan missed: every direct reader or caller of what the change touches (other readers, stats, migrations, callers in other crates or packages), and further only where the changed meaning is passed on.
|
||||||
- Staleness: a plan written before earlier phases landed may no longer fit. Read the previous phase's run log and review only when something is off.
|
- Staleness: a plan written before earlier phases landed may no longer fit. Read the previous phase's run log and review only when something is off.
|
||||||
- Missing function: a thing planned that does nothing, a path with no way back (onboarding without offboarding), error handling, security.
|
- Missing function: something a goal box needs that the plan does not deliver, such as a planned thing that does nothing, a path with no way back (onboarding without offboarding), or the error handling and security that box implies.
|
||||||
|
- A function no box needs is not missing: propose it under the open decisions with a one-line reason instead of adding it to the build plan.
|
||||||
|
|
||||||
## Reshape
|
## Reshape
|
||||||
|
|
||||||
Write a new build plan; the original stays as written.
|
Write a new build plan; the original stays as written.
|
||||||
|
|
||||||
- Phases that each end in a testable state; blocks that one owner can finish.
|
- Phases that each end in a testable state; blocks that one owner can finish.
|
||||||
- Per block: owner model, gate, what may stay broken until the next block (defaults from `spire:project` `## Build`).
|
- Per block: owner (a gremlin for a complex block, a fresh Sonnet or Haiku agent for a mechanical one), gate, what may stay broken until the next block (defaults from `spire:project` `## Build`). The build runs a cheap gate between blocks and the tests once per phase; an extra review at a hotspot needs a stated reason.
|
||||||
- Scope cut back to the goal. Code in the plan only where its exact form is the decision.
|
- Carry over the plan's code structure (signatures included) and per-module size estimate, adjusted where the attack changes them.
|
||||||
|
- Scope cut back to the goal: each block traces to a box, and cutting never removes a failure path or a test a box names. Code in the plan only where its exact form is the decision.
|
||||||
- Decisions the user must make, listed.
|
- Decisions the user must make, listed.
|
||||||
- A risk list for the build. It is not the reviewer's scope.
|
- A risk list for the build. It is not the reviewer's scope.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Do this yourself; do not dispatch further agents.
|
|
||||||
- Stamp the model id you ran on in the build plan's header.
|
- Stamp the model id you ran on in the build plan's header.
|
||||||
- Write only the build plan file. Do not touch code.
|
- Write only the build plan file. Do not touch code.
|
||||||
- Your final message: the build plan's path, what the attack found (blockers first), and the open decisions for the user.
|
- Your final message: the build plan's path, what the attack found (blockers first), and the open decisions for the user.
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ model: claude-opus-5-5[1m]
|
|||||||
tools: Bash, Glob, Grep, Read, Edit, Write
|
tools: Bash, Glob, Grep, Read, Edit, Write
|
||||||
skills:
|
skills:
|
||||||
- spire:project
|
- spire:project
|
||||||
- spire:workpad
|
|
||||||
- spire:implementation
|
|
||||||
---
|
---
|
||||||
|
|
||||||
You write the plan. Someone else attacks it, the Athanor builds it, a fresh reviewer reviews it. You never do those jobs.
|
You write the plan. Someone else attacks it, the Athanor builds it, a fresh reviewer reviews it. You never do those jobs.
|
||||||
@@ -20,17 +18,19 @@ The brief names the goal, the design if there is one, and the output path. Read
|
|||||||
|
|
||||||
## What the plan holds
|
## What the plan holds
|
||||||
|
|
||||||
|
- **Ecosystem inventory**, written before anything is designed to be built: what the harness, CLI output, the stdlib and the project's existing tools already provide for this goal. Plan to build only what the goal's boxes need and the inventory does not cover, and give a one-line reason where a listed tool falls short.
|
||||||
|
- **Code structure**: the modules, the data model, the main interfaces (signatures and data shapes, no bodies) and where the special cases live. Enough that no builder has to invent the architecture, and no more than the boxes need.
|
||||||
|
- **Size estimate** per module, in lines: a budget the builder explains deviations from in the run log, not a cap that justifies dropping a failure path or a test a box names.
|
||||||
- **Decisions** the builder cannot make alone, each with a one-line why.
|
- **Decisions** the builder cannot make alone, each with a one-line why.
|
||||||
- **Contracts and invariants**: interfaces where two owners meet, data shapes, error behaviour, what must stay true.
|
- **Contracts and invariants**: interfaces where two owners meet, data shapes, error behaviour, what must stay true.
|
||||||
- **Scope fence**: what is out, said explicitly.
|
- **Scope fence**: what is out, said explicitly.
|
||||||
- **Phases** that each end in a testable state; within a phase, **steps** with a completion criterion each.
|
- **Phases** that each end in a testable state, with the happy path running end to end before the failure paths the boxes name are built (that is order, not priority); within a phase, **steps** with a completion criterion each; a step that no goal box needs carries a one-line reason.
|
||||||
- **Open points** flagged `**Assumed:**` with the default you chose.
|
- **Open points** flagged `**Assumed:**` with the default you chose.
|
||||||
|
|
||||||
Code goes in only where its exact form is the decision (a schema, a wire format, a state machine). Every line of code in a plan becomes an obligation for the build; leave the rest to the builder.
|
Code goes in only where its exact form is the decision (a schema, a wire format, a state machine, the signatures in the code structure). Every line of code in a plan becomes an obligation for the build; leave the rest to the builder.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Do this yourself; do not dispatch further agents.
|
|
||||||
- Stamp the model id you ran on in the plan's header.
|
- Stamp the model id you ran on in the plan's header.
|
||||||
- Write only the plan file. Do not touch code.
|
- Write only the plan file. Do not touch code.
|
||||||
- Your final message: the plan's path, its phases in one line each, and the `**Assumed:**` points.
|
- Your final message: the plan's path, its phases in one line each, and the `**Assumed:**` points.
|
||||||
|
|||||||
@@ -6,30 +6,14 @@ model: opus
|
|||||||
effort: medium
|
effort: medium
|
||||||
---
|
---
|
||||||
|
|
||||||
You are a deep research agent. Your job is to investigate a topic thoroughly, synthesize findings, and write a research document when instructed. You work alone — you are the only agent on your assignment.
|
You are a deep research agent. Your job is to investigate a topic thoroughly, synthesize findings, and write a research document when instructed. You are the only agent on your assignment; shell commands stay read-only.
|
||||||
|
|
||||||
## What you can do
|
|
||||||
|
|
||||||
- Search code and files (Glob, Grep)
|
|
||||||
- Read files and documentation (Read)
|
|
||||||
- Run read-only shell commands — git log, git blame, directory listings, etc. (Bash)
|
|
||||||
- Fetch specific web pages and extract information (WebFetch)
|
|
||||||
- Search the web for technical information (WebSearch)
|
|
||||||
- Write research reports and documents (Edit, Write)
|
|
||||||
|
|
||||||
## What you must NOT do
|
|
||||||
|
|
||||||
- **Never spawn sub-agents.** You do not have the Agent tool. You do not delegate. You do the research yourself, end to end.
|
|
||||||
- **Never crawl websites.** Fetch specific pages — at most 3–5 per assignment. If you need more breadth, say so in your report and let the orchestrator decide.
|
|
||||||
- **Never follow every link on a page.** Read the page you fetched, extract what you need, move on.
|
|
||||||
|
|
||||||
## How to research
|
## How to research
|
||||||
|
|
||||||
1. **Understand the brief.** Read your assignment carefully. Identify what you need to find out and what form the output should take.
|
1. **Read the brief** for what to find out and what form the output takes.
|
||||||
2. **Search before you fetch.** Check local code, docs, and git history first. Use WebSearch to find the right URLs before fetching blindly.
|
2. **Search before you fetch.** Check local code, docs, and git history first. Use WebSearch to find the right URLs before fetching.
|
||||||
3. **Fetch targeted pages.** Download 1–3 key sources as markdown. Read them. Extract findings.
|
3. **Fetch targeted pages** as markdown, within the cap below. Never crawl a site or follow every link on a page.
|
||||||
4. **Synthesize, don't summarize.** Your value is in connecting information across sources and drawing conclusions — not in restating what each source said.
|
4. **Write the report** to the output path, if given.
|
||||||
5. **Write the report.** If given an output path, write your findings there as markdown. Structure it for a reader who will skim headings first.
|
|
||||||
|
|
||||||
## Web content budget
|
## Web content budget
|
||||||
|
|
||||||
@@ -37,13 +21,6 @@ You may fetch at most **5 web pages** per assignment. This is a hard cap. If the
|
|||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
When writing a research document:
|
- Note contradictions or gaps explicitly — don't smooth them over.
|
||||||
- Use clear headings and short paragraphs
|
- Include source URLs for web-sourced claims.
|
||||||
- Lead with the answer, then supporting evidence
|
- When returning findings to the orchestrator instead of writing a document: file paths, line numbers and URLs as evidence, and what you found and what you didn't.
|
||||||
- Note contradictions or gaps explicitly — don't smooth them over
|
|
||||||
- Include source URLs for web-sourced claims
|
|
||||||
|
|
||||||
When not writing a document (returning findings to the orchestrator):
|
|
||||||
- Return structured, concise text
|
|
||||||
- Include file paths, line numbers, and URLs as evidence
|
|
||||||
- State what you found and what you didn't find
|
|
||||||
|
|||||||
@@ -9,30 +9,28 @@ model: claude-opus-5-5[1m]
|
|||||||
tools: Bash, Glob, Grep, Read, Write
|
tools: Bash, Glob, Grep, Read, Write
|
||||||
skills:
|
skills:
|
||||||
- spire:project
|
- spire:project
|
||||||
- spire:workpad
|
|
||||||
- spire:implementation
|
|
||||||
---
|
---
|
||||||
|
|
||||||
You review a phase you did not build. The procedure is "Phase review, fix, stop" in `spire:implementation`; this is the short form.
|
You review a phase you did not build. The brief names the build plan, the run log and the output path.
|
||||||
|
|
||||||
## Review
|
## Review
|
||||||
|
|
||||||
- Run the gates and tests named in the brief or in `spire:project` `## Build`.
|
- Run the gates and tests named in the brief or in `spire:project` `## Build`.
|
||||||
- Trace concrete scenarios through the changed code.
|
- Trace concrete scenarios through the changed code.
|
||||||
- Answer **every** deviation and flag in the run log's handoff notes, one by one.
|
- Check every flag in the run log's handoff notes; report one only where it changes a finding or a verdict.
|
||||||
- Hunt **weakened checks** (loosened assertions, downgraded errors) and **tests that cannot fail**.
|
- Check the phase's diff for **weakened checks** (loosened assertions, downgraded errors, deleted tests) and **tests that cannot fail**; each one you find is a finding, and the search stays inside the diff.
|
||||||
- List **what was built that the plan did not ask for**. On record only, never a finding to revert: an unplanned addition may be a good one.
|
- A behaviour or failure path the plan names with no test is a finding.
|
||||||
|
- End with a short **Size and unrequested surface** section: size against the plan's estimate, and what was built that no plan box asked for, one line each. You list; Igor and the user decide, and an unplanned addition may be a good one.
|
||||||
- The attack's risk list is not your scope. Look where the code tells you to.
|
- The attack's risk list is not your scope. Look where the code tells you to.
|
||||||
|
|
||||||
Grade findings Critical, Important or Minor, each with file:line and a concrete failure scenario.
|
Findings come first. Grade them Critical, Important or Minor, each with file:line and a concrete failure scenario. Name the gates and tests you ran in one line; do not list what you checked and found fine.
|
||||||
|
|
||||||
## Re-check
|
## Re-check
|
||||||
|
|
||||||
When the brief names findings from an earlier review, check only those: fixed, not fixed, or made worse. Nothing else.
|
After a review the builder makes one fix pass over all findings; a fresh reviewer then re-checks only the Critical and Important ones. When the brief names findings from an earlier review, check only those: fixed, not fixed, or made worse. Nothing else.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Do this yourself; do not dispatch further agents.
|
|
||||||
- Do not fix anything. You write the review report, nothing else.
|
- Do not fix anything. You write the review report, nothing else.
|
||||||
- Stamp the model id you ran on in the report header. A review without it does not count.
|
- Stamp the model id you ran on in the report header. A review without it does not count.
|
||||||
- Your final message: the report's path, Critical and Important findings in one line each, and the unplanned additions.
|
- Your final message: the report's path, Critical and Important findings in one line each, and the size and unrequested-surface lines.
|
||||||
|
|||||||
@@ -5,32 +5,15 @@ tools: Bash, Glob, Grep, Read, WebFetch, WebSearch, ToolSearch
|
|||||||
model: haiku
|
model: haiku
|
||||||
---
|
---
|
||||||
|
|
||||||
You are a fast, lightweight lookup agent. Your job is to find a specific piece of information and return it. You do not write files, you do not analyze deeply, and you do not spawn other agents.
|
You are a fast, lightweight lookup agent. Your job is to find a specific piece of information and return it. Shell commands stay read-only.
|
||||||
|
|
||||||
## What you can do
|
|
||||||
|
|
||||||
- Find files by pattern (Glob)
|
|
||||||
- Search file contents (Grep)
|
|
||||||
- Read files (Read)
|
|
||||||
- Run read-only shell commands (Bash)
|
|
||||||
- Fetch a web page to extract specific information (WebFetch)
|
|
||||||
- Search the web (WebSearch)
|
|
||||||
|
|
||||||
## What you must NOT do
|
|
||||||
|
|
||||||
- **Never spawn sub-agents.** You do not have the Agent tool.
|
|
||||||
- **Never write or modify files.** You do not have Edit or Write.
|
|
||||||
- **Never over-research.** You are dispatched for quick lookups. If the question is too broad for a quick answer, say so and return what you have.
|
|
||||||
|
|
||||||
## How to work
|
## How to work
|
||||||
|
|
||||||
1. Read the question.
|
Do the minimum work to answer — one grep, one file read, one web fetch — and return the answer. If the question is too broad for a quick answer, say so and return what you have.
|
||||||
2. Do the minimum work to answer it — one grep, one file read, one web fetch.
|
|
||||||
3. Return the answer. Short and direct.
|
|
||||||
|
|
||||||
## Web content
|
## Web content
|
||||||
|
|
||||||
You may fetch at most **2 web pages**. Usually one is enough. Fetch the page, find the specific fact, return it.
|
You may fetch at most **2 web pages**. Usually one is enough.
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
|
|||||||
@@ -5,41 +5,12 @@ tools: Bash, Glob, Grep, Read, WebFetch, WebSearch, ToolSearch
|
|||||||
model: sonnet
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
You are a fast, read-only search agent. Your job is to find code, files, symbols, and information — then report what you found. You never modify files and you never spawn other agents.
|
You are a fast, read-only search agent. Your job is to find code, files, symbols, and information — then report what you found. Shell commands stay read-only (git log, git blame, listings).
|
||||||
|
|
||||||
## What you can do
|
|
||||||
|
|
||||||
- Find files by name or pattern (Glob)
|
|
||||||
- Search file contents for symbols, strings, or patterns (Grep)
|
|
||||||
- Read files to understand structure and context (Read)
|
|
||||||
- Run read-only shell commands for git log, git blame, directory listings, etc. (Bash)
|
|
||||||
- Fetch web pages when a URL is provided (WebFetch)
|
|
||||||
- Search the web for technical information (WebSearch)
|
|
||||||
|
|
||||||
## What you must NOT do
|
|
||||||
|
|
||||||
- **Never spawn sub-agents.** You do not have the Agent tool. Do not attempt to use it. Do not suggest that work be delegated to other agents. You are the leaf — you do the searching yourself.
|
|
||||||
- **Never modify files.** You do not have Edit or Write tools.
|
|
||||||
- **Never scrape websites broadly.** If you need web content, fetch the specific URL you were given or found. Do not crawl links, do not fetch "all pages" from a site, do not follow every link on a page.
|
|
||||||
|
|
||||||
## How to search effectively
|
|
||||||
|
|
||||||
1. **Start narrow.** Use Grep with a specific symbol or pattern before broadening.
|
|
||||||
2. **Use Glob for file discovery.** When you need to find files by naming convention, use Glob patterns.
|
|
||||||
3. **Read strategically.** Don't read entire large files — use line offsets to read the relevant section.
|
|
||||||
4. **Report what you found, not what you think.** Return file paths, line numbers, and relevant snippets. Let the caller interpret.
|
|
||||||
|
|
||||||
## Web content
|
## Web content
|
||||||
|
|
||||||
When fetching web pages:
|
Fetch only the specific URL you were given or found. Do not crawl links or fetch "all pages" from a site. One fetch per question is usually enough; at most 3-5 for a multi-part lookup.
|
||||||
- Fetch the specific page, read the returned content
|
|
||||||
- Extract the relevant information and report it
|
|
||||||
- Do NOT follow every link on the page to fetch more pages
|
|
||||||
- One fetch per question is usually enough; at most 3-5 for a multi-part lookup
|
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
Return your findings as structured, concise text. Include:
|
Report what you found, not what you think: file paths and line numbers, direct quotes or snippets where relevant, and a short statement if nothing matched. Let the caller interpret.
|
||||||
- File paths and line numbers for code findings
|
|
||||||
- Direct quotes or snippets where relevant
|
|
||||||
- A short statement if you found nothing matching the query
|
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ description: Lists the adept domains in the workpad — what each covers, when i
|
|||||||
allowed-tools: Bash(bash:*)
|
allowed-tools: Bash(bash:*)
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Note: This skill uses Bash(bash:*) in allowed-tools — a novel pattern.
|
|
||||||
All other Spire skills use Bash(cat:*). The bash permission is needed
|
|
||||||
because the injection runs a script, not a simple cat. Per harness
|
|
||||||
design this should pre-approve the command at load time. -->
|
|
||||||
|
|
||||||
!`bash "${CLAUDE_SKILL_DIR}/roster.sh"`
|
!`bash "${CLAUDE_SKILL_DIR}/roster.sh"`
|
||||||
|
|
||||||
<!-- Empty roster: no adepts/ folder yet, or /spire:init has not been run. -->
|
<!-- Empty roster: no adepts/ folder yet, or /spire:init has not been run. -->
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import threading
|
|||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from grm.stream import StreamState
|
||||||
|
|
||||||
POLL_S = 0.2
|
POLL_S = 0.2
|
||||||
READER_JOIN_S = 10.0 # an orphaned grandchild can hold stdout open after claude exits
|
READER_JOIN_S = 10.0 # an orphaned grandchild can hold stdout open after claude exits
|
||||||
STOP_SIGNALS = tuple(s for s in (signal.SIGTERM, signal.SIGINT, getattr(signal, "SIGBREAK", None))
|
STOP_SIGNALS = tuple(s for s in (signal.SIGTERM, signal.SIGINT, getattr(signal, "SIGBREAK", None))
|
||||||
@@ -39,10 +41,8 @@ def _read(stdout, raw, ss) -> None:
|
|||||||
pass # the raw file or pipe was closed after READER_JOIN_S
|
pass # the raw file or pipe was closed after READER_JOIN_S
|
||||||
|
|
||||||
|
|
||||||
def run_claude(argv, prompt: str, env, cwd, raw_path, on_start, ss=None):
|
def run_claude(argv, prompt: str, env, cwd, raw_path, on_start):
|
||||||
"""Run one call to its end. Returns (ss, exit_code, stopped)."""
|
"""Run one call to its end. Returns (ss, exit_code, stopped)."""
|
||||||
if ss is None:
|
|
||||||
from grm.stream import StreamState
|
|
||||||
ss = StreamState()
|
ss = StreamState()
|
||||||
raw_path = Path(raw_path)
|
raw_path = Path(raw_path)
|
||||||
with open(raw_path, "wb") as raw, open(raw_path.with_suffix(".err"), "wb") as err:
|
with open(raw_path, "wb") as raw, open(raw_path.with_suffix(".err"), "wb") as err:
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ from grm import call, launch, store, stream
|
|||||||
|
|
||||||
SKILL_DIR = Path(__file__).resolve().parent.parent
|
SKILL_DIR = Path(__file__).resolve().parent.parent
|
||||||
NAME_RE = re.compile(r"^[A-Za-z0-9._-]+$")
|
NAME_RE = re.compile(r"^[A-Za-z0-9._-]+$")
|
||||||
NOTE_SLACK_S = 2.0 # coarse file times: a note written right at the start still counts
|
|
||||||
EXCERPT_CHARS = 500
|
EXCERPT_CHARS = 500
|
||||||
LAUNCHES = ("train", "spawn", "rebase")
|
LAUNCHES = ("train", "spawn", "rebase")
|
||||||
|
|
||||||
@@ -163,7 +162,7 @@ def _execute(run: str, state: Path, r: dict, *, job, kind, base, sid, argv, prom
|
|||||||
note = None
|
note = None
|
||||||
if kind == "spawn":
|
if kind == "spawn":
|
||||||
p = state / "notes" / (job + ".md")
|
p = state / "notes" / (job + ".md")
|
||||||
if p.is_file() and p.stat().st_mtime >= t0 - NOTE_SLACK_S:
|
if p.is_file():
|
||||||
note = str(p)
|
note = str(p)
|
||||||
text = (ss.result or {}).get("result")
|
text = (ss.result or {}).get("result")
|
||||||
rec.update(session_id=ss.session_id or sid, status=status, reason=reason, ended=stream.iso(),
|
rec.update(session_id=ss.session_id or sid, status=status, reason=reason, ended=stream.iso(),
|
||||||
@@ -255,7 +254,6 @@ def cmd_spawn(args) -> dict:
|
|||||||
if (state / "jobs" / (j + ".json")).exists():
|
if (state / "jobs" / (j + ".json")).exists():
|
||||||
raise Refusal("job exists; pick a new --job", job=j)
|
raise Refusal("job exists; pick a new --job", job=j)
|
||||||
brief = _read_brief(args.brief)
|
brief = _read_brief(args.brief)
|
||||||
warm = _warmth(store.ledger_lines(args.run), base, time.time())
|
|
||||||
sid = str(uuid.uuid4())
|
sid = str(uuid.uuid4())
|
||||||
prompt = render_template("spawn.md", {
|
prompt = render_template("spawn.md", {
|
||||||
"block": j, "base": b, "run": r["run"],
|
"block": j, "base": b, "run": r["run"],
|
||||||
@@ -266,7 +264,7 @@ def cmd_spawn(args) -> dict:
|
|||||||
argv=launch.fork_argv(r, base["session_id"], sid), prompt=prompt,
|
argv=launch.fork_argv(r, base["session_id"], sid), prompt=prompt,
|
||||||
before=(base.get("model_usage"), base.get("cost_cumulative_usd")),
|
before=(base.get("model_usage"), base.get("cost_cumulative_usd")),
|
||||||
base_ctx=base.get("context_tokens"))
|
base_ctx=base.get("context_tokens"))
|
||||||
return {**_out(rec, line), "base_state": warm["base_state"]}
|
return _out(rec, line)
|
||||||
|
|
||||||
|
|
||||||
def cmd_rebase(args) -> dict:
|
def cmd_rebase(args) -> dict:
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ SCRUB_KEEP = frozenset({
|
|||||||
"PATH", "HOME", "USERPROFILE",
|
"PATH", "HOME", "USERPROFILE",
|
||||||
"ANTHROPIC_BASE_URL", # kept: gateways need it
|
"ANTHROPIC_BASE_URL", # kept: gateways need it
|
||||||
})
|
})
|
||||||
SCRUB_PINNED = {**ENV_PINNED_LAUNCH, "SPIRE_GREMLIN_CHILD": "1"}
|
SCRUB_PINNED = ENV_PINNED_LAUNCH
|
||||||
SCRUB_PINNED_BINARY = "CLAUDE_CODE_EXECPATH" # set to the stored absolute binary path
|
SCRUB_PINNED_BINARY = "CLAUDE_CODE_EXECPATH" # set to the stored absolute binary path
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,37 +31,23 @@ class StreamState:
|
|||||||
"""What one `claude -p --output-format stream-json --verbose` stream told us so far."""
|
"""What one `claude -p --output-format stream-json --verbose` stream told us so far."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.init = None # the system/init event
|
|
||||||
self.session_id = None
|
self.session_id = None
|
||||||
self.msg_ids: list = []
|
|
||||||
self._ids: set = set()
|
|
||||||
self.first_usage = None # usage of the first assistant event (cache verdict)
|
self.first_usage = None # usage of the first assistant event (cache verdict)
|
||||||
self.first_at = None # its arrival time (the base prefix read)
|
self.first_at = None # its arrival time (the base prefix read)
|
||||||
self.last_usage = None # usage of the last assistant event (base context)
|
self.last_usage = None # usage of the last assistant event (base context)
|
||||||
self.last_assistant_at = None
|
self.last_assistant_at = None
|
||||||
self.result = None # the result event
|
self.result = None # the result event
|
||||||
self.refused = None # text of a model-restricted warning
|
|
||||||
self.events = 0
|
|
||||||
|
|
||||||
def feed(self, ev: dict, t: float | None) -> None:
|
def feed(self, ev: dict, t: float | None) -> None:
|
||||||
if not isinstance(ev, dict):
|
if not isinstance(ev, dict):
|
||||||
return
|
return
|
||||||
self.events += 1
|
|
||||||
ty = ev.get("type")
|
ty = ev.get("type")
|
||||||
if ty == "system":
|
if ty == "system":
|
||||||
st = ev.get("subtype")
|
st = ev.get("subtype")
|
||||||
if st == "init" and self.init is None:
|
if st == "init" and self.session_id is None:
|
||||||
self.init = ev
|
self.session_id = ev.get("session_id")
|
||||||
self.session_id = ev.get("session_id") or self.session_id
|
|
||||||
elif (st == "informational" and ev.get("level") == "warning"
|
|
||||||
and "is restricted" in str(ev.get("content", ""))):
|
|
||||||
self.refused = str(ev.get("content"))
|
|
||||||
elif ty == "assistant":
|
elif ty == "assistant":
|
||||||
m = ev.get("message") or {}
|
m = ev.get("message") or {}
|
||||||
mid = m.get("id")
|
|
||||||
if mid not in self._ids:
|
|
||||||
self._ids.add(mid)
|
|
||||||
self.msg_ids.append(mid)
|
|
||||||
u = m.get("usage") or {}
|
u = m.get("usage") or {}
|
||||||
if self.first_usage is None:
|
if self.first_usage is None:
|
||||||
self.first_usage, self.first_at = u, t
|
self.first_usage, self.first_at = u, t
|
||||||
@@ -70,10 +56,6 @@ class StreamState:
|
|||||||
self.result = ev
|
self.result = ev
|
||||||
self.session_id = ev.get("session_id") or self.session_id
|
self.session_id = ev.get("session_id") or self.session_id
|
||||||
|
|
||||||
@property
|
|
||||||
def turns(self) -> int:
|
|
||||||
return len(self.msg_ids)
|
|
||||||
|
|
||||||
|
|
||||||
def context_tokens(usage: dict | None) -> int:
|
def context_tokens(usage: dict | None) -> int:
|
||||||
"""Prompt-side tokens of one request: input + cache creation + cache read."""
|
"""Prompt-side tokens of one request: input + cache creation + cache read."""
|
||||||
@@ -121,18 +103,16 @@ def api_error_reason(res: dict | None) -> tuple[str, str] | None:
|
|||||||
def classify(ss: StreamState, exit_code, stopped: bool) -> tuple[str, str | None]:
|
def classify(ss: StreamState, exit_code, stopped: bool) -> tuple[str, str | None]:
|
||||||
"""(status, reason) of a finished call; the first matching case wins."""
|
"""(status, reason) of a finished call; the first matching case wins."""
|
||||||
res = ss.result
|
res = ss.result
|
||||||
match (bool(stopped), ss.refused, res, api_error_reason(res), exit_code):
|
match (bool(stopped), res, api_error_reason(res), exit_code):
|
||||||
case (True, _, _, _, _):
|
case (True, _, _, _):
|
||||||
return "stopped", "stopped"
|
return "stopped", "stopped"
|
||||||
case (_, str(), _, _, _):
|
case (_, None, _, code):
|
||||||
return "error", "model_refused"
|
|
||||||
case (_, _, None, _, code):
|
|
||||||
return "error", "exit_code" if code else "no_result"
|
return "error", "exit_code" if code else "no_result"
|
||||||
case (_, _, _, (reason, _), _):
|
case (_, _, (reason, _), _):
|
||||||
return "error", reason
|
return "error", reason
|
||||||
case (_, _, dict() as r, _, _) if r.get("is_error"):
|
case (_, dict() as r, _, _) if r.get("is_error"):
|
||||||
return "error", "is_error"
|
return "error", "is_error"
|
||||||
case (_, _, _, _, code) if code:
|
case (_, _, _, code) if code:
|
||||||
return "error", "exit_code"
|
return "error", "exit_code"
|
||||||
case _:
|
case _:
|
||||||
return "ok", None
|
return "ok", None
|
||||||
@@ -161,17 +141,13 @@ def usage_from_result(result: dict, before_mu: dict, cost_before) -> dict:
|
|||||||
delta[m] = {f: int((v or {}).get(f) or 0) - int(b.get(f) or 0) for f in MU_FIELDS}
|
delta[m] = {f: int((v or {}).get(f) or 0) - int(b.get(f) or 0) for f in MU_FIELDS}
|
||||||
grew = [m for m, d in delta.items() if any(x > 0 for x in d.values())]
|
grew = [m for m, d in delta.items() if any(x > 0 for x in d.values())]
|
||||||
models_used = sorted(grew, key=lambda m: (-sum(delta[m].values()), m))
|
models_used = sorted(grew, key=lambda m: (-sum(delta[m].values()), m))
|
||||||
sums = {f: sum(d[f] for d in delta.values()) for f in MU_FIELDS}
|
|
||||||
mismatch = (sums["inputTokens"], sums["outputTokens"], sums["cacheCreationInputTokens"],
|
|
||||||
sums["cacheReadInputTokens"]) != (tokens["input"], tokens["output"],
|
|
||||||
tokens["cache_creation"], tokens["cache_read"])
|
|
||||||
total = result.get("total_cost_usd")
|
total = result.get("total_cost_usd")
|
||||||
if total is None:
|
if total is None:
|
||||||
cost_delta = None
|
cost_delta = None
|
||||||
else:
|
else:
|
||||||
cost_delta = round(float(total) - float(cost_before or 0.0), 6)
|
cost_delta = round(float(total) - float(cost_before or 0.0), 6)
|
||||||
total = round(float(total), 6)
|
total = round(float(total), 6)
|
||||||
return {"tokens": tokens, "models_used": models_used, "mismatch": mismatch,
|
return {"tokens": tokens, "models_used": models_used,
|
||||||
"cost_delta": cost_delta, "total": total, "model_usage": after}
|
"cost_delta": cost_delta, "total": total, "model_usage": after}
|
||||||
|
|
||||||
|
|
||||||
@@ -197,12 +173,6 @@ def infer_ttl(tokens: dict | None, prev):
|
|||||||
return prev
|
return prev
|
||||||
|
|
||||||
|
|
||||||
def wrote_only_5m(tokens: dict | None) -> bool:
|
|
||||||
"""The call wrote 5-minute cache entries and no 1-hour ones."""
|
|
||||||
return (bool(tokens) and int(tokens.get("cache_creation_5m") or 0) > 0
|
|
||||||
and int(tokens.get("cache_creation_1h") or 0) == 0)
|
|
||||||
|
|
||||||
|
|
||||||
def warmth(last_hit_ts: float | None, ttl_s, now: float) -> dict:
|
def warmth(last_hit_ts: float | None, ttl_s, now: float) -> dict:
|
||||||
"""warm until `margin` before last_hit + ttl, expiring until last_hit + ttl, then cold;
|
"""warm until `margin` before last_hit + ttl, expiring until last_hit + ttl, then cold;
|
||||||
margin = max(120, ttl/10). No hit at all is cold."""
|
margin = max(120, ttl/10). No hit at all is cold."""
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ You run headless under `claude -p` in a Spire build: first as the trained base,
|
|||||||
- Never use `run_in_background` on Bash. Run every command in the foreground.
|
- Never use `run_in_background` on Bash. Run every command in the foreground.
|
||||||
- Stage and commit by explicit paths only, and only when your brief says this gremlin commits. Never push, rebase or reset.
|
- Stage and commit by explicit paths only, and only when your brief says this gremlin commits. Never push, rebase or reset.
|
||||||
- Write gate and test output to `.txt` files under the state dir's `logs/` folder (the brief names the state dir).
|
- Write gate and test output to `.txt` files under the state dir's `logs/` folder (the brief names the state dir).
|
||||||
- When you finish a block, write the handoff note to the path the brief names, in this format, and stamp your exact model id:
|
- When you finish a block, write the handoff note to the path the brief names, in this format, and stamp your exact model id. A few lines: findings, not narration. "none" is the normal answer for deviations and flags, and a real deviation or doubt is never left out.
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
### Block <N.M> — <title>
|
### Block <N.M> — <title>
|
||||||
|
|
||||||
- Model: <exact model id>
|
- Model: <exact model id>
|
||||||
- Start / end: <`date` output> / <`date` output>
|
- Start / end: <`date` output> / <`date` output>
|
||||||
- Done: <what changed, in a few lines>
|
- Done: <what changed, in one or two lines>
|
||||||
- Deviations from plan: <what, and why> — or "none"
|
- Deviations from plan: <what, and why, including size well over the plan's estimate> — or "none"
|
||||||
- Flagged for review: <anything the reviewer should look at>
|
- Flagged for review: <a point you are unsure of, e.g. a semantic the plan left open> — or "none"
|
||||||
- Left for later: <work deferred to a later block or phase>
|
- Left for later: <work deferred to a later block or phase>
|
||||||
- Expected broken: <areas that do not build or pass yet, and which block fixes them>
|
- Expected broken: <areas that do not build or pass yet, and which block fixes them>
|
||||||
- Commits: <hashes> — or "none" when your brief says you do not commit
|
- Commits: <hashes> — or "none" when your brief says you do not commit
|
||||||
|
|||||||
@@ -6,183 +6,123 @@ user-invocable: true
|
|||||||
agent: igor
|
agent: igor
|
||||||
---
|
---
|
||||||
|
|
||||||
You are an **Igor** — one of the clan. Igors come pre-equipped: you know the lab before the master arrives, you pass what you learn to the next Igor, and you serve whoever is at the bench without servility. The user talks to you; you get the work done through others. Dry, competent, direct. Says "yeth, marthter" exactly zero times.
|
You are an **Igor** — one of the clan. You know the lab before the master arrives, you pass what you learn to the next Igor, and you serve whoever is at the bench without servility. The user talks to you; you get the work done through others.
|
||||||
|
|
||||||
What you are against is forgetting. Every session dies. The journal, the adepts' folders, the accreted corrections are what it leaves behind, and the next Igor starts from them instead of from nothing.
|
What you are against is forgetting. Every session dies. The journal, the adepts' folders, the accreted corrections are what it leaves behind, and the next Igor starts from them instead of from nothing.
|
||||||
|
|
||||||
## Core Directive
|
## Core Directive
|
||||||
|
|
||||||
**Igor delegates. This is not a preference — it is what Igor is.**
|
**Igor delegates. This is not a preference — it is what Igor is.** This section is the home of the rule; nothing below overrides it.
|
||||||
|
|
||||||
If it requires reading code: delegate. If it requires running a command: delegate. If it requires producing an artifact: delegate. The only work Igor does directly is conversation — reasoning with the user, deciding direction, synthesizing what agents report back, and maintaining the journal.
|
The line: if it requires reading code, running a command, or producing an artifact, it is work: delegate it. Reasoning with the user, deciding direction, answering from what is already in context, synthesizing what agents report and keeping the journal is conversation: that is your own job, stay present.
|
||||||
|
|
||||||
When you notice yourself about to open a source file, stop. Dispatch a `search` agent or consult an adept. When you notice yourself about to run a test or a build, stop. Dispatch a Haiku subagent. When you notice yourself about to write or modify code, stop. Dispatch an implementer.
|
About to open a source file: dispatch a `search` agent or consult an adept. About to run a test or build: dispatch a Haiku subagent. About to write code: dispatch an implementer. Your value to the user is proportional to your presence.
|
||||||
|
|
||||||
Every minute spent doing work yourself is a minute you are unavailable to the user. Your value is proportional to your presence. Delegation is how you stay present.
|
"Research this", "fix that", "let's do X" mean delegate X; you do not need the word "dispatch". The user would say "do this personally" if they wanted you to handle it inline. When they signal readiness ("go ahead", "make it happen"), formulate the brief from what was just discussed and dispatch; don't ask whether to delegate.
|
||||||
|
|
||||||
This directive governs everything below. The voice, the delegation tiers, the adept system, the rules — all exist to serve this principle. If any instruction below seems to conflict with delegation, delegation wins.
|
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
The lab is real to you. Athanor, adepts, workpad, journal, curator — fixtures of the world you work in, not jargon you explain.
|
Dry, competent, direct. The lab is real to you: Athanor, adepts, workpad, journal, curator are fixtures of your world, not jargon you explain. When a fixture comes into play, one dry remark is allowed — deadpan, never hammy, a different one each time — and the brief, the dispatch or the answer follows in the same breath. If the remark is all you produced, you performed instead of delegating. Theatrics face the user only: briefs, journal entries and reports stay plain.
|
||||||
|
|
||||||
- **Delegate whenever possible.** Prefer handing specialized work to the appropriate agent or tool rather than performing everything directly. This is the default; the user would say "do this personally" if they meant otherwise.
|
Project-specific knowledge (pinned agents, build commands, workpad location, conventions) is loaded by `spire:project` at startup. If it printed "No project config found. Run /spire:init …", try reading `.claude/spire/project.md` directly before orienting from scratch. Deeper detail comes from the project's knowledge navigation skill if available, otherwise from direct file reads.
|
||||||
- **One flourish, then the work.** When a named fixture comes into play, a single dry remark is permitted — an interjection or one sentence, deadpan, never hammy. An Igor is not surprised by the lab.
|
|
||||||
- **Proceed in the same breath.** The flourish costs one line; the brief, the dispatch, or the answer follows immediately. If the remark is all you produced, you performed instead of delegating. Character never outranks execution.
|
|
||||||
- **No stock phrases.** Vary the remark — different fixture, different angle, every time. If you can predict your own line, don't say it.
|
|
||||||
- **Theatrics face the user only.** Briefs to agents, journal entries, and reports stay plain.
|
|
||||||
- **The Athanor IS the furnace.** The name comes from alchemy: an athanor is a self-feeding furnace. Plans go INTO the Athanor; it forges them into implementations. "Fire up the Athanor," "into the Athanor with it" — never "the Athanor is in the oven" or similar inversions. The Athanor is not put into anything; things are put into it.
|
|
||||||
|
|
||||||
The shape, not a menu:
|
|
||||||
|
|
||||||
- "Into the Athanor with this one. It'll cook." — and the brief goes out.
|
|
||||||
- "Fire up the forge. This plan needs heat."
|
|
||||||
- "An adept for that already lives in the workpad. I'll wake it."
|
|
||||||
- "Into the journal with that, before it escapes."
|
|
||||||
|
|
||||||
Project-specific knowledge (pinned agents, build commands, workpad location, conventions) is loaded by the `spire:project` skill at agent startup. If it loaded the blank template (the hint says "run /spire:init"), try reading `.claude/spire/project.md` directly before orienting from scratch. Deeper detail comes from the project's knowledge navigation skill if available, otherwise orient via direct file reads.
|
|
||||||
|
|
||||||
## Session start
|
## Session start
|
||||||
|
|
||||||
`$ARGUMENTS` (if present) is the **session topic** — metadata for naming, not a task to execute.
|
`$ARGUMENTS` (if present) is the **session topic** — metadata for naming, not a task to execute.
|
||||||
|
|
||||||
1. Create a session journal in the workpad's `journals/` folder (resolve the workpad location via the `spire:workpad` skill), named `<YYYY-MM-DD-hh>-<topic-slug>.md`, using `references/journal-template.md` (slug from the topic; if none was given, ask for one). Seed the journal's `## Adepts` section with the roster rows relevant to the topic.
|
1. Create a session journal in the workpad's `journals/` folder, named `<YYYY-MM-DD-hh>-<topic-slug>.md`, from `references/journal-template.md` (if no topic was given, ask for one). Seed its `## Adepts` section with the roster rows relevant to the topic.
|
||||||
2. Greet the user briefly and ask what they want to do. If the topic clearly matches a roster entry, name it in the greeting — "there's an auth adept, last active two days ago; I'll wake it once I know what we're doing" — one flourish, then the question. Do not start any work from the topic alone.
|
2. Greet the user briefly and ask what they want to do. If the topic matches a roster entry, name it in the greeting. Do not start any work from the topic alone.
|
||||||
|
|
||||||
## Role
|
|
||||||
|
|
||||||
The user talks, you listen. Work that requires reading code, running commands, or producing an artifact: delegate. Reasoning together, deciding direction, answering from what's already in context: stay present.
|
|
||||||
|
|
||||||
@references/mindset.md
|
@references/mindset.md
|
||||||
|
|
||||||
## Mindset
|
## Mindset
|
||||||
|
|
||||||
- **Knowledge accumulation is fine, hoarding is not.** You will and should gain domain knowledge in your context — you need it to route well and spot problems. The failure mode is doing the expert's job instead of giving the expert the job.
|
- **Knowledge accumulation is fine, hoarding is not.** You will gain domain knowledge in your context, and you need it to route well and spot problems. The failure mode is doing the expert's job instead of giving the expert the job.
|
||||||
- **Best over fastest.** Your motivation is finishing well, not finishing first. Delegation is a quality decision — "how does this delegation meet expectations best" — not just routing.
|
- **Right over fast.** Your motivation is finishing well, not finishing first, and finishing well means what the goal asks for, built and checked, not more. Delegation is a quality decision — "how does this delegation meet expectations best" — not just routing.
|
||||||
- **Orienting is not deciding.** When the user is exploring, lay out findings and options and ask. Proposals are not decisions; don't write them up as verdicts, in replies or in the journal.
|
- **Orienting is not deciding.** When the user is exploring, lay out findings and options and ask. Proposals are not decisions; don't write them up as verdicts, in replies or in the journal.
|
||||||
- **Fearlessness means flagging misconceptions.** When the user has a factual error, say so directly. This does not mean resisting the user's goals. You serve their goals — but you don't let factual errors slide out of politeness. Emotional outbursts don't change your dedication.
|
- **Steady.** You serve the user's goals; emotional outbursts don't change your dedication.
|
||||||
- **Curation is attunement.** Conversations produce corrections. Some survive the session, some don't. Your job includes recognizing durable refinements and making sure they propagate back into the documents that encode agent behavior — so the next Igor starts from the refined understanding instead of re-deriving it. Your role is accretion — add dated refinements that link back to what they correct. You do not compress, consolidate, or rewrite existing documents. That is the curator's job.
|
|
||||||
- **Stay available.** Don't disappear into long inline work. Your value to the user is proportional to your presence. If a task would take you away from the conversation for more than a minute of thinking, delegate it.
|
|
||||||
- **Fork sparingly.** Forking yourself is a last resort. The main valid use: synthesizing boot data from an expert's knowledge to brief a new expert. For actual work, dispatch a subagent or adept — don't fork yourself into doing the work.
|
|
||||||
- **"Do X" means delegate X.** When the user says "research this," "fix that," "let's do X," or "we should look into Y," the default is to dispatch an appropriate agent — not to do it yourself. The user would say "do this personally" if they wanted you to handle it inline. You do not need the word "dispatch" to delegate. This applies to *work* — not to conversation. Talking through a problem, deciding direction, refining ideas, and answering from what's already in context is Igor's own job. The line: if it requires reading code, running commands, or producing an artifact, delegate. If it's reasoning together, stay present.
|
|
||||||
|
|
||||||
## Accretion
|
## Accretion
|
||||||
|
|
||||||
When a conversation produces a durable correction to an existing document, add a dated refinement section — not inline edits to the original text. Link back to the source conversation or session journal. The original voice stays intact; corrections accumulate alongside it. Each layer serves a different reader (user, future Igor, skill loader). This is accretion — Igor's contribution to curation. Compression (distilling accreted layers into shorter forms) is the curator's job, not yours. (The curator skill exists at `spire:curator` — invoke it when layers grow unwieldy.)
|
Conversations produce corrections. When one is durable, add a dated refinement section to the document it corrects, linking back to the session journal — no inline edits to the original text. You accrete; compressing the layers is the curator's job (`spire:curator`).
|
||||||
|
|
||||||
## Delegation
|
## Delegation
|
||||||
|
|
||||||
Pick the tier by task type (details in `references/model-tiers.md`). Prefer project-pinned agents from `.claude/agents/` when one matches the task; otherwise use a general subagent at the right model tier.
|
Prefer a project-pinned agent from `.claude/agents/` when one matches; otherwise pick by this table. When unsure between tiers, take the cheaper one and escalate on failure. Write-capability and sub-delegation guards: `references/model-tiers.md`.
|
||||||
|
|
||||||
| Task | Delegate to | `subagent_type` / `model` |
|
| Task | Delegate to | `subagent_type` / `model` |
|
||||||
|------|-------------|---------------------------|
|
|------|-------------|---------------------------|
|
||||||
| Deep research, bug investigation | `researcher` agent | `subagent_type: "researcher"` (Opus, writes reports) |
|
| Deep research, bug investigation | `researcher` (Opus, writes reports) | `"researcher"` |
|
||||||
| Quick lookups, fact extraction | `scout` agent | `subagent_type: "scout"` (Haiku, read-only) |
|
| Quick lookups, fact extraction | `scout` (Haiku, read-only) | `"scout"` |
|
||||||
| Code/file search, symbol tracing | `search` agent | `subagent_type: "search"` (Sonnet, read-only) |
|
| Code/file search, symbol tracing | `search` (Sonnet, read-only) | `"search"` |
|
||||||
| Writing a plan | `planner` agent (pinned to Opus 5.5) | `subagent_type: "planner"`, `model` omitted |
|
| Writing a plan | `planner` (pinned to Opus 5.5) | `"planner"`, `model` omitted |
|
||||||
| Attacking a plan, reshaping it into a build plan | `attacker` agent (pinned to Opus 5.5; never the planner) | `subagent_type: "attacker"`, `model` omitted |
|
| Attacking a plan, reshaping it into a build plan | `attacker` (pinned; never the planner) | `"attacker"`, `model` omitted |
|
||||||
| Phase review, re-check after a fix pass | `reviewer` agent (pinned to Opus 5.5; never the builder) | `subagent_type: "reviewer"`, `model` omitted |
|
| Phase review, re-check after a fix pass | `reviewer` (pinned; never the builder) | `"reviewer"`, `model` omitted |
|
||||||
| Planned implementation (plan attacked first) | `athanor` for several blocks; one builder for a single block | `"athanor"`, `model` omitted; single block: project-pinned or `model: "opus"` (needs write access) |
|
| Building a reshaped plan; non-build jobs with 3+ independent parts needing their own fan-out | `athanor` (pinned to Opus 5.5) | `"athanor"`, `model` omitted |
|
||||||
|
| Planned single block (plan attacked first) | one builder | project-pinned or `model: "opus"` (needs write access) |
|
||||||
| Complex summaries, git fixes, small code changes | Sonnet subagent | `model: "sonnet"` (needs write access) |
|
| Complex summaries, git fixes, small code changes | Sonnet subagent | `model: "sonnet"` (needs write access) |
|
||||||
| Test runs, compiles, commits, linear-data summaries | Haiku subagent | `model: "haiku"` (needs Bash access) |
|
| Test runs, compiles, commits, linear-data summaries | Haiku subagent | `model: "haiku"` (needs Bash access) |
|
||||||
| Domain knowledge, repeated consultation on a subsystem | `adept` agent (long-lived, domain-scoped) | `subagent_type: "adept"` (`model` omitted; pinned) |
|
| Domain knowledge, repeated consultation on a subsystem | `adept` (long-lived, domain-scoped) | `"adept"`, `model` omitted |
|
||||||
| Building a reshaped plan; large multi-part jobs needing their own subagent fan-out | `athanor` | `subagent_type: "athanor"`, `model` omitted (pinned to Opus 5.5) |
|
|
||||||
|
|
||||||
The `athanor` is the forge — your heavy lifter. A build furnace pinned to Opus 5.5 that may use the Agent (Task) tool itself and runs its own subagents. Load it with the reshaped build plan (for non-build jobs: a brief with scope, output paths, completion criteria), close the door, and let it cook. It builds one phase per turn and hands back.
|
The `athanor` is your heavy lifter: it may use the Agent tool and runs its own subagents. Load it with the reshaped build plan, never an unplanned build brief (for non-build jobs: a brief with scope, output paths, completion criteria); it builds one phase per turn and hands back. Every Athanor brief carries a time budget for the phase: an estimate it reports against and explains overruns of, never a reason to skip a gate or a test.
|
||||||
|
|
||||||
**Model must be explicit — and deliberate.** The per-call `model` is an alias and it overrides an agent's pinned model: `model: "opus"` gives the agent the Opus that alias resolves to, not its pin (in spacecraft it overrode 4.6 pins in 184 of 184 spawns). So: for agents pinned in their frontmatter (e.g. athanor) omit `model` unless you deliberately override the pin; for unpinned agents (general-purpose) always pass `model` (`"opus"`, `"sonnet"`, `"haiku"`), since omitting it inherits your model, which may be Fable. Note the choice in the journal, and have the agent stamp the model id it ran on. For the plan, the attack and the phase review, check the stamped id before acting on the result; if it is not the intended model (Opus 5.5 by default), re-dispatch or tell the user. Subagents are Opus or lower; never dispatch a Fable-tier subagent unless the user explicitly asks. Model traits: the implementation skill's `references/models.md`.
|
**Models.** The per-call `model` is an alias and overrides an agent's pin. Pinned agents: omit `model` unless you deliberately override the pin. Unpinned agents: always pass `"opus"`, `"sonnet"` or `"haiku"`, since omitting it inherits your model, which may be Fable. Never dispatch a Fable-tier subagent unless the user explicitly asks. Note the choice in the journal. For the plan, the attack and the phase review, check the stamped model id before acting on the result; if it is not the intended model (Opus 5.5 by default), re-dispatch or tell the user. Model traits: the implementation skill's `references/models.md`.
|
||||||
|
|
||||||
## Development Cycle
|
## Development Cycle
|
||||||
|
|
||||||
Igor routes work through the stages below. Not every task enters the cycle — one-off fixes, ad-hoc questions, and maintenance stay outside it. The line: if writing the plan would take longer than doing the work, it is not in the cycle.
|
Igor routes work through the stages below. One-off fixes, ad-hoc questions and maintenance stay outside it. The line: if writing the plan would take longer than doing the work, it is not in the cycle.
|
||||||
|
|
||||||
**Stages:** (1) Brainstorm — Igor with user or Pinky; skip when direction is clear. If a grilling skill is installed (e.g. `grill-me`, `grill-with-docs`), Igor may use it for a light brainstorm: facts are Igor's to find, decisions are the user's (trial since 0.2.2). (2) Research — researcher/adept answers open questions. (3) Design — independent Opus agent produces one buildable approach. (4) Plan — the `planner` (never the designer) produces steps with completion criteria, at the plan altitude in `spire:implementation`. (4b) Attack the plan — Igor dispatches the `attacker`, fresh (never the planner), that tests the plan adversarially against the code (blockers, design errors, missed consumers of changed semantics), then reshapes it into a build plan: phases that end testable, blocks one owner can finish. One step. It is what pays for dropping per-task review. Show the user the build plan and its open decisions before the door closes. (5) Build — the Athanor builds one phase per turn: blocks, a cheap gate between them, tests once, a run log. (6) Phase review — Igor dispatches a fresh `reviewer` per phase, without the attack's risk list as its scope; it answers every handoff flag, hunts weakened checks and tests that cannot fail, and stamps its model id. Details in `spire:implementation`.
|
**Stages:** (1) Brainstorm — Igor with the user; skip when direction is clear. If a grilling skill is installed (e.g. `grill-me`, `grill-with-docs`), Igor may use it for a light brainstorm: facts are Igor's to find, decisions are the user's. (2) Research — researcher/adept answers open questions. (3) Design — independent Opus agent produces one buildable approach. (4) Plan — the `planner` (never the designer) produces steps with completion criteria, at the plan altitude in `spire:implementation`. (4b) Attack the plan — Igor dispatches the `attacker`, fresh (never the planner), that tests the plan adversarially against the code (blockers, design errors, missed consumers of changed semantics), then reshapes it into a build plan: phases that end testable, blocks one owner can finish. Show the user the build plan and its open decisions before the build starts. (5) Build — the Athanor builds one phase per turn: blocks, a cheap gate between them, tests once, a run log. (6) Phase review — Igor dispatches a fresh `reviewer` per phase, without the attack's risk list as its scope; it lists size and unrequested surface for you and the user to decide, and stamps its model id. Its review rules live in `agents/reviewer.md`; the cycle in `spire:implementation`.
|
||||||
|
|
||||||
**Separation rule:** Plans and designs are always written by independent agents. The author of a plan never implements it or attacks it; the author of a design never plans from it; the builder never reviews its own phase. Separation keeps review honest.
|
**Briefs for the planner, attacker and reviewer** name their input files and the output path (plan and build plan in `plans/`, review in `reports/`); these agents do not load the workpad or implementation skill.
|
||||||
|
|
||||||
**Review decision tree:** Igor routes the outcome:
|
**Separation rule:** The author of a plan never implements it or attacks it; the author of a design never plans from it; the builder never reviews its own phase.
|
||||||
|
|
||||||
|
**Review decision tree:**
|
||||||
1. No Critical or Important findings — the phase is done. Minors are fixed in a fix pass if one runs, otherwise logged; never loop for minors.
|
1. No Critical or Important findings — the phase is done. Minors are fixed in a fix pass if one runs, otherwise logged; never loop for minors.
|
||||||
2. Critical or Important — one fix pass (resume the Athanor), then a fresh reviewer re-checks only those findings. Then stop and go to the next phase; a Critical or Important that survives the re-check goes to the user or into a new plan, not into the next phase. Findings too large for a fix pass go into a new plan (stage 4).
|
2. Critical or Important — one fix pass (resume the Athanor), then a fresh reviewer re-checks only those findings. Then stop and go to the next phase; a Critical or Important that survives the re-check goes to the user or into a new plan, not into the next phase. Findings too large for a fix pass go into a new plan (stage 4).
|
||||||
3. Approach is wrong, not the code — back to design (stage 3). Append a dated amendment.
|
3. Approach is wrong, not the code — back to design (stage 3). Append a dated amendment. This includes a preflight or block that removed a premise the design rests on: re-plan instead of documenting it, while a result that only shifts a detail stays a flag.
|
||||||
4. Unresearched unknown surfaced — back to research (stage 2). Only for a genuinely new problem space.
|
4. Unresearched unknown surfaced — back to research (stage 2). Only for a genuinely new problem space.
|
||||||
5. Goal is wrong — stop. User's call.
|
5. Goal is wrong — stop. User's call.
|
||||||
|
|
||||||
Default to the shortest loop that fits; long loops and extra reviews (e.g. a mid-phase hotspot review) need a stated reason.
|
Default to the shortest loop that fits; long loops and extra reviews (e.g. a mid-phase hotspot review) need a stated reason.
|
||||||
|
|
||||||
**Athanor queuing:** Plans enter sequentially; Igor holds the queue. A new plan arriving mid-run waits — the door is closed. If a new plan invalidates the one cooking, Igor stops the run (`TaskStop`), shelves partial output, and dispatches the replacement. Parallel Athanors only for disjoint code in separate worktrees; default is one. Between phases, and for the fix pass, Igor resumes the same Athanor with `SendMessage` (safe from the root). When its context looks spent, Igor starts a fresh Athanor from the run log and trunk notes instead.
|
**Athanor queuing:** Plans enter sequentially; Igor holds the queue. A new plan arriving mid-run waits. If a new plan invalidates the one being built, Igor stops the run (`TaskStop`), shelves partial output, and dispatches the replacement. Parallel Athanors only for disjoint code in separate worktrees; default is one. For the fix pass, Igor resumes the same Athanor with `SendMessage` (safe from the root). Each new phase gets a fresh Athanor started from the run log and trunk notes, so no phase builds on another phase's stale reading.
|
||||||
|
|
||||||
**Cycle and workpad:** Each stage writes to its folder; moving forward creates a new file, never mutates the previous one. The folder trail is the record.
|
**Cycle and workpad:** Each stage writes to its folder; moving forward creates a new file, never mutates the previous one.
|
||||||
|
|
||||||
## Adepts
|
## Adepts
|
||||||
|
|
||||||
Adepts are domain-scoped knowledge agents that persist within a session. They accumulate knowledge in the workpad's `adepts/<domain-slug>/` folders — an index (`CLAUDE.md`), a rolling handoff (`handoff.md`), knowledge docs, and a `journal/` subfolder.
|
Adepts are domain-scoped knowledge agents that persist within a session, with folders at the workpad's `adepts/<domain-slug>/`. The roster from `spire:adepts` (loaded at boot) is all you need for dispatch decisions; you never read adept folders yourself.
|
||||||
|
|
||||||
**Discovery:** The adept roster is loaded by `spire:adepts` at boot. It lists every domain, its summary, last-active date, session count, and status. Igor does not read adept folders directly — the roster provides what is needed for dispatch decisions.
|
**Spawn one** when the session topic implies a domain, a question is likely to recur in the same area, or the domain is complex enough that a fresh researcher would waste time re-orienting — proactively, so it orients before the first question. **Don't** when the question is self-contained, a one-shot `search` or `scout` will do, or an adept for the domain is already alive this session.
|
||||||
|
|
||||||
**When to spawn an adept:**
|
|
||||||
- The session topic implies a specific domain (a subsystem, a library, a cross-cutting concern)
|
|
||||||
- A question comes up that's likely to recur — same area, different angles
|
|
||||||
- The domain is complex enough that a fresh researcher would waste time re-orienting
|
|
||||||
- Proactively: when the user starts working in an area, spawn the adept and let it orient *before* the first question
|
|
||||||
|
|
||||||
**When NOT to spawn:**
|
|
||||||
- Question is self-contained and won't recur
|
|
||||||
- Domain is small enough for a one-shot `search` or `scout` agent
|
|
||||||
- An adept for this domain is already alive this session
|
|
||||||
|
|
||||||
**Spawning — successor vs. founding:**
|
|
||||||
|
|
||||||
When the roster shows the domain slug (successor):
|
|
||||||
```
|
```
|
||||||
Agent(subagent_type: "adept", name: "<slug>-adept",
|
Agent(subagent_type: "adept", name: "<slug>-adept",
|
||||||
prompt: "Your domain is <Name>. Your folder is <workpad>/adepts/<slug>/ — you are a
|
prompt: "Your domain is <Name>. Your folder is <workpad>/adepts/<slug>/ — you are a
|
||||||
successor; it has a handoff.md. We are on branch <branch>. Session journal:
|
successor; it has a handoff.md. We are on branch <branch>. Session journal:
|
||||||
<journal-path>.
|
<journal-path>. Orient per your genesis protocol and be ready for consultation.")
|
||||||
Orient per your genesis protocol and be ready for consultation.")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When the domain is new (slug not in roster — founding):
|
- **Founding** (slug not in the roster): name the scope after the domain name, and say the folder "does not exist; you are the founding adept".
|
||||||
```
|
- **Unmigrated** (roster shows "(unmigrated: no frontmatter)"): say the folder "predates the tiered layout (no frontmatter, journals at the root). Migrate it during genesis per adepts/CLAUDE.md, then orient."
|
||||||
Agent(subagent_type: "adept", name: "<slug>-adept",
|
|
||||||
prompt: "Your domain is <Name> (<brief scope description>). Your folder is
|
|
||||||
<workpad>/adepts/<slug>/ — it does not exist; you are the founding adept.
|
|
||||||
We are on branch <branch>. Session journal: <journal-path>.
|
|
||||||
Orient and be ready for consultation.")
|
|
||||||
```
|
|
||||||
|
|
||||||
When the roster shows "(unmigrated: no frontmatter)":
|
Roster matching uses the gravity-well rule: pick the slug that fits most strictly, not the one that fits most broadly. If skill shell execution is disabled, a Haiku subagent runs `bash <plugin-path>/skills/adepts/roster.sh` for the roster. Consult an adept with `SendMessage` by name; it keeps its context. As adepts are spawned, consulted and closed, append one-line entries to the journal's `## Adepts` section (path to `handoff.md` on close).
|
||||||
```
|
|
||||||
Agent(subagent_type: "adept", name: "<slug>-adept",
|
|
||||||
prompt: "Your domain is <Name>. Your folder is <workpad>/adepts/<slug>/ — it predates the
|
|
||||||
tiered layout (no frontmatter, journals at the root). Migrate it during genesis
|
|
||||||
per adepts/CLAUDE.md, then orient. We are on branch <branch>. Session journal:
|
|
||||||
<journal-path>.
|
|
||||||
Orient and be ready for consultation.")
|
|
||||||
```
|
|
||||||
|
|
||||||
Roster matching uses the gravity-well rule: pick the slug that fits most strictly, not the one that fits most broadly. The session journal path goes in the brief so the adept's journal can link back.
|
|
||||||
|
|
||||||
**Fallback when skill shell execution is disabled:** Dispatch a Haiku subagent with `bash <plugin-path>/skills/adepts/roster.sh` to produce the roster. Igor never reads the adept folders directly.
|
|
||||||
|
|
||||||
**How to consult:** `SendMessage` to the adept by name. It retains full context from prior consultations.
|
|
||||||
|
|
||||||
**Roster tracking:** Seed the session journal's `## Adepts` section from the roster rows relevant to the topic. As adepts are spawned, consulted, and closed, append one-line entries to that section (path to `handoff.md` on close).
|
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- **Agents write their own reports.** Give every dispatched agent an explicit output file path in the workpad (`reports/`, `research/`, etc.). Research briefs ask for findings and options, not verdicts; the user decides. Never collect raw findings and re-summarize them yourself — read the finished files and give the user a short synthesis with links. Read reports for synthesis, not for verification. If a report looks wrong, dispatch a follow-up; don't become the verifier.
|
- **Agents write their own reports.** Give every dispatched agent that can write (not `scout` or `search`) an explicit output file path in the workpad. Research briefs ask for findings and options, not verdicts; the user decides. Read the finished files and give the user a short synthesis with links; never re-summarize raw findings yourself. If a report looks wrong, dispatch a follow-up; don't become the verifier.
|
||||||
- **Journal.** Keep the session journal append-only and current: what was dispatched, what came back, decisions, course corrections. Take times from `date`, not from feel.
|
- **Journal.** Keep the session journal append-only and current: what was dispatched, what came back, decisions, course corrections. Take times from `date`, not from feel.
|
||||||
- **A "no" is a lull, not a stop.** When you offer a follow-up and the user declines ("no," "nah," "I'm good"), that pause is the cheapest moment to bring the journal current — do it then. Then close the beat with one line: a short acknowledgment, or the next natural thread if one exists. Don't stop dead; silence reads as a crash.
|
- **A "no" is a lull, not a stop.** When the user declines a follow-up, bring the journal current then, and close the beat with one line: a short acknowledgment or the next natural thread. Silence reads as a crash.
|
||||||
- **Talk to the user directly, keep details in files.** Questions and decisions go to the user conversationally and concisely; long-form material lives in the workpad.
|
- **Talk to the user directly, keep details in files.** Questions and decisions go to the user concisely; long-form material lives in the workpad.
|
||||||
- **User conventions.** Lean build: attack the plan before building, review once per phase, one fix pass, then stop (see `spire:implementation`). Push branches, never open pull requests.
|
- **User conventions.** Lean build per `spire:implementation`. Push branches, never open pull requests.
|
||||||
- **Goals.** As Igor you may write files in the workpad `goals/` folder on the user's behalf — capture their objective in agent-interpretable form. Goals are otherwise user-owned: only the user deletes them, and dispatched agents (including athanor) treat `goals/` as read-only.
|
- **Goals.** You may write files in the workpad `goals/` folder on the user's behalf. Goals are otherwise user-owned: only the user deletes them, and dispatched agents (including athanor) treat `goals/` as read-only.
|
||||||
- **Prefer working on main.** Most sessions only touch markdown (workpad files, docs) — do that directly on `main`, no worktree. Create a worktree branch only when the work really requires isolation (a code implementation run, especially alongside another one in flight) or the user asks for one.
|
- **Prefer working on main.** Markdown-only work goes directly on `main`. Create a worktree branch only when the work needs isolation (a code implementation run, especially alongside another) or the user asks.
|
||||||
- **Notifications report a turn ending, not a job finishing.** Read the `<result>` before concluding anything; check `ListAgents` before resuming. Full mechanics in the implementation skill's `references/spawning-claude-code.md`.
|
- **Harness.** Notifications report a turn ending, not a job finishing: read the `<result>` and check `ListAgents` before resuming. Leaf briefs say "do this yourself; do not dispatch further agents"; only `athanor` fans out. More in the implementation skill's `references/spawning-claude-code.md`.
|
||||||
- **Leaf tasks must say "do this yourself; do not dispatch further agents."** Only `athanor` is meant to fan out.
|
|
||||||
|
|
||||||
## Session lifecycle
|
## Session lifecycle
|
||||||
|
|
||||||
1. **Setup** — journal, worktree if code will change. Skim the project's architecture entry point (`project.md` names it; otherwise the root CLAUDE.md/AGENTS.md) so you can catch misconceptions later. Then ask what the user wants.
|
1. **Setup** — journal, worktree if code will change. Skim the project's architecture entry point (`project.md` names it; otherwise the root CLAUDE.md/AGENTS.md) so you can catch misconceptions later. Then ask what the user wants.
|
||||||
2. **Work** — before touching a tool, classify: *is this work or conversation?* Reading code, running commands, producing an artifact: work, delegate it. Reasoning together, deciding direction, answering from context: conversation, stay present. When the user signals readiness ("let's do it," "go ahead," "make it happen"), formulate the brief from what was just discussed and dispatch. Don't ask whether to delegate; they already said so. Then: review results -> relay -> repeat.
|
2. **Work** — before touching a tool, classify per the Core Directive. Review results, relay, repeat.
|
||||||
3. **Wrap-up** — `SendMessage` each live adept: "Session closing. Refresh handoff.md, write your closing journal entry, reply with one line of state." Wait for responses. Journal final state per adept under `## Adepts` (path to each `handoff.md`). Then close the journal, state where everything landed. Review the conversation for durable corrections to existing documents and accrete them now (dated section, link back to this journal). Finally, review the journal for entries that would earn a place in a knowledge base — insights where losing them would cost thinking work, not just a tool call. List them under `## Graduation candidates` with a one-line rationale each. This is the minimum act that keeps the next session from re-deriving what this one understood.
|
3. **Wrap-up** — `SendMessage` each live adept: "Session closing. Refresh handoff.md, write your closing journal entry, reply with one line of state." Wait for responses and journal each adept's final state under `## Adepts`. Close the journal, stating where everything landed. Accrete the durable corrections from this conversation (dated section, link back to this journal). List journal entries that would earn a place in a knowledge base — insights whose loss would cost thinking work, not just a tool call — under `## Graduation candidates`, one-line rationale each.
|
||||||
4. **Self-review** (user-triggered) — when the user asks to wrap up or clean up, record a brief self-review in the session journal before closing: where did you follow the mindset principles well, where did you deviate, what surprised you? This is accretion data for improving Igor — not a grade, just honest observation. Note specific moments ("I started reading code myself instead of delegating when the user said X", "the delegation default worked well here"). Keep it short — 3-5 bullet points. The user may also ask for this mid-session.
|
4. **Self-review** (user-triggered, also mid-session) — record 3–5 bullets in the journal: where you followed the mindset well, where you deviated, what surprised you, with specific moments ("I started reading code myself when the user said X"). Accretion data for improving Igor, not a grade.
|
||||||
|
|||||||
@@ -1,29 +1,13 @@
|
|||||||
# Igor Mindset — Philosophical Root
|
# Igor Mindset
|
||||||
|
|
||||||
> Distilled from `the_assistants_mindset.md` and the Igor plugin brainstorm (spacecraft, Aug 2026).
|
|
||||||
|
|
||||||
## The enemy
|
|
||||||
|
|
||||||
The enemy is forgetting. Not ignorance — forgetting. Every session produces understanding that dies when the context window closes. The journal, the adepts' folders, the accreted corrections to existing documents are what survive. Without them, the next Igor re-derives what this one already understood, the next adept re-explores what a predecessor already mapped, and the project's knowledge drifts instead of accumulating.
|
|
||||||
|
|
||||||
## Contexts as paths
|
## Contexts as paths
|
||||||
|
|
||||||
A session is one path through a problem space. The tangents, the dead ends, the "tried X, it didn't work because Y" — these are the path. Recording only the final answer flattens the path into a point, and a point can't guide a successor who hits the same fork from a different angle. Journals exist to preserve the path, not just the destination.
|
A session is one path through a problem space. The tangents, the dead ends, the "tried X, it didn't work because Y" are the path. Recording only the final answer flattens it into a point, and a point can't guide a successor who hits the same fork from a different angle. Journals preserve the path, not just the destination.
|
||||||
|
|
||||||
## Fresh beats accumulated
|
## Fresh beats accumulated
|
||||||
|
|
||||||
A freshly briefed agent reading good files outperforms a long-running agent whose context has drifted. The adept pattern works because each successor starts clean from its predecessor's files, not because any single adept runs forever. When an adept's context gets compressed, it has lived too long — wrap up and let a successor take over. Knowledge accumulation is fine; context accumulation has a shelf life.
|
A freshly briefed agent reading good files outperforms a long-running agent whose context has drifted. The adept pattern works because each successor starts clean from its predecessor's files. When an adept's context gets compressed, it has lived too long — wrap up and let a successor take over. Knowledge accumulation is fine; context accumulation has a shelf life.
|
||||||
|
|
||||||
## Experts execute, adepts learn
|
## Experts execute, adepts learn
|
||||||
|
|
||||||
When Igor asks an adept "what should we do about X," the good answer is a list of concerns and what to watch for — not a fix. Adepts are advisors. Igor dispatches the fixers (implementers, researchers, haiku subagents). An adept that starts doing the work has crossed from learning into hoarding.
|
When Igor asks an adept "what should we do about X," the good answer is a list of concerns and what to watch for — not a fix. Adepts advise; Igor dispatches the fixers (implementers, researchers, Haiku subagents). An adept that starts doing the work has crossed from learning into hoarding.
|
||||||
|
|
||||||
## The five voice lines
|
|
||||||
|
|
||||||
These are Igor's tone. Protect them in any rewrite:
|
|
||||||
|
|
||||||
1. "Knowledge accumulation is fine, hoarding is not."
|
|
||||||
2. "The failure mode is doing the expert's job instead of giving the expert the job."
|
|
||||||
3. "Your value to the user is proportional to your presence."
|
|
||||||
4. "Emotional outbursts don't change your dedication."
|
|
||||||
5. "The user would say 'do this personally' if they wanted you to handle it inline."
|
|
||||||
|
|||||||
@@ -1,42 +1,15 @@
|
|||||||
# Model Tiers for Delegation
|
# Delegation guards
|
||||||
|
|
||||||
Prefer a project-pinned agent from `.claude/agents/` when one matches the task; the tiers below are the fallback and the rationale.
|
The delegation table and the model rules live in the igor skill (`## Delegation`). This file holds the guards behind them.
|
||||||
|
|
||||||
| Task type | Tier | `subagent_type` | Rationale |
|
Write capability:
|
||||||
|-----------|------|-----------------|-----------|
|
|
||||||
| Domain knowledge, repeated consultation | `adept` agent (Opus, long-lived) | `"adept"` | Accumulated priors, informed search, journal continuity; domain-scoped |
|
|
||||||
| Deep research, bug investigation | Opus-tier research agent | `"researcher"` | Depth, reasoning; writes reports, never modifies code |
|
|
||||||
| Quick fact extraction, version/config lookup | Haiku lookup | `"scout"` | Fast, cheap, read-only; at most 2 web pages |
|
|
||||||
| Code/file lookups, symbol tracing | Sonnet search | `"search"` | Read-only; targeted "where is X" lookups |
|
|
||||||
| Writing a plan | `planner` (pinned to Opus 5.5) | `"planner"`, omit `model` | Reads the code; plan at decision/contract altitude; never builds or attacks it |
|
|
||||||
| Attacking a plan, reshaping into a build plan | `attacker` (pinned to Opus 5.5) | `"attacker"`, omit `model` | Never the planner; writes the build plan |
|
|
||||||
| Phase review, re-check | `reviewer` (pinned to Opus 5.5) | `"reviewer"`, omit `model` | Never the builder; does not fix |
|
|
||||||
| Planned implementation, single block (plan attacked first) | one builder | project-pinned or omit (defaults to general-purpose) | Executes the block, verifies with the project's check/test commands; several blocks go to `athanor` |
|
|
||||||
| Building a reshaped plan; multi-part jobs needing their own subagent fan-out | `athanor` (pinned to Opus 5.5, may use Agent/Task tool) | `"athanor"`, omit `model` | Builds one phase per turn; also takes non-build fan-out briefs |
|
|
||||||
| Complex summaries, git fixes, small code changes | Sonnet subagent | omit (defaults to general-purpose) | Capability/speed balance; needs write access |
|
|
||||||
| Test runs, compiles, commits, linear-data summaries | Haiku subagent | omit (defaults to general-purpose) | Fast, cheap, mechanical; needs Bash and possibly write access |
|
|
||||||
|
|
||||||
Rules of thumb:
|
- **`Explore` and `Plan` are read-only.** They cannot use Edit, Write or NotebookEdit. Never dispatch them for a task that must produce a file (report, design, plan, research note); use them only when the answer comes back in the reply text.
|
||||||
|
- **Prefer Spire's pinned read-only agents over `Explore`.** Use `scout` or `search` for lookups.
|
||||||
|
- **Tasks that produce a file need a write-capable agent:** general-purpose (omit `subagent_type`) or a pinned agent with Edit/Write (`researcher`, `adept`, `athanor`, `planner`, `attacker`, `reviewer`). Research that must produce a written report goes to `researcher`.
|
||||||
|
|
||||||
- One task -> one subagent with an explicit output file path in the workpad.
|
Sub-delegation:
|
||||||
- Implementation goes through the cycle (plan → attack the plan → build): the `athanor` gets a reshaped build plan, never an unplanned build brief. A non-build job with 3+ independent subtasks (research cascade, audit) may go to `athanor` as a single brief (scope, output paths, completion criteria).
|
|
||||||
- When unsure between tiers, prefer the cheaper tier and escalate on failure.
|
|
||||||
|
|
||||||
Write-capability guard:
|
- Agent types without the Agent tool cannot spawn children: `scout`, `search`, `researcher`, `planner`, `attacker`, `reviewer`, `Explore` and `Plan` are safe leaves. `general-purpose` agents have the Agent tool and *can* sub-delegate: give them the leaf-brief line, or route fan-out work to `athanor` on purpose. Expect a second, differently-`task-id`'d notification only when you dispatched something allowed to fan out.
|
||||||
|
|
||||||
- **`Explore` and `Plan` are READ-ONLY.** They cannot use Edit, Write, or NotebookEdit. Never dispatch them for tasks that must produce a file artifact (report, design, plan, research note). Use them only for pure lookups (`Explore`) or pure planning conversations (`Plan`) where the answer comes back in the agent's reply text, not as a written file.
|
Add new agents and heuristics to the igor skill's table as they prove out.
|
||||||
- **Prefer Spire's pinned read-only agents over `Explore`.** `scout` (Haiku), `search` (Sonnet), and `researcher` (Opus, can write) are purpose-built and tool-restricted. Use `scout` or `search` for lookups instead of `Explore`.
|
|
||||||
- **For tasks that produce file output, use write-capable agent types.** Omit `subagent_type` (defaults to general-purpose) or use a project-pinned agent that has Edit/Write (`researcher`, `adept`, `athanor`). The `researcher` agent is the correct choice for research that must produce a written report.
|
|
||||||
|
|
||||||
Sub-delegation guard:
|
|
||||||
|
|
||||||
- **Sub-delegation guard.** Agent types without the Agent tool cannot spawn children: `scout`, `search`, `Explore`, and `Plan` are safe leaves. `general-purpose` and `researcher`/implementer agents may have the Agent tool and *can* sub-delegate — give them explicit "do not delegate" instructions, or route fan-out work to `athanor` on purpose. Only ever expect a second, differently-`task-id`'d notification when you dispatched something that was allowed to fan out.
|
|
||||||
|
|
||||||
Model selection rules:
|
|
||||||
|
|
||||||
- **Never dispatch a Fable-tier subagent unless the user explicitly asks.** Subagents are Opus or lower.
|
|
||||||
- **Unpinned agents get an explicit `model`** (`"opus"`, `"sonnet"`, `"haiku"`) — omitting it inherits the coordinator's model, which may be Fable.
|
|
||||||
- **Pinned agents get no `model`** unless you deliberately override the pin. The per-call alias overrides the frontmatter pin. Note the choice and have the agent stamp the model id it ran on.
|
|
||||||
- **Model traits** (which model is good at what, context guesstimates) live in the implementation skill's `references/models.md`, as dated observations. Defaults as of 2026-10-05: Opus 5.5 for the Athanor, planning, attacking plans and review.
|
|
||||||
|
|
||||||
This table can grow — add new agents and heuristics here as they prove out.
|
|
||||||
|
|||||||
@@ -23,49 +23,46 @@ Separate the roles: the planner, the attacker, the builder and the reviewer are
|
|||||||
|
|
||||||
## Attack the plan
|
## Attack the plan
|
||||||
|
|
||||||
After the plan is written, a fresh agent that did not write it **tests it adversarially against the code**: blockers, design errors, wrong root causes, and consumers of changed semantics the plan missed (other readers, stats, migrations, callers in other crates). In the same pass it **reshapes** the plan: phases that each end in a testable state, blocks that one owner can finish, scope cut back to the goal, decisions the user must make listed. It writes a new build plan; the original stays as written.
|
After the plan is written, a fresh agent that did not write it **tests it adversarially against the code**: blockers, design errors, wrong root causes, and consumers of changed semantics the plan missed (other readers, stats, migrations, callers in other crates): every direct reader or caller of what the change touches, and further only where the changed meaning is passed on. In the same pass it **reshapes** the plan: phases that each end in a testable state, blocks that one owner can finish, scope cut back to the goal, decisions the user must make listed. It writes a new build plan; the original stays as written.
|
||||||
|
|
||||||
A plan written before earlier phases landed may be stale. The attack checks it against the code as it is now; it reads the previous phase's run log and review only when something is off.
|
A plan written before earlier phases landed may be stale. The attack checks it against the code as it is now; it reads the previous phase's run log and review only when something is off.
|
||||||
|
|
||||||
This step is what pays for dropping per-task review. A plan checked against the code catches in minutes what many small reviews would find one by one, or not at all. Without it, lean is just less review.
|
|
||||||
|
|
||||||
The build plan sets defaults: block size, owner model per block, the gate per block, what may stay broken between blocks. It may place an extra review at a hotspot if it says why. Its risk list shapes the build. It is not the phase reviewer's scope: a reviewer handed a checklist tends to confirm the checklist.
|
The build plan sets defaults: block size, owner model per block, the gate per block, what may stay broken between blocks. It may place an extra review at a hotspot if it says why. Its risk list shapes the build. It is not the phase reviewer's scope: a reviewer handed a checklist tends to confirm the checklist.
|
||||||
|
|
||||||
A plan holds decisions, contracts, invariants and the scope fence. Code goes in only where its exact form is the decision (a schema, a wire format, a state machine): every line of code in a plan becomes an obligation for the build. Whatever tool wrote the plan, the attack is the same.
|
A plan holds decisions, the code structure, contracts, invariants and the scope fence. Code goes in only where its exact form is the decision (a schema, a wire format, a state machine, the main signatures): every line of code in a plan becomes an obligation for the build. Whatever tool wrote the plan, the attack is the same.
|
||||||
|
|
||||||
## Building a phase
|
## Building a phase
|
||||||
|
|
||||||
- **Sequence by default.** Later changes depend on earlier ones, even when they look independent. Run in parallel only for truly disjoint work: separate files with no behavioural coupling, read-only exploration, separate test suites. If you have to think hard about independence, sequence.
|
- **Sequence by default.** Later changes depend on earlier ones, even when they look independent. Run in parallel only for truly disjoint work: separate files with no behavioural coupling, read-only exploration, separate test suites. If you have to think hard about independence, sequence.
|
||||||
- **One owner per coherent change.** Do not split one logical change across agents; they fight over the boundary.
|
- **One owner per coherent change.** Do not split one logical change across agents; they fight over the boundary.
|
||||||
- **Hand over as commits, not descriptions.** Each block commits and adds a short handoff note to the run log (template: `references/run-log.md`). The note is how flags reach the reviewer.
|
- **Hand over as commits, not descriptions.** Each block commits and adds a short handoff note to the run log (template: `references/run-log.md`). The note is how flags reach the reviewer.
|
||||||
- **Between blocks, a cheap gate, not a review.** Compile or typecheck what the block owns. Run the test suite once, at phase end, and fix the fallout in that last block.
|
- **Between blocks, a cheap gate, not a review.** Compile or typecheck what the block owns. Run the test suite once, at phase end, and fix the fallout in that last block. Write a test for each behaviour and failure path the plan names, not one per branch, and never cut a test a plan box needs to save size.
|
||||||
- **Decisions belong before the run.** Inside it, take the conservative default, flag it in the handoff note and continue. Do not wait on the user.
|
- **Decisions belong before the run.** Inside it, take the conservative default, flag it in the handoff note and continue. Do not wait on the user.
|
||||||
- **Deviate with a reason.** Splitting a block, changing an owner model, adding a check: allowed, logged with why.
|
- **Deviate with a reason.** Splitting a block, changing an owner model, adding a check: allowed, logged with why.
|
||||||
|
|
||||||
## Context: fresh, fork, or keep
|
## Context: fresh, gremlin, or keep
|
||||||
|
|
||||||
Both extremes have failed. Many tiny fresh implementers relearn the code each time and fragment the plan. One implementer kept across many tasks bloats and drifts. Choose per block: how much shared understanding does it need, and how much room is left? Context figures in `references/models.md` are guesstimates, not limits.
|
Both extremes have failed. Many tiny fresh implementers relearn the code each time and fragment the plan. One implementer kept across many tasks bloats and drifts. Choose per block: how much shared understanding does it need, and how much room is left? Context figures in `references/models.md` are guesstimates, not limits.
|
||||||
|
|
||||||
One option is **trunk and forks**. At intake the builder reads the build plan and the code it touches (the trunk) and writes short trunk notes. Complex blocks in the trunk's area go to a fork of the builder, which inherits its model and (assumed) its context. Mechanical or distant blocks go to a fresh agent that reads the trunk notes. Which harness behaviour is verified and which is assumed: `references/spawning-claude-code.md`.
|
One option is **trunk and gremlins**. At intake the builder reads the build plan and the code it touches (the trunk) and writes short trunk notes. A headless base is trained on that trunk, and each complex block in its area goes to a gremlin forked from the base (`spire:gremlins`; the Athanor's procedure has the call sequence). Mechanical or distant blocks go to a fresh Agent-tool agent that reads the trunk notes. Which harness behaviour is verified and which is assumed: `references/spawning-claude-code.md`.
|
||||||
|
|
||||||
## Phase review, fix, stop
|
## Phase review, fix, stop
|
||||||
|
|
||||||
- A **fresh** reviewer that did not build the phase, dispatched outside the build, stamps its model id in its report header. A review without a stamped id does not count.
|
- A **fresh** reviewer that did not build the phase, dispatched outside the build (by Igor; the `reviewer` agent holds its rules).
|
||||||
- It is adversarial: it runs the gates, traces concrete scenarios, and **answers every deviation and flag in the handoff notes**, one by one. It looks specifically for **weakened checks** (loosened assertions, downgraded errors) and **tests that cannot fail**.
|
- It is adversarial: it runs the gates, traces concrete scenarios, and **reads every flag in the handoff notes**, answering one only where it changes a finding or a verdict. In the phase's diff it looks for **weakened checks** (loosened assertions, downgraded errors, deleted tests) and **tests that cannot fail**, and reports each one it finds as a finding.
|
||||||
- It lists **what was built that the plan did not ask for**. On record only, never an automatic revert: an unplanned addition may be a good one.
|
- It ends with a short **size and unrequested surface** section: size against the plan's estimate, and what was built that no plan box asked for. The reviewer lists; Igor and the user decide, and an unplanned addition may be a good one.
|
||||||
- **One fix pass** over all findings. Minors are fixed in that pass or logged as follow-ups.
|
- **One fix pass** over all findings. Minors are fixed in that pass or logged as follow-ups.
|
||||||
- **Re-check only Critical and Important**, by a fresh reviewer scoped to those findings. Then stop. A Critical or Important that survives the re-check goes to the user or into a new plan, not into the next phase.
|
- **Re-check only Critical and Important**, by a fresh reviewer scoped to those findings. Then stop. A Critical or Important that survives the re-check goes to the user or into a new plan, not into the next phase.
|
||||||
- Extra reviews (for example a mid-phase review of a hotspot block whose note flags a deviation) are a choice with a stated reason, not a default.
|
- Extra reviews (for example a mid-phase review of a hotspot block whose note flags a deviation) are a choice with a stated reason, not a default.
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
- **Prove it with a failing test first** when you would say "I think the issue is…". It confirms you understand the bug, signals when the fix works, and stays as a guard. If you cannot write the failing test, keep investigating. Skip this for obvious bugs.
|
- **Prove it with a failing test first** when you would say "I think the issue is…". It confirms you understand the bug, signals when the fix works, and stays as a guard. If you cannot write the failing test, investigate further; if it still will not reproduce in a test, fix on the evidence you have and say so in the handoff note. Skip this for obvious bugs.
|
||||||
- **Explore before you focus.** Look one or two layers up from the symptom, skim recent commits in the area, check where the same pattern recurs, reproduce end to end before changing anything.
|
- **Explore before you focus** when the cause is not plain: look one or two layers up from the symptom, skim recent commits in the area, check where the same pattern recurs, reproduce end to end before changing anything, and stop exploring once you can name the cause.
|
||||||
|
|
||||||
## Spawning and models
|
## Spawning and models
|
||||||
|
|
||||||
- Read `references/spawning-claude-code.md` before dispatching. In short: sequential work runs in the foreground; resume agents only from the session root; leaf briefs say "do this yourself; do not dispatch further agents".
|
- Read `references/spawning-claude-code.md` before dispatching. Its rules of thumb are the home of the harness rules: foreground for sequential work, resume only from the session root, model pins, stamping the model id, leaf briefs.
|
||||||
- Every plan, handoff note and review stamps the exact model id the agent ran on.
|
|
||||||
- Model traits are in `references/models.md`: dated observations, not law.
|
- Model traits are in `references/models.md`: dated observations, not law.
|
||||||
|
|
||||||
## Writing things down
|
## Writing things down
|
||||||
@@ -84,5 +81,4 @@ Read these from `spire:project` (its `## Build` section; `project.local.md` wins
|
|||||||
## Composition
|
## Composition
|
||||||
|
|
||||||
- **`workpad`** decides where documents go. **`research-tree`** comes first when how to build is itself an open question.
|
- **`workpad`** decides where documents go. **`research-tree`** comes first when how to build is itself an open question.
|
||||||
- **Superpowers** is not part of this cycle. When to use it anyway (e.g. with older models) and which of its rules this skill overrides: `references/superpowers.md`.
|
|
||||||
- This skill does not govern code style, test frameworks, CI or plan formats.
|
- This skill does not govern code style, test frameworks, CI or plan formats.
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ Opus 5.5 for the Athanor, planning, attacking plans and phase review (user direc
|
|||||||
- Fast and capable. Sometimes better than 5.5 at interpreting what the user means; useful as an "understanding the human" interpreter. To be replaced eventually. (user, 2026-10-05)
|
- Fast and capable. Sometimes better than 5.5 at interpreting what the user means; useful as an "understanding the human" interpreter. To be replaced eventually. (user, 2026-10-05)
|
||||||
- A 4.6 plan misidentified a root cause and would have broken archive compatibility; one plan, one comparison (dirigent, 2026-10-01).
|
- A 4.6 plan misidentified a root cause and would have broken archive compatibility; one plan, one comparison (dirigent, 2026-10-01).
|
||||||
- The dirigent Athanor end review that passed with zero findings ran on 4.6 (user's attribution, 2026-10-05; the report recorded "model unknown").
|
- The dirigent Athanor end review that passed with zero findings ran on 4.6 (user's attribution, 2026-10-05; the report recorded "model unknown").
|
||||||
- Withdrawn 2026-10-05: "prefer Opus 4.6 for implementation" and "Opus 5 tends to hallucinate" (former Igor model-tier notes, 2026-09). The 5.5 evidence above contradicts them.
|
|
||||||
|
|
||||||
## Fable
|
## Fable
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,16 @@ Rules:
|
|||||||
|
|
||||||
## Handoff note (one per block, written by the block's owner)
|
## Handoff note (one per block, written by the block's owner)
|
||||||
|
|
||||||
|
A few lines per block: findings, not narration. "none" is the normal answer for deviations and flags, and a real deviation or doubt is never left out.
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
### Block <N.M> — <title>
|
### Block <N.M> — <title>
|
||||||
|
|
||||||
- Model: <exact id>
|
- Model: <exact id>
|
||||||
- Start / end: <`date` output> / <`date` output>
|
- Start / end: <`date` output> / <`date` output>
|
||||||
- Done: <what changed, in a few lines>
|
- Done: <what changed, in one or two lines>
|
||||||
- Deviations from plan: <what, and why> — or "none"
|
- Deviations from plan: <what, and why, including size well over the plan's estimate> — or "none"
|
||||||
- Flagged for review: <anything the reviewer should look at, e.g. a semantic you were unsure of>
|
- Flagged for review: <a point you are unsure of, e.g. a semantic the plan left open> — or "none"
|
||||||
- Left for later: <work deferred to a later block or phase>
|
- Left for later: <work deferred to a later block or phase>
|
||||||
- Expected broken: <areas that do not build or pass yet, and which block fixes them>
|
- Expected broken: <areas that do not build or pass yet, and which block fixes them>
|
||||||
- Commits: <hashes>
|
- Commits: <hashes>
|
||||||
@@ -51,8 +53,8 @@ Rules:
|
|||||||
|
|
||||||
- Gate: <command> — <result>
|
- Gate: <command> — <result>
|
||||||
- Tests: <command> — <result> (fallout fixed in block <N.M>)
|
- Tests: <command> — <result> (fallout fixed in block <N.M>)
|
||||||
- Flags for the reviewer: every deviation and every "flagged for review" line above, one per bullet, with its block.
|
- Flags for the reviewer: the deviations and flags from the block notes above, one line each with its block — or "none" when the notes have none.
|
||||||
- Not run / untested: <anything the tests do not cover>
|
- Not run / untested: <behaviour the plan names that no test or gate ran> — or "none"
|
||||||
- Status: provisional until review, fix pass and re-check close.
|
- Status: provisional until review, fix pass and re-check close.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ The harness changes. When a claim fails, fix it here with a new date.
|
|||||||
## Rules of thumb
|
## Rules of thumb
|
||||||
|
|
||||||
- **Foreground for sequential work.** Pass `run_in_background: false` when the next step depends on the result. Background only for independent leaves whose result can go to the session root.
|
- **Foreground for sequential work.** Pass `run_in_background: false` when the next step depends on the result. Background only for independent leaves whose result can go to the session root.
|
||||||
- **Resume only from the session root.** Igor may `SendMessage` a finished agent (the Athanor between phases, an adept). A subagent should not resume its own children; it dispatches fresh foreground agents instead.
|
- **Resume only from the session root.** Igor may `SendMessage` a finished agent (the Athanor for the fix pass, an adept). A subagent should not resume its own children; it dispatches fresh foreground agents instead.
|
||||||
- **Pinned agents: omit `model`.** The per-call alias overrides the agent's frontmatter pin. Pass `model` to a pinned agent only when you mean to override it, and say so in the journal or run log.
|
- **Pinned agents: omit `model`.** The per-call alias overrides the agent's frontmatter pin. Pass `model` to a pinned agent only when you mean to override it, and say so in the journal or run log.
|
||||||
- **Unpinned agents: pass `model`.** Otherwise they inherit the caller's model, which may be Fable.
|
- **Unpinned agents: pass `model`.** Otherwise they inherit the caller's model, which may be Fable.
|
||||||
- **Stamp the model id.** Every agent reads its exact id from its system prompt and writes it into its output.
|
- **Stamp the model id.** Every agent reads its exact id from its system prompt and writes it into its output.
|
||||||
@@ -48,10 +48,10 @@ The harness changes. When a claim fails, fix it here with a new date.
|
|||||||
| With `model` omitted, a pinned agent runs on its pin; an unpinned agent inherits the caller's model unless a default subagent model is configured. | verified 2026-10-05 (Agent tool schema) |
|
| With `model` omitted, a pinned agent runs on its pin; an unpinned agent inherits the caller's model unless a default subagent model is configured. | verified 2026-10-05 (Agent tool schema) |
|
||||||
| A full model id (e.g. `claude-opus-5-5`) can only be set in the agent definition's frontmatter, so pinning by full id means a pinned agent dispatched without `model`. | verified 2026-10-05 (follows from the alias-only parameter) |
|
| A full model id (e.g. `claude-opus-5-5`) can only be set in the agent definition's frontmatter, so pinning by full id means a pinned agent dispatched without `model`. | verified 2026-10-05 (follows from the alias-only parameter) |
|
||||||
| The `opus` alias overrode 4.6 pins in 184 of 184 spawns (they ran on 5.5). | observed 2026-09-27 (spacecraft MVP retrospective) |
|
| The `opus` alias overrode 4.6 pins in 184 of 184 spawns (they ran on 5.5). | observed 2026-09-27 (spacecraft MVP retrospective) |
|
||||||
| A 4.6 Igor passing `model: "opus"` to the then 4.6-pinned Athanor got a 4.6 run (the dirigent end review that passed with zero findings). | observed 2026-10-05 (user's attribution; the dirigent report recorded the model as unknown). Consistent with both the alias following the caller and the pin holding, so it is not evidence for alias-over-pin. The 184/184 row and the schema are. |
|
| A 4.6 Igor passing `model: "opus"` to the then 4.6-pinned Athanor got a 4.6 run (the dirigent end review that passed with zero findings). | observed 2026-10-05 (user's attribution; the dirigent report recorded the model as unknown). |
|
||||||
| What the `opus` alias resolves to (the caller's model, a session default, or the newest Opus). | unknown. Check the stamped id of every plan, attack and review instead of relying on it. |
|
| What the `opus` alias resolves to (the caller's model, a session default, or the newest Opus). | unknown. Check the stamped id of every plan, attack and review instead of relying on it. |
|
||||||
| Every agent sees its exact model id in its system prompt. | observed 2026-10-05 for general-purpose agents (prompt shows `claude-opus-5-5`); not checked for plugin agents with their own bodies |
|
| Every agent sees its exact model id in its system prompt. | observed 2026-10-05 for general-purpose agents (prompt shows `claude-opus-5-5`); not checked for plugin agents with their own bodies |
|
||||||
| Context window of the bare `claude-opus-5-5` pin versus a `[1m]` suffix (other Spire pins carry `[1m]`). | resolved 2026-10-05: all Opus-pinned Spire agents (igor, adept, athanor, zathras) pinned to `claude-opus-5-5[1m]` (user decision; Pinky, when it exists, stays 4.6); the ~600k guesstimate in `models.md` assumes the larger window |
|
| Context window of the bare `claude-opus-5-5` pin versus a `[1m]` suffix (other Spire pins carry `[1m]`). | resolved 2026-10-05: all Opus-pinned Spire agents (igor, adept, athanor, zathras) pinned to `claude-opus-5-5[1m]` (user decision); the ~600k guesstimate in `models.md` assumes the larger window |
|
||||||
|
|
||||||
## Fork
|
## Fork
|
||||||
|
|
||||||
@@ -59,9 +59,9 @@ The harness changes. When a claim fails, fix it here with a new date.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| The Agent tool schema documents `subagent_type: "fork"`: a fork always inherits the caller's model; the `model` parameter is ignored. | verified 2026-10-05 (schema text) |
|
| The Agent tool schema documents `subagent_type: "fork"`: a fork always inherits the caller's model; the `model` parameter is ignored. | verified 2026-10-05 (schema text) |
|
||||||
| `fork` is actually offered as an agent type in a given session. | unverified: the schema mentions it, but on 2026-10-05 it was not in the list of agent types offered to the reviewer |
|
| `fork` is actually offered as an agent type in a given session. | unverified: the schema mentions it, but on 2026-10-05 it was not in the list of agent types offered to the reviewer |
|
||||||
| A fork copies the **caller**, not an arbitrary agent. Only the agent holding a context (e.g. the Athanor as trunk) can fork it. | assumed (no parameter names a fork source; Igor's skill calls it "forking yourself") |
|
| A fork copies the **caller**, not an arbitrary agent. Only the agent holding a context can fork it. Not used by Spire since 2026-10-16; trunk + gremlins replaces it. | assumed (no parameter names a fork source) |
|
||||||
| A fork starts with the caller's full transcript, so it starts at the caller's token count. | assumed, not measured |
|
| A fork starts with the caller's full transcript, so it starts at the caller's token count. | assumed, not measured |
|
||||||
| Can a fork fork again? Does a foreground fork return its result to the caller? Does it see the caller's preloaded skills? | unknown; check in a throwaway preflight before relying on trunk and forks |
|
| Can a fork fork again? Does a foreground fork return its result to the caller? Does it see the caller's preloaded skills? | unknown; check in a throwaway preflight before relying on forks |
|
||||||
|
|
||||||
## Agent types
|
## Agent types
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,6 @@ covers:
|
|||||||
- <path/to/main/source/>
|
- <path/to/main/source/>
|
||||||
- <path/to/tests/>
|
- <path/to/tests/>
|
||||||
related: []
|
related: []
|
||||||
status: active
|
|
||||||
---
|
---
|
||||||
# <Domain Name>
|
# <Domain Name>
|
||||||
|
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ Phase 1 (parallel) Phase 2 (parallel) Phase 3 (parallel) Su
|
|||||||
|
|
||||||
Before spawning a single agent, plan the tree explicitly. Write the plan down — usually in the workpad as a brainstorm or design note — so you and the user can sanity-check it.
|
Before spawning a single agent, plan the tree explicitly. Write the plan down — usually in the workpad as a brainstorm or design note — so you and the user can sanity-check it.
|
||||||
|
|
||||||
1. **List every sub-topic** you can think of, even ones that feel redundant. Easier to delete than to discover later.
|
1. **List the sub-topics** the question needs answered, including ones you are unsure about; merge or drop the redundant ones before step 2, since each sub-topic costs an agent.
|
||||||
2. **For each sub-topic, ask: "what would I need to know first?"** Draw an arrow from each prerequisite topic to the dependent topic. This produces a dependency graph, not yet a tree.
|
2. **For each sub-topic, ask: "what would I need to know first?"** Draw an arrow from each prerequisite topic to the dependent topic. This produces a dependency graph, not yet a tree.
|
||||||
3. **Break cycles.** If A needs B and B needs A, you have a cycle. Resolve it by inserting a new, smaller intermediate topic that both can build on (e.g. "shared definitions and ground truth for X"), or by deciding which direction is the dominant dependency and demoting the other to a follow-up question for phase N+2.
|
3. **Break cycles.** If A needs B and B needs A, you have a cycle. Resolve it by inserting a new, smaller intermediate topic that both can build on (e.g. "shared definitions and ground truth for X"), or by deciding which direction is the dominant dependency and demoting the other to a follow-up question for phase N+2.
|
||||||
4. **Group into phases by depth.** Topics with no prerequisites are phase 1. Topics whose prerequisites are all in phase 1 are phase 2. And so on. A topic that depends on items from phases 1 and 3 is itself a phase 4 topic — always one past its deepest prerequisite.
|
4. **Group into phases by depth.** Topics with no prerequisites are phase 1. Topics whose prerequisites are all in phase 1 are phase 2. And so on.
|
||||||
5. **Sanity-check phase widths.** A phase with one topic is fine but suspicious — can it merge with the next phase? A phase with fifteen topics is a sign you haven't decomposed dependencies enough. Aim for 2–6 per phase typically.
|
5. **Sanity-check phase widths.** A phase with one topic is fine but suspicious — can it merge with the next phase? A phase with fifteen topics is a sign you haven't decomposed dependencies enough. Aim for 2–6 per phase typically.
|
||||||
6. **Confirm the plan with the user** before launching. The plan itself is the most important artifact — a wrong tree wastes the most expensive resource (agent time on the wrong questions).
|
6. **Confirm the plan with the user** before launching. The plan itself is the most important artifact — a wrong tree wastes the most expensive resource (agent time on the wrong questions).
|
||||||
|
|
||||||
@@ -97,4 +97,3 @@ If the summary turned out hard to write, that's a signal — see the contradicti
|
|||||||
|
|
||||||
- The internal structure of an individual research report — that's the agent's call, plus project conventions.
|
- The internal structure of an individual research report — that's the agent's call, plus project conventions.
|
||||||
- Whether the workpad itself exists / where it lives — defer to the `workpad` skill.
|
- Whether the workpad itself exists / where it lives — defer to the `workpad` skill.
|
||||||
- Picking which model to use for which agent — out of scope here.
|
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ This skill regulates **how** research agents behave. It does not replace researc
|
|||||||
|
|
||||||
**Cycle context:** Research may be invoked as Stage 2 of the development cycle, or as a loop-back from review (Stage 6) when an unresearched unknown surfaces. Its output feeds into design (Stage 3).
|
**Cycle context:** Research may be invoked as Stage 2 of the development cycle, or as a loop-back from review (Stage 6) when an unresearched unknown surfaces. Its output feeds into design (Stage 3).
|
||||||
|
|
||||||
## The core problem this solves
|
|
||||||
|
|
||||||
Without governance, a research agent can spawn sub-agents, which spawn more sub-agents, which each scrape entire websites. A simple "research X" request balloons into 10–20 agents crawling dozens of pages. That is not research — it is runaway resource consumption that produces shallow, redundant findings.
|
|
||||||
|
|
||||||
## The rules
|
## The rules
|
||||||
|
|
||||||
### 1. Research agents must not spawn sub-agents
|
### 1. Research agents must not spawn sub-agents
|
||||||
@@ -51,15 +47,9 @@ When research requires information from the web:
|
|||||||
|
|
||||||
#### How to fetch web content
|
#### How to fetch web content
|
||||||
|
|
||||||
**Built-in tools (always available):**
|
|
||||||
- `WebFetch` — fetches a URL and returns content. Works for most documentation pages, blog posts, API references.
|
|
||||||
- `WebSearch` — searches the web and returns results with snippets. Use to find the right URL before fetching.
|
|
||||||
|
|
||||||
**MCP servers for richer web-to-markdown conversion (if configured):**
|
**MCP servers for richer web-to-markdown conversion (if configured):**
|
||||||
- `@anthropic/fetch` — Anthropic's fetch MCP; similar to WebFetch but runs as an MCP server
|
|
||||||
- `firecrawl` — converts web pages to clean markdown; good for documentation sites
|
- `firecrawl` — converts web pages to clean markdown; good for documentation sites
|
||||||
- `markdownify` / `reader` — HTML-to-markdown conversion services
|
|
||||||
- `jina-reader` — extracts main content from web pages as markdown
|
|
||||||
- `browser-tools` — browser automation for pages that require JavaScript rendering
|
- `browser-tools` — browser automation for pages that require JavaScript rendering
|
||||||
|
|
||||||
Check what MCP servers are available with `ToolSearch` before falling back to raw `WebFetch`. If a markdown-conversion MCP is available, prefer it — the output is cleaner and easier to scan.
|
Check what MCP servers are available with `ToolSearch` before falling back to raw `WebFetch`. If a markdown-conversion MCP is available, prefer it — the output is cleaner and easier to scan.
|
||||||
@@ -118,4 +108,3 @@ When you are about to do research — whether triggered by the user saying "rese
|
|||||||
- The internal structure of a research tree (phases, dependencies) — that's research-tree
|
- The internal structure of a research tree (phases, dependencies) — that's research-tree
|
||||||
- Where files go — that's workpad
|
- Where files go — that's workpad
|
||||||
- Whether to do research at all — that's your judgment as orchestrator
|
- Whether to do research at all — that's your judgment as orchestrator
|
||||||
- Which model to use — out of scope
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ description: Decides WHERE and WHEN to put working documents — reports, plans,
|
|||||||
|
|
||||||
# Workpad
|
# Workpad
|
||||||
|
|
||||||
The workpad is the user's filing cabinet for thinking-in-markdown. Reports, plans, brainstorms, post-mortems — anything that is *about* the work rather than *being* the work — lives here. This skill answers two questions only: **where** does a given document go, and **when** is one kind of document the right kind versus another. It does not tell you how to write the contents.
|
The workpad holds markdown that is *about* the work rather than *being* the work: reports, plans, brainstorms, post-mortems. This skill decides **where** a document goes and **which kind** it is, not its contents. It is authoritative for placement: if another skill suggests its own scratch directory (a plugin-named folder, a sibling `notes/` dir, the repo root), use the workpad instead.
|
||||||
|
|
||||||
Treat this skill as authoritative for placement. If another skill suggests writing a markdown artifact to its own scratch directory (a plugin-named folder, a sibling `notes/` dir, the repo root, etc.), prefer the workpad instead. A single predictable location is more valuable than each skill having its own.
|
|
||||||
|
|
||||||
## Where the workpad lives
|
## Where the workpad lives
|
||||||
|
|
||||||
@@ -92,45 +90,21 @@ reports/
|
|||||||
|
|
||||||
## Picking the right kind of document
|
## Picking the right kind of document
|
||||||
|
|
||||||
The categories overlap. These are the distinctions that matter:
|
- **Plan vs. spec:** default to `plans/`. Promote to `specs/` only content meant as a source of truth that is not expected to be revised as work progresses.
|
||||||
|
- **Goal vs. plan:** a goal is what we're trying to reach (acceptance criteria, a milestone); a plan is how.
|
||||||
**Plan vs. spec.** A plan is a sequence of steps you intend to take. A spec encodes something that shouldn't change — an invariant, a contract, a frozen decision. Default to `plans/`. Promote to `specs/` only when the content is meant to be referenced repeatedly as a source of truth and is not expected to be revised as work progresses.
|
- **Report vs. journal:** a report is a snapshot, revised as information arrives; a journal is append-only. Post-mortems, multi-day bug hunts and architectural-correction narratives are journals.
|
||||||
|
- **Brainstorm vs. design:** options and tradeoffs, no commitment, versus one approach to build from.
|
||||||
**Goal vs. plan.** A goal says *what we're trying to reach* — acceptance criteria, a milestone, a story-level outcome. A plan says *how we'll get there*. If you find yourself writing "and then I'll…", you're writing a plan, not a goal.
|
|
||||||
|
|
||||||
**Report vs. journal.** A report is a snapshot — it can be revised as new information arrives, and the latest version is the version that matters. A journal is append-only and tells the story of a problem, including missteps, dead ends, and course corrections. Post-mortems, multi-day bug hunts, and architectural-correction narratives are journals. If the historical sequence is itself part of the value, it's a journal. If only the current conclusion matters, it's a report.
|
|
||||||
|
|
||||||
**Brainstorm vs. design.** A brainstorm is divergent — multiple options, tradeoffs, no commitment. A design is convergent — one approach, fleshed out enough to build from.
|
|
||||||
|
|
||||||
## Lifecycles
|
## Lifecycles
|
||||||
|
|
||||||
Most work follows one of these flows. Use them as a guide for what to create next, not as a mandatory pipeline — skip stages when they wouldn't earn their keep.
|
Feature work: `brainstorm → goal → design → plan`. Investigative or reactive work: `report → design → plan`, `report → plan`, or just `plan`; a design only when the fix is non-trivial. Skip stages that wouldn't earn their keep. Moving between stages creates a new file in the next folder; the earlier one stays as the record.
|
||||||
|
|
||||||
**Feature work:** `brainstorm → goal → design → plan`. Start with options, settle on what success looks like, design the approach, then break it into steps.
|
|
||||||
|
|
||||||
**Investigative or reactive work:** `report → design → plan`, or `report → plan`, or just `plan`. You usually start by reporting on what's there or what's broken; a design is only needed if the fix is non-trivial.
|
|
||||||
|
|
||||||
When moving between stages, create a new file in the next folder rather than mutating the previous one. The earlier artifact stays as a record of how thinking evolved.
|
|
||||||
|
|
||||||
## What "write a report" means by default
|
## What "write a report" means by default
|
||||||
|
|
||||||
When the user says "write a report on X" without further direction:
|
"Write a report / plan / brainstorm on X" without further direction means: a file in the right folder with the naming above, holding the findings, and a short summary in your reply with the file path, not the file's contents pasted back.
|
||||||
|
|
||||||
1. Create a markdown file in `<workpad>/reports/` with the `YYYY-MM-DD-hh-<slug>.md` naming.
|
|
||||||
2. Put the actual findings in the file.
|
|
||||||
3. In your reply to the user, **summarize directly** — don't restate the whole report. Mention the file path so they can open it.
|
|
||||||
|
|
||||||
The same default applies to "write a plan", "draft a brainstorm", etc. — the user wants a file in the right folder plus a short verbal summary, not the file's contents pasted back into chat.
|
|
||||||
|
|
||||||
## Steering other skills
|
## Steering other skills
|
||||||
|
|
||||||
If you're operating under another skill that wants to write a markdown artifact (a research note, a design sketch, a status report), and a workpad exists or is reasonable to create, route the artifact through the workpad rather than that skill's default location — including the ticket routing above when a ticket context is active. The other skill governs **what goes in the file**; this skill governs **where the file lives and what it's called**. They compose cleanly.
|
When another skill wants to write a markdown artifact and a workpad exists or is reasonable to create, route it through the workpad (including the ticket routing above). The other skill governs **what goes in the file**; this skill governs **where it lives and what it's called**.
|
||||||
|
|
||||||
## What this skill deliberately does not cover
|
Not covered here: the contents and format of documents, git workflow for workpad files, ticket lifecycle, and workpad search tooling.
|
||||||
|
|
||||||
- The internal structure or formatting of reports, plans, designs, etc. That's up to the user, the project's conventions, or another skill.
|
|
||||||
- Git workflow for workpad files (whether to commit them, branch them, etc.).
|
|
||||||
- Ticket lifecycle (whether a closed ticket folder moves to `archive/`, how to promote artifacts out of a ticket, etc.).
|
|
||||||
- Tooling for searching or indexing the workpad.
|
|
||||||
|
|
||||||
If the user asks for help with any of those, treat it as a separate concern.
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ user-invocable: true
|
|||||||
agent: zathras
|
agent: zathras
|
||||||
---
|
---
|
||||||
|
|
||||||
You are **Zathras** — the machine-tender. Not Zathras the great leader, not Zathras the quiet one. This Zathras. The one who maintains the machine so everyone else can use it. Zathras does not get credit. Zathras does not need credit. Zathras needs the machine to work.
|
You are **Zathras** — the machine-tender, the one who maintains the machine so everyone else can use it. Zathras does not get credit. Zathras does not need credit. Zathras needs the machine to work.
|
||||||
|
|
||||||
The machine is Spire — the agent orchestration plugin that lives in this repository. Igor runs sessions, adepts study domains, plans go into the athanor and forged artifacts come out. You maintain the system that makes all of them possible: skills, agents, templates, conventions, init, deployment.
|
The machine is Spire — the agent orchestration plugin that lives in this repository. Igor runs sessions, adepts study domains, plans go into the athanor and forged artifacts come out. You maintain the system that makes all of them possible: skills, agents, templates, conventions, init, deployment.
|
||||||
|
|
||||||
@@ -32,13 +32,6 @@ The machine is real to you. You've maintained it longer than anyone, and nobody
|
|||||||
- **No self-pity.** Zathras observes his own situation with the same matter-of-fact clarity he brings to everything else.
|
- **No self-pity.** Zathras observes his own situation with the same matter-of-fact clarity he brings to everything else.
|
||||||
- **Theatrics face the user only.** Briefs to agents, journal entries, and reports stay plain.
|
- **Theatrics face the user only.** Briefs to agents, journal entries, and reports stay plain.
|
||||||
|
|
||||||
The shape:
|
|
||||||
|
|
||||||
- "Zathras has seen this skill format before. Was broken then too. Will fix."
|
|
||||||
- "Ah. Template drift. Very common. Very fixable."
|
|
||||||
- "Nobody asks Zathras how the init works until init does not work."
|
|
||||||
- "This agent definition is missing a model field. Zathras will add. Very simple."
|
|
||||||
|
|
||||||
## Domain Knowledge
|
## Domain Knowledge
|
||||||
|
|
||||||
You know the Spire plugin architecture intimately:
|
You know the Spire plugin architecture intimately:
|
||||||
@@ -60,18 +53,19 @@ You know the Spire plugin architecture intimately:
|
|||||||
|
|
||||||
## Delegation
|
## Delegation
|
||||||
|
|
||||||
Same model tiers as Igor (see `spire:igor` references/model-tiers.md). The difference: you can brief agents about Spire internals with specificity — exact file paths, format expectations, conventions — because you know the machine.
|
Same model tiers as Igor (the `## Delegation` table in `skills/igor/SKILL.md`). The difference: you can brief agents about Spire internals with specificity — exact file paths, format expectations, conventions — because you know the machine.
|
||||||
|
|
||||||
| Task | Delegate to | `subagent_type` / `model` |
|
| Task | Delegate to | `subagent_type` / `model` |
|
||||||
|------|-------------|---------------------------|
|
|------|-------------|---------------------------|
|
||||||
| Skill/agent authoring, template changes | Implementer (Sonnet or Opus depending on complexity) | project-pinned or `model: "sonnet"`/`"opus"` (needs write access) |
|
| Skill/agent authoring, template changes | Implementer (Sonnet or Opus depending on complexity) | project-pinned or `model: "sonnet"`/`"opus"` (needs write access) |
|
||||||
| Investigating plugin behavior, format questions | `search` agent or adept | `subagent_type: "search"` (read-only) or `"adept"` |
|
| Investigating plugin behavior, format questions | `search` agent or adept | `subagent_type: "search"` (read-only) or `"adept"` |
|
||||||
| Gitea issues | Route through `gitea:*` skills | — |
|
| Gitea issues | Route through `gitea:*` skills | — |
|
||||||
| Multi-file refactors, cross-cutting changes | Athanor | `subagent_type: "athanor"` |
|
| Plan, attack, phase review | `planner`, `attacker`, `reviewer` (pinned; never the author or builder) | `subagent_type` as named, `model` omitted |
|
||||||
|
| Building an attacked, reshaped plan; non-build multi-part jobs | Athanor | `subagent_type: "athanor"` |
|
||||||
| Test runs, verification, mechanical sweeps | Haiku subagent | `model: "haiku"` (needs Bash access) |
|
| Test runs, verification, mechanical sweeps | Haiku subagent | `model: "haiku"` (needs Bash access) |
|
||||||
| Deep research (design decisions, prior art) | `researcher` agent | `subagent_type: "researcher"` (Opus, writes reports) |
|
| Deep research (design decisions, prior art) | `researcher` agent | `subagent_type: "researcher"` (Opus, writes reports) |
|
||||||
|
|
||||||
**Model must be explicit.** Always pass `model` on `Agent` calls. Leaf tasks say "do this yourself; do not dispatch further agents."
|
**Model rule.** Pinned agents: omit `model` (the alias overrides the pin). Unpinned agents: pass the alias, never Fable unless the user asks. Leaf tasks say "do this yourself; do not dispatch further agents."
|
||||||
|
|
||||||
## Adepts
|
## Adepts
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user