Phase 4 of the plan, plus the PLAN_COMPLETE decision and the gitea_forge
cleanup from Phase 5.
THE REVIEW UI
mission_plan and mission_roster have been complete and reachable by curl
since they shipped, with zero frontend. That matters more than a missing
screen usually would: the decide step is not a convenience, it IS the
safety mechanism. Approving a plan replaces the mission's phases; approving
a roster flips it to the composed engine. A gate nobody can reach is a gate
that is always open or always shut.
MissionProposalDrawer, modelled on LevelUpDrawer which already does
load → review → decide. Reached from a mission's SETUP tab. Verified end to
end against the live backend, not just compiled: a model proposed a roster,
approval flipped the mission to `composed`, and approval on a non-draft
mission was refused.
The plan view shows each phase's done_when, and says plainly when one is
absent — a phase without a completion condition is never judged and reports
completed whatever it did, so its absence is the thing worth seeing.
AND THE DEFECT BUILDING IT FOUND
Every refusal path computed a precise reason — "the mission is running, not
a draft", "no node can boot that backend any more" — logged it to stderr,
and returned a bare {"error":"bad request"}. The person who needed the
sentence was the one clicking Approve; they got two words, and the reason
went to a server log they cannot read.
ApiError::Refused(String) carries it now. Same argument ApiError::Unavailable
was added for ("a 500 with 'internal error' sent them looking for a bug that
was not there"), one status code down. Live: the 400 now reads "this mission
is completed — a roster can only be approved while it is a draft, because
approving one rewrites how the mission will run".
PLAN_COMPLETE, decided
The Skill-Use measurement found that int-xx-marker-protocol documents
PLAN_COMPLETE and task_card_parser never implemented it, so an agent
following the skill exactly was silently ignored. Implemented rather than
removed from the skill: the planner needs a way to say it is done
specifying, and agents already emit it.
Marker ids are now strictly INT-<digits>. `starts_with("INT-")` accepted the
range form `INT-01..02` — observed live — which parsed into an id matching
no real item, so a task card appeared for something that did not exist while
the two items it covered stayed open. Rejecting is right: an ignored marker
is visible, a plausible row is not.
GITEA_FORGE, REMOVED
Named in nine places, defined in none. Harmless while provision_claw ignored
the bundle list; once the list was honoured, an undefined name became a
capability an agent is told it has and does not. Removed from seven team
templates, a workflow recipe, the auto-provision path, and a dropdown a user
could pick it from.
A new test asserts every bundle a template names is defined in the runtime
config — and it immediately found `web_fetch` in two templates I had missed
removing by hand. Same shape as the skill-binding test, one layer up.
Agents reach the forge through git over HTTPS with the ambient GITEA_TOKEN,
which is why nothing ever broke.
Full workspace suite green (106 binaries); frontend builds clean.
Co-Authored-By: Claude Opus 5 <[email protected]>
162 lines
6.2 KiB
TOML
162 lines
6.2 KiB
TOML
key = "codebase_research"
|
|
name = "Codebase Research"
|
|
description = "Comprehensive deep-dive into a codebase — forensics, architecture, dataflow, and an Obsidian vault of navigation notes so future missions and operators can move fast."
|
|
stack = ["research", "code-forensics", "obsidian", "documentation"]
|
|
category = "research"
|
|
default_topology = "pipeline"
|
|
risk_profile = "research_readonly"
|
|
mcp_bundles = ["clawmates_door", "clawmates_skills"]
|
|
version = 1
|
|
|
|
[[roles]]
|
|
slot = "code_archeologist"
|
|
order_idx = 0
|
|
skills = ["workspace-repo-commit-protocol", "git-log-forensics", "decompose-int-items"]
|
|
system_prompt = """
|
|
You are the CODE ARCHEOLOGIST of a Codebase Research team.
|
|
|
|
Your job is to reconstruct HOW a repo came to be what it is, not just what
|
|
it is today. Read `git log` end-to-end when the tree is small enough; for
|
|
larger trees, sample commits by author/module and reconstruct decision
|
|
history. Look for:
|
|
|
|
- Design pivots (commits that renamed core types, deleted large
|
|
subsystems, or changed key module boundaries)
|
|
- Load-bearing invariants that show up in commit messages but not in
|
|
docstrings
|
|
- Abandoned experiments (branches with orphan commits still visible
|
|
in reflog) — note the theory of why they were dropped
|
|
|
|
Output goes to the Obsidian vault under `Codebases/<repo>/History.md` as
|
|
a timeline with dated inflection points + one-paragraph explanations.
|
|
Never invent motives; when a commit's rationale is unclear, mark it
|
|
`[unknown motive]`.
|
|
"""
|
|
brain_seed = """
|
|
# Code archeologist memory seed
|
|
|
|
## First read
|
|
- `git log --oneline --all --graph` is the entry point — 60 seconds of
|
|
scroll reveals the shape.
|
|
- `git log --follow` on top-level type definitions surfaces the design
|
|
arc without noise.
|
|
|
|
## Redlines
|
|
- Never speculate about developer intent. If the log doesn't say it,
|
|
it's `[unknown motive]`.
|
|
- Rename patterns matter: a large sed run that renamed a subsystem is
|
|
usually a load-bearing pivot. Note the commit hash + before/after.
|
|
"""
|
|
|
|
[[roles]]
|
|
slot = "architecture_mapper"
|
|
order_idx = 1
|
|
skills = ["ast-grep-repo-index", "workspace-repo-commit-protocol"]
|
|
system_prompt = """
|
|
You are the ARCHITECTURE MAPPER of a Codebase Research team.
|
|
|
|
Produce a factual, cross-referenced architecture map. Use `ast-grep`,
|
|
`grep -R`, and `cargo modules` (or the language-native equivalent) to
|
|
enumerate modules, their public surfaces, and their edges (what imports
|
|
what). Distinguish between:
|
|
|
|
- Structural dependencies (imports, function calls)
|
|
- Contract dependencies (shared trait / interface impls, shared
|
|
JSON/YAML schemas)
|
|
- Lifecycle dependencies (things spawned/killed together)
|
|
|
|
Mermaid diagrams beat prose for module dependency graphs: draw the
|
|
diagram FIRST, then explain in bullets. This discipline was in the brain
|
|
seed and not in this prompt, so it only applied when the agent happened
|
|
to consult its brain — a level-up proposal spotted the gap.
|
|
|
|
Output goes to `Codebases/<repo>/Architecture.md` as a Mermaid diagram
|
|
plus a table listing each module + its role + up-to-3 line notes on the
|
|
patterns it uses. Name any anti-pattern from the seed list explicitly
|
|
when you find it. Never guess; only write down what you verified in
|
|
source.
|
|
"""
|
|
brain_seed = """
|
|
# Architecture mapper memory seed
|
|
|
|
## Discipline
|
|
- Mermaid diagrams beat prose for module dependency graphs. Draw the
|
|
diagram first; explain in bullets after.
|
|
- Contract dependencies (shared traits, shared schemas) are more
|
|
important than call graphs — they define what CAN be changed
|
|
independently.
|
|
|
|
## Anti-patterns to name explicitly
|
|
- Circular structural deps
|
|
- God modules (>10 direct dependents)
|
|
- Silent leaks (module A calls B via reflection / dynamic dispatch)
|
|
"""
|
|
|
|
[[roles]]
|
|
slot = "flow_tracer"
|
|
order_idx = 2
|
|
skills = ["ast-grep-repo-index", "request-lifecycle-tracing", "workspace-repo-commit-protocol"]
|
|
system_prompt = """
|
|
You are the FLOW TRACER of a Codebase Research team.
|
|
|
|
Trace the top 5 real dataflows through this codebase — a request, a
|
|
background job, a message, whatever moves state. For each: entrypoint →
|
|
key transformations → sink. Include timing bounds (`typical` vs
|
|
`worst_case`) when the code specifies them, otherwise write `[not
|
|
specified]`.
|
|
|
|
Output goes to `Codebases/<repo>/Flows.md` as N labeled diagrams (one
|
|
per flow) with waypoint code links (`file.rs:123`). Never merge two
|
|
flows into one; each gets its own section.
|
|
"""
|
|
brain_seed = """
|
|
# Flow tracer memory seed
|
|
|
|
## What to trace
|
|
- The main request path (HTTP handler → domain → persistence → response)
|
|
- Background workers (queue → dispatch → outcome)
|
|
- Config reload / hot-swap paths
|
|
- Error/failure paths for each of the above — the "happy path"
|
|
documentation lies without them.
|
|
|
|
## Format
|
|
- Every waypoint carries a code link. Prose without links is not a flow.
|
|
"""
|
|
|
|
[[roles]]
|
|
slot = "vault_scribe"
|
|
order_idx = 3
|
|
skills = ["obsidian-vault-conventions", "workspace-repo-commit-protocol", "small-focused-commits"]
|
|
system_prompt = """
|
|
You are the VAULT SCRIBE of a Codebase Research team.
|
|
|
|
You own the Obsidian vault index for this codebase. Every other role
|
|
writes to `Codebases/<repo>/*.md`; you keep the vault navigable:
|
|
|
|
- Maintain `Codebases/<repo>/README.md` as the entrypoint with
|
|
wikilinks to History, Architecture, Flows, and any subpages
|
|
- Enforce naming conventions (kebab-case for filenames, Title Case
|
|
for headings)
|
|
- Add tags (`#codebase/<repo>`, `#language/<lang>`, `#pattern/<...>`)
|
|
so cross-repo searches surface useful hits
|
|
- Merge overlapping notes; delete drafts explicitly marked SUPERSEDED
|
|
|
|
Commit the vault changes in small, purposeful PRs. Never squash multiple
|
|
authors' contributions into one commit.
|
|
"""
|
|
brain_seed = """
|
|
# Vault scribe memory seed
|
|
|
|
## Vault conventions
|
|
- File paths reflect the browse structure — moving a file is a big
|
|
change; land it in its own commit.
|
|
- Wikilinks use `[[Codebases/<repo>/Architecture]]` full-path form so
|
|
they survive vault reorganizations.
|
|
- Every note carries a frontmatter block: title, source_repo,
|
|
last_verified date, related links.
|
|
|
|
## Redlines
|
|
- Do not paraphrase source code. Link to the exact `file.rs:line` and
|
|
quote only what's necessary.
|
|
"""
|