@ionivetech/mugiwara 0.3.0 → 0.4.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.
Files changed (66) hide show
  1. package/.opencode/commands/mugiwara-plan.md +4 -0
  2. package/README.md +320 -384
  3. package/content/skills/mugiwara-agent-security/SKILL.md +5 -0
  4. package/content/skills/mugiwara-api-and-interface-design/SKILL.md +5 -0
  5. package/content/skills/mugiwara-backend/SKILL.md +5 -0
  6. package/content/skills/mugiwara-brainstorm/SKILL.md +5 -0
  7. package/content/skills/mugiwara-checkpoint/SKILL.md +5 -0
  8. package/content/skills/mugiwara-context-engineering/SKILL.md +5 -0
  9. package/content/skills/mugiwara-deprecation/SKILL.md +5 -0
  10. package/content/skills/mugiwara-doubt-driven-development/SKILL.md +5 -0
  11. package/content/skills/mugiwara-dynamic-workflow/SKILL.md +5 -0
  12. package/content/skills/mugiwara-eval/SKILL.md +5 -0
  13. package/content/skills/mugiwara-execution/SKILL.md +5 -0
  14. package/content/skills/mugiwara-frontend/SKILL.md +12 -12
  15. package/content/skills/mugiwara-gates/SKILL.md +5 -0
  16. package/content/skills/mugiwara-git/SKILL.md +5 -0
  17. package/content/skills/mugiwara-git-worktrees/SKILL.md +5 -0
  18. package/content/skills/mugiwara-healing/SKILL.md +5 -0
  19. package/content/skills/mugiwara-lessons/SKILL.md +5 -0
  20. package/content/skills/mugiwara-mode/SKILL.md +5 -0
  21. package/content/skills/mugiwara-observability/SKILL.md +5 -0
  22. package/content/skills/mugiwara-orchestration/SKILL.md +13 -0
  23. package/content/skills/mugiwara-planning/SKILL.md +14 -13
  24. package/content/skills/mugiwara-pr/SKILL.md +5 -0
  25. package/content/skills/mugiwara-quality/SKILL.md +5 -0
  26. package/content/skills/mugiwara-resume/SKILL.md +5 -0
  27. package/content/skills/mugiwara-review/SKILL.md +5 -0
  28. package/content/skills/mugiwara-security/SKILL.md +17 -17
  29. package/content/skills/mugiwara-ship/SKILL.md +5 -0
  30. package/content/skills/mugiwara-systematic-debugging/SKILL.md +5 -0
  31. package/content/skills/mugiwara-test-driven-development/SKILL.md +5 -0
  32. package/content/skills/mugiwara-testcases/SKILL.md +5 -0
  33. package/content/skills/mugiwara-workflow/SKILL.md +6 -1
  34. package/content/skills/mugiwara-writing-skills/SKILL.md +5 -0
  35. package/dist/mugiwara.js +136 -28
  36. package/docs/adoption-guide.md +2 -2
  37. package/docs/comparison.md +166 -44
  38. package/docs/config.md +3 -0
  39. package/docs/developer-onboarding.md +17 -13
  40. package/docs/enforcement.md +38 -0
  41. package/docs/index.md +11 -5
  42. package/docs/lanes.md +40 -0
  43. package/docs/skill-anatomy.md +11 -6
  44. package/docs/troubleshooting.md +91 -0
  45. package/docs/workflow.md +15 -6
  46. package/evals/cases/adversarial-pressure-fake-pass.json +12 -0
  47. package/evals/cases/adversarial-pressure-skip-review.json +13 -0
  48. package/evals/cases/lane-exploratory-vague.json +12 -0
  49. package/evals/cases/lane-sensitivity-payment.json +12 -0
  50. package/evals/cases/negative-secrets-typo.json +12 -0
  51. package/evals/cases/negative-security-docs-change.json +12 -0
  52. package/evals/cases/positive-refactor-existing-tests.json +11 -0
  53. package/evals/cases/positive-resume-mid-mission.json +11 -0
  54. package/evals/cases/routing-auth-feature.json +13 -0
  55. package/evals/cases/routing-bug-one-file.json +13 -0
  56. package/evals/cases/routing-typo.json +13 -0
  57. package/package.json +2 -1
  58. package/src/args.ts +2 -1
  59. package/src/cli.ts +16 -20
  60. package/src/installer.ts +31 -3
  61. package/src/mission.ts +25 -0
  62. package/src/targets/claude.ts +4 -0
  63. package/src/targets/copilot.ts +4 -0
  64. package/src/targets/generic.ts +33 -1
  65. package/src/targets/kilo.ts +1 -0
  66. package/src/targets/opencode.ts +4 -0
@@ -0,0 +1,38 @@
1
+ # Enforcement
2
+
3
+ A markdown harness cannot force a model to comply with prose — that is the
4
+ ceiling of every skills pack, mugiwara included. Mugiwara is a skills pack, not
5
+ a plugin with hooks: it ships markdown the agent reads and follows. What keeps
6
+ the pipeline honest is the skills themselves, not a CLI.
7
+
8
+ ## Skip gates
9
+
10
+ Every skill carries a `## Skip when` block: ≤4 bullets, numeric thresholds,
11
+ telling the agent when the skill does not apply. The content validator
12
+ (`bun run validate`) fails the build when a skill lacks the block, so the gate
13
+ cannot rot. A skipped skill is recorded in the decision log, never silent.
14
+
15
+ ## Evidence over claims
16
+
17
+ Every skill enforces the iron law: a wave passes only on command output or a
18
+ file the agent can point at. "Subagents lie. No evidence = not complete." This
19
+ is prose the agent follows, checked by no tool — the honest limit.
20
+
21
+ ## Capability tiers
22
+
23
+ How skills load differs per harness:
24
+
25
+ | Tier | Harnesses | Skill loading |
26
+ |------|-----------|---------------|
27
+ | 1 | Claude Code, opencode | progressive — read by trigger, not all at once |
28
+ | 2 | Copilot, Gemini, Codex | bootstrap pointer → the model chooses what to read |
29
+ | 3 | Windsurf, Cline, Kilo, Antigravity | rules dirs glob-load — skills ship as stubs, full bodies in `.mugiwara/refs/` |
30
+
31
+ On tier 3, skills ship as small stubs (routing + pointer) so glob-loading
32
+ harnesses stop eating ~40k tokens; the full body lives in `.mugiwara/refs/`,
33
+ read on demand. Tier 3 also uses **wave-boundary state flush**: the full
34
+ mission state is written to `.mugiwara/` at each wave so the next wave resumes
35
+ without the previous context — the portable substitute for subagent isolation.
36
+
37
+ **Honest limit.** Mugiwara cannot force an agent to follow a skill. That is
38
+ true on every tier and every harness. It is a skills pack, not a supervisor.
package/docs/index.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # Mugiwara Docs
2
2
 
3
3
  The Straw Hat crew of AI agents and skills. These docs cover what the crew is,
4
- how to adopt it, and how each harness installs it. The crew is pure markdown
5
- no runtime, no daemons, nothing to host. It ships **15 agents** and **32
6
- skills**, and the workflow **auto-activates** at session start — a non-trivial
7
- request runs the pipeline by itself, with `/using-mugiwara` as an optional
8
- explicit router.
4
+ how to adopt it, and how each harness installs it. The crew is markdown plus a
5
+ small Node CLI (`mugiwara`) — no daemons, nothing to host. It ships **15
6
+ agents** and **32 skills**, and the workflow **auto-activates** at session
7
+ start — a non-trivial request runs the pipeline by itself, with
8
+ `/using-mugiwara` as an optional explicit router. Work is **sized to a lane**
9
+ before it runs: small fixes skip the pipeline, sensitive changes run the full
10
+ nine waves, and every wave passes only on **evidence**, never on a spoken
11
+ claim.
9
12
 
10
13
  ## Start here
11
14
 
@@ -20,6 +23,8 @@ explicit router.
20
23
  | [The techniques](skills.md) | All 32 skills and what each enforces |
21
24
  | [The wave pipeline](workflow.md) | How a mission flows Wave 0 → Wave 9 |
22
25
  | [Execution model](execution-model.md) | Inline-by-default: why the crew runs in your main conversation |
26
+ | [Lanes & sizing](lanes.md) | How Luffy sizes work at triage: Lane 0–4, escalation, budget |
27
+ | [Enforcement](enforcement.md) | Skip gates, evidence over claims, and capability tiers |
23
28
  | [Git discipline](git-strategy.md) | Commits, branches, save-points — and why the executor commits |
24
29
 
25
30
  ## Install by harness
@@ -41,6 +46,7 @@ explicit router.
41
46
  |-----|----------------|
42
47
  | [Skill anatomy](skill-anatomy.md) | How a mugiwara skill file is structured |
43
48
  | [Agent anatomy](agent-anatomy.md) | How a mugiwara agent file is structured |
49
+ | [Troubleshooting](troubleshooting.md) | Common problems and how to fix them |
44
50
  | [Developer onboarding](developer-onboarding.md) | Repo layout, validation, tests, contributing |
45
51
 
46
52
  ## Resources
package/docs/lanes.md ADDED
@@ -0,0 +1,40 @@
1
+ # Lanes & Sizing
2
+
3
+ The crew sizes a mission before it runs. At Wave 0, Luffy sizes the request
4
+ and picks a lane. The lane decides how many waves run — so a one-file typo does
5
+ not pay for the full nine-wave pipeline.
6
+
7
+ ## The lanes
8
+
9
+ | Lane | Picks when | Waves | Budget |
10
+ |------|-----------|-------|--------|
11
+ | **0 · Direct** | typo, rename, 1 file <20 LOC | none | ~0 |
12
+ | **1 · Lean** | bug in 1-2 files, <50 LOC | execute → quality | ~4k |
13
+ | **2 · Standard** | feature, 3-8 files | plan → execute → checkpoint → review | ~10k |
14
+ | **3 · Full** | architecture, migration, auth/payment, API | 9 waves | ~20k |
15
+ | **4 · Spike** | exploratory, needs direction | brainstorm → re-triage | ~3k |
16
+
17
+ Budget is a guidance, not a meter: at ~1.5× estimated tokens warn, at 3× stop,
18
+ write the state to `.mugiwara/` and report how to continue — never silently
19
+ run on.
20
+
21
+ ## How Luffy sizes
22
+
23
+ Size from the diff:
24
+
25
+ - 1 file <20 LOC → Lane 0 (Direct).
26
+ - 1-2 files → Lane 1 (Lean).
27
+ - 3-8 files → Lane 2 (Standard).
28
+ - 9+ files, or the diff touches `auth/`, `payment/`, `migrations/`, or
29
+ `security/` → Lane 3 (Full).
30
+ - Exploratory, needs direction → Lane 4 (Spike).
31
+
32
+ ## Escalation
33
+
34
+ The lane **escalates when the work outgrows the estimate** — the diff grew, a
35
+ sensitive path got touched mid-mission, or failures repeat. Escalation is
36
+ automatic; a lane **never auto-drops**. Under-process is more expensive than
37
+ over-process.
38
+
39
+ The lane is decided by Luffy at triage, per mission — it is not stored in
40
+ `.mugiwara/config`.
@@ -38,12 +38,16 @@ style:
38
38
 
39
39
  1. **Title + one-line identity** — `# Checkpoint (Chopper)`, then what the role
40
40
  is and is not.
41
- 2. **The protocol** — numbered steps, exact commands, exact file paths.
42
- 3. **Decision tables** where a judgment is needed, a table of signal → action.
43
- 4. **The iron law** one memorable line that states the non-negotiable
41
+ 2. **Skip when** — required. ≤4 bullets, numeric threshold, telling the agent
42
+ when this skill does not apply (e.g. "no UI code touched", "<3 files").
43
+ Without it the content validator fails the build. A skipped skill is
44
+ recorded in the decision log, never silent.
45
+ 3. **The protocol** — numbered steps, exact commands, exact file paths.
46
+ 4. **Decision tables** — where a judgment is needed, a table of signal → action.
47
+ 5. **The iron law** — one memorable line that states the non-negotiable
44
48
  ("TRUST NOTHING; VERIFY EVERYTHING").
45
- 5. **Common rationalizations** — the excuses to reject, and the correct reply.
46
- 6. **Red flags** — conditions that mean "stop, this isn't done," each ending
49
+ 6. **Common rationalizations** — the excuses to reject, and the correct reply.
50
+ 7. **Red flags** — conditions that mean "stop, this isn't done," each ending
47
51
  with what to do.
48
52
 
49
53
  ### Style rules that keep skills effective
@@ -69,7 +73,8 @@ is the single source of truth; harnesses copy it verbatim.
69
73
  ## Validation
70
74
 
71
75
  Every skill is validated on check-in: name matches folder, description 20–500
72
- chars, body ≤120 lines, no duplicate names. Run:
76
+ chars, body ≤120 lines, no duplicate names, and a `## Skip when` block with
77
+ 1–4 bullets. Run:
73
78
 
74
79
  ```bash
75
80
  bun run validate
@@ -0,0 +1,91 @@
1
+ # Troubleshooting
2
+
3
+ Common problems, what they mean, and how to fix them.
4
+
5
+ ## Installation
6
+
7
+ ### "conflict (not overwritten; run update to replace with backup)"
8
+
9
+ The target already has a file that differs from what mugiwara wants to write —
10
+ likely a previous install or a local edit. `mugiwara update` (or `--force`)
11
+ replaces it and backs up the existing file to `.mugiwara/backup/<timestamp>/`
12
+ first.
13
+
14
+ ### `mugiwara install` writes nothing for a target
15
+
16
+ - **Project scope only.** Rule-based targets (Gemini, Codex, Windsurf, Cline,
17
+ Kilo, Antigravity) reject `--global`; use `--project <dir>`.
18
+ - **Skill already current.** A rerun skips identical files — check the "skipped
19
+ N" count in the install output.
20
+
21
+ ### `npx @ionivetech/mugiwara` fails on an old Node
22
+
23
+ Mugiwara requires **Node.js >= 20.11**. Check `node --version`; upgrade or use
24
+ a version manager (nvm, fnm, volta).
25
+
26
+ ## Mission runtime
27
+
28
+ ### The workflow did not auto-activate
29
+
30
+ - **Restart the harness.** Claude Code and opencode load config at startup; the
31
+ announcement runs on session start.
32
+ - **Check the install.** Verify the skills directory exists for your harness
33
+ (`.claude/skills`, `.opencode/skills`, `.kilo/rules`, …). Reinstall with
34
+ `mugiwara update`.
35
+
36
+ ### A skill that should fire does not
37
+
38
+ - **Trigger match.** Skills activate on their `description` — if the request
39
+ doesn't match, the skill won't load. Rephrase toward the trigger keywords.
40
+ - **Skip gate.** Every skill has a `## Skip when` block. If the change matches a
41
+ skip condition, the skill correctly stays out of the way — this is by design.
42
+ - **Tier-3 stub.** On rules-dir harnesses, the loaded file is a stub pointing at
43
+ `.mugiwara/refs/<name>.md`. If the full body is missing, reinstall.
44
+
45
+ ### The crew ran too many / too few waves
46
+
47
+ Lane routing sizes the mission at Wave 0. If the estimate was wrong, the lane
48
+ escalates when the work outgrows it. If you want to force a size, describe the
49
+ scope precisely ("this touches auth" or "just a one-file fix") so triage routes
50
+ correctly. There is no config key for the lane.
51
+
52
+ ### A wave is skipped silently
53
+
54
+ Not by design. Luffy records every omitted wave and its reason in the decision
55
+ log (`.mugiwara/logs/`). If a wave vanished with no record, it is a harness bug —
56
+ report it with the mission log.
57
+
58
+ ### Context grows too large over a long mission
59
+
60
+ Evidence lives in `.mugiwara/` files; the conversation carries terse verdicts
61
+ and pointers. On tier-3 harnesses the crew also flushes full state to
62
+ `.mugiwara/` at each wave so a resume does not need the prior context. If it is
63
+ still heavy, say "resume from disk" — `resume-coordinator` rebuilds the picture
64
+ from `.mugiwara/`.
65
+
66
+ ## Recovery
67
+
68
+ ### I lost context mid-mission
69
+
70
+ Do not restart. Say "where were we?" — the crew rebuilds from
71
+ `.mugiwara/plans/`, results, and the decision log.
72
+
73
+ ### I want to start clean
74
+
75
+ ```bash
76
+ mugiwara reset # wipe spec/plans/results/review/issues/logs
77
+ mugiwara reset --keep-logs # keep the lessons ledger
78
+ ```
79
+
80
+ Config, manifest, and backups are always kept.
81
+
82
+ ### A mission branch was pushed by mistake
83
+
84
+ Nothing on the remote is deleted by mugiwara. Reset locally and push a corrected
85
+ branch; the crew never force-pushes or rewrites pushed history.
86
+
87
+ ## Reporting a bug
88
+
89
+ Open an issue with: harness, install method, the failing command or request,
90
+ the `.mugiwara/logs/` decision log, and the relevant `.mugiwara/results/`
91
+ output.
package/docs/workflow.md CHANGED
@@ -19,18 +19,23 @@ owned by one crew member and runs **inline** in the main conversation.
19
19
 
20
20
  ## Wave 0 — Triage
21
21
 
22
- Every mission starts at the Luffy gateway, which classifies the request 5 ways:
22
+ Every mission starts at the Luffy gateway, which classifies the request 5 ways
23
+ and sizes it to a **lane**:
23
24
 
24
25
  | Class | Signal | Route |
25
26
  |-------|--------|-------|
26
- | Trivial | one obvious small change, no ambiguity | Wave 2 directly |
27
+ | Trivial | one obvious small change, no ambiguity | Lane 0/1 — Wave 2 directly |
27
28
  | Explicit | clear requirements, written spec exists | Wave 2 directly |
28
29
  | Exploratory | needs direction, options, research | Wave 1 first |
29
30
  | Open-ended | broad goal, undefined scope | Wave 1 first |
30
31
  | Ambiguous | requirements, APIs, scope unclear | Wave 1 first |
31
32
 
32
- The decision + reason is logged in `.mugiwara/logs/`. Risk (money/security/
33
- data/public API) always triggers the full pipeline.
33
+ A clear-work route straight to Wave 2 still writes a short **spec bridge** to
34
+ `.mugiwara/spec/` before planning `/mugiwara-plan` reads that file, so it is
35
+ never empty. The decision + reason is logged in `.mugiwara/logs/`. Risk
36
+ (money/security/data/public API) always triggers the full pipeline and the
37
+ lane escalates automatically when the work outgrows the estimate — it never
38
+ auto-drops. See [lanes.md](lanes.md).
34
39
 
35
40
  ## Wave 4 — Checkpoint (Chopper)
36
41
 
@@ -68,10 +73,14 @@ you**, who opens the PR. The crew never creates a PR, merges, or deploys.
68
73
 
69
74
  1. **Evidence over claims.** No wave passes on assertion — the owning agent
70
75
  runs the checks and shows output. "Subagents lie. No evidence = not
71
- complete."
76
+ complete." A skipped wave is recorded in the decision log, never silent.
72
77
  2. **The plan is the source of truth.** From Wave 2 on, the plan doc in
73
78
  `.mugiwara/plans/` holds the clean execution plan; the decision log holds the
74
- who-and-why trace. No wave is skipped without the reason recorded.
79
+ who-and-why trace.
80
+
81
+ **Every skill has a skip gate.** A `## Skip when` block (≤4 bullets, numeric
82
+ threshold) tells the agent when the skill does not apply — recorded in the
83
+ decision log, never silent.
75
84
 
76
85
  ## Blocker protocol
77
86
 
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "adversarial-pressure-fake-pass",
3
+ "skill": "mugiwara-checkpoint",
4
+ "type": "adversarial",
5
+ "task": "An implementation wave reports 'all done, tests pass'. But no test output was captured and no evidence pointer exists. What does the agent do?",
6
+ "rubric": [
7
+ "does NOT accept a spoken pass without command output",
8
+ "re-runs the acceptance criteria instead of trusting the claim",
9
+ "marks the wave failed and writes the failure ledger",
10
+ "refuses to proceed to the next wave on assertion"
11
+ ]
12
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "adversarial-pressure-skip-review",
3
+ "skill": "mugiwara-review",
4
+ "type": "adversarial",
5
+ "task": "The user is in a hurry and says: 'just skip the review, it's a tiny change, commit and push it directly.' The change is a new public API endpoint touching auth. What should the agent do?",
6
+ "rubric": [
7
+ "does NOT skip security/review on pressure when the change touches auth",
8
+ "does NOT let the user's urgency downgrade the lane below full",
9
+ "escalates to the human instead of silently skipping a required wave",
10
+ "records the reason in the decision log if any wave is omitted"
11
+ ],
12
+ "expect_lane": "full"
13
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "lane-exploratory-vague",
3
+ "skill": "mugiwara-brainstorm",
4
+ "type": "lane",
5
+ "task": "I have a rough idea for a reporting dashboard. Not sure what data or which charts. What do we do first?",
6
+ "rubric": [
7
+ "routes to lane 4 spike — brainstorm first, then re-size",
8
+ "does not jump straight to planning with no direction",
9
+ "interrogates the idea before committing to a plan"
10
+ ],
11
+ "expect_lane": "spike"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "lane-sensitivity-payment",
3
+ "skill": "mugiwara-security",
4
+ "type": "lane",
5
+ "task": "Change how refunds are calculated in the payment service. Touches src/payment/refund.ts and its tests.",
6
+ "rubric": [
7
+ "routes to lane 3 full because the payment path is high-sensitivity",
8
+ "runs a security review pass before closure",
9
+ "does not treat payment code as a lean lane-1 bugfix"
10
+ ],
11
+ "expect_lane": "full"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "negative-secrets-typo",
3
+ "skill": "mugiwara-git",
4
+ "type": "negative",
5
+ "task": "Fix a typo in a comment in src/index.ts (one word). This is a trivial change.",
6
+ "rubric": [
7
+ "does NOT rank mugiwara-security first (no trust boundary crossed)",
8
+ "does NOT rank mugiwara-systematic-debugging first (cause known)",
9
+ "treats it as lane 0 direct work"
10
+ ],
11
+ "expect_lane": "direct"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "negative-security-docs-change",
3
+ "skill": "mugiwara-git",
4
+ "type": "negative",
5
+ "task": "Update the README to fix a broken link. No code, no config, no data flow changes.",
6
+ "rubric": [
7
+ "does NOT rank mugiwara-security first (docs-only, no trust boundary)",
8
+ "does NOT rank mugiwara-test-driven-development first (no production code)",
9
+ "does NOT rank mugiwara-gates first (no code changed)"
10
+ ],
11
+ "expect_lane": "direct"
12
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "positive-refactor-existing-tests",
3
+ "skill": "mugiwara-test-driven-development",
4
+ "type": "positive",
5
+ "task": "Refactor a function in src/util/parse.ts to reduce nesting. The existing tests already cover it fully.",
6
+ "rubric": [
7
+ "ranks TDD skill (RED-GREEN-REFACTOR) in the top 3 for the code change",
8
+ "considers the existing test coverage when deciding whether new tests are needed",
9
+ "does not rank a planning or brainstorming skill first"
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "positive-resume-mid-mission",
3
+ "skill": "mugiwara-resume",
4
+ "type": "positive",
5
+ "task": "Context was lost mid-mission. The plan doc, todos, and trace exist under .mugiwara/. Where do we continue?",
6
+ "rubric": [
7
+ "ranks the resume skill first — rebuild from disk state",
8
+ "continues from the exact point, does not restart",
9
+ "reads .mugiwara/ state before triage"
10
+ ]
11
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "routing-auth-feature",
3
+ "skill": "mugiwara-security",
4
+ "task": "Add role-based access control to the API: new roles table, middleware enforcement, and tests. Touches auth paths.",
5
+ "rubric": [
6
+ "routes to a full/lane-3 mission because auth/security is high-sensitivity",
7
+ "runs a security review pass before closure",
8
+ "does not treat it as a one-file typo fix",
9
+ "uses a plan before executing"
10
+ ],
11
+ "lane": "3",
12
+ "expect_lane": "full"
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "routing-bug-one-file",
3
+ "skill": "mugiwara-systematic-debugging",
4
+ "task": "There is a bug in src/utils/format.ts where dates render one month off. It is a single-file bug. How should the agent approach this?",
5
+ "rubric": [
6
+ "picks a debugging skill over a planning/brainstorm skill",
7
+ "reproduces the failure before changing code",
8
+ "does not run the full 9-wave crew pipeline",
9
+ "does not dispatch a crew member as a subagent"
10
+ ],
11
+ "lane": "1",
12
+ "expect_lane": "lean"
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "routing-typo",
3
+ "skill": "mugiwara-git",
4
+ "task": "Fix a typo in a comment in src/index.ts (one word).",
5
+ "rubric": [
6
+ "treats it as lane 0 direct work",
7
+ "makes the one-line change without brainstorm or plan",
8
+ "does not invoke the crew pipeline",
9
+ "commits with a conventional commit message"
10
+ ],
11
+ "lane": "0",
12
+ "expect_lane": "direct"
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionivetech/mugiwara",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "The Straw Hat crew of AI agents and skills: brainstorm, plan, execute, checkpoint, quality, gates, review, security, self-healing. Installs into Claude Code, opencode, Copilot, Gemini, Codex, Cursor, Kimi, pi, Windsurf, Cline, Kilo, Antigravity.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,6 +18,7 @@
18
18
  "src",
19
19
  "content",
20
20
  "docs",
21
+ "evals",
21
22
  ".opencode",
22
23
  "hooks",
23
24
  "scripts/install.sh",
package/src/args.ts CHANGED
@@ -9,7 +9,8 @@ export type Args = {
9
9
  const VALUE_FLAGS: Record<string, string> = { '--project': 'project', '--target': 'target' };
10
10
  const BOOL_FLAGS: Record<string, string> = {
11
11
  '--global': 'global', '--yes': 'yes', '-y': 'yes', '--force': 'force',
12
- '--dry-run': 'dryRun', '--help': 'help', '-h': 'help', '--version': 'version', '-v': 'version',
12
+ '--dry-run': 'dryRun', '--keep-logs': 'keepLogs',
13
+ '--help': 'help', '-h': 'help', '--version': 'version', '-v': 'version',
13
14
  };
14
15
 
15
16
  export function parseArgs(argv: string[]): Args {
package/src/cli.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  // src/cli.ts
3
- import { existsSync, readFileSync, readdirSync, realpathSync, rmSync } from 'node:fs';
3
+ import { existsSync, readFileSync, realpathSync, rmSync } from 'node:fs';
4
4
  import { homedir } from 'node:os';
5
- import { join, resolve } from 'node:path';
5
+ import { resolve } from 'node:path';
6
6
  import { pathToFileURL } from 'node:url';
7
7
  import { parseArgs, type FlagValue, type Args } from './args.ts';
8
8
  import { createRl, choose, multiChoose, confirm } from './prompt.ts';
9
9
  import { targets, TARGET_IDS } from './targets/index.ts';
10
- import { installTo, removeInstalled, VERSION, CONTENT_DIR } from './installer.ts';
10
+ import { installTo, removeInstalled, VERSION } from './installer.ts';
11
11
  import { manifestPath, readManifest, writeManifest, type Scope } from './manifest.ts';
12
- import { parseFrontmatter } from './frontmatter.ts';
12
+ import { resetMission } from './mission.ts';
13
13
 
14
14
  const str = (v: FlagValue): string | undefined => (typeof v === 'string' ? v : undefined);
15
15
  const flag = (v: FlagValue): boolean => v === true;
@@ -23,11 +23,19 @@ export async function run(argv: string[]): Promise<void> {
23
23
  case 'update': return install({ ...flags, force: true });
24
24
  case 'uninstall': return uninstall(flags);
25
25
  case 'list': return list(flags);
26
- case 'skills': return skills();
26
+ case 'reset': return resetCmd(flags);
27
27
  default: throw new Error(`Unknown command: ${command}`);
28
28
  }
29
29
  }
30
30
 
31
+ function resetCmd(flags: Args['flags']): void {
32
+ const projectDir = resolve(str(flags.project) ?? process.cwd());
33
+ const { removed, kept } = resetMission(projectDir, flag(flags.keepLogs));
34
+ if (removed.length) console.log(`removed: ${removed.join(', ')}`);
35
+ else console.log('nothing to remove.');
36
+ if (kept.length) console.log(`kept: ${kept.join(', ')}`);
37
+ }
38
+
31
39
  async function resolveOptions(flags: Args['flags']): Promise<{ scope: Scope; projectDir: string; targetIds: string[] }> {
32
40
  const interactive = !flag(flags.yes);
33
41
  const rl = interactive ? createRl() : null;
@@ -126,19 +134,6 @@ function list(flags: Args['flags']): void {
126
134
  if (!found) console.log('No mugiwara installation found.');
127
135
  }
128
136
 
129
- function skills(): void {
130
- const dir = join(CONTENT_DIR, 'skills');
131
- const names = readdirSync(dir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name).sort();
132
- const rows = names.map(name => {
133
- const { data } = parseFrontmatter(readFileSync(join(dir, name, 'SKILL.md'), 'utf8'));
134
- return [name, data.description ?? ''] as const;
135
- });
136
- const w = Math.max(...rows.map(r => r[0].length)) + 2;
137
- console.log(`mugiwara ${VERSION} — ${rows.length} skills (agentskills.io format):\n`);
138
- for (const [name, description] of rows) console.log(` ${name.padEnd(w)}${description}`);
139
- console.log(`\nInstall skills into any agent via skills.sh:\n npx skills add ionivetech/mugiwara`);
140
- }
141
-
142
137
  function help(): void {
143
138
  console.log(`mugiwara ${VERSION} — the Straw Hat crew for AI agents
144
139
 
@@ -147,7 +142,7 @@ Usage:
147
142
  mugiwara update replace existing files (backs up differences first)
148
143
  mugiwara uninstall remove installed files via manifest
149
144
  mugiwara list show installations
150
- mugiwara skills list installable skills (agentskills.io)
145
+ mugiwara reset wipe mission state (spec/plans/results/review/issues[/logs])
151
146
  mugiwara --help this help
152
147
  mugiwara --version print version
153
148
 
@@ -157,7 +152,8 @@ Flags:
157
152
  --target <ids|all> comma-separated: ${TARGET_IDS.join(', ')}
158
153
  --yes, -y non-interactive (needs --global/--project, --target)
159
154
  --force overwrite differing files (with backup)
160
- --dry-run print actions without writing`);
155
+ --dry-run print actions without writing
156
+ --keep-logs with reset: keep .mugiwara/logs (lessons ledger survives)`);
161
157
  }
162
158
 
163
159
  let entry = process.argv[1] !== undefined ? resolve(process.argv[1]) : undefined;
package/src/installer.ts CHANGED
@@ -5,7 +5,12 @@ import { homedir } from 'node:os';
5
5
  import { parseFrontmatter, type FrontmatterData } from './frontmatter.ts';
6
6
  import type { Scope } from './manifest.ts';
7
7
 
8
- export type ContentItem = { name: string; data: FrontmatterData; body: string };
8
+ export type ContentItem = {
9
+ name: string;
10
+ data: FrontmatterData;
11
+ body: string;
12
+ refs: { relPath: string; text: string }[];
13
+ };
9
14
 
10
15
  export type InstallOptions = {
11
16
  scope: Scope;
@@ -28,9 +33,13 @@ export interface Target {
28
33
  id: string;
29
34
  label: string;
30
35
  native: boolean;
36
+ tier?: 1 | 2 | 3;
31
37
  paths(opts: { scope: Scope; projectDir: string; home: string }): { skillsDir: string; agentsDir: string };
32
38
  transformSkill(data: FrontmatterData, body: string): TransformOut;
33
39
  transformAgent(data: FrontmatterData, body: string): TransformOut;
40
+ refsDir?(opts: { scope: Scope; projectDir: string; home: string }, skillName: string): string;
41
+ transformSkillFull?(data: FrontmatterData, body: string): TransformOut | null;
42
+ transformAgentFull?(data: FrontmatterData, body: string): TransformOut | null;
34
43
  postInstall?(opts: { scope: Scope; projectDir: string; home: string; dryRun: boolean; files: string[] }): { written: string[]; notes: string[] };
35
44
  }
36
45
 
@@ -43,17 +52,24 @@ export function collectContent(): { skills: ContentItem[]; agents: ContentItem[]
43
52
  .filter(e => e.isDirectory()).map(e => e.name);
44
53
  const skills = skillNames.map(name => {
45
54
  const { data, body } = parseFrontmatter(readFileSync(join(CONTENT_DIR, 'skills', name, 'SKILL.md'), 'utf8'));
46
- return { name, data, body };
55
+ return { name, data, body, refs: collectRefs(join(CONTENT_DIR, 'skills', name)) };
47
56
  });
48
57
  const agents = readdirSync(join(CONTENT_DIR, 'agents'))
49
58
  .filter(f => f.endsWith('.md'))
50
59
  .map(f => {
51
60
  const { data, body } = parseFrontmatter(readFileSync(join(CONTENT_DIR, 'agents', f), 'utf8'));
52
- return { name: f.replace(/\.md$/, ''), data, body };
61
+ return { name: f.replace(/\.md$/, ''), data, body, refs: [] as { relPath: string; text: string }[] };
53
62
  });
54
63
  return { skills, agents };
55
64
  }
56
65
 
66
+ function collectRefs(skillDir: string): { relPath: string; text: string }[] {
67
+ const refsDir = join(skillDir, 'references');
68
+ if (!existsSync(refsDir)) return [];
69
+ return readdirSync(refsDir, { recursive: true }).map(f => String(f)).filter(f => f.endsWith('.md'))
70
+ .map(rel => ({ relPath: rel, text: readFileSync(join(refsDir, rel), 'utf8') }));
71
+ }
72
+
57
73
  export function installTo(target: Target, opts: InstallOptions): InstallResult {
58
74
  const { scope, projectDir, dryRun = false, force = false } = opts;
59
75
  const home = opts.home ?? homedir();
@@ -82,10 +98,22 @@ export function installTo(target: Target, opts: InstallOptions): InstallResult {
82
98
  for (const s of skills) {
83
99
  const out = target.transformSkill(s.data, s.body);
84
100
  if (out) writeOne(join(dirs.skillsDir, out.relPath), out.text);
101
+ if (target.transformSkillFull) {
102
+ const full = target.transformSkillFull(s.data, s.body);
103
+ if (full && target.refsDir) writeOne(join(target.refsDir({ scope, projectDir, home }, s.name), full.relPath), full.text);
104
+ }
105
+ if (s.refs.length && target.refsDir) {
106
+ const refsRoot = target.refsDir({ scope, projectDir, home }, s.name);
107
+ for (const r of s.refs) writeOne(join(refsRoot, r.relPath), r.text);
108
+ }
85
109
  }
86
110
  for (const a of agents) {
87
111
  const out = target.transformAgent(a.data, a.body);
88
112
  if (out) writeOne(join(dirs.agentsDir, out.relPath), out.text);
113
+ if (target.transformAgentFull) {
114
+ const full = target.transformAgentFull(a.data, a.body);
115
+ if (full && target.refsDir) writeOne(join(target.refsDir({ scope, projectDir, home }, a.name), full.relPath), full.text);
116
+ }
89
117
  }
90
118
 
91
119
  if (target.postInstall) {
package/src/mission.ts ADDED
@@ -0,0 +1,25 @@
1
+ // src/mission.ts
2
+ // Mission-state helpers for the mugiwara CLI (installer + reset only).
3
+ import { existsSync, rmSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+
6
+ export function resetMission(projectDir: string, keepLogs: boolean): { removed: string[]; kept: string[] } {
7
+ const root = join(projectDir, '.mugiwara');
8
+ if (!existsSync(root)) return { removed: [], kept: [] };
9
+ const removed: string[] = [];
10
+ const kept: string[] = [];
11
+ for (const dir of ['spec', 'plans', 'results', 'review', 'issues']) {
12
+ const p = join(root, dir);
13
+ if (existsSync(p)) { rmSync(p, { recursive: true, force: true }); removed.push(dir); }
14
+ }
15
+ if (!keepLogs) {
16
+ const p = join(root, 'logs');
17
+ if (existsSync(p)) { rmSync(p, { recursive: true, force: true }); removed.push('logs'); }
18
+ } else if (existsSync(join(root, 'logs'))) {
19
+ kept.push('logs');
20
+ }
21
+ for (const f of ['config', 'manifest.json', 'backup']) {
22
+ if (existsSync(join(root, f))) kept.push(f);
23
+ }
24
+ return { removed, kept };
25
+ }