codecartographer-pi 0.12.10 → 0.13.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.
- package/.codecarto/CONTRIBUTING.md +1 -1
- package/.codecarto/GUIDE.md +4 -3
- package/.codecarto/NEW_THREAD_BLURB.md +9 -10
- package/.codecarto/findings/defect-scan-mechanical/SKILL.md +1 -1
- package/.codecarto/skills/spec-delta-application/SKILL.md +1 -1
- package/.codecarto/templates/architecture-map.md +2 -1
- package/.codecarto/templates/behavioral-contracts.md +2 -1
- package/.codecarto/templates/closeout-template.md +5 -2
- package/.codecarto/templates/mechanical-defects.md +4 -2
- package/.codecarto/templates/protocols-and-state.md +2 -1
- package/.codecarto/templates/reverse-engineering-bundle.md +2 -1
- package/.codecarto/templates/semantic-defects.md +3 -1
- package/.codecarto/templates/thread-log-entry-template.md +11 -13
- package/.codecarto/workflow/VALIDATE.md +17 -14
- package/.codecarto/workflow/pipeline-architecture-only.yaml +2 -2
- package/.codecarto/workflow/pipeline-defect-scan.yaml +4 -4
- package/.codecarto/workflow/pipeline-full-with-audit.yaml +12 -12
- package/.codecarto/workflow/pipeline-full-with-deep-audit.yaml +15 -15
- package/.codecarto/workflow/pipeline-lite.yaml +6 -6
- package/.codecarto/workflow/pipeline.yaml +10 -10
- package/.codecarto/workflow/scaffold-version.yaml +6 -0
- package/README.md +23 -1
- package/dist/core/completion.js +13 -0
- package/dist/core/prompts.js +20 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/workspace.d.ts +9 -0
- package/dist/core/workspace.js +54 -0
- package/dist/extensions/codecarto/index.js +4 -1
- package/dist/mcp-server/server.d.ts +5 -0
- package/dist/mcp-server/server.js +32 -5
- package/package.json +11 -3
|
@@ -25,7 +25,7 @@ Key things to verify:
|
|
|
25
25
|
- Pipeline YAML files parse correctly and phase dependencies resolve.
|
|
26
26
|
- SKILL.md instructions produce output that matches the corresponding template.
|
|
27
27
|
- Validation protocol (VALIDATE.md) catches missing or incomplete sections.
|
|
28
|
-
- `status.yaml` updates correctly after each phase, with the schema-split `open_questions` / `carry_forward` lists used for what each is for (see GUIDE.md "Open Questions vs Carry-Forward").
|
|
28
|
+
- `status.yaml` updates correctly after each phase from the session's phase handoff, with the schema-split `open_questions` / `carry_forward` lists used for what each is for (see GUIDE.md "Open Questions vs Carry-Forward").
|
|
29
29
|
- All file paths referenced in pipeline YAML, GUIDE.md, and SKILL.md files exist.
|
|
30
30
|
|
|
31
31
|
#### THREAD_LOG.md de-dup check
|
package/.codecarto/GUIDE.md
CHANGED
|
@@ -39,8 +39,8 @@ If this is the first LLM to touch this project — no closeouts in `closeouts/`,
|
|
|
39
39
|
If the user accepts the orchestrator role:
|
|
40
40
|
|
|
41
41
|
1. Initialize `CONVENTIONS.md` from `templates/conventions-template.md` and `DECISIONS.md` from `templates/decisions-template.md` (skeletons only — populate as patterns and decisions accumulate).
|
|
42
|
-
2.
|
|
43
|
-
3. **Do not run the architecture phase yourself.** The orchestrator never executes pipeline phases — that is the implementing-session role (see §Roles). Instead, **draft an implementing-session prompt for the architecture phase** that a fresh thread will execute. Hand the prompt to the user; they spin up a new thread with it; the implementing thread runs the phase, validates, writes a closeout, and reports back; you (the orchestrator) read the returned closeout
|
|
42
|
+
2. Confirm the project name. `project_name` defaults to the repository directory name and is persisted by the framework on the first completion; it only needs attention if the project should be called something else.
|
|
43
|
+
3. **Do not run the architecture phase yourself.** The orchestrator never executes pipeline phases — that is the implementing-session role (see §Roles). Instead, **draft an implementing-session prompt for the architecture phase** that a fresh thread will execute. Hand the prompt to the user; they spin up a new thread with it; the implementing thread runs the phase, validates, writes a closeout, and reports back; you (the orchestrator) read the returned closeout and update `CONVENTIONS.md` / `DECISIONS.md` from it, then draft the next phase's prompt. The implementing session's own completion already applied its handoff to `workflow/status.yaml` — the orchestrator never edits that file. **Phase work always happens in fresh implementing-session threads, never in the orchestration thread.** A useful self-check: if you find yourself reading a `findings/<phase>/SKILL.md` or writing a `findings/<phase>/<primary-output>.md`, you have slipped into the implementing-session role — stop, draft the prompt, hand off.
|
|
44
44
|
|
|
45
45
|
If the user declines:
|
|
46
46
|
|
|
@@ -63,7 +63,7 @@ Read these files in order before doing any analysis:
|
|
|
63
63
|
|
|
64
64
|
All paths in this guide are relative to `.codecarto/` unless stated otherwise.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
A blank `project_name` in `workflow/status.yaml` needs no action: the framework resolves it to this repository's directory name and persists it on the first completion.
|
|
67
67
|
|
|
68
68
|
Treat this workspace as durable memory across sessions. Do not invent a new structure. Use the one that exists.
|
|
69
69
|
|
|
@@ -80,6 +80,7 @@ Some files in this workspace are **read-only instructions** and must not be modi
|
|
|
80
80
|
| Source code (read-only) | `../` (everything outside `.codecarto/`) | Read only. Analyze but never modify. |
|
|
81
81
|
| Synthesis input (user-maintained) | `inputs/vision.md` | The user fills this before the synthesis pipeline starts. Implementing phases read it but do not rewrite the raw brief. |
|
|
82
82
|
| Workflow state (framework-owned) | `workflow/status.yaml` | Read to understand progress. Implementing sessions never edit it directly; completion applies a validated phase handoff under a lock. |
|
|
83
|
+
| Scaffold version stamp (framework-owned) | `workflow/scaffold-version.yaml` | Written at release, copied by init. The framework compares it to its own version to warn about stale scaffolds. Never edit. |
|
|
83
84
|
| Findings (read-write) | `findings/<phase>/<primary-output>.md`, secondary output files | Create and update during phases. |
|
|
84
85
|
| Phase handoff (read-write) | `scratch/handoffs/<phase>.yaml` | Implementing sessions propose state changes and closeout content here. The framework validates and applies them. |
|
|
85
86
|
| Closeouts (framework-owned) | `closeouts/<date>-<phase-or-module>.md`, `THREAD_LOG.md` | Completion writes or updates one canonical closeout and one idempotent index entry. |
|
|
@@ -9,7 +9,7 @@ All CodeCartographer files are inside `.codecarto/`. Paths below are relative to
|
|
|
9
9
|
Read these in order before doing work:
|
|
10
10
|
|
|
11
11
|
1. `GUIDE.md` - the LLM entry point and session guide
|
|
12
|
-
2. `workflow/status.yaml` -
|
|
12
|
+
2. `workflow/status.yaml` - current progress and routed items (framework-owned: read it, never edit it)
|
|
13
13
|
3. `CONVENTIONS.md` if present - cross-cutting patterns this project follows
|
|
14
14
|
4. The current phase's existing output file, if present
|
|
15
15
|
5. The current phase's `SKILL.md`
|
|
@@ -20,18 +20,17 @@ Where to store results:
|
|
|
20
20
|
|
|
21
21
|
- Durable findings: `findings/<phase>/`
|
|
22
22
|
- Rough notes: `scratch/`
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- Cross-session log: append a one-line index entry to `THREAD_LOG.md` pointing at your closeout file
|
|
23
|
+
- State changes (owner notes, open questions, carry-forward routings): `scratch/handoffs/<phase>.yaml` — completion applies it to `workflow/status.yaml`; never edit `status.yaml` directly
|
|
24
|
+
- Closeouts and `THREAD_LOG.md`: framework-owned; supply `closeout_summary` and optional `closeout_content` in the handoff
|
|
26
25
|
|
|
27
26
|
After completing work:
|
|
28
27
|
|
|
29
28
|
1. Run validation per `workflow/VALIDATE.md`. Append the validation block to the output.
|
|
30
|
-
2.
|
|
31
|
-
3. Record 2-3 key observations in
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
34
|
-
6. If the session made cross-cutting decisions or proposed conventions,
|
|
29
|
+
2. Write `scratch/handoffs/<phase>.yaml` (see `templates/phase-handoff.yaml`): `schema_version: 1`, the exact `phase_id`, arrays for `owner_notes`, `open_questions`, `carry_forward`, `carry_forward_closures`, `open_question_closures`, `post_pipeline`, and `decisions`, plus `closeout_summary` and optional multiline `closeout_content`. See GUIDE.md "Open Questions vs Carry-Forward" for the entry shape.
|
|
30
|
+
3. Record 2-3 key observations in the handoff's `owner_notes`.
|
|
31
|
+
4. Store the durable output in the declared `findings/` path.
|
|
32
|
+
5. Run completion. The framework verifies the primary output and validation, applies the handoff to `workflow/status.yaml`, and writes the closeout and `THREAD_LOG.md` entry.
|
|
33
|
+
6. If the session made cross-cutting decisions or proposed conventions, record them in the handoff's `decisions` array and the closeout content's "Decisions Beyond Prompt" and "Proposed Conventions" sections. The orchestrator promotes them to `DECISIONS.md` and `CONVENTIONS.md` respectively.
|
|
35
34
|
|
|
36
35
|
## File-System Sync Warning
|
|
37
36
|
|
|
@@ -44,4 +43,4 @@ To stay safe:
|
|
|
44
43
|
- **Never chain Edit and bash heredocs against the same file in a single session** — pick one writer and stick with it.
|
|
45
44
|
- Keep test code in a separate file from production code so a sync gap on one doesn't poison the other.
|
|
46
45
|
|
|
47
|
-
This is not a CodeCartographer issue per se, but the framework's reliance on
|
|
46
|
+
This is not a CodeCartographer issue per se, but the framework's reliance on large narrative files (findings reports, primary outputs) magnifies the cost — every truncated write is a potential silent data loss in a load-bearing place.
|
|
@@ -57,4 +57,4 @@ If the semantic phase later finds related defects, those go in its own report
|
|
|
57
57
|
- Auth, input validation, secrets, and trust boundary defects → pass 4 in `defect-scan-semantic`.
|
|
58
58
|
- API/spec/state-machine drift → pass 5 in `defect-scan-semantic`.
|
|
59
59
|
|
|
60
|
-
If you spot something semantic during this phase, record it as a `carry_forward` entry in `
|
|
60
|
+
If you spot something semantic during this phase, record it as a `carry_forward` entry in your phase handoff at `scratch/handoffs/defect-scan-mechanical.yaml` with `target_phase: defect-scan-semantic`. Completion applies it to `workflow/status.yaml`, and the semantic phase receives it as a routed item in its prompt. Listing it only in your report's routing table does not route it.
|
|
@@ -86,7 +86,7 @@ Per the standard closeout ritual:
|
|
|
86
86
|
|
|
87
87
|
- Append a one-line entry to `THREAD_LOG.md` pointing at the closeout file.
|
|
88
88
|
- Write `closeouts/<YYYY-MM-DD>-spec-deltas.md` using `templates/closeout-template.md`.
|
|
89
|
-
-
|
|
89
|
+
- If a delta closed an `open_questions` or `carry_forward` entry, record that in the closeout. Do not edit `status.yaml` — phase state is framework-owned, and post-pipeline work has no completion step that applies handoffs, so a hand-edit here is unreviewed and can be overwritten by a later phase completion.
|
|
90
90
|
- Append numbered entries to `DECISIONS.md` for any decisions made during triage that weren't already in the deltas (e.g., "rejected Δ7 because the spec already covered the case at §X").
|
|
91
91
|
|
|
92
92
|
## What to avoid
|
|
@@ -126,7 +126,8 @@
|
|
|
126
126
|
|
|
127
127
|
<!-- Items deferred to a specific later phase whose rubric is the right place to close them.
|
|
128
128
|
Each entry: { id, kind: defer-to-phase, target_phase, description, deferred_reason }.
|
|
129
|
-
Mirror these into
|
|
129
|
+
Mirror these into your phase handoff at scratch/handoffs/<phase>.yaml under carry_forward;
|
|
130
|
+
completion applies them to workflow/status.yaml. Never write that file yourself. -->
|
|
130
131
|
|
|
131
132
|
| ID | Target Phase | Description | Deferred Reason |
|
|
132
133
|
|---|---|---|---|
|
|
@@ -114,7 +114,8 @@
|
|
|
114
114
|
<!-- Items deferred to a specific later phase whose rubric is the right place to close them.
|
|
115
115
|
Common targets from contracts: protocols (wire-format details), porting (synthesis-level resolution).
|
|
116
116
|
Each entry: { id, kind: defer-to-phase, target_phase, description, deferred_reason }.
|
|
117
|
-
Mirror these into
|
|
117
|
+
Mirror these into your phase handoff at scratch/handoffs/<phase>.yaml under carry_forward;
|
|
118
|
+
completion applies them to workflow/status.yaml. Never write that file yourself. -->
|
|
118
119
|
|
|
119
120
|
| ID | Target Phase | Description | Deferred Reason |
|
|
120
121
|
|---|---|---|---|
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
## Open Questions Left Behind
|
|
59
59
|
|
|
60
60
|
<!-- Items that are still genuinely unknown after this session.
|
|
61
|
-
Mirror these into
|
|
61
|
+
Mirror these into your phase handoff under open_questions; completion applies them
|
|
62
|
+
to workflow/status.yaml. This table documents them — it does not record them. -->
|
|
62
63
|
|
|
63
64
|
| ID | Kind | Description | Deferred Reason |
|
|
64
65
|
|---|---|---|---|
|
|
@@ -67,7 +68,9 @@
|
|
|
67
68
|
## Carry-Forward Routed
|
|
68
69
|
|
|
69
70
|
<!-- Items deferred to a specific later phase.
|
|
70
|
-
Mirror these into
|
|
71
|
+
Mirror these into your phase handoff under carry_forward, each with a target_phase;
|
|
72
|
+
completion applies them to workflow/status.yaml. This table documents them — it does
|
|
73
|
+
not route them. -->
|
|
71
74
|
|
|
72
75
|
| ID | Target Phase | Description | Deferred Reason |
|
|
73
76
|
|---|---|---|---|
|
|
@@ -79,8 +79,10 @@
|
|
|
79
79
|
### Routed To Semantic Phase
|
|
80
80
|
|
|
81
81
|
<!-- Items spotted during this phase that are actually semantic in nature
|
|
82
|
-
(concurrency, security, contract drift). Mirror these into
|
|
83
|
-
|
|
82
|
+
(concurrency, security, contract drift). Mirror these into your phase handoff at
|
|
83
|
+
scratch/handoffs/defect-scan-mechanical.yaml as carry_forward entries with
|
|
84
|
+
target_phase: defect-scan-semantic; completion applies them to workflow/status.yaml.
|
|
85
|
+
The table below documents the routing — it does not perform it. -->
|
|
84
86
|
|
|
85
87
|
| ID | Description | Why Routed |
|
|
86
88
|
|----|-------------|-----------|
|
|
@@ -109,7 +109,8 @@
|
|
|
109
109
|
<!-- Items deferred to a specific later phase whose rubric is the right place to close them.
|
|
110
110
|
Common target from protocols: porting (synthesis-level resolution).
|
|
111
111
|
Each entry: { id, kind: defer-to-phase, target_phase, description, deferred_reason }.
|
|
112
|
-
Mirror these into
|
|
112
|
+
Mirror these into your phase handoff at scratch/handoffs/<phase>.yaml under carry_forward;
|
|
113
|
+
completion applies them to workflow/status.yaml. Never write that file yourself. -->
|
|
113
114
|
|
|
114
115
|
| ID | Target Phase | Description | Deferred Reason |
|
|
115
116
|
|---|---|---|---|
|
|
@@ -140,7 +140,8 @@
|
|
|
140
140
|
<!-- Items deferred to a specific later phase whose rubric is the right place to close them.
|
|
141
141
|
Common target from porting: reimplementation-spec (rule-pinning, opinionated decisions).
|
|
142
142
|
Each entry: { id, kind: defer-to-phase, target_phase, description, deferred_reason }.
|
|
143
|
-
Mirror these into
|
|
143
|
+
Mirror these into your phase handoff at scratch/handoffs/<phase>.yaml under carry_forward;
|
|
144
|
+
completion applies them to workflow/status.yaml. Never write that file yourself. -->
|
|
144
145
|
|
|
145
146
|
| ID | Target Phase | Description | Deferred Reason |
|
|
146
147
|
|---|---|---|---|
|
|
@@ -85,7 +85,9 @@
|
|
|
85
85
|
|
|
86
86
|
### Carry-Forward Closure
|
|
87
87
|
|
|
88
|
-
<!-- carry_forward entries
|
|
88
|
+
<!-- carry_forward entries routed to defect-scan-semantic (delivered in this phase's prompt)
|
|
89
|
+
that were closed here. Address each in the findings above, then list its id under
|
|
90
|
+
carry_forward_closures in your phase handoff so completion removes the entry. -->
|
|
89
91
|
|
|
90
92
|
| ID | Source Phase | Closed Because |
|
|
91
93
|
|----|--------------|---------------|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
# THREAD_LOG.md Entry
|
|
1
|
+
# THREAD_LOG.md Entry Format (framework-owned)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
The full body of each session lives in a separate closeout file under `closeouts/`.
|
|
3
|
+
`THREAD_LOG.md` is written by completion, not by sessions. Completion appends one index entry per completed phase, built from the `closeout_summary` in your phase handoff and the canonical closeout filename, and skips the append when an entry already links that closeout — so retries never duplicate.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Your input to this file is the handoff's `closeout_summary`. The full body of each session lives in a separate closeout file under `closeouts/`; for that file, use `templates/closeout-template.md`.
|
|
7
6
|
|
|
8
|
-
## Entry format
|
|
7
|
+
## Entry format produced
|
|
9
8
|
|
|
10
9
|
```
|
|
11
|
-
- YYYY-MM-DD — <phase-or-module> — <
|
|
10
|
+
- YYYY-MM-DD — <phase-or-module> — <closeout_summary> — [closeout](closeouts/YYYY-MM-DD-phase-or-module.md)
|
|
12
11
|
```
|
|
13
12
|
|
|
14
13
|
## Example
|
|
@@ -17,11 +16,10 @@ For the closeout file itself, use `templates/closeout-template.md`.
|
|
|
17
16
|
- 2026-05-02 — architecture — mapped 14 packages across 3 layers; 2 carry-forward items routed to defect-scan — [closeout](closeouts/2026-05-02-architecture.md)
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
##
|
|
19
|
+
## Writing a good closeout_summary
|
|
21
20
|
|
|
22
|
-
- One
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- Before appending, scan the bottom 5 entries to avoid duplicating a prior session's entry.
|
|
21
|
+
- One clause, no more than ~20 words — it has to read well inside the one-line entry above.
|
|
22
|
+
- Name what the phase established and what it routed onward, as in the example.
|
|
23
|
+
- Omitting it is allowed; completion falls back to `Validation: <overall>`, which carries no information about the work.
|
|
24
|
+
|
|
25
|
+
Everything else in the entry — the date, the phase slug, the closeout link, and de-duplication across retries — is supplied by the framework. Do not append to `THREAD_LOG.md` yourself; a hand-written entry will sit alongside the canonical one rather than replacing it.
|
|
@@ -13,8 +13,8 @@ Run this check after completing a phase's primary output, before marking the pha
|
|
|
13
13
|
4. Append a validation block to the end of the primary output file (see format below).
|
|
14
14
|
5. If any criterion is FAIL, do not mark the phase as complete. Fix the output first.
|
|
15
15
|
6. If any criterion is PARTIAL, route the gap appropriately:
|
|
16
|
-
- If the gap is **still genuinely unknown** (needs a runtime test, maintainer decision, or spec ruling that no later phase will close), record it under `open_questions`
|
|
17
|
-
- If the gap is **deferred to a specific later phase** in this pipeline (the next phase's rubric is the right place to close it), record it under `carry_forward` with an explicit `target_phase` field. See GUIDE.md "Open Questions vs Carry-Forward" for the entry shape.
|
|
16
|
+
- If the gap is **still genuinely unknown** (needs a runtime test, maintainer decision, or spec ruling that no later phase will close), record it under `open_questions` in your phase handoff at `scratch/handoffs/<phase>.yaml`.
|
|
17
|
+
- If the gap is **deferred to a specific later phase** in this pipeline (the next phase's rubric is the right place to close it), record it under `carry_forward` in the same handoff with an explicit `target_phase` field. See GUIDE.md "Open Questions vs Carry-Forward" for the entry shape.
|
|
18
18
|
- You may still mark the phase complete if the gaps are documented under one of the two lists and are non-blocking for downstream phases.
|
|
19
19
|
|
|
20
20
|
## Validation Block Format
|
|
@@ -56,20 +56,23 @@ Below is what a real PASS WITH GAPS block looks like — useful when a phase fin
|
|
|
56
56
|
**Overall:** PASS WITH GAPS
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
You record the `arch-CF2` entry in your phase handoff at `scratch/handoffs/architecture.yaml`:
|
|
60
60
|
|
|
61
61
|
```yaml
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
schema_version: 1
|
|
63
|
+
phase_id: architecture
|
|
64
|
+
carry_forward:
|
|
65
|
+
- id: arch-CF2
|
|
66
|
+
kind: defer-to-phase
|
|
67
|
+
target_phase: protocols
|
|
68
|
+
description: MCP server endpoints and websocket subscription channel listed by name only; schemas not extracted.
|
|
69
|
+
deferred_reason: Wire-format extraction is the protocols phase's rubric; deferring avoids guessing at shapes here.
|
|
70
|
+
closeout_summary: Architecture mapped; wire formats deferred to protocols.
|
|
70
71
|
```
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
Completion validates the handoff and applies the entry to `workflow/status.yaml` under the architecture phase's `carry_forward`. Never write that file yourself — see GUIDE.md "Trust Boundaries."
|
|
74
|
+
|
|
75
|
+
The protocols phase then receives `arch-CF2` in its phase prompt as a routed item. It either resolves it (addressing it in the phase output and listing the id under `carry_forward_closures` in its own handoff, so completion removes the entry atomically) or re-defers it by writing a fresh `carry_forward` entry naming a later `target_phase`.
|
|
73
76
|
|
|
74
77
|
## Rules
|
|
75
78
|
|
|
@@ -77,5 +80,5 @@ The protocols phase, on session start, scans `carry_forward` entries with `targe
|
|
|
77
80
|
- Do not inflate results. A criterion you are uncertain about is PARTIAL, not PASS.
|
|
78
81
|
- If the output file already has a validation block from a prior session, replace it with a fresh one.
|
|
79
82
|
- Validation checks the output against the pipeline's criteria only. It does not re-evaluate the source code.
|
|
80
|
-
- For automated agents: a phase with any FAIL result must not
|
|
81
|
-
- A PARTIAL row's `Evidence` cell must name what is missing and (if applicable) which `open_questions` or `carry_forward` entry tracks the gap. "Incomplete" alone is not honest enough.
|
|
83
|
+
- For automated agents: a phase with any FAIL result must not be completed. Completion refuses FAIL and MISSING validations outright.
|
|
84
|
+
- A PARTIAL row's `Evidence` cell must name what is missing and (if applicable) which `open_questions` or `carry_forward` entry tracks the gap. "Incomplete" alone is not honest enough. Record that entry in the phase handoff — an evidence cell that only *describes* the routing does not perform it.
|
|
@@ -35,5 +35,5 @@ phases:
|
|
|
35
35
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
36
36
|
handoff_requirements:
|
|
37
37
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
38
|
-
-
|
|
39
|
-
-
|
|
38
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
39
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -36,8 +36,8 @@ phases:
|
|
|
36
36
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
37
37
|
handoff_requirements:
|
|
38
38
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
39
|
-
-
|
|
40
|
-
-
|
|
39
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
40
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
41
41
|
- id: defect-scan
|
|
42
42
|
purpose: Run a multi-pass defect scan to identify bugs, security issues, and code quality problems for maintenance prioritization.
|
|
43
43
|
skill_path: findings/defect-scan/SKILL.md
|
|
@@ -59,5 +59,5 @@ phases:
|
|
|
59
59
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
60
60
|
handoff_requirements:
|
|
61
61
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
62
|
-
-
|
|
63
|
-
-
|
|
62
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
63
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -40,8 +40,8 @@ phases:
|
|
|
40
40
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
41
41
|
handoff_requirements:
|
|
42
42
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
43
|
-
-
|
|
44
|
-
-
|
|
43
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
44
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
45
45
|
- id: defect-scan
|
|
46
46
|
purpose: Run a multi-pass defect scan to identify legacy bugs, security issues, and code quality problems before porting.
|
|
47
47
|
skill_path: findings/defect-scan/SKILL.md
|
|
@@ -63,8 +63,8 @@ phases:
|
|
|
63
63
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
64
64
|
handoff_requirements:
|
|
65
65
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
66
|
-
-
|
|
67
|
-
-
|
|
66
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
67
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
68
68
|
- id: contracts
|
|
69
69
|
purpose: Recover user-visible behavior, defaults, side effects, error behavior, and black-box acceptance checks.
|
|
70
70
|
skill_path: findings/contracts/SKILL.md
|
|
@@ -95,8 +95,8 @@ phases:
|
|
|
95
95
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
96
96
|
handoff_requirements:
|
|
97
97
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
98
|
-
-
|
|
99
|
-
-
|
|
98
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
99
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
100
100
|
- id: protocols
|
|
101
101
|
purpose: Capture event catalogs, state machines, persistence formats, and compatibility hazards.
|
|
102
102
|
skill_path: findings/protocols/SKILL.md
|
|
@@ -126,8 +126,8 @@ phases:
|
|
|
126
126
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
127
127
|
handoff_requirements:
|
|
128
128
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
129
|
-
-
|
|
130
|
-
-
|
|
129
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
130
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
131
131
|
- id: porting
|
|
132
132
|
purpose: Synthesize architecture, contracts, protocols, and defect findings into a reverse-engineering bundle oriented toward porting.
|
|
133
133
|
skill_path: findings/porting/SKILL.md
|
|
@@ -165,8 +165,8 @@ phases:
|
|
|
165
165
|
- The Source Index makes the bundle a self-contained compression boundary and identifies targeted deep-read triggers.
|
|
166
166
|
handoff_requirements:
|
|
167
167
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
168
|
-
-
|
|
169
|
-
-
|
|
168
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
169
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
170
170
|
- id: reimplementation-spec
|
|
171
171
|
purpose: Produce the final language-agnostic reimplementation plan and acceptance spec.
|
|
172
172
|
skill_path: findings/reimplementation-spec/SKILL.md
|
|
@@ -189,5 +189,5 @@ phases:
|
|
|
189
189
|
- Lower-level findings are deep-read only when the porting bundle identifies a gap, conflict, missing acceptance detail, or defect rationale.
|
|
190
190
|
handoff_requirements:
|
|
191
191
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
192
|
-
-
|
|
193
|
-
-
|
|
192
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
193
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -41,8 +41,8 @@ phases:
|
|
|
41
41
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
42
42
|
handoff_requirements:
|
|
43
43
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
44
|
-
-
|
|
45
|
-
-
|
|
44
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
45
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
46
46
|
- id: defect-scan-mechanical
|
|
47
47
|
purpose: Early, context-light defect pass covering logic, error handling, and configuration hazards. Runs before contracts so mechanical bugs are surfaced for the contracts and porting phases to reference.
|
|
48
48
|
skill_path: findings/defect-scan-mechanical/SKILL.md
|
|
@@ -60,13 +60,13 @@ phases:
|
|
|
60
60
|
- Each finding has location, severity, evidence level, and recommended action.
|
|
61
61
|
- Findings are organized by pass and sorted by severity.
|
|
62
62
|
- Summary tables are complete and counts match the detailed findings.
|
|
63
|
-
- Items spotted that are actually semantic in nature are routed
|
|
63
|
+
- Items spotted that are actually semantic in nature are routed onward via a carry_forward entry in the phase handoff targeting defect-scan-semantic.
|
|
64
64
|
- Findings are marked with evidence levels.
|
|
65
65
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
66
66
|
handoff_requirements:
|
|
67
67
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
68
|
-
-
|
|
69
|
-
-
|
|
68
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
69
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
70
70
|
- id: contracts
|
|
71
71
|
purpose: Recover user-visible behavior, defaults, side effects, error behavior, and black-box acceptance checks.
|
|
72
72
|
skill_path: findings/contracts/SKILL.md
|
|
@@ -98,8 +98,8 @@ phases:
|
|
|
98
98
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
99
99
|
handoff_requirements:
|
|
100
100
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
101
|
-
-
|
|
102
|
-
-
|
|
101
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
102
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
103
103
|
- id: protocols
|
|
104
104
|
purpose: Capture event catalogs, state machines, persistence formats, and compatibility hazards.
|
|
105
105
|
skill_path: findings/protocols/SKILL.md
|
|
@@ -130,8 +130,8 @@ phases:
|
|
|
130
130
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
131
131
|
handoff_requirements:
|
|
132
132
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
133
|
-
-
|
|
134
|
-
-
|
|
133
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
134
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
135
135
|
- id: defect-scan-semantic
|
|
136
136
|
purpose: Deep, context-rich defect pass covering concurrency, security, and API contract violations. Runs after protocols so contracts/protocols context is available, and before porting so the porting phase can synthesize all defects with full understanding of the system.
|
|
137
137
|
skill_path: findings/defect-scan-semantic/SKILL.md
|
|
@@ -160,8 +160,8 @@ phases:
|
|
|
160
160
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
161
161
|
handoff_requirements:
|
|
162
162
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
163
|
-
-
|
|
164
|
-
-
|
|
163
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
164
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
165
165
|
- id: porting
|
|
166
166
|
purpose: Synthesize architecture, contracts, protocols, and both defect passes into a reverse-engineering bundle oriented toward porting. Fill the Defect Synthesis section by consolidating mechanical-defects.md and semantic-defects.md into a single porting-oriented view.
|
|
167
167
|
skill_path: findings/porting/SKILL.md
|
|
@@ -202,8 +202,8 @@ phases:
|
|
|
202
202
|
- The Source Index makes the bundle a self-contained compression boundary and identifies targeted deep-read triggers.
|
|
203
203
|
handoff_requirements:
|
|
204
204
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
205
|
-
-
|
|
206
|
-
-
|
|
205
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
206
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
207
207
|
- id: reimplementation-spec
|
|
208
208
|
purpose: Produce the final language-agnostic reimplementation plan and acceptance spec. The Strategic Alignment Hook in GUIDE.md decides between the default and opinionated template variants.
|
|
209
209
|
skill_path: findings/reimplementation-spec/SKILL.md
|
|
@@ -227,5 +227,5 @@ phases:
|
|
|
227
227
|
- Lower-level findings are deep-read only when the porting bundle identifies a gap, conflict, missing acceptance detail, or defect rationale.
|
|
228
228
|
handoff_requirements:
|
|
229
229
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
230
|
-
-
|
|
231
|
-
-
|
|
230
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
231
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -37,8 +37,8 @@ phases:
|
|
|
37
37
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
38
38
|
handoff_requirements:
|
|
39
39
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
40
|
-
-
|
|
41
|
-
-
|
|
40
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
41
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
42
42
|
- id: contracts
|
|
43
43
|
purpose: Recover user-visible behavior, defaults, side effects, error behavior, and black-box acceptance checks.
|
|
44
44
|
skill_path: findings/contracts/SKILL.md
|
|
@@ -68,8 +68,8 @@ phases:
|
|
|
68
68
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
69
69
|
handoff_requirements:
|
|
70
70
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
71
|
-
-
|
|
72
|
-
-
|
|
71
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
72
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
73
73
|
- id: protocols
|
|
74
74
|
purpose: Capture event catalogs, state machines, persistence formats, and compatibility hazards.
|
|
75
75
|
skill_path: findings/protocols/SKILL.md
|
|
@@ -99,5 +99,5 @@ phases:
|
|
|
99
99
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
100
100
|
handoff_requirements:
|
|
101
101
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
102
|
-
-
|
|
103
|
-
-
|
|
102
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
103
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -39,8 +39,8 @@ phases:
|
|
|
39
39
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
40
40
|
handoff_requirements:
|
|
41
41
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
42
|
-
-
|
|
43
|
-
-
|
|
42
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
43
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
44
44
|
- id: contracts
|
|
45
45
|
purpose: Recover user-visible behavior, defaults, side effects, error behavior, and black-box acceptance checks.
|
|
46
46
|
skill_path: findings/contracts/SKILL.md
|
|
@@ -71,8 +71,8 @@ phases:
|
|
|
71
71
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
72
72
|
handoff_requirements:
|
|
73
73
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
74
|
-
-
|
|
75
|
-
-
|
|
74
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
75
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
76
76
|
- id: protocols
|
|
77
77
|
purpose: Capture event catalogs, state machines, persistence formats, and compatibility hazards.
|
|
78
78
|
skill_path: findings/protocols/SKILL.md
|
|
@@ -102,8 +102,8 @@ phases:
|
|
|
102
102
|
- Coverage and limits name inspected scope, skipped scope, evidence basis, and blind spots.
|
|
103
103
|
handoff_requirements:
|
|
104
104
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
105
|
-
-
|
|
106
|
-
-
|
|
105
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
106
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
107
107
|
- id: porting
|
|
108
108
|
purpose: Synthesize architecture, contracts, and protocols into a reverse-engineering bundle oriented toward porting.
|
|
109
109
|
skill_path: findings/porting/SKILL.md
|
|
@@ -139,8 +139,8 @@ phases:
|
|
|
139
139
|
- The Source Index makes the bundle a self-contained compression boundary and identifies targeted deep-read triggers.
|
|
140
140
|
handoff_requirements:
|
|
141
141
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
142
|
-
-
|
|
143
|
-
-
|
|
142
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
143
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
144
144
|
- id: reimplementation-spec
|
|
145
145
|
purpose: Produce the final language-agnostic reimplementation plan and acceptance spec.
|
|
146
146
|
skill_path: findings/reimplementation-spec/SKILL.md
|
|
@@ -163,5 +163,5 @@ phases:
|
|
|
163
163
|
- Lower-level findings are deep-read only when the porting bundle identifies a gap, conflict, missing acceptance detail, or defect rationale.
|
|
164
164
|
handoff_requirements:
|
|
165
165
|
- Run validation per workflow/VALIDATE.md. Append validation block to primary output.
|
|
166
|
-
-
|
|
167
|
-
-
|
|
166
|
+
- Write the phase handoff to scratch/handoffs/<phase>.yaml with owner notes, open questions, and carry-forward routings; completion applies it to workflow/status.yaml.
|
|
167
|
+
- Provide closeout_summary and optional closeout_content in the handoff; completion writes the closeout and THREAD_LOG.md entry.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Version of the CodeCartographer release that shipped this .codecarto/
|
|
2
|
+
# scaffold. The framework compares it against its own version to warn when a
|
|
3
|
+
# workspace's framework-owned files (GUIDE.md, templates/, workflow/ pipelines
|
|
4
|
+
# and VALIDATE.md) predate the running release. Written at release time and
|
|
5
|
+
# copied verbatim by init — never edit by hand.
|
|
6
|
+
scaffold_version: 0.13.0
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/codecartographer-pi)
|
|
10
10
|
[](package.json)
|
|
11
11
|
|
|
12
|
-
> **
|
|
12
|
+
> **Understand an unfamiliar codebase with an AI agent — and get a validated spec you can rebuild from.** CodeCartographer turns a repository into layered architecture, behavioral contracts, defect findings, and a language-agnostic reimplementation spec, with each phase validated before the next one runs. Works with Pi, Claude Code, Cursor, Codex, or any MCP-capable agent.
|
|
13
13
|
|
|
14
14
|
```text
|
|
15
15
|
● CodeCartographer
|
|
@@ -19,6 +19,24 @@
|
|
|
19
19
|
⎿ extracting behavioral contracts from server/index.ts…
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
<p align="center">
|
|
23
|
+
<img src="docs/demo-dashboard-hero.png" alt="CodeCartographer dashboard — a mid-run pipeline with architecture and defect-scan phases complete, contracts in progress, per-phase token and tool-use telemetry.">
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Why CodeCartographer
|
|
29
|
+
|
|
30
|
+
Asking an LLM to "analyze this repo" loses context halfway through, hallucinates findings, and leaves no artifact the next session can pick up. CodeCartographer fixes three things:
|
|
31
|
+
|
|
32
|
+
1. **The filesystem is the memory, not the conversation.** Each phase writes a smaller, templated, evidence-tagged artifact to `.codecarto/findings/`. Later phases re-read the specific upstream files they need. A new session — or a context compaction — picks up from `status.yaml` without losing progress.
|
|
33
|
+
|
|
34
|
+
2. **Every phase is validated before the pipeline advances.** Completion criteria are real: a `FAIL` output stops the run. You can't accidentally build a reimplementation spec on top of hallucinated architecture.
|
|
35
|
+
|
|
36
|
+
3. **The output is a spec, not a chat log.** The final `reimplementation-spec.md` is language-agnostic, module-inventoried, and carries acceptance scenarios plus known unknowns. Hand it to another agent to rebuild from.
|
|
37
|
+
|
|
38
|
+
Every finding is tagged with an evidence level: `observed fact`, `strong inference`, `portability hazard`, or `open question`.
|
|
39
|
+
|
|
22
40
|
---
|
|
23
41
|
|
|
24
42
|
## At a glance
|
|
@@ -36,6 +54,8 @@
|
|
|
36
54
|
|
|
37
55
|
Publish completed reimplementation specs from Pi or MCP, then run the `synthesis` pipeline to turn a product vision and explicitly confirmed library entries into a conflict-aware `project-plan.md` with a decision-level provenance ledger.
|
|
38
56
|
|
|
57
|
+
> **If CodeCartographer saves you a day of codebase archaeology, star the repo** — it helps the next person find it.
|
|
58
|
+
|
|
39
59
|
OpenAI Build Week reviewers: see the [new-vs-existing scope and one-command demo](docs/build-week-2026.md).
|
|
40
60
|
|
|
41
61
|
---
|
|
@@ -70,6 +90,8 @@ pi -e /absolute/path/to/CodeCartographer/extensions/codecarto/index.ts
|
|
|
70
90
|
|
|
71
91
|
Use this when your coding agent isn't Pi — Claude Code, Codex, opencode, Cursor, Claude Desktop, or anything else that speaks MCP. The host drives the conversation and runs the LLM; CodeCartographer provides phase prompts, validation, and experimental library publish/list/reindex operations.
|
|
72
92
|
|
|
93
|
+
> **30-second setup for Claude Code, Cursor, Codex, and Claude Desktop: see the [MCP quickstart](docs/mcp-quickstart.md).**
|
|
94
|
+
|
|
73
95
|
```bash
|
|
74
96
|
npm install --global codecartographer-pi
|
|
75
97
|
```
|
package/dist/core/completion.js
CHANGED
|
@@ -54,6 +54,19 @@ export async function completeValidatedPhase(cwd, validation, sourceLabel) {
|
|
|
54
54
|
if (handoff && handoff.phase_id !== validation.phaseId) {
|
|
55
55
|
throw new Error(`Invalid handoff: phase_id ${handoff.phase_id} does not match ${validation.phaseId}`);
|
|
56
56
|
}
|
|
57
|
+
// A phase that declares handoff_requirements must not complete without its
|
|
58
|
+
// handoff: silently proceeding writes empty carry_forward/open_questions and
|
|
59
|
+
// severs the cross-phase routing channel (issue #84). Phases without the
|
|
60
|
+
// declaration keep the lenient path for custom pipelines.
|
|
61
|
+
if (!handoff) {
|
|
62
|
+
const declaringPhase = resolvePhase(initialState, validation.phaseId);
|
|
63
|
+
if (declaringPhase?.handoff_requirements?.length) {
|
|
64
|
+
throw new Error(`Phase ${validation.phaseId} declares handoff_requirements, but no phase handoff exists at .codecarto/scratch/handoffs/${validation.phaseId}.yaml. `
|
|
65
|
+
+ `Write the handoff first (see GUIDE.md and templates/phase-handoff.yaml): schema_version: 1, the exact phase_id, `
|
|
66
|
+
+ `arrays for owner_notes, open_questions, carry_forward, carry_forward_closures, open_question_closures, post_pipeline, and decisions (omitted arrays default to empty), `
|
|
67
|
+
+ `plus closeout_summary and optional closeout_content. Then re-run completion.`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
57
70
|
if (handoff) {
|
|
58
71
|
const activePhases = new Set(initialState.pipeline.phase_order);
|
|
59
72
|
const sourceIndex = initialState.pipeline.phase_order.indexOf(validation.phaseId);
|
package/dist/core/prompts.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { readdir } from "node:fs/promises";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { pathExists } from "./utils.js";
|
|
7
|
+
import { describeScaffoldStaleness } from "./workspace.js";
|
|
7
8
|
import { runPhasePreflight } from "./synthesis.js";
|
|
8
9
|
export function describeEntry(entry) {
|
|
9
10
|
const parts = [];
|
|
@@ -30,6 +31,7 @@ export function collectRoutedCarryForward(state, targetPhaseId) {
|
|
|
30
31
|
export async function buildPhasePrompt(state, phase, forced, options = {}) {
|
|
31
32
|
const preflight = options.preflight ?? await runPhasePreflight(state, phase);
|
|
32
33
|
const synthesisWorkflow = state.pipeline.workflow_name === "evidence-backed-project-synthesis";
|
|
34
|
+
const handoffTemplateExists = await pathExists(join(state.workspaceDir, "templates", "phase-handoff.yaml"));
|
|
33
35
|
const lines = [
|
|
34
36
|
`Read .codecarto/GUIDE.md and continue the CodeCartographer workflow for the phase \`${phase.id}\`.`,
|
|
35
37
|
synthesisWorkflow
|
|
@@ -39,8 +41,10 @@ export async function buildPhasePrompt(state, phase, forced, options = {}) {
|
|
|
39
41
|
"Required reads before analysis:",
|
|
40
42
|
"- .codecarto/GUIDE.md",
|
|
41
43
|
"- .codecarto/workflow/status.yaml",
|
|
42
|
-
"- .codecarto/templates/phase-handoff.yaml",
|
|
43
44
|
];
|
|
45
|
+
if (handoffTemplateExists) {
|
|
46
|
+
lines.push("- .codecarto/templates/phase-handoff.yaml");
|
|
47
|
+
}
|
|
44
48
|
const primaryOutput = phase.primary_output ? `.codecarto/${phase.primary_output}` : undefined;
|
|
45
49
|
if (primaryOutput) {
|
|
46
50
|
lines.push(`- ${primaryOutput} if it already exists (continue instead of duplicating work)`);
|
|
@@ -69,6 +73,21 @@ export async function buildPhasePrompt(state, phase, forced, options = {}) {
|
|
|
69
73
|
if (await pathExists(decisionsPath)) {
|
|
70
74
|
lines.push("- .codecarto/DECISIONS.md (numbered project decisions; new entries are appended in your closeout)");
|
|
71
75
|
}
|
|
76
|
+
// Stale-scaffold warnings (issue #85): a workspace copied from an old
|
|
77
|
+
// template can contradict the runtime contract. Both surfaces render this
|
|
78
|
+
// prompt, so warn here rather than per-host.
|
|
79
|
+
const scaffoldWarnings = [];
|
|
80
|
+
if (!handoffTemplateExists) {
|
|
81
|
+
scaffoldWarnings.push(`.codecarto/templates/phase-handoff.yaml is missing — this scaffold predates the v0.12.0 handoff contract. Completion still requires a phase handoff at .codecarto/scratch/handoffs/${phase.id}.yaml; refresh the framework-owned files (GUIDE.md, templates/, workflow/VALIDATE.md, workflow/pipeline*.yaml) from the current CodeCartographer template, and trust this prompt over the workspace GUIDE.md where they disagree.`);
|
|
82
|
+
}
|
|
83
|
+
const staleness = describeScaffoldStaleness(state);
|
|
84
|
+
if (staleness)
|
|
85
|
+
scaffoldWarnings.push(staleness);
|
|
86
|
+
if (scaffoldWarnings.length > 0) {
|
|
87
|
+
lines.push("");
|
|
88
|
+
for (const warning of scaffoldWarnings)
|
|
89
|
+
lines.push(`WARNING: ${warning}`);
|
|
90
|
+
}
|
|
72
91
|
const routed = collectRoutedCarryForward(state, phase.id);
|
|
73
92
|
if (routed.length > 0) {
|
|
74
93
|
lines.push("", `Items routed to \`${phase.id}\` for closure (carry_forward from earlier phases):`);
|
package/dist/core/types.d.ts
CHANGED
|
@@ -67,6 +67,8 @@ export type WorkspaceState = {
|
|
|
67
67
|
pipelinePath: string;
|
|
68
68
|
status: NormalizedStatus;
|
|
69
69
|
pipeline: PipelineFile;
|
|
70
|
+
/** From workflow/scaffold-version.yaml; undefined for scaffolds that predate the marker. */
|
|
71
|
+
scaffoldVersion?: string;
|
|
70
72
|
};
|
|
71
73
|
export type ValidationOverall = "PASS" | "PASS WITH GAPS" | "FAIL" | "MISSING";
|
|
72
74
|
export type ValidationResult = {
|
package/dist/core/workspace.d.ts
CHANGED
|
@@ -2,6 +2,15 @@ import type { PhaseHandoff, WorkspaceState } from "./types.ts";
|
|
|
2
2
|
export declare const packagedWorkspaceDir: string;
|
|
3
3
|
export declare const PACKAGE_VERSION: string;
|
|
4
4
|
export declare function getWorkspaceState(cwd: string): Promise<WorkspaceState | null>;
|
|
5
|
+
/**
|
|
6
|
+
* Human-readable staleness notice for the workspace's .codecarto/ scaffold,
|
|
7
|
+
* or null when the scaffold matches the running framework. A missing marker
|
|
8
|
+
* means the scaffold was copied from a release that predates it — those
|
|
9
|
+
* scaffolds may also predate the v0.12.0 handoff contract, whose GUIDE and
|
|
10
|
+
* pipelines instruct the exact opposite completion protocol. Warn, never
|
|
11
|
+
* fail: unversioned workspaces must keep working.
|
|
12
|
+
*/
|
|
13
|
+
export declare function describeScaffoldStaleness(state: WorkspaceState): string | null;
|
|
5
14
|
export declare function updateStatusAtomically(cwd: string, updater: (state: WorkspaceState) => Promise<{
|
|
6
15
|
state: WorkspaceState;
|
|
7
16
|
handoff?: PhaseHandoff;
|
package/dist/core/workspace.js
CHANGED
|
@@ -76,6 +76,17 @@ export async function getWorkspaceState(cwd) {
|
|
|
76
76
|
}
|
|
77
77
|
const pipeline = await loadYamlFile(pipelinePath);
|
|
78
78
|
const status = normalizeStatus(rawStatus, pipeline, pipelineRelativePath, cwd);
|
|
79
|
+
const scaffoldVersionPath = join(workspaceDir, "workflow", "scaffold-version.yaml");
|
|
80
|
+
let scaffoldVersion;
|
|
81
|
+
if (await pathExists(scaffoldVersionPath)) {
|
|
82
|
+
const marker = await loadYamlFile(scaffoldVersionPath);
|
|
83
|
+
if (typeof marker.scaffold_version === "string" && marker.scaffold_version.trim()) {
|
|
84
|
+
scaffoldVersion = marker.scaffold_version.trim();
|
|
85
|
+
}
|
|
86
|
+
else if (typeof marker.scaffold_version === "number") {
|
|
87
|
+
scaffoldVersion = String(marker.scaffold_version);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
79
90
|
return {
|
|
80
91
|
cwd,
|
|
81
92
|
workspaceDir,
|
|
@@ -83,8 +94,51 @@ export async function getWorkspaceState(cwd) {
|
|
|
83
94
|
pipelinePath,
|
|
84
95
|
pipeline,
|
|
85
96
|
status,
|
|
97
|
+
...(scaffoldVersion !== undefined && { scaffoldVersion }),
|
|
86
98
|
};
|
|
87
99
|
}
|
|
100
|
+
// Numeric x.y.z comparison; null when either side is not a plain dotted triple.
|
|
101
|
+
function compareDottedVersions(a, b) {
|
|
102
|
+
const parse = (version) => {
|
|
103
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version.trim());
|
|
104
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
105
|
+
};
|
|
106
|
+
const left = parse(a);
|
|
107
|
+
const right = parse(b);
|
|
108
|
+
if (!left || !right)
|
|
109
|
+
return null;
|
|
110
|
+
for (let i = 0; i < 3; i++) {
|
|
111
|
+
if (left[i] !== right[i])
|
|
112
|
+
return left[i] < right[i] ? -1 : 1;
|
|
113
|
+
}
|
|
114
|
+
return 0;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Human-readable staleness notice for the workspace's .codecarto/ scaffold,
|
|
118
|
+
* or null when the scaffold matches the running framework. A missing marker
|
|
119
|
+
* means the scaffold was copied from a release that predates it — those
|
|
120
|
+
* scaffolds may also predate the v0.12.0 handoff contract, whose GUIDE and
|
|
121
|
+
* pipelines instruct the exact opposite completion protocol. Warn, never
|
|
122
|
+
* fail: unversioned workspaces must keep working.
|
|
123
|
+
*/
|
|
124
|
+
export function describeScaffoldStaleness(state) {
|
|
125
|
+
const scaffold = state.scaffoldVersion;
|
|
126
|
+
if (!scaffold) {
|
|
127
|
+
return "This workspace's .codecarto/ scaffold has no workflow/scaffold-version.yaml marker (introduced after v0.12.11), so its framework-owned files (GUIDE.md, templates/, workflow/ pipelines and VALIDATE.md) may predate the v0.12.0 handoff contract. Refresh them from the packaged CodeCartographer template.";
|
|
128
|
+
}
|
|
129
|
+
const comparison = compareDottedVersions(scaffold, PACKAGE_VERSION);
|
|
130
|
+
if (comparison === 0)
|
|
131
|
+
return null;
|
|
132
|
+
if (comparison === null) {
|
|
133
|
+
return scaffold === PACKAGE_VERSION
|
|
134
|
+
? null
|
|
135
|
+
: `This workspace's scaffold version (${scaffold}) does not match the running framework (${PACKAGE_VERSION}). Refresh the framework-owned files (GUIDE.md, templates/, workflow/) from the packaged template.`;
|
|
136
|
+
}
|
|
137
|
+
if (comparison < 0) {
|
|
138
|
+
return `This workspace's scaffold (v${scaffold}) is older than the running framework (v${PACKAGE_VERSION}). Refresh the framework-owned files (GUIDE.md, templates/, workflow/) from the packaged template to pick up pipeline and template fixes.`;
|
|
139
|
+
}
|
|
140
|
+
return `This workspace's scaffold (v${scaffold}) is newer than the running framework (v${PACKAGE_VERSION}). Upgrade CodeCartographer to at least v${scaffold}.`;
|
|
141
|
+
}
|
|
88
142
|
export async function updateStatusAtomically(cwd, updater) {
|
|
89
143
|
const workspaceDir = join(cwd, ".codecarto");
|
|
90
144
|
const statusPath = join(workspaceDir, "workflow", "status.yaml");
|
|
@@ -8,7 +8,7 @@ import { narrateDashboard } from "./dashboard-narrator.js";
|
|
|
8
8
|
import { writeDashboard } from "./dashboard-writer.js";
|
|
9
9
|
import { parseNextFlags } from "./next-flags.js";
|
|
10
10
|
import { phaseCompactionExtension } from "./phase-compaction.js";
|
|
11
|
-
import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, canonicalPath, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isWithinPathResolved, listSkillNames, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, packagedWorkspaceDir, pathExists, PACKAGE_VERSION, PhasePreflightError, PIPELINE_ALIASES, publishEntry, resolvePhase, resolvePipelineChoice, runPhasePreflight, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, } from "../../core/index.js";
|
|
11
|
+
import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, canonicalPath, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, describeScaffoldStaleness, deriveSlug, discoverLibrary, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isWithinPathResolved, listSkillNames, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, packagedWorkspaceDir, pathExists, PACKAGE_VERSION, PhasePreflightError, PIPELINE_ALIASES, publishEntry, resolvePhase, resolvePipelineChoice, runPhasePreflight, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, } from "../../core/index.js";
|
|
12
12
|
import { initLibrary } from "../../core/library.js";
|
|
13
13
|
import { resolveUserConfigPath } from "../../core/orchestrator-config.js";
|
|
14
14
|
const STATUS_WIDGET_ID = "codecarto-widget";
|
|
@@ -71,6 +71,9 @@ function buildStatusLines(state, extraLines = []) {
|
|
|
71
71
|
`Post-pipeline work: ${postPipelinePending} pending`,
|
|
72
72
|
`Next: ${nextAction}`,
|
|
73
73
|
];
|
|
74
|
+
const scaffoldNotice = describeScaffoldStaleness(state);
|
|
75
|
+
if (scaffoldNotice)
|
|
76
|
+
lines.push(`Scaffold: ${scaffoldNotice}`);
|
|
74
77
|
if (extraLines.length > 0) {
|
|
75
78
|
lines.push("", ...extraLines);
|
|
76
79
|
}
|
|
@@ -78,6 +78,11 @@ export declare function handleSkill(args: {
|
|
|
78
78
|
}>;
|
|
79
79
|
structuredContent?: Record<string, unknown>;
|
|
80
80
|
}>;
|
|
81
|
+
export declare function readSpecArg(args: {
|
|
82
|
+
spec?: unknown;
|
|
83
|
+
spec_path?: unknown;
|
|
84
|
+
cwd?: unknown;
|
|
85
|
+
}, allowedRoots: string[]): Promise<string>;
|
|
81
86
|
export declare function handlePublish(args: Record<string, unknown>): Promise<{
|
|
82
87
|
content: Array<{
|
|
83
88
|
type: "text";
|
|
@@ -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, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isValidSlug, 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, 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";
|
|
@@ -118,7 +118,8 @@ export async function handleStatus(args) {
|
|
|
118
118
|
const currentOpenQuestions = currentPhase === "complete" ? 0 : state.status.phases[currentPhase]?.open_questions.length ?? 0;
|
|
119
119
|
const terminalOpenQuestions = Object.values(state.status.phases).reduce((sum, phase) => sum + (phase.open_questions?.length ?? 0), 0);
|
|
120
120
|
const postPipelinePending = state.status.post_pipeline.filter((entry) => entry.status !== "resolved").length;
|
|
121
|
-
const
|
|
121
|
+
const scaffoldNotice = describeScaffoldStaleness(state);
|
|
122
|
+
const summaryLines = [
|
|
122
123
|
`Phase: ${currentPhase}`,
|
|
123
124
|
`Pipeline state: ${currentPhase === "complete" ? "complete" : "in progress"}`,
|
|
124
125
|
`Pipeline: ${getPipelineLabel(state.status.pipeline)} (${state.status.pipeline})`,
|
|
@@ -127,8 +128,12 @@ export async function handleStatus(args) {
|
|
|
127
128
|
`Carry-forward (pipeline phases): ${totalCarryForward}`,
|
|
128
129
|
`Post-pipeline work: ${postPipelinePending} pending`,
|
|
129
130
|
`Next: ${state.status.next_actions[0] ?? (nextPhase ? `Begin ${nextPhase.id}` : "All phases complete.")}`,
|
|
130
|
-
]
|
|
131
|
+
];
|
|
132
|
+
if (scaffoldNotice)
|
|
133
|
+
summaryLines.push(`Scaffold: ${scaffoldNotice}`);
|
|
134
|
+
const summary = summaryLines.join("\n");
|
|
131
135
|
return textResult(summary, {
|
|
136
|
+
...(scaffoldNotice ? { scaffoldNotice } : {}),
|
|
132
137
|
currentPhase,
|
|
133
138
|
pipeline: state.status.pipeline,
|
|
134
139
|
pipelineLabel: getPipelineLabel(state.status.pipeline),
|
|
@@ -325,16 +330,33 @@ function buildGenerationFromArg(model_metadata) {
|
|
|
325
330
|
out.notes = m.notes;
|
|
326
331
|
return out;
|
|
327
332
|
}
|
|
328
|
-
|
|
333
|
+
// `allowedRoots` is deliberately required and must be non-empty whenever
|
|
334
|
+
// spec_path is used. It previously defaulted to `[]`, which made containment
|
|
335
|
+
// opt-in: a caller that omitted it would read any absolute path the client
|
|
336
|
+
// asked for, silently reopening the arbitrary-file-read class of bug fixed in
|
|
337
|
+
// v0.12.11. Containment is now the default posture and an empty root set is a
|
|
338
|
+
// programming error rather than a bypass.
|
|
339
|
+
export async function readSpecArg(args, allowedRoots) {
|
|
329
340
|
if (typeof args.spec === "string" && args.spec.length > 0)
|
|
330
341
|
return args.spec;
|
|
331
342
|
if (typeof args.spec_path === "string" && args.spec_path.length > 0) {
|
|
332
343
|
if (!isAbsolute(args.spec_path)) {
|
|
333
344
|
throw new McpError(ErrorCode.InvalidParams, `spec_path must be absolute, got: ${args.spec_path}`);
|
|
334
345
|
}
|
|
346
|
+
if (!Array.isArray(allowedRoots) || allowedRoots.length === 0) {
|
|
347
|
+
throw new McpError(ErrorCode.InternalError, "refusing to read spec_path without a containment root — this is a caller bug, not a client error");
|
|
348
|
+
}
|
|
335
349
|
if (!(await pathExists(args.spec_path))) {
|
|
336
350
|
throw new McpError(ErrorCode.InvalidParams, `spec_path does not exist: ${args.spec_path}`);
|
|
337
351
|
}
|
|
352
|
+
// Enforce path containment: spec_path must be within an allowed root
|
|
353
|
+
// (cwd's .codecarto/ or the configured library path) to prevent
|
|
354
|
+
// arbitrary file reads.
|
|
355
|
+
const resolvedSpecPath = await canonicalPath(args.spec_path);
|
|
356
|
+
const withinAllowed = await Promise.all(allowedRoots.map((root) => isWithinPathResolved(resolvedSpecPath, root)));
|
|
357
|
+
if (!withinAllowed.some((result) => result)) {
|
|
358
|
+
throw new McpError(ErrorCode.InvalidParams, `spec_path must be within the workspace (.codecarto/) or the configured library path. Got: ${args.spec_path}`);
|
|
359
|
+
}
|
|
338
360
|
return readFile(args.spec_path, "utf8");
|
|
339
361
|
}
|
|
340
362
|
throw new McpError(ErrorCode.InvalidParams, "Either spec (inline content) or spec_path (absolute file path) is required");
|
|
@@ -375,7 +397,12 @@ export async function handlePublish(args) {
|
|
|
375
397
|
if (!marker) {
|
|
376
398
|
throw new McpError(ErrorCode.InvalidParams, `No CodeCartographer library at ${libraryPath} (missing .codecarto-library marker). Create one before publishing.`);
|
|
377
399
|
}
|
|
378
|
-
|
|
400
|
+
// Build allowed roots for spec_path containment: workspace .codecarto/ and library path
|
|
401
|
+
const allowedRoots = [libraryPath];
|
|
402
|
+
if (typeof args.cwd === "string" && args.cwd.trim() !== "") {
|
|
403
|
+
allowedRoots.push(join(args.cwd.trim(), ".codecarto"));
|
|
404
|
+
}
|
|
405
|
+
const spec = await readSpecArg(args, allowedRoots);
|
|
379
406
|
if (typeof args.source_repo !== "string" || args.source_repo.trim() === "") {
|
|
380
407
|
throw new McpError(ErrorCode.InvalidParams, "source_repo is required");
|
|
381
408
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codecartographer-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"mcpName": "io.github.HuginnIndustries/codecartographer",
|
|
5
|
-
"description": "
|
|
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",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"pi-package",
|
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
"mcp",
|
|
14
14
|
"software-planning",
|
|
15
15
|
"code-analysis",
|
|
16
|
-
"synthesis"
|
|
16
|
+
"synthesis",
|
|
17
|
+
"codebase",
|
|
18
|
+
"ai-agent",
|
|
19
|
+
"context-engineering",
|
|
20
|
+
"code-understanding",
|
|
21
|
+
"spec-driven"
|
|
17
22
|
],
|
|
18
23
|
"license": "MIT",
|
|
19
24
|
"author": "James Sesler",
|
|
@@ -59,5 +64,8 @@
|
|
|
59
64
|
},
|
|
60
65
|
"devDependencies": {
|
|
61
66
|
"typescript": "^5.9.3"
|
|
67
|
+
},
|
|
68
|
+
"overrides": {
|
|
69
|
+
"undici": "^8.10.0"
|
|
62
70
|
}
|
|
63
71
|
}
|