Files
reliquary/docs/workpad/research/2026-09-29-17-orbit/phase-1-review-fit.md
T
g4borg 0dee6c415b 📝 Add orbit research tree, goal, and session journal
Research tree on using the orbit code-graph CLI for review in Rust
projects: the Python/Django field guide recorded as phase 0, orbit 0.133
capabilities on spacecraft and dirigent, fit with Spire's review stage,
and tested review recipes (changed definitions, blast radius, blindness
preflight). Includes the orbit-skill goal and the Igor session journal.
2026-09-29 19:52:59 +02:00

191 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 1
topic: review-fit
depends-on: phase-0-field-guide-python-django.md
status: findings
---
# Phase 1: How orbit fits Spire's review stage
## TL;DR
- Spire's development cycle (`docs/workpad/designs/2026-09-22-development-cycle.md`) has a **Review** stage (Stage 6): "a fresh Opus reviewer measures output against plan and design," fed the Athanor's diff + plan reference. **There is no dedicated `reviewer` agent file yet** — Stage 6 is currently a generic Opus subagent dispatch, not a pinned agent like `search`/`scout`/`researcher`/`adept`/`athanor`. This is the single biggest opening for an orbit skill: it can be the thing that turns "a fresh Opus reviewer" into "a fresh Opus reviewer with a code-graph."
- Orbit is a strong fit for **exactly the questions review asks and grep answers poorly**: what did this diff touch structurally, what else depends on it (blast radius), does it break a trait contract, does it cross a module boundary it shouldn't, how does the branch's graph differ from main's. All five map to concrete orbit subcommands per the phase-0 field guide's §8/§12/§13.
- **`search`** (read-only, Sonnet) is the natural agent to carry orbit calls during review — it already has Bash and no write tools, matching orbit's "call from the shell, not MCP" guidance (guide §13). **`researcher`** would use orbit for one-off deep investigations (e.g., an architecture-survey-style review). **`adept`** could keep a running "blast radius" map for a domain across sessions. **`athanor`** decomposes review work but shouldn't itself be the one running orbit queries — it should dispatch a `search` (or a future `reviewer`) subagent to do so.
- Skills in this marketplace are per-plugin folders (`plugins/<name>/skills/<skill>/SKILL.md`, optional `references/`); no central registry — a plugin just needs the file to exist under `skills/`, and agents preload skills via a `skills:` frontmatter list (as `adept.md`, `athanor.md`, `zathras.md` do).
- **Recommendation: standalone plugin `plugins/orbit/`** with one skill (`orbit:review` or similar), not folded into Spire. Reasons in §4. Spire agents pick it up the same way they already pick up `tome` (an optional sibling plugin): check for it, use it if present, degrade gracefully (grep) if absent.
- `.claude/spire/project.md` (scaffolded by `plugins/spire/skills/init/SKILL.md`) already has a "Domain skills to route to subagents when relevant" field — this is the natural place to flag "orbit available for this project," no new mechanism needed.
---
## 1. How review works in Spire today
The development cycle is documented in `docs/workpad/designs/2026-09-22-development-cycle.md` and mirrored into `plugins/spire/skills/igor/SKILL.md` (§"Development Cycle", lines 91–110). Six stages, review is the decision point:
> `docs/workpad/designs/2026-09-22-development-cycle.md:30`
> | 6. Review | fresh Opus reviewer (never the Athanor that cooked it) | diff + plan | `reports/` — findings with severity |
> `docs/workpad/designs/2026-09-22-development-cycle.md:42`
> **Review** measures output against the plan and design, not taste. Severity: `low` (nits), `medium` (wrong but contained), `high` (load-bearing, or plan not fulfilled).
The review decision tree (same file, lines 44–52; repeated in `igor/SKILL.md:99-106`) routes findings: none/low → done, medium/high → new plan (short loop back to Stage 4), wrong approach → back to design (Stage 3), unresearched unknown → back to research (Stage 2), wrong goal → stop, user's call.
**Inputs to review**, per the table: the diff produced by the Athanor, plus the plan it was given. The design doc is implicitly in scope too ("wrong approach... back to design"), though the table only lists "diff + plan" as formal input.
**Who reviews**: "fresh Opus reviewer (never the Athanor that cooked it)" — `athanor.md` reinforces this from the producer's side:
> `plugins/spire/agents/athanor.md:39`
> **Output goes to a fresh reviewer.** Your deliverable (diff + plan reference) is reviewed by an independent agent in Stage 6 — never by you. Do not self-review.
Searching the whole `plugins/spire` tree for "reviewer" turns up exactly three hits — the two above plus one in `plugins/spire/skills/implementation/SKILL.md:10`:
> "Its output (diff + plan reference) goes to a fresh reviewer for Stage 6 (Review)."
**There is no `plugins/spire/agents/reviewer.md`.** The full agent roster is `adept.md, athanor.md, igor.md, researcher.md, scout.md, search.md, zathras.md` — no reviewer. Stage 6 today means Igor dispatching a plain Opus subagent (per the delegation table in `igor/SKILL.md:76-85`, closest match is "Complex summaries, git fixes, small code changes → Sonnet subagent" or an ad-hoc Opus dispatch; none of the pinned tiers is explicitly "review"). This is a gap, not a hidden agent — worth flagging back to the goal owner if a `reviewer` agent is ever formalized, since that would be the natural place to pin orbit as a preloaded skill (the same pattern `adept.md`/`athanor.md`/`zathras.md` use for `spire:workpad`, `spire:project`, etc.).
There's also no dedicated "review skill" in `plugins/spire/skills/` — review is described entirely in `igor/SKILL.md` and the design doc, not factored into its own skill file the way implementation is (`plugins/spire/skills/implementation/SKILL.md`).
## 2. Which Spire agents benefit from orbit, and where
| Agent | Benefit | Concrete review question orbit answers |
|---|---|---|
| **search** (`plugins/spire/agents/search.md`) | Highest-value integration point. Already Bash + read-only, no Agent tool — matches orbit's own guidance ("call orbit from the shell," guide §13). Igor already dispatches `search` for "code/file search, symbol tracing" (`igor/SKILL.md:80`); during review this becomes "what does the diff touch, structurally." | Changed-definitions inventory: for each file in the diff, `orbit repo-map class/api <file>` to get the shape instead of eyeballing a raw diff. |
| **the (future) reviewer / current ad-hoc Opus reviewer at Stage 6** | This is where orbit's value concentrates — reviewing a diff against a plan is exactly "did this change reach further than the plan said, and correctly." | Blast radius: `orbit repo-map extends <Trait/Class>` and CALLS-edge SQL joins to answer "what depends on the code this diff changed" before signing off severity. Trait implementor coverage: `repo-map extends <Trait>` lists every impl — check the diff didn't leave one impl un-updated after a trait method signature change. Module boundary violations: `orbit repo-map imports <path>` / `orbit sql` over `gl_imported_symbol` to check a diff didn't introduce a downward or cross-boundary import it shouldn't have. Branch-vs-main structural diff: orbit indexes per-worktree snapshots (guide §7/§13 "orbit indexes snapshots, not history"); indexing both the branch worktree and main and diffing `repo-map api`/`class` output for the touched modules gives a structural diff a text diff can't — new/removed public surface, changed method signatures — directly answering "does this diff fulfill the plan" (Stage 6's stated job). |
| **researcher** (`plugins/spire/agents/researcher.md`) | Has Edit/Write and does deep multi-source investigation; a good fit for the rarer "review found the approach is wrong, back to design" loop, where an architecture-survey-style orbit workflow (guide §12.3) is warranted rather than a quick diff check. | E.g., "is the new trait actually a good abstraction boundary" — inventory of existing implementors and their shape before recommending a design change. |
| **adept** (`plugins/spire/agents/adept.md`) | Long-lived, domain-scoped, accumulates `key-files.md`/`architecture.md`. Could keep a standing note of a domain's key trait hierarchies or module boundaries (from a one-time orbit survey), refreshed via its existing "drift check" (`git log <verified-at>..HEAD -- <covers paths>`, `adept.md:30-34`) rather than re-running orbit every consultation. Orbit would seed the doc; the drift check already tells the adept when to re-verify. | Not a review-question answerer directly, but a place blast-radius/boundary knowledge could live between review sessions instead of being recomputed each time. |
| **athanor** (`plugins/spire/agents/athanor.md`) | Should not itself run orbit — it dispatches. But when decomposing a large implementation brief, it could dispatch a `search` subagent with an orbit query to establish blast radius *before* implementing, feeding the plan rather than only the post-hoc review (implementation-support use case, explicitly deferred per the plan's "Direction" note: "First use case: review... Implementation support comes later"). Flag this as later-phase, not now. | — |
| **scout** (`plugins/spire/agents/scout.md`) | Too lightweight/Haiku-tier for orbit's multi-step index→query workflow; orbit's own guide (§13) stresses re-indexing discipline and hypothesis-then-grep-verify, which doesn't fit scout's "one grep, one read, done" scope (`scout.md:27-29`). Not a good fit. | — |
| **igor** | Never runs tools directly (`igor/SKILL.md:15-23`, Core Directive) — it routes. Igor's role re: orbit is purely: know an orbit skill exists, and brief `search`/a reviewer with it when the task is structural. | — |
Net: **search** for the diff-touches-what step, **the Stage-6 reviewer** (ad-hoc today, ideally its own pinned agent later) for blast-radius/trait-coverage/boundary/branch-diff, **researcher** for the rarer redesign-triggering deep dive, **adept** as a place to cache the results across a session.
## 3. Skill structure in this marketplace
Confirmed by inventory (`find plugins -iname SKILL.md`, 25 hits across `bevy`, `dioxus`, `g4b_ai`, `gitea`, `project-uv`, `spire`, `tome`). Structure:
```
plugins/<plugin-name>/
.claude-plugin/plugin.json # name, version, description, author — no skill list needed
skills/
<skill-name>/
SKILL.md # required: YAML frontmatter + body
references/ # optional: longer supporting docs, loaded on demand
*.md
scripts/ (or *.sh at skill root, e.g. spire/skills/adepts/roster.sh)
agents/
<agent-name>.md # frontmatter can preload skills via `skills:`
```
**`.claude-plugin/plugin.json`** (e.g. `plugins/spire/.claude-plugin/plugin.json`, `plugins/tome/.claude-plugin/plugin.json`) is just plugin metadata — `name`, `version`, `description`, `author`. **No per-skill registration** — any `skills/<name>/SKILL.md` under the plugin directory is auto-discovered. Enabling the plugin (`"spire@reliquary": true` in `.claude/settings.json` → `enabledPlugins`) is what exposes all its skills/agents to a project.
**`SKILL.md` frontmatter fields observed** (from `plugins/spire/skills/*/SKILL.md`):
- `name` (required)
- `description` (required — long, keyword-dense, written to match model-invocation triggers; see `svg/SKILL.md:2` or `workpad/SKILL.md:2` for the house style — enumerates trigger phrases explicitly)
- `allowed-tools` — restricts what the skill may invoke, e.g. `project/SKILL.md`: `allowed-tools: Bash(cat:*)`; `init/SKILL.md`: a longer allowlist
- `disable-model-invocation: true` — for human-triggered-only skills (`init/SKILL.md`)
- Skill bodies can contain a leading `!`command`` line that runs and injects output before the harness even shows the skill body — `project/SKILL.md` does this to cat `project.md` inline.
**How agents load skills**: agent frontmatter has an optional `skills:` list of `<plugin>:<skill>` names, preloaded at agent spawn:
> `plugins/spire/agents/adept.md:12-14`
> ```
> skills:
> - spire:workpad
> - spire:adepts
> ```
> `plugins/spire/agents/athanor.md:14-20`
> ```
> skills:
> - spire:project
> - spire:workpad
> - spire:implementation
> - superpowers:using-superpowers
> - superpowers:subagent-driven-development
> - superpowers:dispatching-parallel-agents
> ```
Cross-plugin skill references work fine (`superpowers:*` skills loaded into `athanor`, `tome:navigate` referenced conditionally in `athanor.md:25` and `igor` boot). This is the precedent for a standalone `plugins/orbit/` plugin whose skill gets referenced from Spire agents without merging code.
**Minimal template matching house style:**
```markdown
---
name: <skill-name>
description: >
<One paragraph, keyword-dense, states WHEN to use it — enumerate trigger
phrases and situations explicitly, the way workpad/SKILL.md and svg/SKILL.md
do, so model-invocation matches reliably. State what it is NOT for too,
if there's a nearby skill it could be confused with (e.g. "not a
replacement for grep").>
---
# <Skill Title>
<One-paragraph statement of what decision or workflow this skill governs —
not "how to write code," but "how to decide X" (cf. workpad/SKILL.md's
opening: "This skill answers two questions only...").>
## <first decision point / section>
...
## Composition with other skills
- **`<related-skill>`** governs <adjacent concern>; defer to it for that.
```
References subfolder is used for material too long to inline (`svg/skills/references/inline-svg.md`, `layout-legibility.md`; `igor/skills/references/mindset.md`, `model-tiers.md`, `harness-notes.md`, `journal-template.md`) — the SKILL.md stays a decision-routing document and `@references/foo.md` is inlined via the `@`-include syntax seen in `igor/SKILL.md:56` (`@references/mindset.md`).
## 4. Placement options for an orbit skill
**(a) Inside Spire** (`plugins/spire/skills/orbit/SKILL.md` or similar):
- Pro: zero extra enablement step for anyone who already has Spire; trivially preloadable into `search`/`athanor`/a future `reviewer` via their existing `skills:` frontmatter lists, same as `spire:workpad`.
- Con: **orbit is an external tool, not every project has it, and not every Spire project is Rust** (the plan's own framing: first use case is "Rust projects that use Spire," implementation support later — implying non-Rust and non-Spire uses exist too). Bundling it into Spire ties an optional, project-conditional capability to a plugin that's supposed to be broadly applicable orchestration machinery. It also means every Spire user who doesn't have orbit installed carries dead skill-description weight in their agents' trigger-matching search space.
- Con: mixes concerns — Spire's own `CLAUDE.md` frames it as "agent orchestration," not "a place for tool-specific integrations." `tome` was split out as a separate plugin for exactly this reason (knowledge navigation is optional per project, and it's referenced conditionally — `athanor.md:25`: "If the project has the `tome` plugin installed, use `tome:navigate`... otherwise orient via direct file reads").
**(b) Standalone plugin `plugins/orbit/`** (mirroring `tome`'s shape):
- Pro: matches the `tome` precedent exactly — an optional capability plugin, enabled per-project (`enabledPlugins: {"orbit@reliquary": true}` only where orbit is installed and useful), referenced conditionally from Spire agents ("if the project has the `orbit` plugin installed, use `orbit:review`; otherwise fall back to grep" — same sentence shape as the tome line above).
- Pro: reusable outside Spire entirely — any project/agent setup in this marketplace could enable `orbit@reliquary` without pulling in Spire's orchestration machinery. Matches the plan's stated aim that implementation support (non-review) comes later and might have a different consumer than the review skill.
- Pro: can iterate/version independently — this is explicitly an "early prototype" (plan.md), and a standalone plugin can be broken or rewritten without touching Spire's stability.
- Con: one more plugin to enable per project; Spire agents need an explicit conditional check (cheap — same pattern already used for tome).
**(c) Other** (e.g., a project-level skill under `.claude/skills/` outside the marketplace, or folding into an existing plugin like `gitea`): no evidence in the repo of a per-project (non-plugin) skill mechanism being used anywhere; `gitea` is a different concern (ticket workflow) and not a natural home. Not recommended — no structural precedent for it in this marketplace, whereas (a)/(b) both have precedent (Spire itself, and the tome/Spire split).
**Recommendation: (b), standalone `plugins/orbit/`.** It mirrors the one existing precedent in this exact repo for "optional, tool-dependent, project-conditional capability that Spire agents use if present" — `tome`. A Spire agent picks it up the same way `athanor.md:25` already picks up tome: a conditional line ("if `.claude/spire/project.md` (or plugin.json availability) flags orbit, use `orbit:review`; otherwise use grep/read"), with the actual availability fact recorded once per project rather than re-detected every session (see §5).
## 5. Per-project facts and orbit availability
`.claude/spire/project.md` is scaffolded by `plugins/spire/skills/init/SKILL.md` (Phase 3, "Scaffold project.md"). It is read at agent startup by the tiny `spire:project` skill:
> `plugins/spire/skills/project/SKILL.md`
> ```
> ---
> name: project
> description: Loads per-project Spire configuration (override or bundled template).
> allowed-tools: Bash(cat:*)
> ---
> !`cat "${CLAUDE_PROJECT_DIR}/.claude/spire/project.md" 2>/dev/null || echo "No project config found. Run /spire:init to set up this project."`
> ```
The scaffolded template (`init/SKILL.md`, Phase 3.2) already includes exactly the right slot:
> ```markdown
> - **Tome skill**: <detected tome skill or "none detected...">
> ...
> - **Domain skills to route to subagents when relevant**: <!-- detect and list, or leave as placeholder -->
> ```
This is the natural, zero-new-mechanism place to flag orbit: extend `init`'s Phase 2 detection (2.5, "Tome presence" — `init/SKILL.md`, section 2.5) with a parallel "2.6 — Orbit presence" check (e.g. `which orbit`, or a `.orbit/` index directory in the repo root, or an `orbit@reliquary` entry in `enabledPlugins`), and populate the "Domain skills to route to subagents when relevant" field (or add a dedicated "Orbit" line next to "Tome skill") with either the detected skill name or "none detected — fall back to grep." Agents (`search` during review, a future `reviewer`) then read this fact for free via the existing `spire:project` preload — no new per-project config file or convention needed, just one more detection phase in `init` and one more line in the template it writes.
## Sources
- `docs/workpad/designs/2026-09-22-development-cycle.md`
- `plugins/spire/skills/igor/SKILL.md`
- `plugins/spire/agents/athanor.md`, `adept.md`, `researcher.md`, `search.md`, `scout.md`, `zathras.md`
- `plugins/spire/skills/implementation/SKILL.md`, `workpad/SKILL.md`, `research-tree/SKILL.md`, `project/SKILL.md`, `init/SKILL.md`, `svg/SKILL.md`
- `plugins/spire/.claude-plugin/plugin.json`, `plugins/tome/.claude-plugin/plugin.json`, `plugins/tome/skills/navigate/SKILL.md`
- `.claude/settings.json` (enabledPlugins)
- `docs/workpad/goals/orbit-skill.md`, `docs/workpad/research/2026-09-29-17-orbit/plan.md`
- `docs/workpad/research/2026-09-29-17-orbit/phase-0-field-guide-python-django.md` (§1, §7, §8, §12, §13)