codecartographer-pi 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,4 +3,4 @@
3
3
  # workspace's framework-owned files (GUIDE.md, templates/, workflow/ pipelines
4
4
  # and VALIDATE.md) predate the running release. Written at release time and
5
5
  # copied verbatim by init — never edit by hand.
6
- scaffold_version: 0.13.0
6
+ scaffold_version: 0.14.0
package/README.md CHANGED
@@ -92,6 +92,8 @@ Use this when your coding agent isn't Pi — Claude Code, Codex, opencode, Curso
92
92
 
93
93
  > **30-second setup for Claude Code, Cursor, Codex, and Claude Desktop: see the [MCP quickstart](docs/mcp-quickstart.md).**
94
94
 
95
+ > **Teaching an agent to drive it:** call the `codecarto_guide` tool — the server returns the full drive loop, the phase-handoff contract, executor selection, and recovery patterns, with nothing to install. The same content ships as an installable skill at `agent-skill/codecartographer/` for agents that load skills from disk.
96
+
95
97
  ```bash
96
98
  npm install --global codecartographer-pi
97
99
  ```
@@ -0,0 +1,143 @@
1
+ ---
2
+ name: codecartographer
3
+ description: Drive the CodeCartographer MCP server to reverse-engineer a repository or synthesize a new project through validated analysis phases. Use when asked to run CodeCartographer, analyze or reverse-engineer a codebase, produce architecture/contracts/protocols/defect/porting/reimplementation artifacts, or operate a .codecarto/ workspace.
4
+ version: 1.0.0
5
+ license: MIT
6
+ ---
7
+
8
+ # Driving CodeCartographer
9
+
10
+ CodeCartographer is a pipeline state machine, not an agent. It hands you a phase prompt, checks the artifact you produce against that phase's criteria, and gates completion. **It never reads your repository and never writes your findings** — you do that.
11
+
12
+ Three roles, and you hold two of them:
13
+
14
+ | Role | Who | Does |
15
+ |---|---|---|
16
+ | State machine | the MCP server | phase order, prompts, validation parsing, completion gate, canonical state |
17
+ | Orchestrator | you | pick the pipeline, drive the loop, choose an executor, verify |
18
+ | Executor | you, or a model you delegate to | read the repo, write the phase artifact |
19
+
20
+ ## The drive loop
21
+
22
+ ```
23
+ codecarto_status → codecarto_init (first time only)
24
+
25
+ ┌──────── codecarto_next ────────┐
26
+ │ ↓ │
27
+ │ execute the phase │
28
+ │ (write primary output) │
29
+ │ ↓ │
30
+ │ write the phase handoff │
31
+ │ ↓ │
32
+ │ codecarto_validate │
33
+ │ ↓ │
34
+ │ codecarto_complete │
35
+ └───────── repeat until ──────────┘
36
+ status reports "complete"
37
+ ```
38
+
39
+ 1. **`codecarto_status`** — always start here. It reports the active pipeline, progress, next action, and any scaffold-staleness warning. Every tool takes an absolute `cwd` pointing at the target repository.
40
+ 2. **`codecarto_init`** — only when no `.codecarto/` exists. Choose the pipeline deliberately (see `references/pipeline-selection.md`). Never pass `force: true` without the user's explicit approval; it moves an existing workspace, findings and all, to a backup directory.
41
+ 3. **`codecarto_next`** — returns the prompt for the next eligible phase. It returns *text*; it does not execute anything. Use `codecarto_phase` only to force a specific phase out of order, and only when the user asked for that.
42
+ 4. **Execute** — see "Executing a phase" below.
43
+ 5. **Write the handoff** — see "The handoff contract" below. This is the step integrations most often miss, and completion now refuses without it.
44
+ 6. **`codecarto_validate`** — parses the validation block you appended to the primary output. Returns `PASS`, `PASS WITH GAPS`, `FAIL`, or `MISSING`.
45
+ 7. **`codecarto_complete`** — marks the phase done, applies your handoff to canonical state, and writes the closeout and `THREAD_LOG.md` entry. It refuses anything worse than `PASS WITH GAPS`.
46
+
47
+ When `codecarto_status` reports all phases complete, post-pipeline skills become available via `codecarto_list_skills` and `codecarto_skill`.
48
+
49
+ ## The handoff contract
50
+
51
+ Since v0.12.0 the framework owns `workflow/status.yaml`, `closeouts/`, and `THREAD_LOG.md`. **Never write those files.** A session proposes state changes in one file:
52
+
53
+ ```
54
+ .codecarto/scratch/handoffs/<phase-id>.yaml
55
+ ```
56
+
57
+ ```yaml
58
+ schema_version: 1
59
+ phase_id: architecture
60
+ owner_notes:
61
+ - Mapped 14 packages across 3 layers.
62
+ open_questions: []
63
+ carry_forward:
64
+ - id: arch-CF2
65
+ kind: defer-to-phase
66
+ target_phase: protocols
67
+ description: MCP endpoints listed by name only; schemas not extracted.
68
+ deferred_reason: Wire-format extraction is the protocols phase's rubric.
69
+ closeout_summary: Architecture mapped; wire formats deferred to protocols.
70
+ ```
71
+
72
+ Omitted arrays default to empty. `phase_id` must match the phase exactly. `carry_forward` targets must be a *later* phase in the active pipeline — anything else belongs in `post_pipeline`. Full schema and closure semantics: `references/handoff-contract.md`.
73
+
74
+ Two failure modes worth naming, because both have happened in the field:
75
+
76
+ - **No handoff written.** Completion fails with an error naming the expected path. Earlier versions completed silently with empty state, which severed cross-phase routing for an entire run without a trace.
77
+ - **Routing described but not performed.** Writing "routed to the semantic phase" in your report's prose table does *not* route anything. The handoff entry is the routing; the table documents it.
78
+
79
+ ## Executing a phase
80
+
81
+ A phase executor takes the prompt from `codecarto_next` plus the repository path, and must:
82
+
83
+ 1. read the repository (or, for late synthesis phases, the prior `findings/` artifacts);
84
+ 2. write the exact primary output path the prompt names;
85
+ 3. append a validation block whose last line is `**Overall:** PASS` or `**Overall:** PASS WITH GAPS`;
86
+ 4. write the phase handoff;
87
+ 5. touch nothing outside `.codecarto/`.
88
+
89
+ Anything satisfying that contract works. Choose per phase, by weight and context budget rather than by brand — see `references/executors.md` for adapters (running it in your own context, delegating to a CLI agent, using local models for scoped pre-passes) and for the concrete selection rules.
90
+
91
+ The short version: use the strongest model available for synthesis phases (`porting`, `reimplementation-spec`) where reasoning quality drives the artifact's value, delegate the wide repository reads to whatever has the largest usable context, and reserve small local models for narrow, verifiable pre-passes whose output you treat as evidence rather than as findings.
92
+
93
+ ## Validation gates
94
+
95
+ | Result | Meaning | Do |
96
+ |---|---|---|
97
+ | `PASS` | every criterion satisfied | complete |
98
+ | `PASS WITH GAPS` | some criterion PARTIAL, gaps documented | complete only if the gaps are acceptable for the user's goal; the gaps must be tracked in the handoff |
99
+ | `FAIL` | a criterion is unmet | fix the artifact, re-validate; completion will refuse |
100
+ | `MISSING` | primary output or validation block absent | the executor did not finish; see `references/phase-recovery.md` |
101
+
102
+ A PARTIAL row's evidence must name what is missing and which `open_questions` or `carry_forward` entry tracks it — and that entry must exist in the handoff, not only in the prose.
103
+
104
+ ## Verify before reporting success
105
+
106
+ - `codecarto_validate` returned `PASS` or an accepted `PASS WITH GAPS`
107
+ - `codecarto_complete` succeeded
108
+ - the primary output file exists and is non-trivial
109
+ - `codecarto_status` shows the expected progress and next action
110
+ - if you delegated, the executor's own result reports success — do not infer it from exit code alone
111
+
112
+ ## Pitfalls
113
+
114
+ - `codecarto_next` returns a prompt. Something still has to *do* the phase.
115
+ - Never hand-edit `workflow/status.yaml`, append `THREAD_LOG.md`, or write a second closeout. Propose through the handoff.
116
+ - Do not force phases out of DAG order unless the user asked.
117
+ - If `codecarto_status` reports a scaffold-staleness warning, refresh the workspace's framework-owned files before trusting anything written inside `.codecarto/`; a stale scaffold's `GUIDE.md` can contradict this contract.
118
+ - A delegated run that times out may still have written its artifact. Check for the file and validate before retrying.
119
+ - The drop-in `.codecarto/` template works without MCP, but the server is preferred: it owns atomic state updates, validation parsing, and the completion gate.
120
+
121
+ ## When the run drives a rewrite
122
+
123
+ If the goal is to rebuild or refactor rather than to understand, two phases carry that weight and both have their own reference:
124
+
125
+ - the defect scans feed `porting` and `reimplementation-spec` as inputs, not as an appendix — `references/deep-audit-synthesis.md`;
126
+ - the spec should describe the least error-prone build order, not a clone — `references/kernel-first-rewrite.md`.
127
+
128
+ ## References
129
+
130
+ Running the pipeline:
131
+
132
+ - `references/pipeline-selection.md` — choosing a variant, and switching without losing work
133
+ - `references/executors.md` — the executor contract, adapters, and model selection
134
+ - `references/handoff-contract.md` — full handoff schema, routing, and closure semantics
135
+ - `references/phase-recovery.md` — stalled, interrupted, and failed phase runs
136
+
137
+ Using what it produces:
138
+
139
+ - `references/deep-audit-synthesis.md` — defect dispositions, hazards as normative rules, reporting
140
+ - `references/kernel-first-rewrite.md` — rings, build order, acceptance harness, strategic assumptions
141
+ - `references/carrying-results-forward.md` — starting implementation, autonomy boundaries, publishing findings
142
+
143
+ This guide is also served by the `codecarto_guide` MCP tool, so an agent with the server configured can read it without installing anything.
@@ -0,0 +1,53 @@
1
+ # After the pipeline completes
2
+
3
+ Two things usually follow a finished run: someone starts implementing, and the findings need a home outside the analysed repository.
4
+
5
+ ## Starting implementation
6
+
7
+ When a completed `reimplementation-spec` is the input to real work rather than more analysis:
8
+
9
+ 1. **Read the spec first and treat it as the contract.** Not the source repository, and not the architecture map — the spec is what later disagreements resolve against.
10
+ 2. **Inspect the target repository's actual stack before choosing a layout.** Its project and build files, whether the existing test suite currently compiles, and its root build configuration. A layout chosen before this is a layout that gets redone.
11
+ 3. **Prefer a non-destructive adjacent module** when the existing product is large or defect-prone: leave the legacy code untouched, add a small kernel module beside it with its own focused test project, and wire it into the workspace only once the layout is settled.
12
+ 4. **Write acceptance tests against fakes before touching real providers, UI, or adapters** — see `kernel-first-rewrite.md`.
13
+ 5. **Isolate new tests when the legacy suite is unrelatedly broken.** A filtered run often still compiles the whole legacy assembly and surfaces failures that have nothing to do with the new work. Do not expand into repairing the legacy suite unless the user asked for that scope.
14
+ 6. **Carry the "do not clone" hazards through as test names**, so the reason a rule exists survives into the code.
15
+
16
+ ## Autonomy boundaries
17
+
18
+ If implementation will proceed while the user is away, settle the boundary before they go: whether work may edit code, run tests, commit, and push. Prefer scoping permission to the specific worker over disabling approvals globally, and exclude force-pushes, history rewrites, unrelated destructive changes, and anything touching secrets.
19
+
20
+ Verify independently after any autonomous run reports success — check the repository state yourself, run the tests yourself, confirm generated and workflow-state files are untracked, and inspect the commit scope. Report exact commit hashes and test counts rather than a claim of success.
21
+
22
+ ## Publishing findings into a product repository
23
+
24
+ When the results should inform a *new* repository, publish a curated snapshot rather than the raw workspace, which is noisy and carries executable workflow state:
25
+
26
+ ```text
27
+ docs/codecarto/
28
+ README.md
29
+ architecture-map.md
30
+ behavioral-contracts.md
31
+ protocols-and-state.md
32
+ mechanical-defects.md
33
+ semantic-defects.md
34
+ reverse-engineering-bundle.md
35
+ reimplementation-spec.md
36
+ ```
37
+
38
+ The README should say that these are curated audit outputs from the source repository, that `reimplementation-spec.md` is the canonical implementation contract, and — when true — that the new product is a ground-up rework rather than a source-level port.
39
+
40
+ Keep the workspace itself untracked in the new repository:
41
+
42
+ ```gitignore
43
+ .codecarto/
44
+ .codecarto-backup-*/
45
+ ```
46
+
47
+ Before publishing, confirm the tests pass and that neither the workspace nor build output is tracked:
48
+
49
+ ```bash
50
+ git ls-files | grep -E '^\.codecarto' || echo "clean"
51
+ ```
52
+
53
+ Default to this curated shape. Copy the raw `.codecarto/` workspace across only when the user explicitly wants executable workflow state in the new repository — for example, to continue the pipeline there.
@@ -0,0 +1,54 @@
1
+ # Turning a deep audit into rewrite guidance
2
+
3
+ Use this when the run exists to decide *how to rebuild or refactor* something, not merely to describe it. It assumes a pipeline with defect scans — `full-with-audit` or `full-with-deep-audit`.
4
+
5
+ If the user expected defect findings and none appeared, check the active variant first: `full` has no defect phases at all.
6
+
7
+ ## Defect scans are contract inputs, not an appendix
8
+
9
+ The common failure is treating defect reports as a separate document that the porting and spec phases summarize politely and move past. They are inputs to those phases' actual decisions. Every defect should reach the porting bundle carrying an explicit disposition:
10
+
11
+ | Disposition | Means | Consequence for the port |
12
+ |---|---|---|
13
+ | `fix before porting` | the defect would be reproduced by a faithful port | design it out; the spec states the correct behavior |
14
+ | `port differently` | the behavior is needed but the mechanism is wrong | spec the intent, not the implementation |
15
+ | `leave behind` | dead, vestigial, or actively harmful | name it explicitly so a later reader doesn't "restore" it |
16
+
17
+ Add the acceptance-test implication alongside each row. A hazard with no test in the spec will be reintroduced by whoever implements it.
18
+
19
+ Close a carry-forward item only once its guidance is represented in an artifact a later phase actually consumes — not merely mentioned in the phase that raised it.
20
+
21
+ ## Convert hazards into normative rules
22
+
23
+ In the final spec, a defect becomes a rule plus a black-box scenario. "The old code had a race in session writes" is an observation; "session writes MUST be atomic: temp file, fsync, same-filesystem rename, sidecars after the primary file — verified by a crash-injection test" is a contract.
24
+
25
+ Hazards worth checking for in agent-like or CLI tools, drawn from real deep-audit runs. Treat as prompts, not a checklist to assert blindly:
26
+
27
+ - non-atomic session, checkpoint, or index writes
28
+ - record parsing that keys on substring detection rather than a schema discriminator
29
+ - JSON-RPC responses not correlated by `id`, so an out-of-order reply satisfies the wrong request
30
+ - subprocess `stdout`/`stderr` piped but not drained concurrently, deadlocking on a full pipe
31
+ - timeouts that log but never kill the process tree
32
+ - shell interpolation of externally supplied variables in hook or plugin execution
33
+ - background process features with no ownership, cleanup, readiness, or recovery semantics
34
+ - config validation that cannot distinguish an absent value from an explicit zero, or that skips range checks
35
+ - config fields parsed and then never read — each needs an implement / remove / deprecate decision
36
+ - permission checks bypassed by a second read path that loses provenance
37
+ - stream reducers that early-`continue` after one field kind and silently drop others in the same event
38
+
39
+ ## Preserve behavior, not bugs
40
+
41
+ Preserve observable behavior as tests and contracts. Do not clone an accidental bug unless something external depends on it — and when it does, say so explicitly and mark it as compatibility-significant rather than letting it look like good design.
42
+
43
+ ## Reporting
44
+
45
+ Separate these when reporting, and lead with the recommendation rather than the narrative:
46
+
47
+ - what the pipeline completed and validated
48
+ - the high-signal defects that actually shape the rewrite
49
+ - the recommended build sequence
50
+ - what must be preserved exactly
51
+ - what to fix rather than copy
52
+ - what remains open
53
+
54
+ See `kernel-first-rewrite.md` for the build sequence this feeds.
@@ -0,0 +1,75 @@
1
+ # Phase executors
2
+
3
+ CodeCartographer does not run models. Any executor that satisfies the contract below can run a phase, so pick per phase rather than committing to one tool for a whole pipeline.
4
+
5
+ ## The executor contract
6
+
7
+ Given the prompt text from `codecarto_next` and the absolute repository path, an executor must:
8
+
9
+ 1. read the repository — or, for late synthesis phases, the prior `.codecarto/findings/` artifacts rather than the source tree;
10
+ 2. write the exact primary output path the prompt names;
11
+ 3. append a validation block whose final line is `**Overall:** PASS` or `**Overall:** PASS WITH GAPS`;
12
+ 4. write `.codecarto/scratch/handoffs/<phase-id>.yaml`;
13
+ 5. modify nothing outside `.codecarto/`.
14
+
15
+ Anything meeting all five works. Nothing else about the executor matters to the framework.
16
+
17
+ ## Choosing one
18
+
19
+ Two properties decide it: how much repository the phase must read, and how much reasoning quality changes the artifact's worth.
20
+
21
+ | Phase | Reads | Reasoning weight | Typical choice |
22
+ |---|---|---|---|
23
+ | `architecture` | wide — whole tree | moderate | largest usable context |
24
+ | `contracts`, `protocols` | wide, but guided by architecture | high | strong model, large context |
25
+ | `defect-scan-*` | wide, pattern-driven | high for semantic, moderate for mechanical | strong model; mechanical tolerates a cheaper one |
26
+ | `porting`, `reimplementation-spec` | narrow — prior findings only | highest | the strongest model available, always |
27
+ | `vision-capture`, `goal-synthesis-*` | narrow — vision brief and library | high | strong model |
28
+
29
+ Two rules that matter more than any specific product:
30
+
31
+ - **Synthesis phases deserve your best model.** `porting` and `reimplementation-spec` read almost nothing new; their entire value is the quality of the reasoning over prior findings. Saving tokens there is a false economy — that artifact is what someone builds from.
32
+ - **Wide-read phases deserve your largest usable context**, because the binding constraint is how much of the tree fits before the executor starts guessing.
33
+
34
+ Prefer whatever is strongest and largest among what the user actually has configured. Ask if it is unclear which models are available rather than assuming a particular vendor.
35
+
36
+ ## Adapter: run it in your own context
37
+
38
+ Simplest and usually correct for small and mid-size repositories. Take the prompt from `codecarto_next` and follow it with your own file, search, and edit tools.
39
+
40
+ Choose this when the repository fits comfortably in your context, when the phase is a synthesis phase reading only prior findings, or when you want to interleave judgment with the user.
41
+
42
+ ## Adapter: delegate to a CLI coding agent
43
+
44
+ Right when the phase would consume more context than you want to spend, or when you want the phase isolated from the orchestration conversation.
45
+
46
+ Pass the prompt through a file rather than inline — phase prompts contain backticks, quotes, and newlines that mangle badly in shell quoting:
47
+
48
+ ```bash
49
+ # Write the prompt from codecarto_next to a file first, then:
50
+ <agent-cli> --prompt-file /tmp/codecarto-phase.md --workdir /abs/path/to/repo
51
+ ```
52
+
53
+ Whatever CLI you use:
54
+
55
+ - set the working directory to the target repository;
56
+ - grant read, write, edit, and search tools; grant shell access only if the phase needs it;
57
+ - request structured output if available, so success is machine-checkable rather than inferred;
58
+ - for long phases, run in the background with a completion signal instead of blocking indefinitely;
59
+ - afterwards, confirm the primary output exists and inspect the executor's own success report — a zero exit code is not evidence the artifact was written.
60
+
61
+ ## Adapter: local or small models for scoped pre-passes
62
+
63
+ Useful for saving context, but only in a specific shape: narrow, verifiable summaries of one subsystem at a time.
64
+
65
+ - Generate per-subsystem notes, never whole-repository analysis.
66
+ - Write them under `.codecarto/scratch/` as supporting evidence. Primary outputs still live in `findings/` and still have to pass validation.
67
+ - Feed the notes to the phase executor as *auxiliary evidence*, and tell it explicitly not to re-run the pre-pass.
68
+ - Treat the output as hints to verify, never as findings. A local model's claim about the code is a lead; the phase artifact needs the evidence level to match what was actually confirmed.
69
+ - If a large local model fails on memory, drop to a smaller one and narrow the scope. The lesson is "scope the notes smaller," not "local models don't work."
70
+
71
+ ## Mixing executors across one pipeline
72
+
73
+ Normal and often optimal: a cheap wide pass for `architecture`, a strong model for `contracts` and the semantic defect scan, your best for `reimplementation-spec`. The framework neither knows nor cares — each phase is validated on its artifact alone.
74
+
75
+ Keep one thing consistent regardless of executor: every phase writes its handoff. A mixed pipeline where one executor forgets is exactly how cross-phase routing goes missing.
@@ -0,0 +1,80 @@
1
+ # The phase handoff
2
+
3
+ Every phase proposes its state changes in one file, which completion validates and applies atomically:
4
+
5
+ ```
6
+ .codecarto/scratch/handoffs/<phase-id>.yaml
7
+ ```
8
+
9
+ The framework owns `workflow/status.yaml`, `closeouts/`, and `THREAD_LOG.md`, and owns all canonical timestamps. A session never writes them.
10
+
11
+ ## Schema (version 1)
12
+
13
+ ```yaml
14
+ schema_version: 1
15
+ phase_id: architecture # must match the phase exactly
16
+ owner_notes: [] # 2-3 durable observations; appended to the phase's notes
17
+ open_questions: [] # genuinely unknown, no later phase will close them
18
+ carry_forward: [] # deferred to a specific later phase in this pipeline
19
+ carry_forward_closures: [] # ids of carry_forward entries this phase resolved
20
+ open_question_closures: [] # ids of open questions this phase resolved, removed everywhere
21
+ post_pipeline: [] # work after the pipeline; every entry needs a stable id
22
+ decisions: [] # choices made beyond what the prompt specified
23
+ closeout_summary: "" # one clause, ~20 words; becomes the THREAD_LOG entry
24
+ closeout_content: |- # optional full closeout markdown
25
+ # Closeout — architecture
26
+ ```
27
+
28
+ Omitted arrays default to empty. A malformed collection fails completion without mutating anything.
29
+
30
+ `.codecarto/templates/phase-handoff.yaml` in the workspace is a copyable skeleton.
31
+
32
+ ## Entry shapes
33
+
34
+ `open_questions` entries:
35
+
36
+ ```yaml
37
+ - id: q-loadconfig-ambiguity # stable; auto-assigned if omitted
38
+ kind: needs-runtime-test
39
+ description: loadConfig returns {} on both ENOENT and parse error.
40
+ deferred_reason: Distinguishing them needs a runtime probe this phase cannot run.
41
+ ```
42
+
43
+ `carry_forward` entries add `target_phase`:
44
+
45
+ ```yaml
46
+ - id: arch-CF2
47
+ kind: defer-to-phase
48
+ target_phase: protocols
49
+ description: MCP endpoints listed by name only; schemas not extracted.
50
+ deferred_reason: Wire-format extraction is the protocols phase's rubric.
51
+ ```
52
+
53
+ Allowed `kind` values: `needs-runtime-test`, `needs-maintainer-decision`, `needs-spec-ruling`, `defer-to-phase`, `needs-fixture-capture`.
54
+
55
+ ## Open question or carry-forward?
56
+
57
+ - **`open_questions`** — nobody in this pipeline will resolve it. It needs a runtime test, a maintainer decision, or a spec ruling. It survives to the end as a known unknown.
58
+ - **`carry_forward`** — a specific later phase's rubric is the right place to close it. It is a routing, and it must name a real downstream phase.
59
+
60
+ `carry_forward` targets are validated: the target must exist in the active pipeline and come *after* the current phase. A target that is earlier, equal, or absent fails completion. Work that belongs after the pipeline goes in `post_pipeline` instead.
61
+
62
+ ## Closing routed items
63
+
64
+ A later phase receives routed items in its phase prompt. To close one:
65
+
66
+ 1. address it in that phase's output;
67
+ 2. list its id under `carry_forward_closures` in that phase's handoff.
68
+
69
+ Completion then removes the entry atomically. Resolving an open question works the same way through `open_question_closures`, which removes the id from every phase that raised it.
70
+
71
+ Re-deferring instead of closing means writing a fresh `carry_forward` entry naming a later `target_phase`.
72
+
73
+ ## The failure this prevents
74
+
75
+ Before completion required a handoff, a phase could finish with empty state and no signal. A real seven-phase run documented five cross-phase routings in its report prose, wrote no handoffs, and completed all seven phases with `carry_forward: []` throughout. Every downstream phase's routed-item intake was empty. The findings survived only because each phase happened to re-read the previous phase's full markdown.
76
+
77
+ Two habits follow from that:
78
+
79
+ - Writing the routing in a report table documents it. The handoff entry *is* it.
80
+ - A validation Evidence cell that says "routed to the semantic phase" is a claim about state. If the handoff entry does not exist, the claim is false and nothing will contradict it.
@@ -0,0 +1,56 @@
1
+ # Kernel-first rewrite shape
2
+
3
+ A pattern for the `reimplementation-spec` phase when the goal is the least error-prone path to a replacement rather than a clone. It has held up on agent-like CLI tools; the reasoning generalizes to any system with a small semantic core and a wide adapter surface.
4
+
5
+ ## Classify the strategic assumptions first
6
+
7
+ Before writing the spec, state which of these the user has actually committed to. Guessing produces a spec that is wrong in a way nobody notices until implementation.
8
+
9
+ - **Platform** — is a specific OS or runtime assumed? If so, record which primitives the MVP may rely on (atomic rename, fsync, process groups, a POSIX shell).
10
+ - **Architecture inspiration** — if the user pointed at another project, is it shape-only inspiration or a behavior contract? Default to shape-only unless they said otherwise.
11
+ - **Stack lock** — if the language and runtime are not chosen, keep the spec language-agnostic *even when the platform is fixed*. Use the opinionated template only when stack, project identity, module names, and toolchain are all committed.
12
+ - **Build order** — kernel-first with fake-driven acceptance tests, or something the user prefers instead.
13
+
14
+ Record the chosen variant in the spec front matter and the validation block, so a later opinionated re-run is traceable.
15
+
16
+ ## Rings
17
+
18
+ Frame the replacement as rings, innermost first. This keeps high-risk surface out of the MVP while preserving the seams it will later attach to.
19
+
20
+ 1. **Kernel** — the semantic core. For an agent tool: the loop, stream reduction, loop-detection, tool planning and execution, the permission decision, context-pressure policy.
21
+ 2. **Ports** — the interfaces the kernel talks through: provider stream, tool registry, persistence, permission prompt, event sink, clock and randomness, process execution.
22
+ 3. **Adapters** — concrete implementations of those ports: a specific provider API, filesystem persistence, a terminal renderer, a subprocess runner.
23
+ 4. **Extensions** — everything optional: MCP, LSP, hooks, background execution, subagents, memory, plan modes.
24
+ 5. **Delivery modes** — interactive, one-shot print, RPC, embedded SDK.
25
+
26
+ The kernel must be buildable and testable without any ring above it. If it isn't, the boundary is in the wrong place.
27
+
28
+ ## Acceptance harness before adapters
29
+
30
+ The first implementation artifact is a deterministic harness, not a working product:
31
+
32
+ - a fake provider yielding scripted stream events, including malformed and mixed-field ones;
33
+ - fake tools with deterministic success, error, crash, and cancel outcomes;
34
+ - a fake permission prompt;
35
+ - temp-directory persistence fixtures;
36
+ - black-box tests for turn lifecycle, tool pipeline ordering, loop-break semantics, atomic persistence, config validation, cancellation, and stream reduction.
37
+
38
+ Real providers, UI, and extensions come only after that harness is green. Every "do not clone" hazard from `deep-audit-synthesis.md` should appear here as a named test.
39
+
40
+ ## Milestone ordering
41
+
42
+ Small, independently reviewable slices, each one commit with its tests. An order that has worked:
43
+
44
+ 1. tool pipeline result contract and failure semantics
45
+ 2. crash-safe durable persistence
46
+ 3. capability-based permission kernel
47
+ 4. minimal deterministic input-schema validation
48
+ 5. provider abstraction, proven against the fake streaming provider
49
+ 6. loop orchestration over fake provider and fake tools
50
+ 7. real adapters, only once the seams above are proven
51
+
52
+ Stop after a coherent slice rather than stacking changes past the point of reviewability. For schema validation specifically, start with a deliberately small subset — root object, properties, required, primitive types, `additionalProperties: false`, and failing cleanly on a malformed schema — and extend only when a contract demands it.
53
+
54
+ ## What kernel-first is not
55
+
56
+ It is not a reduced scope or a prototype. It is the safest route to a *full* replacement: the parts most likely to be subtly wrong get built first, in isolation, under deterministic tests, before anything depends on them.
@@ -0,0 +1,48 @@
1
+ # Recovering a stalled or failed phase
2
+
3
+ Treat the workspace as the source of truth. Before assuming anything failed, run `codecarto_status` and `codecarto_validate`.
4
+
5
+ ## First: check whether it actually failed
6
+
7
+ A delegated run that times out, is interrupted, or returns empty output **may still have written its artifact**. Executors commonly write the file and then die during cleanup or summary.
8
+
9
+ 1. Does the primary output file exist?
10
+ 2. If yes, run `codecarto_validate`. A `PASS` means the phase succeeded regardless of how the executor exited.
11
+ 3. Only retry when the artifact is absent or validation is `MISSING`/`FAIL`.
12
+
13
+ Retrying a phase that already succeeded wastes the run and can overwrite a good artifact with a worse one.
14
+
15
+ ## Diagnosing by validation result
16
+
17
+ **`MISSING`** — no primary output, or no validation block. The executor did not finish. Retry with reduced scope.
18
+
19
+ **`FAIL`** — a criterion is unmet. The validation output names which. Repair the artifact against that criterion specifically; do not regenerate the whole thing.
20
+
21
+ **`PASS WITH GAPS` you did not intend** — the executor marked criteria PARTIAL. Read the evidence cells: either the gaps are real and belong in the handoff as `open_questions`/`carry_forward`, or the executor under-read and should retry.
22
+
23
+ **Completion refuses despite `PASS`** — almost always a missing handoff. The error names the expected path. Write `.codecarto/scratch/handoffs/<phase-id>.yaml` and complete again.
24
+
25
+ ## Writing a recovery prompt
26
+
27
+ Narrower than the original, not a repeat of it:
28
+
29
+ - name the exact primary output path;
30
+ - require the validation block, with the literal `**Overall:** PASS` or `**Overall:** PASS WITH GAPS` final line;
31
+ - require the handoff file, naming its path;
32
+ - constrain traversal explicitly — skip vendored code, build output, generated files, and lockfiles unless the phase needs them;
33
+ - for late phases, direct it to read prior `.codecarto/findings/` artifacts *instead of* the source tree, which is usually why the first attempt exhausted its budget;
34
+ - narrow the tool grant. For an analysis-writing retry, read/write/edit/search is typically enough; shell access is often what let the first run wander.
35
+
36
+ ## Repeated failure on the same phase
37
+
38
+ If two reduced-scope attempts fail, the problem is usually scope, not the executor:
39
+
40
+ - Split the reading. Use scoped pre-passes over individual subsystems, save the notes under `.codecarto/scratch/`, and give the retry those notes as evidence.
41
+ - Consider whether the pipeline variant is right. A repository too large for one `architecture` pass may want `architecture-only` first, reviewed, then a switch.
42
+ - Check for a scaffold-staleness warning in `codecarto_status`. A workspace whose framework-owned files predate the running version can carry instructions that contradict the current contract, which produces artifacts that fail validation for reasons the executor cannot see.
43
+
44
+ ## What not to do
45
+
46
+ - Do not hand-edit `workflow/status.yaml` to move past a failure. Completion is the only writer, and a manual edit is unreviewed state that the next completion may overwrite.
47
+ - Do not mark a phase complete to unblock the pipeline. Downstream phases read upstream findings; a hollow artifact propagates.
48
+ - Do not delete and re-init to escape a bad phase. `codecarto_init --force` moves the whole workspace, including phases that succeeded.
@@ -0,0 +1,38 @@
1
+ # Choosing a pipeline
2
+
3
+ Pass an alias to `codecarto_init` as `pipeline`. The default is `full-with-deep-audit`.
4
+
5
+ | Alias | Phases | Use when |
6
+ |---|---|---|
7
+ | `architecture-only` | architecture | quick structural read; "what is this repo" |
8
+ | `lite` | architecture → contracts → protocols | understanding a system you will keep, not rewrite |
9
+ | `defect-scan` | architecture → defect-scan | maintenance audit of a system you already understand |
10
+ | `full` | architecture → contracts → protocols → porting → reimplementation-spec | porting or rewriting, no defect audit |
11
+ | `full-with-audit` | adds a single defect-scan after architecture | porting, with defects surfaced once |
12
+ | `full-with-deep-audit` *(default)* | splits the scan: mechanical after architecture, semantic after protocols | porting or rewriting where correctness matters |
13
+ | `synthesis` | vision-capture → goal-synthesis-propose → spec-merge → goal-synthesis-finalize | forward synthesis of a *new* product, not reverse-engineering |
14
+
15
+ ## Deep audit versus plain audit
16
+
17
+ `full-with-deep-audit` runs the defect scan in two passes for a reason worth understanding before choosing:
18
+
19
+ - **mechanical** (logic, error handling, configuration) runs early, right after architecture, so contracts and porting can cite its findings;
20
+ - **semantic** (concurrency, security, API contract violations) runs after protocols, because judging those needs the state machines and wire formats in hand.
21
+
22
+ The mechanical pass routes anything it cannot settle locally to the semantic pass. If the user expects "seven phases," they mean this variant.
23
+
24
+ Choose `full-with-audit` when one combined pass is enough and you want fewer phases. Choose `full-with-deep-audit` when the output will drive a rewrite, since a semantic pass without protocols context will miss the findings that most change a port.
25
+
26
+ ## Synthesis is a different workspace
27
+
28
+ The `synthesis` pipeline plans a new product from a vision brief and a library of reusable specs. It does **not** treat the surrounding repository as source evidence. It has preflight gates: a completed `inputs/vision.md`, a valid non-empty library, and — for merge and finalization — at least one human-confirmed selection. `codecarto_vision` runs the guided interview that produces the brief.
29
+
30
+ Do not reach for it when the user wants a repository analyzed.
31
+
32
+ ## Switching later
33
+
34
+ Use `codecarto_switch_pipeline`, never a hand-edit. It preserves findings, handoffs, usage data, closeouts, and per-phase progress; phases present in both variants keep their completion status, phases unique to the new variant start pending, and phases only in the old one are dropped from state while their findings stay on disk.
35
+
36
+ Switching from `full` to `full-with-deep-audit` mid-run is the common case — the user wanted the defect scans and started without them. That works and keeps the completed architecture, contracts, and protocols phases.
37
+
38
+ Re-initializing with `force: true` is the destructive alternative: it moves the entire existing workspace to a backup directory. Only do that when the user explicitly asks, and say what will move.
@@ -0,0 +1,18 @@
1
+ /** Packaged agent-skill directory. Wrappers serve its contents through codecarto_guide. */
2
+ export declare const packagedAgentSkillDir: string;
3
+ /** A guide document: the main skill or one of its topic references. */
4
+ export type GuideDocument = {
5
+ /** `overview` for SKILL.md, otherwise the reference's basename without `.md`. */
6
+ topic: string;
7
+ /** Markdown body, with SKILL.md's installer frontmatter stripped. */
8
+ content: string;
9
+ };
10
+ /** Topic names available to {@link readGuide}, `overview` first. */
11
+ export declare function listGuideTopics(): Promise<string[]>;
12
+ /**
13
+ * Read one guide document.
14
+ * @param topic - `overview` (default) for the main skill, or a reference name from {@link listGuideTopics}.
15
+ * @returns the requested document.
16
+ * @throws when the packaged skill is missing, or the topic is not one of {@link listGuideTopics}.
17
+ */
18
+ export declare function readGuide(topic?: string): Promise<GuideDocument>;
@@ -0,0 +1,50 @@
1
+ // Serves the packaged agent skill — the instructions for driving this server —
2
+ // so an MCP client can read them without installing the skill files. The shipped
3
+ // markdown under agent-skill/ is the single source: nothing here duplicates its
4
+ // prose, and a drift test would have nothing to compare.
5
+ import { readdir, readFile } from "node:fs/promises";
6
+ import { basename, join } from "node:path";
7
+ import { pathExists } from "./utils.js";
8
+ import { packageRoot } from "./workspace.js";
9
+ /** Packaged agent-skill directory. Wrappers serve its contents through codecarto_guide. */
10
+ export const packagedAgentSkillDir = join(packageRoot, "agent-skill", "codecartographer");
11
+ /**
12
+ * Strip a leading YAML frontmatter block. The frontmatter is skill-installer
13
+ * metadata (name, version, license) that carries no instruction value for an
14
+ * agent reading the guide through the tool.
15
+ */
16
+ function stripFrontmatter(markdown) {
17
+ const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n/.exec(markdown);
18
+ return match ? markdown.slice(match[0].length).trimStart() : markdown;
19
+ }
20
+ /** Topic names available to {@link readGuide}, `overview` first. */
21
+ export async function listGuideTopics() {
22
+ const referencesDir = join(packagedAgentSkillDir, "references");
23
+ if (!(await pathExists(referencesDir)))
24
+ return ["overview"];
25
+ const names = (await readdir(referencesDir))
26
+ .filter((name) => name.endsWith(".md"))
27
+ .map((name) => basename(name, ".md"))
28
+ .sort();
29
+ return ["overview", ...names];
30
+ }
31
+ /**
32
+ * Read one guide document.
33
+ * @param topic - `overview` (default) for the main skill, or a reference name from {@link listGuideTopics}.
34
+ * @returns the requested document.
35
+ * @throws when the packaged skill is missing, or the topic is not one of {@link listGuideTopics}.
36
+ */
37
+ export async function readGuide(topic = "overview") {
38
+ const requested = topic.trim() || "overview";
39
+ const available = await listGuideTopics();
40
+ if (!available.includes(requested)) {
41
+ throw new Error(`Unknown guide topic ${requested}. Available: ${available.join(", ")}.`);
42
+ }
43
+ const path = requested === "overview"
44
+ ? join(packagedAgentSkillDir, "SKILL.md")
45
+ : join(packagedAgentSkillDir, "references", `${requested}.md`);
46
+ if (!(await pathExists(path))) {
47
+ throw new Error(`Packaged agent skill is missing at ${path}. Reinstall codecartographer-pi.`);
48
+ }
49
+ return { topic: requested, content: stripFrontmatter(await readFile(path, "utf8")) };
50
+ }
@@ -8,6 +8,7 @@ export * from "./workspace.ts";
8
8
  export * from "./completion.ts";
9
9
  export * from "./orchestrator-config.ts";
10
10
  export * from "./usage.ts";
11
+ export * from "./guide.ts";
11
12
  export * from "./dashboard.ts";
12
13
  export * from "./library.ts";
13
14
  export * from "./synthesis.ts";
@@ -11,6 +11,7 @@ export * from "./workspace.js";
11
11
  export * from "./completion.js";
12
12
  export * from "./orchestrator-config.js";
13
13
  export * from "./usage.js";
14
+ export * from "./guide.js";
14
15
  export * from "./dashboard.js";
15
16
  export * from "./library.js";
16
17
  export * from "./synthesis.js";
@@ -1,4 +1,6 @@
1
1
  import type { PhaseHandoff, WorkspaceState } from "./types.ts";
2
+ /** Installed package root. Anchors packaged assets served to clients (template, agent skill). */
3
+ export declare const packageRoot: string;
2
4
  export declare const packagedWorkspaceDir: string;
3
5
  export declare const PACKAGE_VERSION: string;
4
6
  export declare function getWorkspaceState(cwd: string): Promise<WorkspaceState | null>;
@@ -26,7 +26,8 @@ function findPackageRoot(start) {
26
26
  }
27
27
  }
28
28
  const coreDir = dirname(fileURLToPath(import.meta.url));
29
- const packageRoot = findPackageRoot(coreDir);
29
+ /** Installed package root. Anchors packaged assets served to clients (template, agent skill). */
30
+ export const packageRoot = findPackageRoot(coreDir);
30
31
  // Path to the packaged framework template directory. Wrappers copy this on
31
32
  // /codecarto-init.
32
33
  export const packagedWorkspaceDir = join(packageRoot, ".codecarto");
@@ -171,6 +171,15 @@ export declare function handleListSkills(args: {
171
171
  }>;
172
172
  structuredContent?: Record<string, unknown>;
173
173
  }>;
174
+ export declare function handleGuide(args: {
175
+ topic?: string;
176
+ }): Promise<{
177
+ content: Array<{
178
+ type: "text";
179
+ text: string;
180
+ }>;
181
+ structuredContent?: Record<string, unknown>;
182
+ }>;
174
183
  export declare function buildServer(): Server<{
175
184
  method: string;
176
185
  params?: {
@@ -15,7 +15,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
15
15
  import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
16
16
  import { cp, mkdir, readFile, rename, writeFile } from "node:fs/promises";
17
17
  import { basename, isAbsolute, join } from "node:path";
18
- import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, canonicalPath, completeValidatedPhase, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, describeScaffoldStaleness, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isValidSlug, isWithinPathResolved, listEntries, listSkillNames, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, PACKAGE_VERSION, packagedWorkspaceDir, pathExists, PhasePreflightError, publishEntry, reindex as libraryReindex, resolvePhase, resolvePipelineChoice, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, } from "../core/index.js";
18
+ import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, canonicalPath, completeValidatedPhase, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, describeScaffoldStaleness, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isValidSlug, isWithinPathResolved, listEntries, listGuideTopics, readGuide, listSkillNames, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, PACKAGE_VERSION, packagedWorkspaceDir, pathExists, PhasePreflightError, publishEntry, reindex as libraryReindex, resolvePhase, resolvePipelineChoice, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, } from "../core/index.js";
19
19
  import { initLibrary } from "../core/library.js";
20
20
  import { loadUserConfig, resolveUserConfigPath } from "../core/orchestrator-config.js";
21
21
  import { writeDashboard } from "../extensions/codecarto/dashboard-writer.js";
@@ -876,6 +876,19 @@ const TOOLS = [
876
876
  required: ["cwd"],
877
877
  },
878
878
  },
879
+ {
880
+ name: "codecarto_guide",
881
+ description: "Return the instructions for driving this server: the status/next/execute/validate/complete loop, the phase-handoff contract, pipeline selection, executor choice, and recovery. Call this first when you have not run a CodeCartographer pipeline before. Takes no workspace.",
882
+ inputSchema: {
883
+ type: "object",
884
+ properties: {
885
+ topic: {
886
+ type: "string",
887
+ description: "Guide topic. Omit for the overview; other topics are listed in every response.",
888
+ },
889
+ },
890
+ },
891
+ },
879
892
  {
880
893
  name: "codecarto_list_skills",
881
894
  description: "List available post-pipeline skills installed in the workspace.",
@@ -905,7 +918,19 @@ const HANDLERS = {
905
918
  codecarto_usage: handleUsage,
906
919
  codecarto_dashboard: handleDashboard,
907
920
  codecarto_list_skills: handleListSkills,
921
+ codecarto_guide: handleGuide,
908
922
  };
923
+ export async function handleGuide(args) {
924
+ const topics = await listGuideTopics();
925
+ const document = await readGuide(args.topic).catch((error) => {
926
+ throw new McpError(ErrorCode.InvalidParams, error instanceof Error ? error.message : String(error));
927
+ });
928
+ const other = topics.filter((name) => name !== document.topic);
929
+ const footer = other.length > 0
930
+ ? `\n\n---\nOther guide topics: ${other.join(", ")} (call codecarto_guide with topic).`
931
+ : "";
932
+ return textResult(`${document.content}${footer}`, { topic: document.topic, topics });
933
+ }
909
934
  // ---------- server bootstrap ----------
910
935
  export function buildServer() {
911
936
  const server = new Server({ name: "codecartographer", version: PACKAGE_VERSION }, { capabilities: { tools: {} } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codecartographer-pi",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "mcpName": "io.github.HuginnIndustries/codecartographer",
5
5
  "description": "Turn an unfamiliar codebase into a validated reimplementation spec, then synthesize confirmed specs and a product vision into a traceable plan.",
6
6
  "type": "module",
@@ -35,6 +35,7 @@
35
35
  },
36
36
  "files": [
37
37
  ".codecarto/**/*",
38
+ "agent-skill/**/*",
38
39
  "dist/**/*",
39
40
  "assets/logo.svg",
40
41
  "README.md",