@ionivetech/mugiwara 0.3.0 → 0.5.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/.opencode/commands/mugiwara-plan.md +4 -0
- package/README.md +214 -418
- package/content/agents/brook-healing.md +2 -2
- package/content/agents/chopper-checkpoint.md +2 -1
- package/content/agents/eval-runner.md +4 -4
- package/content/agents/franky-gates.md +1 -1
- package/content/agents/jinbe-security.md +2 -1
- package/content/agents/luffy-orchestrator.md +3 -3
- package/content/agents/memory-keeper.md +1 -1
- package/content/agents/nami-planner.md +2 -2
- package/content/agents/resume-coordinator.md +8 -9
- package/content/agents/robin-reviewer.md +3 -2
- package/content/agents/sanji-quality.md +1 -1
- package/content/agents/skeptic-verifier.md +4 -3
- package/content/agents/using-mugiwara.md +3 -3
- package/content/agents/usopp-brainstorm.md +3 -3
- package/content/agents/zoro-execution.md +4 -3
- package/content/skills/mugiwara-agent-security/SKILL.md +19 -2
- package/content/skills/mugiwara-backend/SKILL.md +7 -8
- package/content/skills/mugiwara-backend/references/source-backed-example.md +77 -0
- package/content/skills/mugiwara-brainstorm/SKILL.md +7 -2
- package/content/skills/mugiwara-checkpoint/SKILL.md +7 -2
- package/content/skills/mugiwara-checkpoint/references/ledger-format.md +34 -0
- package/content/skills/{mugiwara-doubt-driven-development → mugiwara-claim-audit}/SKILL.md +7 -2
- package/content/skills/{mugiwara-context-engineering → mugiwara-context-budget}/SKILL.md +7 -2
- package/content/skills/mugiwara-context-budget/references/context-budget.md +37 -0
- package/content/skills/{mugiwara-api-and-interface-design → mugiwara-contract-first}/SKILL.md +9 -2
- package/content/skills/mugiwara-contract-first/references/versioning-playbook.md +36 -0
- package/content/skills/mugiwara-execution/SKILL.md +9 -2
- package/content/skills/mugiwara-execution/references/worked-example.md +88 -0
- package/content/skills/mugiwara-frontend/SKILL.md +21 -22
- package/content/skills/mugiwara-frontend/references/design-tokens.md +25 -0
- package/content/skills/mugiwara-frontend/references/slop-catalog.md +19 -0
- package/content/skills/mugiwara-gates/SKILL.md +9 -4
- package/content/skills/mugiwara-git/SKILL.md +6 -1
- package/content/skills/mugiwara-healing/SKILL.md +39 -7
- package/content/skills/mugiwara-healing/references/failure-taxonomy.md +23 -0
- package/content/skills/mugiwara-lessons/SKILL.md +6 -1
- package/content/skills/mugiwara-orchestration/SKILL.md +18 -5
- package/content/skills/mugiwara-planning/SKILL.md +16 -15
- package/content/skills/mugiwara-planning/references/anti-patterns.md +17 -0
- package/content/skills/mugiwara-planning/references/plan-template.md +46 -0
- package/content/skills/mugiwara-pr/SKILL.md +6 -1
- package/content/skills/{mugiwara-test-driven-development → mugiwara-proof-order}/SKILL.md +7 -2
- package/content/skills/mugiwara-proof-order/references/proof-order-examples.md +62 -0
- package/content/skills/mugiwara-quality/SKILL.md +8 -3
- package/content/skills/mugiwara-resume/SKILL.md +46 -30
- package/content/skills/mugiwara-review/SKILL.md +6 -1
- package/content/skills/mugiwara-review/references/five-axis-worksheet.md +36 -0
- package/content/skills/mugiwara-review/references/severity-rubric.md +20 -0
- package/content/skills/{mugiwara-systematic-debugging → mugiwara-root-cause}/SKILL.md +9 -2
- package/content/skills/mugiwara-root-cause/references/four-phase-worked.md +71 -0
- package/content/skills/mugiwara-security/SKILL.md +18 -18
- package/content/skills/mugiwara-security/references/owasp-mapping.md +30 -0
- package/content/skills/mugiwara-security/references/stride-worksheet.md +37 -0
- package/content/skills/mugiwara-ship/SKILL.md +6 -1
- package/content/skills/{mugiwara-deprecation → mugiwara-sunset}/SKILL.md +7 -2
- package/content/skills/mugiwara-testcases/SKILL.md +6 -1
- package/content/skills/mugiwara-testcases/references/intake-formats.md +42 -0
- package/content/skills/mugiwara-workflow/SKILL.md +26 -24
- package/dist/mugiwara.js +165 -28
- package/docs/adoption-guide.md +2 -2
- package/docs/agents.md +2 -2
- package/docs/audit-trail.md +65 -0
- package/docs/comparison.md +58 -63
- package/docs/compliance-matrix.md +81 -0
- package/docs/config.md +7 -2
- package/docs/cost.md +45 -0
- package/docs/developer-onboarding.md +17 -13
- package/docs/enforcement.md +35 -0
- package/docs/getting-started.md +103 -41
- package/docs/harness-matrix.md +41 -0
- package/docs/index.md +11 -5
- package/docs/lanes.md +82 -0
- package/docs/skill-anatomy.md +42 -49
- package/docs/skills.md +36 -54
- package/docs/troubleshooting.md +91 -0
- package/docs/workflow.md +15 -6
- package/evals/cases/adversarial-pressure-fake-pass.json +12 -0
- package/evals/cases/adversarial-pressure-skip-review.json +13 -0
- package/evals/cases/lane-exploratory-vague.json +12 -0
- package/evals/cases/lane-sensitivity-payment.json +12 -0
- package/evals/cases/negative-secrets-typo.json +12 -0
- package/evals/cases/negative-security-docs-change.json +12 -0
- package/evals/cases/positive-refactor-existing-tests.json +11 -0
- package/evals/cases/positive-resume-mid-mission.json +11 -0
- package/evals/cases/routing-auth-feature.json +13 -0
- package/evals/cases/routing-bug-one-file.json +13 -0
- package/evals/cases/routing-typo.json +13 -0
- package/package.json +6 -4
- package/references/definition-of-done.md +42 -0
- package/references/multi-actor.md +44 -0
- package/references/skill-versioning.md +44 -0
- package/references/source-grounding.md +23 -0
- package/references/token-budget.md +34 -0
- package/scripts/evidence.sh +37 -0
- package/scripts/lane.sh +74 -0
- package/scripts/mission-report.sh +88 -0
- package/scripts/release-notes.ts +65 -0
- package/scripts/retrieval-eval.ts +152 -0
- package/scripts/run-evals.ts +113 -0
- package/scripts/savepoint.sh +165 -0
- package/scripts/sync-version.ts +30 -0
- package/scripts/validate-content.ts +226 -0
- package/src/args.ts +2 -1
- package/src/cli.ts +21 -20
- package/src/installer.ts +31 -3
- package/src/mission.ts +48 -0
- package/src/targets/claude.ts +4 -0
- package/src/targets/copilot.ts +4 -0
- package/src/targets/generic.ts +33 -1
- package/src/targets/kilo.ts +1 -0
- package/src/targets/opencode.ts +4 -0
- package/content/skills/mugiwara-dynamic-workflow/SKILL.md +0 -85
- package/content/skills/mugiwara-eval/SKILL.md +0 -82
- package/content/skills/mugiwara-git-worktrees/SKILL.md +0 -62
- package/content/skills/mugiwara-mode/SKILL.md +0 -72
- package/content/skills/mugiwara-observability/SKILL.md +0 -54
- package/content/skills/mugiwara-writing-skills/SKILL.md +0 -60
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: mugiwara-
|
|
3
|
-
description: Use when retiring code
|
|
2
|
+
name: mugiwara-sunset
|
|
3
|
+
description: Use when retiring code or APIs — keep-or-retire gate, safe DB migrations, phased cutovers. Every removal needs a plan and tested way back.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Deprecation & Migration (Brook)
|
|
7
7
|
|
|
8
|
+
## Skip when
|
|
9
|
+
|
|
10
|
+
- No code, API, or feature is being retired or replaced.
|
|
11
|
+
- Purely additive change — nothing removed, no migration path needed.
|
|
12
|
+
|
|
8
13
|
Keeping old code alive is a tax, not a virtue: it keeps costing tests, patches, security reviews, and the attention of everyone who walks past it. Retirement is a craft — the removal itself must be as disciplined as the build.
|
|
9
14
|
|
|
10
15
|
## Sunset or keep
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mugiwara-testcases
|
|
3
|
-
description: Use when
|
|
3
|
+
description: Use when mission declares user test cases — intake formats, immutable-gold rule, declarative-AC routing, consent, failure adjudication. ATDD home.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Test Cases (ATDD Contract)
|
|
7
7
|
|
|
8
|
+
## Skip when
|
|
9
|
+
|
|
10
|
+
- No user-declared test cases or acceptance criteria in this mission.
|
|
11
|
+
- No repo test source declared and no acceptance oracle needed.
|
|
12
|
+
|
|
8
13
|
User tests are the crew's acceptance oracle. This is the single home for the ATDD contract — intake, immutable gold, routing, consent, and failure adjudication. Shared by planning, execution, quality, and gates so they cannot drift.
|
|
9
14
|
|
|
10
15
|
## Accepted formats
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Test Intake Formats
|
|
2
|
+
|
|
3
|
+
Single home for the ATDD contract. Referenced by `mugiwara-quality` and `mugiwara-gates`.
|
|
4
|
+
|
|
5
|
+
## Format 1: Executable tests (user test files)
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Path: tests/acceptance/invitation-flow.test.ts
|
|
9
|
+
Type: integration
|
|
10
|
+
Commands: npm run test:acceptance -- invitation-flow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Imported as immutable gold. Never edit, never skip. Run failing first, green at end.
|
|
14
|
+
|
|
15
|
+
## Format 2: Declarative acceptance (Gherkin/markdown AC)
|
|
16
|
+
|
|
17
|
+
```gherkin
|
|
18
|
+
Feature: Invitation flow
|
|
19
|
+
Scenario: User accepts invitation
|
|
20
|
+
Given an invitation exists for "user@example.com"
|
|
21
|
+
When the user clicks the invitation link
|
|
22
|
+
Then the user is redirected to onboarding
|
|
23
|
+
And the invitation status changes to "accepted"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The crew translates this to a project test file. Write the test, watch it fail, implement, re-run green.
|
|
27
|
+
|
|
28
|
+
## Format 3: Command-verifiable
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Acceptance: curl -X POST /api/invite -d '{"email":"test@ex.com"}' | jq .status
|
|
32
|
+
Expected: "sent"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Run directly. No translation needed.
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- No declared test source → no user tests for the mission.
|
|
40
|
+
- Executable user tests = immutable gold. Change requires user consent + ledger row.
|
|
41
|
+
- Declarative AC tests are model-written → extra Chopper scrutiny (can encode the bug).
|
|
42
|
+
- Cross-cutting user ACs (e2e flow spanning tasks) → plan-level criteria, re-run at checkpoint against whole diff.
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mugiwara-workflow
|
|
3
|
-
description: Use at
|
|
3
|
+
description: Use at start of any non-trivial mission — Luffy triage gateway, then brainstorm/plan/execute/checkpoint/quality/gates/review/heal/closure waves.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Mugiwara Workflow
|
|
7
7
|
|
|
8
|
+
## Skip when
|
|
9
|
+
|
|
10
|
+
- Lane 0 direct work: typo, rename, or single-file fix under 20 LOC.
|
|
11
|
+
- User explicitly declined the harness for this request.
|
|
12
|
+
|
|
8
13
|
The Straw Hat harness: Wave 0 triage + Waves 1-9, with an optional adversarial pass at Wave 4.5. Waves are phases of the mission, not files — Nami writes them into the plan doc, Zoro executes them. The main thread runs the harness and embodies each crew role inline (Execution model below); the harness always starts through Luffy unless the user summons a crew member directly.
|
|
9
14
|
|
|
10
15
|
## Execution model (every harness)
|
|
@@ -31,9 +36,11 @@ Every mission creates and works inside `.mugiwara/` at the repo root:
|
|
|
31
36
|
```
|
|
32
37
|
.mugiwara/
|
|
33
38
|
├── config # runtime mode config: mode/branch/commit/pr key=value (gitignored; project overrides global)
|
|
39
|
+
├── state.json # computed mission state at every wave boundary (scripts/savepoint.sh)
|
|
34
40
|
├── spec/ # brainstorm output: YYYY-MM-DD-<mission>.md
|
|
35
|
-
├── plans/ # plan doc: YYYY-MM-DD-<mission>.md — CLEAN, Nami-only, source of truth from Wave 2
|
|
41
|
+
├── plans/ # plan doc: YYYY-MM-DD-<mission>.md — CLEAN, Nami-only, source of truth from Wave 2
|
|
36
42
|
├── results/ # wave results: audit/quality/gate reports, todos, closure report
|
|
43
|
+
├── reports/ # human-readable mission reports: YYYY-MM-DD-<mission>.md
|
|
37
44
|
├── review/ # review + security findings
|
|
38
45
|
├── issues/ # blocker log: YYYY-MM-DD-<mission>-blockers.md
|
|
39
46
|
└── logs/ # Luffy's decision + check-in log: YYYY-MM-DD-<mission>.md (deleted at cleanup)
|
|
@@ -51,9 +58,9 @@ At session start, after context loss, or on any "where were we?" — embody `res
|
|
|
51
58
|
|
|
52
59
|
## Wave 0 — Luffy Triage (always first)
|
|
53
60
|
|
|
54
|
-
Front door: embody `using-mugiwara` inline (the router) — it routes to the right crew member and records the route. For a full triage embody `luffy-orchestrator` inline. NEVER start directly with brainstorming or planning. Luffy classifies every request 5 ways (Trivial / Explicit / Exploratory / Open-ended / Ambiguous) and routes: Trivial and Explicit → Wave 2 directly; Exploratory, Open-ended, and Ambiguous → Wave 1 brainstorm first. The user may summon any crew member directly — Luffy still records the route.
|
|
61
|
+
Front door: embody `using-mugiwara` inline (the router) — it routes to the right crew member and records the route. For a full triage embody `luffy-orchestrator` inline. NEVER start directly with brainstorming or planning. Luffy classifies every request 5 ways (Trivial / Explicit / Exploratory / Open-ended / Ambiguous) and routes: Trivial and Explicit → Wave 2 directly; Exploratory, Open-ended, and Ambiguous → Wave 1 brainstorm first. Alongside the class, Luffy sizes the mission and picks a lane (0 Direct / 1 Lean / 2 Standard / 3 Full / 4 Spike) — small work skips the pipeline, sensitive work never sneaks through the lean path. The user may summon any crew member directly — Luffy still records the route.
|
|
55
62
|
|
|
56
|
-
Alongside triage, read the mode config per
|
|
63
|
+
Alongside triage, read the mode config per mode config: `.mugiwara/config` (project) then `~/.mugiwara/config` (global); a key missing from both = `guided`. Lazy-create the project config on first WRITE only, never auto-create on read.
|
|
57
64
|
|
|
58
65
|
## Waves
|
|
59
66
|
|
|
@@ -64,7 +71,7 @@ Alongside triage, read the mode config per `mugiwara-mode`: `.mugiwara/config` (
|
|
|
64
71
|
| 2 Planning | Nami | mugiwara-planning | plan doc: waves/tasks/criteria, parallel markers |
|
|
65
72
|
| 3 Execution | Zoro | mugiwara-execution | implemented tasks with evidence |
|
|
66
73
|
| 4 Checkpoint | Chopper | mugiwara-checkpoint | audit report + failure ledger |
|
|
67
|
-
| 4.5 Adversarial | Skeptic | mugiwara-
|
|
74
|
+
| 4.5 Adversarial | Skeptic | mugiwara-claim-audit | findings report + failure ledger |
|
|
68
75
|
| 5 Quality | Sanji | mugiwara-quality | formatter/linter/test results |
|
|
69
76
|
| 6 Gates | Franky | mugiwara-gates | coverage + build verdict |
|
|
70
77
|
| 7 Review | Robin ∥ Jinbe | mugiwara-review + mugiwara-security | severity-tagged findings |
|
|
@@ -83,7 +90,7 @@ Never silently work around a blocker. Brook reads this ledger at Wave 8 to decid
|
|
|
83
90
|
|
|
84
91
|
## Cleanup
|
|
85
92
|
|
|
86
|
-
At closure (Wave 9), after the terminal step, run
|
|
93
|
+
At closure (Wave 9), after the terminal step, run cleanup per `mugiwara-ship`: delete consumed intermediates — superseded results, review, issues, the decision log in `logs/`, and consumed spec. Keep the plan doc, closure report, PR verdict, mission report, `config`, `state.json`, and cross-mission state (`logs/lessons.md`, `backup/`, `manifest.json`). List candidates before deleting.
|
|
87
94
|
|
|
88
95
|
## Rules
|
|
89
96
|
|
|
@@ -91,29 +98,24 @@ At closure (Wave 9), after the terminal step, run the cleanup procedure in `mugi
|
|
|
91
98
|
2. No wave skipped without the reason recorded in the decision log (`.mugiwara/logs/`) — name the wave, owner, and reason at the moment of omission.
|
|
92
99
|
3. Heal loop is bounded: Wave 8 → Wave 4, max 3 cycles. After that, escalate to the human with full history.
|
|
93
100
|
4. Any agent may consult Luffy mid-flight (embody `luffy-orchestrator` inline) for decisions and escalations.
|
|
94
|
-
5. Wave 7 runs Robin and Jinbe
|
|
95
|
-
6. The plan doc
|
|
96
|
-
7. Frontend
|
|
97
|
-
8.
|
|
98
|
-
9.
|
|
99
|
-
10. The crew never merges and never deploys — push the branch + hand the verdict file to the user, who opens the PR; PR review is the terminal gate in every mode.
|
|
101
|
+
5. Wave 7 runs Robin and Jinbe in parallel over the same diff.
|
|
102
|
+
6. The plan doc is the single source of truth from Wave 2 onward.
|
|
103
|
+
7. Frontend tasks in Wave 3 must apply `mugiwara-frontend`.
|
|
104
|
+
8. On session start or context loss — resume via `resume-coordinator` before any wave; never start over.
|
|
105
|
+
9. Push branch + hand verdict file to the user, who opens the PR; crew never merges, never deploys.
|
|
100
106
|
|
|
101
107
|
## Iron Law
|
|
102
108
|
|
|
103
|
-
EVIDENCE OVER CLAIMS. No wave passes on assertion — the owning agent runs the checks and shows output.
|
|
104
|
-
|
|
105
|
-
## Verification gate (every completion claim)
|
|
106
|
-
|
|
107
|
-
A claim is only as strong as the evidence produced in the same turn that made it. "Done", "passes", and "fixed" each name a command that would prove them — run that command, read its full output, then speak. A result from an earlier run, a guess, or a worker's word for it is not proof; re-run it and diff the work against the tree before reporting. Trust is not a substitute for verification.
|
|
109
|
+
EVIDENCE OVER CLAIMS. No wave passes on assertion — the owning agent runs the checks and shows output. "Done", "passes", and "fixed" must be proved by running the check command in the same turn; no stale results, no guesses, no worker's word for it.
|
|
108
110
|
|
|
109
111
|
## Red flags
|
|
110
112
|
|
|
111
|
-
- A wave
|
|
113
|
+
- A wave passes on a spoken claim with no command output.
|
|
112
114
|
- Heal loop beyond 3 cycles with the same failure still open.
|
|
113
|
-
-
|
|
114
|
-
- Execution
|
|
115
|
-
- Mission artifacts
|
|
116
|
-
- Wave order drifts
|
|
117
|
-
-
|
|
115
|
+
- Wave skipped with no reason recorded in the decision log.
|
|
116
|
+
- Execution before triage (Wave 0).
|
|
117
|
+
- Mission artifacts outside `.mugiwara/`.
|
|
118
|
+
- Wave order drifts (e.g. quality before checkpoint).
|
|
119
|
+
- Blocker worked around silently with no ledger row.
|
|
118
120
|
|
|
119
|
-
All mean: stop
|
|
121
|
+
All mean: stop, diagnose with Chopper's ledger, decide continue/retry/escalate.
|
package/dist/mugiwara.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { existsSync as
|
|
4
|
+
import { existsSync as existsSync6, realpathSync, rmSync as rmSync3 } from "node:fs";
|
|
5
5
|
import { homedir as homedir2 } from "node:os";
|
|
6
|
-
import {
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
8
|
|
|
9
9
|
// src/args.ts
|
|
@@ -14,6 +14,7 @@ var BOOL_FLAGS = {
|
|
|
14
14
|
"-y": "yes",
|
|
15
15
|
"--force": "force",
|
|
16
16
|
"--dry-run": "dryRun",
|
|
17
|
+
"--keep-logs": "keepLogs",
|
|
17
18
|
"--help": "help",
|
|
18
19
|
"-h": "help",
|
|
19
20
|
"--version": "version",
|
|
@@ -131,6 +132,10 @@ var target = {
|
|
|
131
132
|
fm.tools = data.tools;
|
|
132
133
|
return { relPath: `${data.name}.md`, text: stringifyFrontmatter(fm, body) };
|
|
133
134
|
},
|
|
135
|
+
refsDir({ scope, projectDir, home }, skillName) {
|
|
136
|
+
const root = scope === "global" ? join(home, ".claude") : join(projectDir, ".claude");
|
|
137
|
+
return join(root, "skills", skillName, "references");
|
|
138
|
+
},
|
|
134
139
|
postInstall({ scope, projectDir, home, dryRun }) {
|
|
135
140
|
const root = scope === "global" ? join(home, ".claude") : join(projectDir, ".claude");
|
|
136
141
|
const hookFile = join(root, "hooks", "session-start.ts");
|
|
@@ -166,6 +171,10 @@ var target2 = {
|
|
|
166
171
|
if (data.tools)
|
|
167
172
|
fm.tools = data.tools;
|
|
168
173
|
return { relPath: `${data.name}.md`, text: stringifyFrontmatter(fm, body) };
|
|
174
|
+
},
|
|
175
|
+
refsDir({ scope, projectDir, home }, skillName) {
|
|
176
|
+
const root = scope === "global" ? join2(home, ".config", "opencode") : join2(projectDir, ".opencode");
|
|
177
|
+
return join2(root, "skills", skillName, "references");
|
|
169
178
|
}
|
|
170
179
|
};
|
|
171
180
|
|
|
@@ -190,6 +199,9 @@ var target3 = {
|
|
|
190
199
|
relPath: `${data.name}.md`,
|
|
191
200
|
text: stringifyFrontmatter({ name: data.name, description: data.description }, body)
|
|
192
201
|
};
|
|
202
|
+
},
|
|
203
|
+
refsDir(_opts, skillName) {
|
|
204
|
+
return join3(_opts.projectDir, ".mugiwara", "refs", skillName);
|
|
193
205
|
}
|
|
194
206
|
};
|
|
195
207
|
|
|
@@ -197,11 +209,13 @@ var target3 = {
|
|
|
197
209
|
import { existsSync as existsSync2, writeFileSync } from "node:fs";
|
|
198
210
|
import { join as join4 } from "node:path";
|
|
199
211
|
function makeGeneric(opts) {
|
|
200
|
-
const { id, label, rulesDir, bootstrapFile, bootstrapPointer } = opts;
|
|
212
|
+
const { id, label, rulesDir, bootstrapFile, bootstrapPointer, tier = bootstrapPointer ? 2 : 3 } = opts;
|
|
213
|
+
const stubOnly = tier === 3;
|
|
201
214
|
return {
|
|
202
215
|
id,
|
|
203
216
|
label,
|
|
204
217
|
native: false,
|
|
218
|
+
tier,
|
|
205
219
|
paths({ scope, projectDir }) {
|
|
206
220
|
if (scope === "global")
|
|
207
221
|
throw new Error(`${label} supports project scope only`);
|
|
@@ -209,6 +223,27 @@ function makeGeneric(opts) {
|
|
|
209
223
|
return { skillsDir: dir, agentsDir: dir };
|
|
210
224
|
},
|
|
211
225
|
transformSkill(data, body) {
|
|
226
|
+
if (stubOnly) {
|
|
227
|
+
return {
|
|
228
|
+
relPath: `${data.name}.md`,
|
|
229
|
+
text: `# ${data.name}
|
|
230
|
+
|
|
231
|
+
> ${data.description}
|
|
232
|
+
|
|
233
|
+
## Skip when
|
|
234
|
+
|
|
235
|
+
Full skill: \`${data.name}\` — read \`.mugiwara/refs/${data.name}.md\` when the crew invokes this role.`
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { relPath: `${data.name}.md`, text: `# ${data.name}
|
|
239
|
+
|
|
240
|
+
> ${data.description}
|
|
241
|
+
|
|
242
|
+
${body}` };
|
|
243
|
+
},
|
|
244
|
+
transformSkillFull(data, body) {
|
|
245
|
+
if (!stubOnly)
|
|
246
|
+
return null;
|
|
212
247
|
return { relPath: `${data.name}.md`, text: `# ${data.name}
|
|
213
248
|
|
|
214
249
|
> ${data.description}
|
|
@@ -216,6 +251,16 @@ function makeGeneric(opts) {
|
|
|
216
251
|
${body}` };
|
|
217
252
|
},
|
|
218
253
|
transformAgent(data, body) {
|
|
254
|
+
if (stubOnly) {
|
|
255
|
+
return {
|
|
256
|
+
relPath: `agent-${data.name}.md`,
|
|
257
|
+
text: `# Agent: ${data.name}
|
|
258
|
+
|
|
259
|
+
> ${data.description}
|
|
260
|
+
|
|
261
|
+
Skills: ${data.skills ?? ""}. Read \`.mugiwara/refs/${data.name}.md\` when embodying this role.`
|
|
262
|
+
};
|
|
263
|
+
}
|
|
219
264
|
return { relPath: `agent-${data.name}.md`, text: `# Agent: ${data.name}
|
|
220
265
|
|
|
221
266
|
> ${data.description}
|
|
@@ -224,6 +269,20 @@ Skills used: ${data.skills ?? ""}
|
|
|
224
269
|
|
|
225
270
|
${body}` };
|
|
226
271
|
},
|
|
272
|
+
transformAgentFull(data, body) {
|
|
273
|
+
if (!stubOnly)
|
|
274
|
+
return null;
|
|
275
|
+
return { relPath: `${data.name}.md`, text: `# Agent: ${data.name}
|
|
276
|
+
|
|
277
|
+
> ${data.description}
|
|
278
|
+
|
|
279
|
+
Skills used: ${data.skills ?? ""}
|
|
280
|
+
|
|
281
|
+
${body}` };
|
|
282
|
+
},
|
|
283
|
+
refsDir({ projectDir }) {
|
|
284
|
+
return join4(projectDir, ".mugiwara", "refs");
|
|
285
|
+
},
|
|
227
286
|
postInstall({ projectDir, dryRun }) {
|
|
228
287
|
if (!bootstrapFile)
|
|
229
288
|
return { written: [], notes: [] };
|
|
@@ -289,7 +348,8 @@ var target8 = makeGeneric({
|
|
|
289
348
|
"instructions": [
|
|
290
349
|
".kilo/rules/*.md"
|
|
291
350
|
]
|
|
292
|
-
}
|
|
351
|
+
}`,
|
|
352
|
+
tier: 3
|
|
293
353
|
});
|
|
294
354
|
|
|
295
355
|
// src/targets/antigravity.ts
|
|
@@ -316,14 +376,20 @@ function collectContent() {
|
|
|
316
376
|
const skillNames = readdirSync(join5(CONTENT_DIR, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
317
377
|
const skills = skillNames.map((name) => {
|
|
318
378
|
const { data, body } = parseFrontmatter(readFileSync2(join5(CONTENT_DIR, "skills", name, "SKILL.md"), "utf8"));
|
|
319
|
-
return { name, data, body };
|
|
379
|
+
return { name, data, body, refs: collectRefs(join5(CONTENT_DIR, "skills", name)) };
|
|
320
380
|
});
|
|
321
381
|
const agents = readdirSync(join5(CONTENT_DIR, "agents")).filter((f) => f.endsWith(".md")).map((f) => {
|
|
322
382
|
const { data, body } = parseFrontmatter(readFileSync2(join5(CONTENT_DIR, "agents", f), "utf8"));
|
|
323
|
-
return { name: f.replace(/\.md$/, ""), data, body };
|
|
383
|
+
return { name: f.replace(/\.md$/, ""), data, body, refs: [] };
|
|
324
384
|
});
|
|
325
385
|
return { skills, agents };
|
|
326
386
|
}
|
|
387
|
+
function collectRefs(skillDir) {
|
|
388
|
+
const refsDir = join5(skillDir, "references");
|
|
389
|
+
if (!existsSync3(refsDir))
|
|
390
|
+
return [];
|
|
391
|
+
return readdirSync(refsDir, { recursive: true }).map((f) => String(f)).filter((f) => f.endsWith(".md")).map((rel) => ({ relPath: rel, text: readFileSync2(join5(refsDir, rel), "utf8") }));
|
|
392
|
+
}
|
|
327
393
|
function installTo(target10, opts) {
|
|
328
394
|
const { scope, projectDir, dryRun = false, force = false } = opts;
|
|
329
395
|
const home = opts.home ?? homedir();
|
|
@@ -360,11 +426,26 @@ function installTo(target10, opts) {
|
|
|
360
426
|
const out = target10.transformSkill(s.data, s.body);
|
|
361
427
|
if (out)
|
|
362
428
|
writeOne(join5(dirs.skillsDir, out.relPath), out.text);
|
|
429
|
+
if (target10.transformSkillFull) {
|
|
430
|
+
const full = target10.transformSkillFull(s.data, s.body);
|
|
431
|
+
if (full && target10.refsDir)
|
|
432
|
+
writeOne(join5(target10.refsDir({ scope, projectDir, home }, s.name), full.relPath), full.text);
|
|
433
|
+
}
|
|
434
|
+
if (s.refs.length && target10.refsDir) {
|
|
435
|
+
const refsRoot = target10.refsDir({ scope, projectDir, home }, s.name);
|
|
436
|
+
for (const r of s.refs)
|
|
437
|
+
writeOne(join5(refsRoot, r.relPath), r.text);
|
|
438
|
+
}
|
|
363
439
|
}
|
|
364
440
|
for (const a of agents) {
|
|
365
441
|
const out = target10.transformAgent(a.data, a.body);
|
|
366
442
|
if (out)
|
|
367
443
|
writeOne(join5(dirs.agentsDir, out.relPath), out.text);
|
|
444
|
+
if (target10.transformAgentFull) {
|
|
445
|
+
const full = target10.transformAgentFull(a.data, a.body);
|
|
446
|
+
if (full && target10.refsDir)
|
|
447
|
+
writeOne(join5(target10.refsDir({ scope, projectDir, home }, a.name), full.relPath), full.text);
|
|
448
|
+
}
|
|
368
449
|
}
|
|
369
450
|
if (target10.postInstall) {
|
|
370
451
|
const post = target10.postInstall({ scope, projectDir, home, dryRun, files: result.written });
|
|
@@ -412,6 +493,62 @@ function writeManifest(file, data) {
|
|
|
412
493
|
`);
|
|
413
494
|
}
|
|
414
495
|
|
|
496
|
+
// src/mission.ts
|
|
497
|
+
import { existsSync as existsSync5, rmSync as rmSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
498
|
+
import { join as join7 } from "node:path";
|
|
499
|
+
function activeActor(projectDir) {
|
|
500
|
+
const stateFile = join7(projectDir, ".mugiwara", "state.json");
|
|
501
|
+
if (!existsSync5(stateFile))
|
|
502
|
+
return null;
|
|
503
|
+
try {
|
|
504
|
+
const state = JSON.parse(readFileSync4(stateFile, "utf8"));
|
|
505
|
+
return state.actor || null;
|
|
506
|
+
} catch {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function resetMission(projectDir, keepLogs, force) {
|
|
511
|
+
const root = join7(projectDir, ".mugiwara");
|
|
512
|
+
if (!existsSync5(root))
|
|
513
|
+
return { removed: [], kept: [] };
|
|
514
|
+
if (!force) {
|
|
515
|
+
const actor = activeActor(projectDir);
|
|
516
|
+
if (actor) {
|
|
517
|
+
return { removed: [], kept: [], blocked: `Active mission for '${actor}'. Use --force to override.` };
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const removed = [];
|
|
521
|
+
const kept = [];
|
|
522
|
+
for (const dir of ["spec", "plans", "results", "review", "issues", "reports"]) {
|
|
523
|
+
const p = join7(root, dir);
|
|
524
|
+
if (existsSync5(p)) {
|
|
525
|
+
rmSync2(p, { recursive: true, force: true });
|
|
526
|
+
removed.push(dir);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
for (const f of ["state.json"]) {
|
|
530
|
+
const p = join7(root, f);
|
|
531
|
+
if (existsSync5(p)) {
|
|
532
|
+
rmSync2(p);
|
|
533
|
+
removed.push(f);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (!keepLogs) {
|
|
537
|
+
const p = join7(root, "logs");
|
|
538
|
+
if (existsSync5(p)) {
|
|
539
|
+
rmSync2(p, { recursive: true, force: true });
|
|
540
|
+
removed.push("logs");
|
|
541
|
+
}
|
|
542
|
+
} else if (existsSync5(join7(root, "logs"))) {
|
|
543
|
+
kept.push("logs");
|
|
544
|
+
}
|
|
545
|
+
for (const f of ["config", "manifest.json", "backup"]) {
|
|
546
|
+
if (existsSync5(join7(root, f)))
|
|
547
|
+
kept.push(f);
|
|
548
|
+
}
|
|
549
|
+
return { removed, kept };
|
|
550
|
+
}
|
|
551
|
+
|
|
415
552
|
// src/cli.ts
|
|
416
553
|
var str = (v) => typeof v === "string" ? v : undefined;
|
|
417
554
|
var flag = (v) => v === true;
|
|
@@ -432,12 +569,27 @@ async function run(argv) {
|
|
|
432
569
|
return uninstall(flags);
|
|
433
570
|
case "list":
|
|
434
571
|
return list(flags);
|
|
435
|
-
case "
|
|
436
|
-
return
|
|
572
|
+
case "reset":
|
|
573
|
+
return resetCmd(flags);
|
|
437
574
|
default:
|
|
438
575
|
throw new Error(`Unknown command: ${command}`);
|
|
439
576
|
}
|
|
440
577
|
}
|
|
578
|
+
function resetCmd(flags) {
|
|
579
|
+
const projectDir = resolve(str(flags.project) ?? process.cwd());
|
|
580
|
+
const force = flag(flags.force);
|
|
581
|
+
const result = resetMission(projectDir, flag(flags.keepLogs), force);
|
|
582
|
+
if (result.blocked) {
|
|
583
|
+
console.error(`✗ ${result.blocked}`);
|
|
584
|
+
process.exit(1);
|
|
585
|
+
}
|
|
586
|
+
if (result.removed.length)
|
|
587
|
+
console.log(`removed: ${result.removed.join(", ")}`);
|
|
588
|
+
else
|
|
589
|
+
console.log("nothing to remove.");
|
|
590
|
+
if (result.kept.length)
|
|
591
|
+
console.log(`kept: ${result.kept.join(", ")}`);
|
|
592
|
+
}
|
|
441
593
|
async function resolveOptions(flags) {
|
|
442
594
|
const interactive = !flag(flags.yes);
|
|
443
595
|
const rl = interactive ? createRl() : null;
|
|
@@ -449,7 +601,7 @@ async function resolveOptions(flags) {
|
|
|
449
601
|
scope = await choose(rl, "Install scope?", ["global (user-wide)", "project (this repo)"]) === 0 ? "global" : "project";
|
|
450
602
|
}
|
|
451
603
|
const projectDir = resolve(str(flags.project) ?? process.cwd());
|
|
452
|
-
if (scope === "project" && !
|
|
604
|
+
if (scope === "project" && !existsSync6(projectDir))
|
|
453
605
|
throw new Error(`Project dir not found: ${projectDir}`);
|
|
454
606
|
let targetIds = str(flags.target)?.split(",").map((s) => s.trim()) ?? null;
|
|
455
607
|
if (targetIds && targetIds.includes("all"))
|
|
@@ -533,7 +685,7 @@ async function uninstall(flags) {
|
|
|
533
685
|
}
|
|
534
686
|
const removed = removeInstalled(manifest, { dryRun: flag(flags.dryRun) });
|
|
535
687
|
if (!flag(flags.dryRun))
|
|
536
|
-
|
|
688
|
+
rmSync3(file);
|
|
537
689
|
console.log(`OK removed ${removed.length} files`);
|
|
538
690
|
}
|
|
539
691
|
function list(flags) {
|
|
@@ -553,22 +705,6 @@ function list(flags) {
|
|
|
553
705
|
if (!found)
|
|
554
706
|
console.log("No mugiwara installation found.");
|
|
555
707
|
}
|
|
556
|
-
function skills() {
|
|
557
|
-
const dir = join7(CONTENT_DIR, "skills");
|
|
558
|
-
const names = readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
559
|
-
const rows = names.map((name) => {
|
|
560
|
-
const { data } = parseFrontmatter(readFileSync4(join7(dir, name, "SKILL.md"), "utf8"));
|
|
561
|
-
return [name, data.description ?? ""];
|
|
562
|
-
});
|
|
563
|
-
const w = Math.max(...rows.map((r) => r[0].length)) + 2;
|
|
564
|
-
console.log(`mugiwara ${VERSION} — ${rows.length} skills (agentskills.io format):
|
|
565
|
-
`);
|
|
566
|
-
for (const [name, description] of rows)
|
|
567
|
-
console.log(` ${name.padEnd(w)}${description}`);
|
|
568
|
-
console.log(`
|
|
569
|
-
Install skills into any agent via skills.sh:
|
|
570
|
-
npx skills add ionivetech/mugiwara`);
|
|
571
|
-
}
|
|
572
708
|
function help() {
|
|
573
709
|
console.log(`mugiwara ${VERSION} — the Straw Hat crew for AI agents
|
|
574
710
|
|
|
@@ -577,7 +713,7 @@ Usage:
|
|
|
577
713
|
mugiwara update replace existing files (backs up differences first)
|
|
578
714
|
mugiwara uninstall remove installed files via manifest
|
|
579
715
|
mugiwara list show installations
|
|
580
|
-
mugiwara
|
|
716
|
+
mugiwara reset wipe mission state (spec/plans/results/review/issues[/logs])
|
|
581
717
|
mugiwara --help this help
|
|
582
718
|
mugiwara --version print version
|
|
583
719
|
|
|
@@ -587,7 +723,8 @@ Flags:
|
|
|
587
723
|
--target <ids|all> comma-separated: ${TARGET_IDS.join(", ")}
|
|
588
724
|
--yes, -y non-interactive (needs --global/--project, --target)
|
|
589
725
|
--force overwrite differing files (with backup)
|
|
590
|
-
--dry-run print actions without writing
|
|
726
|
+
--dry-run print actions without writing
|
|
727
|
+
--keep-logs with reset: keep .mugiwara/logs (lessons ledger survives)`);
|
|
591
728
|
}
|
|
592
729
|
var entry = process.argv[1] !== undefined ? resolve(process.argv[1]) : undefined;
|
|
593
730
|
if (entry !== undefined) {
|
package/docs/adoption-guide.md
CHANGED
|
@@ -43,8 +43,8 @@ mid-wave.
|
|
|
43
43
|
|
|
44
44
|
## Fit the crew to your workflow
|
|
45
45
|
|
|
46
|
-
- **Trivial one-liners** don't need the crew — Luffy routes them
|
|
47
|
-
|
|
46
|
+
- **Trivial one-liners** don't need the crew's full pipeline — Luffy routes them
|
|
47
|
+
to Lane 0 and they run with zero waves. The process scales to the work.
|
|
48
48
|
- **Medium features** run the standard pipeline: triage → plan → execute →
|
|
49
49
|
checkpoint → quality → gates → review → closure.
|
|
50
50
|
- **High-stakes work** (money, security, data, public API) always gets the full
|
package/docs/agents.md
CHANGED
|
@@ -44,8 +44,8 @@ check-ins. The harness stays coherent either way.
|
|
|
44
44
|
|
|
45
45
|
## The crew ships whole
|
|
46
46
|
|
|
47
|
-
Every install gets all 15 agents and all
|
|
47
|
+
Every install gets all 15 agents and all 26 skills. No project-type selection —
|
|
48
48
|
the harness routes each task to the right specialist.
|
|
49
49
|
|
|
50
|
-
See [skills.md](skills.md) for the
|
|
50
|
+
See [skills.md](skills.md) for the 26 techniques, or
|
|
51
51
|
[workflow.md](workflow.md) for the pipeline.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Audit Trail
|
|
2
|
+
|
|
3
|
+
Every artifact the Mugiwara crew produces — what writes it, when, and how to
|
|
4
|
+
read it as a reviewer.
|
|
5
|
+
|
|
6
|
+
## The artifacts
|
|
7
|
+
|
|
8
|
+
| Artifact | Path | Written by | When | For |
|
|
9
|
+
|----------|------|-----------|------|-----|
|
|
10
|
+
| **Plan doc** | `.mugiwara/plans/YYYY-MM-DD-<mission>.md` | Nami (planning) | Wave 2 | Zero-context executor — waves, tasks, criteria, risk |
|
|
11
|
+
| **Spec** | `.mugiwara/spec/YYYY-MM-DD-<mission>.md` | Usopp (brainstorm) / Luffy (spec bridge) | Wave 0–1 | Bridge from idea to plan — goal, acceptance, constraints |
|
|
12
|
+
| **State** | `.mugiwara/state.json` | `scripts/savepoint.sh` | Every wave boundary | Computed mission state: lane, wave, files, blockers, token budget, evidence paths |
|
|
13
|
+
| **Decision log** | `.mugiwara/logs/YYYY-MM-DD-<mission>.md` | Luffy (orchestrator) | Every wave | Route reason, check-in verdicts, mode flips, decisions |
|
|
14
|
+
| **Blocker ledger** | `.mugiwara/issues/YYYY-MM-DD-<mission>-blockers.md` | Any agent | On blocker hit | Row per blocker: wave, task, symptom, attempted, help-needed |
|
|
15
|
+
| **Todo list** | `.mugiwara/results/<mission>-todos.md` | Zoro (execution) | Wave 3 | Checkbox per task, checked with evidence pointer |
|
|
16
|
+
| **Audit report** | `.mugiwara/results/YYYY-MM-DD-<mission>-audit.md` | Chopper (checkpoint) | Wave 4 | Per-task evidence, commit hygiene, parallel-conflict, honest classification |
|
|
17
|
+
| **Quality report** | `.mugiwara/results/YYYY-MM-DD-<mission>-quality.md` | Sanji (quality) | Wave 5 | Formatter/linter/unit/user-test results |
|
|
18
|
+
| **Gate verdict** | `.mugiwara/results/YYYY-MM-DD-<mission>-gates.md` | Franky (gates) | Wave 6 | Coverage thresholds from config, build exit, DoD verdict |
|
|
19
|
+
| **Review findings** | `.mugiwara/review/YYYY-MM-DD-<mission>-review.md` | Robin (review) | Wave 7 | Severity-tagged: path:line → problem → fix |
|
|
20
|
+
| **Security report** | `.mugiwara/review/YYYY-MM-DD-<mission>-security.md` | Jinbe (security) | Wave 7 | STRIDE, OWASP mapping, checklist, CVSS severity |
|
|
21
|
+
| **Heal report** | `.mugiwara/results/YYYY-MM-DD-<mission>-heal.md` | Brook (healing) | Wave 8 | Fixed list, escalated list, updated ledger |
|
|
22
|
+
| **Closure report** | `.mugiwara/results/YYYY-MM-DD-<mission>-closure.md` | Luffy (orchestrator) | Wave 9 | Mission summary, per-wave outcomes, deferred items, lessons |
|
|
23
|
+
| **Mission report** | `.mugiwara/reports/YYYY-MM-DD-<mission>.md` | `scripts/mission-report.sh` | Wave 9 | Human-readable summary: what changed, gates, state, token cost |
|
|
24
|
+
| **PR verdict** | `.mugiwara/results/YYYY-MM-DD-<mission>-pr-verdict.md` | Luffy (orchestrator) | Wave 9 | Ready PR summary block for the user to open the PR |
|
|
25
|
+
| **Trace** | `.mugiwara/results/<mission>-trace.md` | Resume coordinator | Every dispatch | Dispatch → outcome — drives resume (legacy; state.json preferred) |
|
|
26
|
+
| **Lessons ledger** | `.mugiwara/logs/lessons.md` | Memory Keeper | Cross-mission | One row per real lesson, append-only, all actors share |
|
|
27
|
+
| **Evidence logs** | `.mugiwara/results/<label>-<hash>.log` | `scripts/evidence.sh` | On demand | Command stdout/stderr capture with timestamp and exit code |
|
|
28
|
+
|
|
29
|
+
## How to read as a reviewer
|
|
30
|
+
|
|
31
|
+
1. **Start with the mission report** (`reports/`) — one file, what changed, gates, token cost.
|
|
32
|
+
2. **Check the gate verdict** (`results/<mission>-gates.md`) — coverage from config, build, DoD. Any FAIL needs explanation.
|
|
33
|
+
3. **Spot-check the audit report** (`results/<mission>-audit.md`) — did Chopper re-run checks or accept claims? Every criterion gets a command run + evidence row.
|
|
34
|
+
4. **Review findings count** (`review/`) — how many blocker/major/minor? Were they healed? Check the heal report for closure.
|
|
35
|
+
5. **State.json** for raw numbers — lane, wave, files, blockers open, heal cycle, token budget status (ok/warn/stop).
|
|
36
|
+
|
|
37
|
+
## What stays after cleanup
|
|
38
|
+
|
|
39
|
+
After Wave 9 closure (run via `mugiwara-ship` cleanup procedure):
|
|
40
|
+
|
|
41
|
+
**Kept** (audit trail + PR material):
|
|
42
|
+
- `config` — runtime config
|
|
43
|
+
- `plans/<mission>.md` — clean plan doc
|
|
44
|
+
- `results/<mission>-closure.md` — closure report
|
|
45
|
+
- `results/<mission>-pr-verdict.md` — PR material
|
|
46
|
+
- `reports/<mission>.md` — mission report
|
|
47
|
+
- `state.json` — final mission state (unless another actor's mission is active)
|
|
48
|
+
- `logs/lessons.md` — cross-mission lessons
|
|
49
|
+
- `backup/`, `manifest.json` — harness config
|
|
50
|
+
|
|
51
|
+
**Deleted** (consumed/superseded):
|
|
52
|
+
- `spec/<mission>.md` — consumed by planning
|
|
53
|
+
- `results/<mission>-todos.md` — consumed
|
|
54
|
+
- `results/<mission>-audit.md` — superseded by closure
|
|
55
|
+
- `results/<mission>-quality.md` — consumed
|
|
56
|
+
- `results/<mission>-gates.md` — consumed
|
|
57
|
+
- `results/<mission>-heal.md` — consumed
|
|
58
|
+
- `results/<mission>-trace.md` — consumed (state.json is canonical)
|
|
59
|
+
- `review/<mission>-review.md` — consumed
|
|
60
|
+
- `review/<mission>-security.md` — consumed
|
|
61
|
+
- `issues/<mission>-blockers.md` — consumed
|
|
62
|
+
- `logs/<mission>.md` — decision log, per-mission
|
|
63
|
+
|
|
64
|
+
Cleanup lists candidates first (dry-run), then deletes. A mission is only
|
|
65
|
+
closed after cleanup runs.
|