@ionivetech/mugiwara 0.2.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 (99) hide show
  1. package/.opencode/commands/mugiwara-execute.md +11 -0
  2. package/.opencode/commands/mugiwara-heal.md +11 -0
  3. package/.opencode/commands/mugiwara-mode.md +6 -0
  4. package/.opencode/commands/mugiwara-plan.md +15 -0
  5. package/.opencode/commands/mugiwara-review.md +11 -0
  6. package/.opencode/commands/mugiwara-security.md +11 -0
  7. package/.opencode/commands/mugiwara-ship.md +11 -0
  8. package/.opencode/commands/mugiwara.md +11 -0
  9. package/.opencode/plugins/mugiwara.mjs +126 -7
  10. package/README.md +338 -355
  11. package/content/agents/brook-healing.md +2 -2
  12. package/content/agents/luffy-orchestrator.md +3 -2
  13. package/content/agents/robin-reviewer.md +1 -1
  14. package/content/agents/skeptic-verifier.md +1 -1
  15. package/content/agents/using-mugiwara.md +5 -1
  16. package/content/agents/usopp-brainstorm.md +1 -1
  17. package/content/agents/zoro-execution.md +1 -1
  18. package/content/skills/mugiwara-agent-security/SKILL.md +5 -0
  19. package/content/skills/mugiwara-api-and-interface-design/SKILL.md +92 -0
  20. package/content/skills/mugiwara-backend/SKILL.md +5 -0
  21. package/content/skills/mugiwara-brainstorm/SKILL.md +5 -0
  22. package/content/skills/mugiwara-checkpoint/SKILL.md +5 -0
  23. package/content/skills/mugiwara-context-engineering/SKILL.md +64 -0
  24. package/content/skills/mugiwara-deprecation/SKILL.md +5 -0
  25. package/content/skills/mugiwara-doubt-driven-development/SKILL.md +70 -0
  26. package/content/skills/mugiwara-dynamic-workflow/SKILL.md +5 -0
  27. package/content/skills/mugiwara-eval/SKILL.md +5 -0
  28. package/content/skills/mugiwara-execution/SKILL.md +9 -0
  29. package/content/skills/mugiwara-frontend/SKILL.md +61 -59
  30. package/content/skills/mugiwara-frontend/references/checklist.md +37 -0
  31. package/content/skills/mugiwara-gates/SKILL.md +9 -0
  32. package/content/skills/mugiwara-git/SKILL.md +5 -0
  33. package/content/skills/mugiwara-git-worktrees/SKILL.md +67 -0
  34. package/content/skills/mugiwara-healing/SKILL.md +17 -0
  35. package/content/skills/mugiwara-lessons/SKILL.md +5 -0
  36. package/content/skills/mugiwara-mode/SKILL.md +18 -4
  37. package/content/skills/mugiwara-observability/SKILL.md +5 -0
  38. package/content/skills/mugiwara-orchestration/SKILL.md +32 -1
  39. package/content/skills/mugiwara-planning/SKILL.md +25 -26
  40. package/content/skills/mugiwara-pr/SKILL.md +22 -6
  41. package/content/skills/mugiwara-quality/SKILL.md +15 -0
  42. package/content/skills/mugiwara-resume/SKILL.md +5 -0
  43. package/content/skills/mugiwara-review/SKILL.md +5 -0
  44. package/content/skills/mugiwara-security/SKILL.md +51 -14
  45. package/content/skills/mugiwara-ship/SKILL.md +29 -1
  46. package/content/skills/mugiwara-systematic-debugging/SKILL.md +82 -0
  47. package/content/skills/mugiwara-test-driven-development/SKILL.md +89 -0
  48. package/content/skills/mugiwara-testcases/SKILL.md +5 -0
  49. package/content/skills/mugiwara-workflow/SKILL.md +14 -3
  50. package/content/skills/mugiwara-writing-skills/SKILL.md +65 -0
  51. package/dist/mugiwara.js +175 -51
  52. package/docs/adoption-guide.md +3 -3
  53. package/docs/agents.md +2 -2
  54. package/docs/claude-setup.md +9 -4
  55. package/docs/codex-setup.md +3 -1
  56. package/docs/comparison.md +166 -44
  57. package/docs/config.md +53 -0
  58. package/docs/copilot-setup.md +3 -1
  59. package/docs/cursor-setup.md +3 -1
  60. package/docs/developer-onboarding.md +17 -13
  61. package/docs/enforcement.md +38 -0
  62. package/docs/execution-model.md +33 -0
  63. package/docs/gemini-setup.md +4 -1
  64. package/docs/getting-started.md +16 -4
  65. package/docs/index.md +14 -3
  66. package/docs/lanes.md +40 -0
  67. package/docs/modes.md +22 -12
  68. package/docs/opencode-setup.md +9 -2
  69. package/docs/pr-summary.md +54 -0
  70. package/docs/skill-anatomy.md +16 -6
  71. package/docs/skills.md +17 -5
  72. package/docs/troubleshooting.md +91 -0
  73. package/docs/windsurf-setup.md +3 -1
  74. package/docs/workflow.md +15 -6
  75. package/evals/cases/adversarial-pressure-fake-pass.json +12 -0
  76. package/evals/cases/adversarial-pressure-skip-review.json +13 -0
  77. package/evals/cases/lane-exploratory-vague.json +12 -0
  78. package/evals/cases/lane-sensitivity-payment.json +12 -0
  79. package/evals/cases/negative-secrets-typo.json +12 -0
  80. package/evals/cases/negative-security-docs-change.json +12 -0
  81. package/evals/cases/positive-refactor-existing-tests.json +11 -0
  82. package/evals/cases/positive-resume-mid-mission.json +11 -0
  83. package/evals/cases/routing-auth-feature.json +13 -0
  84. package/evals/cases/routing-bug-one-file.json +13 -0
  85. package/evals/cases/routing-typo.json +13 -0
  86. package/hooks/hooks.json +15 -0
  87. package/hooks/session-start.ts +8 -0
  88. package/package.json +3 -1
  89. package/src/args.ts +2 -1
  90. package/src/cli.ts +16 -20
  91. package/src/installer.ts +31 -3
  92. package/src/mission.ts +25 -0
  93. package/src/targets/claude.ts +22 -1
  94. package/src/targets/codex.ts +1 -1
  95. package/src/targets/copilot.ts +4 -0
  96. package/src/targets/gemini.ts +1 -1
  97. package/src/targets/generic.ts +33 -1
  98. package/src/targets/kilo.ts +1 -0
  99. package/src/targets/opencode.ts +4 -0
@@ -5,12 +5,23 @@ description: Use at the start of any non-trivial mission to run the Mugiwara cre
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)
11
16
 
12
17
  **Inline by default.** The main/primary agent runs the pipeline and plays each crew role itself using that member's skill. Every wave's work is performed in the main conversation so the user sees the process live — no hidden subagent jumps, no click-to-expand. The crew members are personas + skills the main thread embodies, not mandatory dispatch targets.
13
18
 
19
+ **Visible wave transitions.** Every wave opens with a main-thread banner `## Wave N — <crew> (<skill>)` and closes with the handoff line `→ Wave N+1 — <crew>` (Wave 9: `→ closure`). No wave starts without its banner; the conversation names who runs now and who takes over next so the user always sees the chain live.
20
+
21
+ **Auto-activation.** Any non-trivial request fires the harness without the user asking. Check first, before exploring or answering: if the request could benefit from the crew, start Wave 0 triage. The user does not need to invoke `using-mugiwara` explicitly — the workflow starts itself.
22
+
23
+ **Checkpoint-report presentation.** The banner marks a stage boundary; no wave passes silently. At each boundary the owning crew reports inline — one compact per-crew report: what ran, the result, the evidence pointer. No narration of every tool call. Each wave closes with a short progress summary (done / in-flight / blocked + next handoff). On failure or risk, PAUSE: report the problem and get a continue / retry / escalate decision before proceeding.
24
+
14
25
  1. For each wave, the main thread loads the owning crew member's skill (e.g. `mugiwara-checkpoint` for Wave 4) and performs that role inline: triage, planning, execution, audit, quality, gates, review, closure — all in the main thread.
15
26
  2. Dispatch a subagent ONLY when the work is genuinely parallel or background: an independent `[PARALLEL]` task batch (Zoro's WORKER subagents, Wave 3), parallel fixes (Brook, Wave 8), or a long-running check that would stall the conversation. Subagent results return to the main thread as a report; the main thread summarizes the outcome inline with evidence pointers.
16
27
  3. Crew members NEVER dispatch another crew member. A crew role that must split work returns the split plan to the main thread, which spawns the workers.
@@ -45,7 +56,7 @@ At session start, after context loss, or on any "where were we?" — embody `res
45
56
 
46
57
  ## Wave 0 — Luffy Triage (always first)
47
58
 
48
- 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.
59
+ 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.
49
60
 
50
61
  Alongside triage, read the mode config per `mugiwara-mode`: `.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.
51
62
 
@@ -77,12 +88,12 @@ Never silently work around a blocker. Brook reads this ledger at Wave 8 to decid
77
88
 
78
89
  ## Cleanup
79
90
 
80
- At closure (Wave 9), delete unused intermediate markdown files in `.mugiwara/` — superseded results, review, issues reports, and the per-mission decision log in `logs/`. Keep the plan doc and the closure report.
91
+ At closure (Wave 9), after the terminal step, run the cleanup procedure in `mugiwara-ship`: delete consumed intermediates — superseded results, review, issues reports, the per-mission decision log in `logs/`, and the consumed spec. Keep the plan doc, the closure report, the PR verdict, `config`, and cross-mission state (`logs/lessons.md`, `backup/`, `manifest.json`). List candidates before deleting.
81
92
 
82
93
  ## Rules
83
94
 
84
95
  1. Evidence over claims: no wave passes on assertion. The owning agent runs the checks and shows output.
85
- 2. No wave skipped without the reason recorded in the decision log (`.mugiwara/logs/`).
96
+ 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.
86
97
  3. Heal loop is bounded: Wave 8 → Wave 4, max 3 cycles. After that, escalate to the human with full history.
87
98
  4. Any agent may consult Luffy mid-flight (embody `luffy-orchestrator` inline) for decisions and escalations.
88
99
  5. Wave 7 runs Robin and Jinbe review passes in parallel — both are inline passes over the same diff, or parallel review subagents for large diffs.
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: mugiwara-writing-skills
3
+ description: Use when authoring a new mugiwara skill or revising an existing one. Enforces the skill anatomy (name/description 20-500 chars, when-to-use, process, rationalizations, red flags, verification), the 120-line body ceiling, and progressive disclosure of detail into a references/ file. Meta-skill: governs the other skills.
4
+ ---
5
+
6
+ # Writing Mugiwara Skills
7
+
8
+ ## Skip when
9
+
10
+ - Not authoring or revising a mugiwara skill — plain application code change.
11
+ - Skill change is a one-line description fix with no anatomy impact.
12
+
13
+ A skill is a process workflow the agent runs on cue, not a reference guide. If it reads like a wiki page, it fails. The description decides when the skill loads; the body decides what happens next. Both must justify their size.
14
+
15
+ ## Skill anatomy
16
+
17
+ Every skill is a single `SKILL.md` at `content/skills/<name>/`, plus an optional `references/` folder for pulled-out detail. The name is the directory name; the validator checks that exact match.
18
+
19
+ | Part | Requirement |
20
+ |------|-------------|
21
+ | name | equals the directory name, `mugiwara-<domain>` |
22
+ | description | one "Use when..." sentence, 20-500 chars, loads the right skill and rejects the wrong ones |
23
+ | body | `# title` + sections below, 120 lines max |
24
+ | references/ | overflow detail, linked from the body |
25
+
26
+ ## When to use
27
+
28
+ Use this skill the moment you start authoring a new skill file or restructuring an existing one. Skip it only for edits so small they cannot touch anatomy, limits, or wording.
29
+
30
+ ## Process
31
+
32
+ 1. **Confirm the niche.** Grep `content/skills/` for overlap; a new skill must not duplicate an existing one. Name it `mugiwara-<domain>`.
33
+ 2. **Write the description first.** One "Use when..." sentence naming the trigger, the behavior, and the boundary of what the skill is not for. Target 60-120 chars; the 500-char cap is a ceiling, not a goal.
34
+ 3. **Draft the body as a workflow.** Concrete numbered steps the agent executes, in order, with decisions and branches embedded. Name the skills it reads or dispatches. Use tables for excusable patterns and quick comparisons.
35
+ 4. **Cut to the ceiling.** Body must end at 120 lines or fewer. Section-by-section trim: merge subsections, kill throat-clearing, convert prose to tables. `ponytail` and `caveman` instincts apply — the body is command output, not a report.
36
+ 5. **Disclose progressively.** If a section exceeds roughly 15-20 lines, move it to `references/<topic>.md`, drop a one-line pointer in the body, and keep the pointer actionable (what to read and why).
37
+ 6. **Check the anatomy list.** Each required section present, in order: title, When to use, Process, Rationalizations, Red flags, Verification.
38
+ 7. **Validate.** Run `bun scripts/validate-content.ts --check content/skills/<name>/SKILL.md` and leave it exiting 0.
39
+
40
+ ## Rationalizations
41
+
42
+ | Excuse | Rebuttal |
43
+ |--------|----------|
44
+ | "It's a guide, not a checklist" | A skill the agent cannot execute is decoration. Rewrite every paragraph as a step or a criterion. |
45
+ | "The detail is essential" | Then move it to `references/` and keep the body a decision tree, not a dump. |
46
+ | "More lines mean more coverage" | 120 lines enforce focus. Cover the decision, not the encyclopedia. |
47
+ | "Long description catches more triggers" | A description that matches everything loads on nothing specific and trains the agent to ignore the skill. |
48
+ | "Patterns are the same everywhere, I'll mirror another skill's text" | Wording must be original. Mirror the shape, never the sentences. |
49
+ | "It's fine for now, I'll validate later" | Validation is the last step of the write, not a follow-up task. |
50
+
51
+ ## Red flags
52
+
53
+ - Body over 120 lines or a description outside 20-500 chars.
54
+ - No "Use when..." trigger sentence, or a description that names no boundary.
55
+ - A section that reads as a lecture instead of steps the agent can run.
56
+ - Required sections missing or out of order.
57
+ - Text copied from another skill, superpowers, or agent-skills.
58
+ - A `references/` file that is unreferenced, or a body so crammed it needed none.
59
+ - An unvalidated file reported as done.
60
+
61
+ Any of these: revise the skill, re-run validation, and confirm both before reporting.
62
+
63
+ ## Verification
64
+
65
+ Evidence of a complete skill: the file passes `--check` with exit 0; `wc -l` on the body is at or under 120; the description triggers only its intended cases; every required section is present and original; and any overflow sits in a linked `references/` file.
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 existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, realpathSync, rmSync as rmSync2 } from "node:fs";
4
+ import { existsSync as existsSync6, realpathSync, rmSync as rmSync3 } from "node:fs";
5
5
  import { homedir as homedir2 } from "node:os";
6
- import { join as join7, resolve } from "node:path";
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",
@@ -79,7 +80,9 @@ async function confirm(rl, question) {
79
80
  }
80
81
 
81
82
  // src/targets/claude.ts
82
- import { join } from "node:path";
83
+ import { existsSync, mkdirSync, copyFileSync } from "node:fs";
84
+ import { dirname, join } from "node:path";
85
+ import { fileURLToPath } from "node:url";
83
86
 
84
87
  // src/frontmatter.ts
85
88
  function parseFrontmatter(text) {
@@ -107,6 +110,8 @@ ${body}`;
107
110
  }
108
111
 
109
112
  // src/targets/claude.ts
113
+ var here = dirname(fileURLToPath(import.meta.url));
114
+ var HOOK_SRC = join(here, "..", "..", "hooks", "session-start.ts");
110
115
  var target = {
111
116
  id: "claude",
112
117
  label: "Claude Code",
@@ -126,6 +131,22 @@ var target = {
126
131
  if (data.tools)
127
132
  fm.tools = data.tools;
128
133
  return { relPath: `${data.name}.md`, text: stringifyFrontmatter(fm, body) };
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
+ },
139
+ postInstall({ scope, projectDir, home, dryRun }) {
140
+ const root = scope === "global" ? join(home, ".claude") : join(projectDir, ".claude");
141
+ const hookFile = join(root, "hooks", "session-start.ts");
142
+ if (dryRun)
143
+ return { written: [], notes: [] };
144
+ if (existsSync(HOOK_SRC) && !existsSync(hookFile)) {
145
+ mkdirSync(dirname(hookFile), { recursive: true });
146
+ copyFileSync(HOOK_SRC, hookFile);
147
+ return { written: [hookFile], notes: [] };
148
+ }
149
+ return { written: [], notes: [] };
129
150
  }
130
151
  };
131
152
 
@@ -150,6 +171,10 @@ var target2 = {
150
171
  if (data.tools)
151
172
  fm.tools = data.tools;
152
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");
153
178
  }
154
179
  };
155
180
 
@@ -174,18 +199,23 @@ var target3 = {
174
199
  relPath: `${data.name}.md`,
175
200
  text: stringifyFrontmatter({ name: data.name, description: data.description }, body)
176
201
  };
202
+ },
203
+ refsDir(_opts, skillName) {
204
+ return join3(_opts.projectDir, ".mugiwara", "refs", skillName);
177
205
  }
178
206
  };
179
207
 
180
208
  // src/targets/generic.ts
181
- import { existsSync, writeFileSync } from "node:fs";
209
+ import { existsSync as existsSync2, writeFileSync } from "node:fs";
182
210
  import { join as join4 } from "node:path";
183
211
  function makeGeneric(opts) {
184
- const { id, label, rulesDir, bootstrapFile, bootstrapPointer } = opts;
212
+ const { id, label, rulesDir, bootstrapFile, bootstrapPointer, tier = bootstrapPointer ? 2 : 3 } = opts;
213
+ const stubOnly = tier === 3;
185
214
  return {
186
215
  id,
187
216
  label,
188
217
  native: false,
218
+ tier,
189
219
  paths({ scope, projectDir }) {
190
220
  if (scope === "global")
191
221
  throw new Error(`${label} supports project scope only`);
@@ -193,6 +223,27 @@ function makeGeneric(opts) {
193
223
  return { skillsDir: dir, agentsDir: dir };
194
224
  },
195
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;
196
247
  return { relPath: `${data.name}.md`, text: `# ${data.name}
197
248
 
198
249
  > ${data.description}
@@ -200,6 +251,16 @@ function makeGeneric(opts) {
200
251
  ${body}` };
201
252
  },
202
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
+ }
203
264
  return { relPath: `agent-${data.name}.md`, text: `# Agent: ${data.name}
204
265
 
205
266
  > ${data.description}
@@ -208,13 +269,27 @@ Skills used: ${data.skills ?? ""}
208
269
 
209
270
  ${body}` };
210
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
+ },
211
286
  postInstall({ projectDir, dryRun }) {
212
287
  if (!bootstrapFile)
213
288
  return { written: [], notes: [] };
214
289
  const notes = [];
215
290
  const written = [];
216
291
  const file = join4(projectDir, bootstrapFile);
217
- if (!existsSync(file)) {
292
+ if (!existsSync2(file)) {
218
293
  if (!dryRun)
219
294
  writeFileSync(file, `${bootstrapPointer}
220
295
  `);
@@ -233,7 +308,7 @@ var target4 = makeGeneric({
233
308
  label: "Gemini",
234
309
  rulesDir: ".gemini/mugiwara",
235
310
  bootstrapFile: "GEMINI.md",
236
- bootstrapPointer: "Mugiwara crew installed in .gemini/mugiwara/ — read .gemini/mugiwara/mugiwara-workflow.md to run the pipeline."
311
+ bootstrapPointer: "Mugiwara crew installed in .gemini/mugiwara/ — read .gemini/mugiwara/mugiwara-workflow.md to run the pipeline inline in the main conversation."
237
312
  });
238
313
 
239
314
  // src/targets/codex.ts
@@ -242,7 +317,7 @@ var target5 = makeGeneric({
242
317
  label: "Codex",
243
318
  rulesDir: ".codex/mugiwara",
244
319
  bootstrapFile: "AGENTS.md",
245
- bootstrapPointer: "Mugiwara crew installed in .codex/mugiwara/ — read .codex/mugiwara/mugiwara-workflow.md to run the pipeline."
320
+ bootstrapPointer: "Mugiwara crew installed in .codex/mugiwara/ — read .codex/mugiwara/mugiwara-workflow.md to run the pipeline inline in the main conversation."
246
321
  });
247
322
 
248
323
  // src/targets/windsurf.ts
@@ -273,7 +348,8 @@ var target8 = makeGeneric({
273
348
  "instructions": [
274
349
  ".kilo/rules/*.md"
275
350
  ]
276
- }`
351
+ }`,
352
+ tier: 3
277
353
  });
278
354
 
279
355
  // src/targets/antigravity.ts
@@ -290,24 +366,30 @@ var targets = { claude: target, opencode: target2, copilot: target3, gemini: tar
290
366
  var TARGET_IDS = Object.keys(targets);
291
367
 
292
368
  // src/installer.ts
293
- import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, writeFileSync as writeFileSync2, copyFileSync, rmSync } from "node:fs";
294
- import { dirname, join as join5 } from "node:path";
369
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, writeFileSync as writeFileSync2, copyFileSync as copyFileSync2, rmSync } from "node:fs";
370
+ import { dirname as dirname2, join as join5 } from "node:path";
295
371
  import { homedir } from "node:os";
296
372
  var CONTENT_DIR = join5(import.meta.dirname, "..", "content");
297
- var pkg = JSON.parse(readFileSync(join5(import.meta.dirname, "..", "package.json"), "utf8"));
373
+ var pkg = JSON.parse(readFileSync2(join5(import.meta.dirname, "..", "package.json"), "utf8"));
298
374
  var VERSION = pkg.version;
299
375
  function collectContent() {
300
376
  const skillNames = readdirSync(join5(CONTENT_DIR, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
301
377
  const skills = skillNames.map((name) => {
302
- const { data, body } = parseFrontmatter(readFileSync(join5(CONTENT_DIR, "skills", name, "SKILL.md"), "utf8"));
303
- return { name, data, body };
378
+ const { data, body } = parseFrontmatter(readFileSync2(join5(CONTENT_DIR, "skills", name, "SKILL.md"), "utf8"));
379
+ return { name, data, body, refs: collectRefs(join5(CONTENT_DIR, "skills", name)) };
304
380
  });
305
381
  const agents = readdirSync(join5(CONTENT_DIR, "agents")).filter((f) => f.endsWith(".md")).map((f) => {
306
- const { data, body } = parseFrontmatter(readFileSync(join5(CONTENT_DIR, "agents", f), "utf8"));
307
- return { name: f.replace(/\.md$/, ""), data, body };
382
+ const { data, body } = parseFrontmatter(readFileSync2(join5(CONTENT_DIR, "agents", f), "utf8"));
383
+ return { name: f.replace(/\.md$/, ""), data, body, refs: [] };
308
384
  });
309
385
  return { skills, agents };
310
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
+ }
311
393
  function installTo(target10, opts) {
312
394
  const { scope, projectDir, dryRun = false, force = false } = opts;
313
395
  const home = opts.home ?? homedir();
@@ -316,8 +398,8 @@ function installTo(target10, opts) {
316
398
  const backupRoot = join5(scope === "global" ? home : projectDir, ".mugiwara");
317
399
  const result = { written: [], skipped: [], backedUp: [], notes: [] };
318
400
  const writeOne = (absPath, text) => {
319
- if (existsSync2(absPath)) {
320
- if (readFileSync(absPath, "utf8") === text) {
401
+ if (existsSync3(absPath)) {
402
+ if (readFileSync2(absPath, "utf8") === text) {
321
403
  result.skipped.push(absPath);
322
404
  return;
323
405
  }
@@ -329,13 +411,13 @@ function installTo(target10, opts) {
329
411
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
330
412
  const backupFile = join5(backupRoot, "backup", ts, absPath.replace(/[^a-zA-Z0-9]+/g, "_"));
331
413
  if (!dryRun) {
332
- mkdirSync(dirname(backupFile), { recursive: true });
333
- copyFileSync(absPath, backupFile);
414
+ mkdirSync2(dirname2(backupFile), { recursive: true });
415
+ copyFileSync2(absPath, backupFile);
334
416
  }
335
417
  result.backedUp.push(absPath);
336
418
  }
337
419
  if (!dryRun) {
338
- mkdirSync(dirname(absPath), { recursive: true });
420
+ mkdirSync2(dirname2(absPath), { recursive: true });
339
421
  writeFileSync2(absPath, text);
340
422
  }
341
423
  result.written.push(absPath);
@@ -344,11 +426,26 @@ function installTo(target10, opts) {
344
426
  const out = target10.transformSkill(s.data, s.body);
345
427
  if (out)
346
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
+ }
347
439
  }
348
440
  for (const a of agents) {
349
441
  const out = target10.transformAgent(a.data, a.body);
350
442
  if (out)
351
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
+ }
352
449
  }
353
450
  if (target10.postInstall) {
354
451
  const post = target10.postInstall({ scope, projectDir, home, dryRun, files: result.written });
@@ -360,7 +457,7 @@ function installTo(target10, opts) {
360
457
  function removeInstalled(manifest, { dryRun = false } = {}) {
361
458
  const removed = [];
362
459
  for (const f of manifest.files) {
363
- if (existsSync2(f)) {
460
+ if (existsSync3(f)) {
364
461
  if (!dryRun)
365
462
  rmSync(f);
366
463
  removed.push(f);
@@ -368,10 +465,10 @@ function removeInstalled(manifest, { dryRun = false } = {}) {
368
465
  }
369
466
  if (!dryRun) {
370
467
  for (const f of manifest.files) {
371
- let d = dirname(f);
372
- while (existsSync2(d) && readdirSync(d).length === 0) {
468
+ let d = dirname2(f);
469
+ while (existsSync3(d) && readdirSync(d).length === 0) {
373
470
  rmSync(d, { recursive: true });
374
- const parent = dirname(d);
471
+ const parent = dirname2(d);
375
472
  if (parent === d)
376
473
  break;
377
474
  d = parent;
@@ -382,20 +479,52 @@ function removeInstalled(manifest, { dryRun = false } = {}) {
382
479
  }
383
480
 
384
481
  // src/manifest.ts
385
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
386
- import { dirname as dirname2, join as join6 } from "node:path";
482
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
483
+ import { dirname as dirname3, join as join6 } from "node:path";
387
484
  function manifestPath({ scope, projectDir, home }) {
388
485
  return scope === "global" ? join6(home, ".mugiwara", "manifest.json") : join6(projectDir, ".mugiwara", "manifest.json");
389
486
  }
390
487
  function readManifest(file) {
391
- return existsSync3(file) ? JSON.parse(readFileSync2(file, "utf8")) : null;
488
+ return existsSync4(file) ? JSON.parse(readFileSync3(file, "utf8")) : null;
392
489
  }
393
490
  function writeManifest(file, data) {
394
- mkdirSync2(dirname2(file), { recursive: true });
491
+ mkdirSync3(dirname3(file), { recursive: true });
395
492
  writeFileSync3(file, JSON.stringify(data, null, 2) + `
396
493
  `);
397
494
  }
398
495
 
496
+ // src/mission.ts
497
+ import { existsSync as existsSync5, rmSync as rmSync2 } from "node:fs";
498
+ import { join as join7 } from "node:path";
499
+ function resetMission(projectDir, keepLogs) {
500
+ const root = join7(projectDir, ".mugiwara");
501
+ if (!existsSync5(root))
502
+ return { removed: [], kept: [] };
503
+ const removed = [];
504
+ const kept = [];
505
+ for (const dir of ["spec", "plans", "results", "review", "issues"]) {
506
+ const p = join7(root, dir);
507
+ if (existsSync5(p)) {
508
+ rmSync2(p, { recursive: true, force: true });
509
+ removed.push(dir);
510
+ }
511
+ }
512
+ if (!keepLogs) {
513
+ const p = join7(root, "logs");
514
+ if (existsSync5(p)) {
515
+ rmSync2(p, { recursive: true, force: true });
516
+ removed.push("logs");
517
+ }
518
+ } else if (existsSync5(join7(root, "logs"))) {
519
+ kept.push("logs");
520
+ }
521
+ for (const f of ["config", "manifest.json", "backup"]) {
522
+ if (existsSync5(join7(root, f)))
523
+ kept.push(f);
524
+ }
525
+ return { removed, kept };
526
+ }
527
+
399
528
  // src/cli.ts
400
529
  var str = (v) => typeof v === "string" ? v : undefined;
401
530
  var flag = (v) => v === true;
@@ -416,12 +545,22 @@ async function run(argv) {
416
545
  return uninstall(flags);
417
546
  case "list":
418
547
  return list(flags);
419
- case "skills":
420
- return skills();
548
+ case "reset":
549
+ return resetCmd(flags);
421
550
  default:
422
551
  throw new Error(`Unknown command: ${command}`);
423
552
  }
424
553
  }
554
+ function resetCmd(flags) {
555
+ const projectDir = resolve(str(flags.project) ?? process.cwd());
556
+ const { removed, kept } = resetMission(projectDir, flag(flags.keepLogs));
557
+ if (removed.length)
558
+ console.log(`removed: ${removed.join(", ")}`);
559
+ else
560
+ console.log("nothing to remove.");
561
+ if (kept.length)
562
+ console.log(`kept: ${kept.join(", ")}`);
563
+ }
425
564
  async function resolveOptions(flags) {
426
565
  const interactive = !flag(flags.yes);
427
566
  const rl = interactive ? createRl() : null;
@@ -433,7 +572,7 @@ async function resolveOptions(flags) {
433
572
  scope = await choose(rl, "Install scope?", ["global (user-wide)", "project (this repo)"]) === 0 ? "global" : "project";
434
573
  }
435
574
  const projectDir = resolve(str(flags.project) ?? process.cwd());
436
- if (scope === "project" && !existsSync4(projectDir))
575
+ if (scope === "project" && !existsSync6(projectDir))
437
576
  throw new Error(`Project dir not found: ${projectDir}`);
438
577
  let targetIds = str(flags.target)?.split(",").map((s) => s.trim()) ?? null;
439
578
  if (targetIds && targetIds.includes("all"))
@@ -517,7 +656,7 @@ async function uninstall(flags) {
517
656
  }
518
657
  const removed = removeInstalled(manifest, { dryRun: flag(flags.dryRun) });
519
658
  if (!flag(flags.dryRun))
520
- rmSync2(file);
659
+ rmSync3(file);
521
660
  console.log(`OK removed ${removed.length} files`);
522
661
  }
523
662
  function list(flags) {
@@ -537,22 +676,6 @@ function list(flags) {
537
676
  if (!found)
538
677
  console.log("No mugiwara installation found.");
539
678
  }
540
- function skills() {
541
- const dir = join7(CONTENT_DIR, "skills");
542
- const names = readdirSync2(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
543
- const rows = names.map((name) => {
544
- const { data } = parseFrontmatter(readFileSync3(join7(dir, name, "SKILL.md"), "utf8"));
545
- return [name, data.description ?? ""];
546
- });
547
- const w = Math.max(...rows.map((r) => r[0].length)) + 2;
548
- console.log(`mugiwara ${VERSION} — ${rows.length} skills (agentskills.io format):
549
- `);
550
- for (const [name, description] of rows)
551
- console.log(` ${name.padEnd(w)}${description}`);
552
- console.log(`
553
- Install skills into any agent via skills.sh:
554
- npx skills add ionivetech/mugiwara`);
555
- }
556
679
  function help() {
557
680
  console.log(`mugiwara ${VERSION} — the Straw Hat crew for AI agents
558
681
 
@@ -561,7 +684,7 @@ Usage:
561
684
  mugiwara update replace existing files (backs up differences first)
562
685
  mugiwara uninstall remove installed files via manifest
563
686
  mugiwara list show installations
564
- mugiwara skills list installable skills (agentskills.io)
687
+ mugiwara reset wipe mission state (spec/plans/results/review/issues[/logs])
565
688
  mugiwara --help this help
566
689
  mugiwara --version print version
567
690
 
@@ -571,7 +694,8 @@ Flags:
571
694
  --target <ids|all> comma-separated: ${TARGET_IDS.join(", ")}
572
695
  --yes, -y non-interactive (needs --global/--project, --target)
573
696
  --force overwrite differing files (with backup)
574
- --dry-run print actions without writing`);
697
+ --dry-run print actions without writing
698
+ --keep-logs with reset: keep .mugiwara/logs (lessons ledger survives)`);
575
699
  }
576
700
  var entry = process.argv[1] !== undefined ? resolve(process.argv[1]) : undefined;
577
701
  if (entry !== undefined) {
@@ -16,7 +16,7 @@ markdown rule files everywhere else.
16
16
 
17
17
  Native targets (Claude Code, opencode, Copilot) register the 15 agents directly.
18
18
  Rule-based targets (Gemini, Codex, Cursor, Windsurf, Cline, Kilo, Antigravity)
19
- get the same 25 skills as markdown rules plus a bootstrap pointer, so the crew
19
+ get the same 32 skills as markdown rules plus a bootstrap pointer, so the crew
20
20
  is still steered even where subagents don't exist.
21
21
 
22
22
  ## Pick your mode
@@ -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 straight to
47
- execution.
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 25 skills. No project-type selection —
47
+ Every install gets all 15 agents and all 32 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 25 techniques, or
50
+ See [skills.md](skills.md) for the 32 techniques, or
51
51
  [workflow.md](workflow.md) for the pipeline.
@@ -20,19 +20,24 @@ npx @ionivetech/mugiwara@latest --global --target claude --yes
20
20
  npx @ionivetech/mugiwara@latest --project ./my-app --target claude --yes
21
21
  ```
22
22
 
23
+ **Update** — re-install from the marketplace (or `mugiwara update` via CLI).
24
+
25
+ **Uninstall** — `/plugin uninstall mugiwara`, or `mugiwara uninstall` via CLI.
26
+
23
27
  ## What you get
24
28
 
25
- - 25 skills in `~/.claude/skills/` (global) or `.claude/skills/` (project).
29
+ - 32 skills in `~/.claude/skills/` (global) or `.claude/skills/` (project).
26
30
  - 15 agents in `~/.claude/agents/` or `.claude/agents/`.
27
- - A SessionStart hook that announces the crew.
31
+ - A SessionStart hook that announces the crew and auto-activates the workflow —
32
+ a non-trivial request runs the pipeline by itself. `/using-mugiwara` is an
33
+ optional explicit router if you want to hand-route a mission.
28
34
 
29
35
  ## Use it
30
36
 
31
37
  ```
32
- > use mugiwara
33
38
  > add dark mode to the settings page
34
39
  ```
35
40
 
36
41
  The crew runs inline in your main conversation; subagents only for parallel
37
42
  batches. At closure the crew pushes the branch and hands you the PR verdict
38
- file — you open the PR.
43
+ file with a ready PR summary block — you open the PR, in every mode.
@@ -13,9 +13,11 @@ Or via the CLI:
13
13
  npx @ionivetech/mugiwara@latest --project ./my-app --target codex --yes
14
14
  ```
15
15
 
16
+ **Update** — `codex plugin update mugiwara`. **Uninstall** — `codex plugin remove mugiwara`.
17
+
16
18
  ## What you get
17
19
 
18
- - 25 skills as markdown rules in `.codex/mugiwara/`.
20
+ - 32 skills as markdown rules in `.codex/mugiwara/`.
19
21
  - An `AGENTS.md` bootstrap pointer (created if missing).
20
22
 
21
23
  ## Notes