@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.
- package/.opencode/commands/mugiwara-execute.md +11 -0
- package/.opencode/commands/mugiwara-heal.md +11 -0
- package/.opencode/commands/mugiwara-mode.md +6 -0
- package/.opencode/commands/mugiwara-plan.md +15 -0
- package/.opencode/commands/mugiwara-review.md +11 -0
- package/.opencode/commands/mugiwara-security.md +11 -0
- package/.opencode/commands/mugiwara-ship.md +11 -0
- package/.opencode/commands/mugiwara.md +11 -0
- package/.opencode/plugins/mugiwara.mjs +126 -7
- package/README.md +338 -355
- package/content/agents/brook-healing.md +2 -2
- package/content/agents/luffy-orchestrator.md +3 -2
- package/content/agents/robin-reviewer.md +1 -1
- package/content/agents/skeptic-verifier.md +1 -1
- package/content/agents/using-mugiwara.md +5 -1
- package/content/agents/usopp-brainstorm.md +1 -1
- package/content/agents/zoro-execution.md +1 -1
- package/content/skills/mugiwara-agent-security/SKILL.md +5 -0
- package/content/skills/mugiwara-api-and-interface-design/SKILL.md +92 -0
- package/content/skills/mugiwara-backend/SKILL.md +5 -0
- package/content/skills/mugiwara-brainstorm/SKILL.md +5 -0
- package/content/skills/mugiwara-checkpoint/SKILL.md +5 -0
- package/content/skills/mugiwara-context-engineering/SKILL.md +64 -0
- package/content/skills/mugiwara-deprecation/SKILL.md +5 -0
- package/content/skills/mugiwara-doubt-driven-development/SKILL.md +70 -0
- package/content/skills/mugiwara-dynamic-workflow/SKILL.md +5 -0
- package/content/skills/mugiwara-eval/SKILL.md +5 -0
- package/content/skills/mugiwara-execution/SKILL.md +9 -0
- package/content/skills/mugiwara-frontend/SKILL.md +61 -59
- package/content/skills/mugiwara-frontend/references/checklist.md +37 -0
- package/content/skills/mugiwara-gates/SKILL.md +9 -0
- package/content/skills/mugiwara-git/SKILL.md +5 -0
- package/content/skills/mugiwara-git-worktrees/SKILL.md +67 -0
- package/content/skills/mugiwara-healing/SKILL.md +17 -0
- package/content/skills/mugiwara-lessons/SKILL.md +5 -0
- package/content/skills/mugiwara-mode/SKILL.md +18 -4
- package/content/skills/mugiwara-observability/SKILL.md +5 -0
- package/content/skills/mugiwara-orchestration/SKILL.md +32 -1
- package/content/skills/mugiwara-planning/SKILL.md +25 -26
- package/content/skills/mugiwara-pr/SKILL.md +22 -6
- package/content/skills/mugiwara-quality/SKILL.md +15 -0
- package/content/skills/mugiwara-resume/SKILL.md +5 -0
- package/content/skills/mugiwara-review/SKILL.md +5 -0
- package/content/skills/mugiwara-security/SKILL.md +51 -14
- package/content/skills/mugiwara-ship/SKILL.md +29 -1
- package/content/skills/mugiwara-systematic-debugging/SKILL.md +82 -0
- package/content/skills/mugiwara-test-driven-development/SKILL.md +89 -0
- package/content/skills/mugiwara-testcases/SKILL.md +5 -0
- package/content/skills/mugiwara-workflow/SKILL.md +14 -3
- package/content/skills/mugiwara-writing-skills/SKILL.md +65 -0
- package/dist/mugiwara.js +175 -51
- package/docs/adoption-guide.md +3 -3
- package/docs/agents.md +2 -2
- package/docs/claude-setup.md +9 -4
- package/docs/codex-setup.md +3 -1
- package/docs/comparison.md +166 -44
- package/docs/config.md +53 -0
- package/docs/copilot-setup.md +3 -1
- package/docs/cursor-setup.md +3 -1
- package/docs/developer-onboarding.md +17 -13
- package/docs/enforcement.md +38 -0
- package/docs/execution-model.md +33 -0
- package/docs/gemini-setup.md +4 -1
- package/docs/getting-started.md +16 -4
- package/docs/index.md +14 -3
- package/docs/lanes.md +40 -0
- package/docs/modes.md +22 -12
- package/docs/opencode-setup.md +9 -2
- package/docs/pr-summary.md +54 -0
- package/docs/skill-anatomy.md +16 -6
- package/docs/skills.md +17 -5
- package/docs/troubleshooting.md +91 -0
- package/docs/windsurf-setup.md +3 -1
- 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/hooks/hooks.json +15 -0
- package/hooks/session-start.ts +8 -0
- package/package.json +3 -1
- package/src/args.ts +2 -1
- package/src/cli.ts +16 -20
- package/src/installer.ts +31 -3
- package/src/mission.ts +25 -0
- package/src/targets/claude.ts +22 -1
- package/src/targets/codex.ts +1 -1
- package/src/targets/copilot.ts +4 -0
- package/src/targets/gemini.ts +1 -1
- package/src/targets/generic.ts +33 -1
- package/src/targets/kilo.ts +1 -0
- package/src/targets/opencode.ts +4 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Execute an approved mugiwara plan as Zoro (execution stage)
|
|
3
|
+
---
|
|
4
|
+
Execute the approved plan as Zoro, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skill: `mugiwara-execution`.
|
|
7
|
+
2. Read the existing plan from `.mugiwara/plans/` — that file is the bridge, never re-plan.
|
|
8
|
+
3. Open a todo list, run tasks sequentially inline; dispatch [PARALLEL] batches to worker subagents only.
|
|
9
|
+
4. Commit per logical task and verify every acceptance criterion with evidence in `.mugiwara/results/`.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-execution for the wave-structured protocol.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Heal earlier-wave failures as Brook (healing stage, after review/security findings)
|
|
3
|
+
---
|
|
4
|
+
Heal failures as Brook, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skill: `mugiwara-healing`.
|
|
7
|
+
2. Read the `.mugiwara/issues` ledger first — stop-the-line triage per failure, never fix blind.
|
|
8
|
+
3. Prove-it before fixing: reproduce or verify the failure from `.mugiwara/results/` evidence.
|
|
9
|
+
4. Apply minimal root-cause fixes, update the ledger with evidence.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-healing for the triage protocol.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Plan a mugiwara mission as Nami (planning stage)
|
|
3
|
+
---
|
|
4
|
+
Plan the mission as Nami, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skill: `mugiwara-planning`.
|
|
7
|
+
2. Classify mission size, interview first, scan full context, write the scaled Quick/Standard/Full plan.
|
|
8
|
+
3. Embody the Nami crew role inline — never Task-dispatch.
|
|
9
|
+
4. Persist the plan to `.mugiwara/plans/`; later stages read it from there as the bridge.
|
|
10
|
+
|
|
11
|
+
Spec input: read `.mugiwara/spec/YYYY-MM-DD-<mission>.md`. If it is empty or
|
|
12
|
+
missing, write the spec bridge from the user's request first (goal, acceptance
|
|
13
|
+
criteria, constraints) before planning — never plan from an empty spec.
|
|
14
|
+
|
|
15
|
+
See skills/mugiwara-planning for the full template and wave structure.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review the mission diff as Robin (review stage, after gates pass)
|
|
3
|
+
---
|
|
4
|
+
Review the diff adversarially as Robin, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skill: `mugiwara-review`.
|
|
7
|
+
2. Run the doubt-driven review: breaking-change damage map first, five-axis review, severity criteria, dispute hierarchy.
|
|
8
|
+
3. Use `.mugiwara/results/` evidence and `.mugiwara/review/` findings as the bridge.
|
|
9
|
+
4. Write findings to `.mugiwara/review/`; escalate after 3 cycles. Never fixes code.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-review for the full protocol.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Security-audit the diff as Jinbe (security stage, can run concurrent with review)
|
|
3
|
+
---
|
|
4
|
+
Security-audit the diff as Jinbe, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skill: `mugiwara-security`.
|
|
7
|
+
2. STRIDE first, OWASP Top 10 mapping, then the full checklist in order: secrets, injection, authn/authz, data exposure, dependencies, deserialization, crypto.
|
|
8
|
+
3. Use `.mugiwara/results/` evidence and `.mugiwara/review/` findings as the bridge.
|
|
9
|
+
4. Write findings to `.mugiwara/review/` with CVSS-style severity. Never fixes code.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-security for the full checklist.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Close the mission as Luffy (closure + ship stage, at mission end)
|
|
3
|
+
---
|
|
4
|
+
Close the mission as Luffy, inline in the main conversation:
|
|
5
|
+
|
|
6
|
+
1. Load the skills: `mugiwara-orchestration` + `mugiwara-ship`.
|
|
7
|
+
2. Run the ship gate: pre-launch checklist, feature flags, staged rollout, mandatory rollback plan — binary GO/NO-GO with evidence.
|
|
8
|
+
3. Bridge on `.mugiwara/plans/` (promise) vs `.mugiwara/results/` (evidence) for the Definition-of-Done verdict.
|
|
9
|
+
4. Close the mission: lessons ledger update, then `/mugiwara-pr` for push + PR material.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-ship for the gate and skills/mugiwara-orchestration for closure.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run the mugiwara crew workflow for a task
|
|
3
|
+
---
|
|
4
|
+
Mugiwara workflow:
|
|
5
|
+
|
|
6
|
+
1. The crew runs inline in the main conversation. Start any non-trivial task through `using-mugiwara` (embodied inline) to route to the right crew member.
|
|
7
|
+
2. The pipeline flows: Luffy triage -> Usopp brainstorm (when needed) -> Nami planning -> Zoro execution -> Chopper checkpoint -> Sanji quality -> Franky gates -> Robin/Jinbe review -> Brook healing -> Luffy closure.
|
|
8
|
+
3. Subagents are used only for parallel work (Zoro's [PARALLEL] workers, Robin + Jinbe concurrent review, independent re-run checks).
|
|
9
|
+
4. Switch runtime mode with `/mugiwara-mode` (guided | semi | auto). Default is guided.
|
|
10
|
+
|
|
11
|
+
See skills/mugiwara-workflow for the full pipeline.
|
|
@@ -9,18 +9,46 @@
|
|
|
9
9
|
// or from the git repo:
|
|
10
10
|
// { "plugin": ["mugiwara@git+https://github.com/ionivetech/mugiwara.git"] }
|
|
11
11
|
|
|
12
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { existsSync, readdirSync, readFileSync, mkdirSync, writeFileSync, appendFileSync, lstatSync, renameSync } from 'node:fs';
|
|
13
|
+
import { homedir, tmpdir } from 'node:os';
|
|
13
14
|
import { dirname, join } from 'node:path';
|
|
14
15
|
import { fileURLToPath } from 'node:url';
|
|
15
16
|
|
|
16
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
|
|
19
|
+
const VALID_MODES = new Set(['guided', 'semi', 'auto']);
|
|
20
|
+
|
|
21
|
+
// Read the runtime mode: `.mugiwara/config` (project) wins over
|
|
22
|
+
// `~/.mugiwara/config` (global) per key; a missing key or a value outside the
|
|
23
|
+
// enum falls back to `guided`. Never creates files on read.
|
|
24
|
+
export function readMode({ projectDir = process.cwd(), home = homedir() } = {}) {
|
|
25
|
+
const readValue = (dir) => {
|
|
26
|
+
const file = join(dir, '.mugiwara', 'config');
|
|
27
|
+
if (!existsSync(file)) return undefined;
|
|
28
|
+
for (const line of readFileSync(file, 'utf8').split(/\r?\n/)) {
|
|
29
|
+
const t = line.trim();
|
|
30
|
+
if (!t || t.startsWith('#')) continue;
|
|
31
|
+
const [k, v] = t.split('=').map((s) => s.trim());
|
|
32
|
+
if (k !== 'mode') continue;
|
|
33
|
+
return VALID_MODES.has(v) ? v : 'INVALID';
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
};
|
|
37
|
+
const proj = readValue(projectDir);
|
|
38
|
+
if (proj === 'INVALID') return 'guided';
|
|
39
|
+
if (proj) return proj;
|
|
40
|
+
const glob = readValue(home);
|
|
41
|
+
if (glob === 'INVALID') return 'guided';
|
|
42
|
+
if (glob) return glob;
|
|
43
|
+
return 'guided';
|
|
44
|
+
}
|
|
45
|
+
|
|
18
46
|
const contentDir = join(__dirname, '..', '..', 'content');
|
|
19
47
|
const skillsDir = join(contentDir, 'skills');
|
|
20
48
|
const agentsDir = join(contentDir, 'agents');
|
|
21
49
|
|
|
22
50
|
const ANNOUNCE =
|
|
23
|
-
"Mugiwara crew available.
|
|
51
|
+
"Mugiwara crew available. The workflow auto-activates for non-trivial requests — no need to call `/using-mugiwara` at session start (it remains an optional router). Run the crew pipeline inline in the main conversation: embody ONE crew role at a time using its skill, wait for its report, then move to the next. Never Task-dispatch a crew member — the crew runs in the main thread; subagents only for [PARALLEL] task batches, concurrent review/security, and independent re-run checks. Progress shows as checkpoint reports at wave/stage boundaries, pausing on failure or risk. Switch mode with `/mugiwara-mode` (guided|semi|auto). See skills/mugiwara-workflow.";
|
|
24
52
|
|
|
25
53
|
// OpenCode per-agent tuning. Content stays portable markdown; these knobs
|
|
26
54
|
// (color, temperature, permission, steps) are opencode-only.
|
|
@@ -72,12 +100,78 @@ function readAgents() {
|
|
|
72
100
|
continue;
|
|
73
101
|
}
|
|
74
102
|
if (!parsed.data.description || !parsed.body) continue;
|
|
75
|
-
agents[name] = { description: parsed.data.description, mode: '
|
|
103
|
+
agents[name] = { description: parsed.data.description, mode: 'all', prompt: parsed.body };
|
|
76
104
|
if (CREW[name]) agents[name] = { ...agents[name], ...CREW[name] };
|
|
77
105
|
}
|
|
78
106
|
return agents;
|
|
79
107
|
}
|
|
80
108
|
|
|
109
|
+
// Parse a user prompt for a mugiwara mode change. Returns the new mode or null.
|
|
110
|
+
// Mirrors the caveman plugin pattern: opencode expands `/mugiwara-mode <level>`
|
|
111
|
+
// into the command file's body ("Set mugiwara mode: <level>...") before
|
|
112
|
+
// chat.message fires, so parse the template's first line too. The slash command
|
|
113
|
+
// and natural-language phrase must sit at the START of the prompt — a bare
|
|
114
|
+
// mention mid-message (pasted untrusted content) never flips autonomy.
|
|
115
|
+
export function parseModeChange(promptRaw) {
|
|
116
|
+
if (typeof promptRaw !== 'string') return null;
|
|
117
|
+
let prompt = promptRaw.trim();
|
|
118
|
+
const wrapped = /^(["'`])([\s\S]*)\1$/.exec(prompt);
|
|
119
|
+
if (wrapped) prompt = wrapped[2].trim();
|
|
120
|
+
prompt = prompt.toLowerCase();
|
|
121
|
+
if (!prompt) return null;
|
|
122
|
+
|
|
123
|
+
const tpl = /^set mugiwara mode:[ \t]*(\S*)/.exec(prompt);
|
|
124
|
+
if (tpl && VALID_MODES.has(tpl[1])) return tpl[1];
|
|
125
|
+
|
|
126
|
+
const slash = /^\/(mugiwara[-\s]?)mode[ \t]+(\S*)/.exec(prompt);
|
|
127
|
+
if (slash && VALID_MODES.has(slash[2])) return slash[2];
|
|
128
|
+
|
|
129
|
+
const natural = /^mugiwara mode[ \t]+(\S*)/.exec(prompt);
|
|
130
|
+
if (natural && VALID_MODES.has(natural[1])) return natural[1];
|
|
131
|
+
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Refuse to follow a symlinked .mugiwara/config — a malicious repo could point
|
|
136
|
+
// it at ~/.bashrc and any mode flip would overwrite the target.
|
|
137
|
+
function assertNotSymlink(file) {
|
|
138
|
+
if (!existsSync(file)) return;
|
|
139
|
+
try {
|
|
140
|
+
const st = lstatSync(file);
|
|
141
|
+
if (st.isSymbolicLink()) throw new Error(`refusing to follow symlink: ${file}`);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (e.code === 'ENOENT') return;
|
|
144
|
+
throw e;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Write `.mugiwara/config` (project) and append a decision-log row.
|
|
149
|
+
// Atomic: write a temp file next to the target, then rename over it, so a
|
|
150
|
+
// crash mid-write never truncates the config (keeps branch/commit keys).
|
|
151
|
+
export function applyModeChange(mode, { projectDir = process.cwd(), home = homedir() } = {}) {
|
|
152
|
+
if (!VALID_MODES.has(mode)) return;
|
|
153
|
+
const dir = join(projectDir, '.mugiwara');
|
|
154
|
+
const file = join(dir, 'config');
|
|
155
|
+
assertNotSymlink(file);
|
|
156
|
+
mkdirSync(dir, { recursive: true });
|
|
157
|
+
const lines = [];
|
|
158
|
+
if (existsSync(file)) {
|
|
159
|
+
for (const line of readFileSync(file, 'utf8').split(/\r?\n/)) {
|
|
160
|
+
const t = line.trim();
|
|
161
|
+
if (t.startsWith('mode=')) continue;
|
|
162
|
+
lines.push(line);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
lines.push(`mode=${mode}`);
|
|
166
|
+
const body = lines.filter((l, i) => !(l === '' && (i === lines.length - 1 || i === 0))).join('\n') + '\n';
|
|
167
|
+
const tmp = join(tmpdir(), `mugiwara-config-${process.pid}-${Date.now()}.tmp`);
|
|
168
|
+
writeFileSync(tmp, body);
|
|
169
|
+
renameSync(tmp, file);
|
|
170
|
+
const log = join(dir, 'logs', `${new Date().toISOString().slice(0, 10)}-mode-flip.md`);
|
|
171
|
+
mkdirSync(dirname(log), { recursive: true });
|
|
172
|
+
appendFileSync(log, `| ${new Date().toISOString()} | mode flip | guided/semi/auto -> ${mode} | user |\n`);
|
|
173
|
+
}
|
|
174
|
+
|
|
81
175
|
export default async () => ({
|
|
82
176
|
config: (config) => {
|
|
83
177
|
config.skills = config.skills || {};
|
|
@@ -91,12 +185,37 @@ export default async () => ({
|
|
|
91
185
|
}
|
|
92
186
|
},
|
|
93
187
|
|
|
188
|
+
// Intercept user messages to detect `/mugiwara-mode` and natural-language
|
|
189
|
+
// mode toggles; write `.mugiwara/config` so the next wave reads the new level.
|
|
190
|
+
'chat.message': async (_input, output) => {
|
|
191
|
+
if (!output) return;
|
|
192
|
+
if (typeof output === 'string') {
|
|
193
|
+
const change = parseModeChange(output);
|
|
194
|
+
if (change) applyModeChange(change);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const parts = output.parts ?? output.messages ?? output;
|
|
198
|
+
if (!Array.isArray(parts)) return;
|
|
199
|
+
for (const part of parts) {
|
|
200
|
+
if (part && typeof part.text === 'string') {
|
|
201
|
+
const change = parseModeChange(part.text);
|
|
202
|
+
if (change) applyModeChange(change);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
|
|
94
207
|
// ponytail-proven hook; appends the announce string to the system prompt.
|
|
208
|
+
// Dedupes: repeated transforms (model switch/compaction) must not grow the
|
|
209
|
+
// prompt unbounded — only append once per string content.
|
|
95
210
|
'experimental.chat.system.transform': async (_input, output) => {
|
|
96
|
-
if (output.system.
|
|
97
|
-
output.system
|
|
98
|
-
|
|
99
|
-
|
|
211
|
+
if (!output.system.some((s) => s.includes('Mugiwara crew available'))) {
|
|
212
|
+
if (output.system.length > 0) {
|
|
213
|
+
output.system[output.system.length - 1] += '\n\n' + ANNOUNCE;
|
|
214
|
+
} else {
|
|
215
|
+
output.system.push(ANNOUNCE);
|
|
216
|
+
}
|
|
100
217
|
}
|
|
218
|
+
const active = `Active mode: ${readMode()} (guided|semi|auto; flip applies next wave).`;
|
|
219
|
+
if (!output.system.some((s) => s.includes('Active mode:'))) output.system.push(active);
|
|
101
220
|
},
|
|
102
221
|
});
|