@ionivetech/mugiwara 0.5.5 → 0.6.1
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.kimi-plugin/plugin.json +1 -1
- package/.opencode/commands/mugiwara-continue.md +16 -0
- package/.opencode/commands/mugiwara-execute.md +6 -4
- package/.opencode/commands/mugiwara-heal.md +6 -4
- package/.opencode/commands/mugiwara-plan.md +6 -4
- package/.opencode/commands/mugiwara-review.md +6 -4
- package/.opencode/commands/mugiwara-security.md +6 -4
- package/.opencode/commands/mugiwara-ship.md +6 -4
- package/.opencode/commands/mugiwara.md +4 -2
- package/.opencode/commands/using-mugiwara.md +7 -13
- package/.opencode/mugiwara-helpers.mjs +24 -0
- package/.opencode/plugins/mugiwara.mjs +28 -8
- package/AGENTS.md +1 -1
- package/GEMINI.md +1 -1
- package/README.md +311 -127
- package/content/agents/brook-healing.md +17 -3
- package/content/agents/chopper-checkpoint.md +17 -3
- package/content/agents/eval-runner.md +17 -2
- package/content/agents/franky-gates.md +19 -5
- package/content/agents/jinbe-security.md +19 -3
- package/content/agents/luffy-orchestrator.md +6 -3
- package/content/agents/memory-keeper.md +15 -0
- package/content/agents/nami-planner.md +21 -6
- package/content/agents/onboarding-guide.md +145 -0
- package/content/agents/resume-coordinator.md +21 -5
- package/content/agents/robin-reviewer.md +18 -3
- package/content/agents/sanji-quality.md +19 -4
- package/content/agents/skeptic-verifier.md +18 -3
- package/content/agents/usopp-brainstorm.md +17 -3
- package/content/agents/zoro-execution.md +18 -3
- package/content/skills/mugiwara-backend/SKILL.md +1 -1
- package/content/skills/mugiwara-brainstorm/SKILL.md +12 -1
- package/content/skills/mugiwara-checkpoint/SKILL.md +2 -2
- package/content/skills/mugiwara-contract-first/SKILL.md +2 -36
- package/content/skills/mugiwara-contract-first/references/process.md +37 -0
- package/content/skills/mugiwara-execution/SKILL.md +51 -34
- package/content/skills/mugiwara-execution/references/dispatch.md +41 -0
- package/content/skills/mugiwara-execution/references/resume-batching.md +32 -0
- package/content/skills/mugiwara-frontend/SKILL.md +1 -1
- package/content/skills/mugiwara-gates/SKILL.md +32 -30
- package/content/skills/mugiwara-healing/SKILL.md +1 -1
- package/content/skills/mugiwara-orchestration/SKILL.md +59 -39
- package/content/skills/mugiwara-orchestration/references/closure.md +34 -0
- package/content/skills/mugiwara-orchestration/references/delegation-pillars.md +40 -0
- package/content/skills/mugiwara-orchestration/references/triage-escalation.md +97 -0
- package/content/skills/mugiwara-planning/SKILL.md +29 -27
- package/content/skills/mugiwara-planning/references/plan-template.md +42 -0
- package/content/skills/mugiwara-pr/SKILL.md +9 -2
- package/content/skills/mugiwara-quality/SKILL.md +17 -6
- package/content/skills/mugiwara-resume/SKILL.md +7 -2
- package/content/skills/mugiwara-review/SKILL.md +20 -1
- package/content/skills/mugiwara-review/references/code-attributes.md +38 -0
- package/content/skills/mugiwara-root-cause/SKILL.md +3 -30
- package/content/skills/mugiwara-root-cause/references/process.md +35 -0
- package/content/skills/mugiwara-security/SKILL.md +17 -32
- package/content/skills/mugiwara-security/references/owasp-top10.md +12 -0
- package/content/skills/mugiwara-security/references/rationalizations.md +8 -0
- package/content/skills/mugiwara-ship/SKILL.md +13 -10
- package/content/skills/mugiwara-testcases/SKILL.md +7 -0
- package/content/skills/mugiwara-workflow/SKILL.md +74 -77
- package/content/skills/mugiwara-workflow/references/workspace-layout.md +50 -0
- package/content/skills/using-mugiwara/SKILL.md +13 -18
- package/dist/mugiwara.js +293 -47
- package/gemini-extension.json +1 -1
- package/hooks/mugiwara-mode-tracker.ts +0 -0
- package/hooks/session-start.ts +1 -1
- package/package.json +11 -4
- package/plugin.json +1 -1
- package/references/multi-actor.md +1 -1
- package/scripts/evidence.sh +28 -6
- package/scripts/gate-selftest.ts +317 -0
- package/scripts/initiative.ts +262 -0
- package/scripts/lane.sh +18 -1
- package/scripts/mission-report.sh +237 -36
- package/scripts/onboard.ts +292 -0
- package/scripts/release-notes.ts +42 -13
- package/scripts/savepoint.sh +151 -60
- package/scripts/validate-content.ts +97 -0
- package/scripts/verify-install.ts +72 -0
- package/src/cli.ts +20 -3
- package/src/installer.ts +71 -8
- package/src/mission.ts +117 -5
- package/src/targets/claude.ts +45 -9
- package/src/targets/generic.ts +1 -1
- package/src/targets/opencode.ts +31 -10
- package/docs/concepts/agents.md +0 -53
- package/docs/concepts/audit-trail.md +0 -65
- package/docs/concepts/comparison.md +0 -58
- package/docs/concepts/config.md +0 -55
- package/docs/concepts/cost.md +0 -45
- package/docs/concepts/execution-model.md +0 -92
- package/docs/concepts/git-strategy.md +0 -62
- package/docs/concepts/lanes.md +0 -82
- package/docs/concepts/modes.md +0 -73
- package/docs/concepts/pr-summary.md +0 -54
- package/docs/concepts/skills.md +0 -55
- package/docs/concepts/workflow.md +0 -89
- package/docs/getting-started.md +0 -158
- package/docs/index.md +0 -56
- package/docs/install/antigravity.md +0 -45
- package/docs/install/claude.md +0 -77
- package/docs/install/cli.md +0 -115
- package/docs/install/codex.md +0 -44
- package/docs/install/copilot.md +0 -45
- package/docs/install/cursor.md +0 -45
- package/docs/install/gemini.md +0 -44
- package/docs/install/index.md +0 -53
- package/docs/install/kimi.md +0 -45
- package/docs/install/opencode.md +0 -143
- package/docs/install/pi.md +0 -46
- package/docs/reference/adoption-guide.md +0 -72
- package/docs/reference/agent-anatomy.md +0 -72
- package/docs/reference/compliance-matrix.md +0 -81
- package/docs/reference/developer-onboarding.md +0 -89
- package/docs/reference/enforcement.md +0 -35
- package/docs/reference/harness-matrix.md +0 -41
- package/docs/reference/skill-anatomy.md +0 -71
- package/docs/troubleshooting.md +0 -91
- package/evals/cases/_no-skill.json +0 -16
- package/evals/cases/adversarial-pressure-fake-pass.json +0 -25
- package/evals/cases/adversarial-pressure-skip-review.json +0 -25
- package/evals/cases/lane-exploratory-vague.json +0 -24
- package/evals/cases/lane-sensitivity-payment.json +0 -24
- package/evals/cases/positive-refactor-existing-tests.json +0 -25
- package/evals/cases/positive-resume-mid-mission.json +0 -24
- package/evals/cases/routing-agent-security.json +0 -25
- package/evals/cases/routing-auth-feature.json +0 -26
- package/evals/cases/routing-backend.json +0 -25
- package/evals/cases/routing-bug-one-file.json +0 -26
- package/evals/cases/routing-claim-audit.json +0 -25
- package/evals/cases/routing-context-budget.json +0 -25
- package/evals/cases/routing-contract-first.json +0 -25
- package/evals/cases/routing-execution.json +0 -25
- package/evals/cases/routing-frontend.json +0 -26
- package/evals/cases/routing-gates.json +0 -25
- package/evals/cases/routing-git.json +0 -25
- package/evals/cases/routing-healing.json +0 -25
- package/evals/cases/routing-lessons.json +0 -25
- package/evals/cases/routing-orchestration.json +0 -25
- package/evals/cases/routing-planning.json +0 -26
- package/evals/cases/routing-pr.json +0 -25
- package/evals/cases/routing-quality.json +0 -25
- package/evals/cases/routing-ship.json +0 -26
- package/evals/cases/routing-sunset.json +0 -25
- package/evals/cases/routing-using-mugiwara.json +0 -25
- package/evals/cases/routing-workflow.json +0 -25
- package/evals/floor.json +0 -6
package/src/installer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/installer.ts
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, copyFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, copyFileSync, rmSync, lstatSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
@@ -11,6 +11,7 @@ export type ContentItem = {
|
|
|
11
11
|
data: FrontmatterData;
|
|
12
12
|
body: string;
|
|
13
13
|
refs: { relPath: string; text: string }[];
|
|
14
|
+
internal?: boolean;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export type InstallOptions = {
|
|
@@ -35,6 +36,7 @@ export interface Target {
|
|
|
35
36
|
label: string;
|
|
36
37
|
native: boolean;
|
|
37
38
|
tier?: 1 | 2 | 3;
|
|
39
|
+
refPointerPrefix?: string;
|
|
38
40
|
paths(opts: { scope: Scope; projectDir: string; home: string }): { skillsDir: string; agentsDir: string };
|
|
39
41
|
transformSkill(data: FrontmatterData, body: string): TransformOut;
|
|
40
42
|
transformAgent(data: FrontmatterData, body: string): TransformOut;
|
|
@@ -48,7 +50,7 @@ export const CONTENT_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', '
|
|
|
48
50
|
const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf8')) as { version: string };
|
|
49
51
|
export const VERSION = pkg.version;
|
|
50
52
|
|
|
51
|
-
export function collectContent(): { skills: ContentItem[]; agents: ContentItem[] } {
|
|
53
|
+
export function collectContent(): { skills: ContentItem[]; agents: ContentItem[]; sharedRefs: { relPath: string; text: string }[] } {
|
|
52
54
|
const skillNames = readdirSync(join(CONTENT_DIR, 'skills'), { withFileTypes: true })
|
|
53
55
|
.filter(e => e.isDirectory()).map(e => e.name);
|
|
54
56
|
const skills = skillNames.map(name => {
|
|
@@ -59,9 +61,17 @@ export function collectContent(): { skills: ContentItem[]; agents: ContentItem[]
|
|
|
59
61
|
.filter(f => f.endsWith('.md'))
|
|
60
62
|
.map(f => {
|
|
61
63
|
const { data, body } = parseFrontmatter(readFileSync(join(CONTENT_DIR, 'agents', f), 'utf8'));
|
|
62
|
-
return { name: f.replace(/\.md$/, ''), data, body, refs: [] as { relPath: string; text: string }[] };
|
|
64
|
+
return { name: f.replace(/\.md$/, ''), data, body, refs: [] as { relPath: string; text: string }[], internal: data.internal === 'true' };
|
|
63
65
|
});
|
|
64
|
-
|
|
66
|
+
const sharedRefsDir = join(dirname(CONTENT_DIR), 'references');
|
|
67
|
+
const sharedRefs: { relPath: string; text: string }[] = [];
|
|
68
|
+
if (existsSync(sharedRefsDir)) {
|
|
69
|
+
for (const f of readdirSync(sharedRefsDir)) {
|
|
70
|
+
if (!f.endsWith('.md')) continue;
|
|
71
|
+
sharedRefs.push({ relPath: f, text: readFileSync(join(sharedRefsDir, f), 'utf8') });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { skills, agents, sharedRefs };
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
function collectRefs(skillDir: string): { relPath: string; text: string }[] {
|
|
@@ -74,7 +84,7 @@ function collectRefs(skillDir: string): { relPath: string; text: string }[] {
|
|
|
74
84
|
export function installTo(target: Target, opts: InstallOptions): InstallResult {
|
|
75
85
|
const { scope, projectDir, dryRun = false, force = false } = opts;
|
|
76
86
|
const home = opts.home ?? homedir();
|
|
77
|
-
const { skills, agents } = collectContent();
|
|
87
|
+
const { skills, agents, sharedRefs } = collectContent();
|
|
78
88
|
const dirs = target.paths({ scope, projectDir, home });
|
|
79
89
|
const backupRoot = join(scope === 'global' ? home : projectDir, '.mugiwara');
|
|
80
90
|
const result: InstallResult = { written: [], skipped: [], backedUp: [], notes: [] };
|
|
@@ -100,10 +110,22 @@ export function installTo(target: Target, opts: InstallOptions): InstallResult {
|
|
|
100
110
|
|
|
101
111
|
for (const s of skills) {
|
|
102
112
|
const out = target.transformSkill(s.data, s.body);
|
|
103
|
-
if (out)
|
|
113
|
+
if (out) {
|
|
114
|
+
let text = out.text;
|
|
115
|
+
if (target.refPointerPrefix !== undefined && target.refPointerPrefix !== '') {
|
|
116
|
+
text = text.replace(/`_shared\/references\//g, '`' + target.refPointerPrefix + '_shared/references/');
|
|
117
|
+
}
|
|
118
|
+
writeOne(join(dirs.skillsDir, out.relPath), text);
|
|
119
|
+
}
|
|
104
120
|
if (target.transformSkillFull) {
|
|
105
121
|
const full = target.transformSkillFull(s.data, s.body);
|
|
106
|
-
if (full && target.refsDir)
|
|
122
|
+
if (full && target.refsDir) {
|
|
123
|
+
let text = full.text;
|
|
124
|
+
if (target.refPointerPrefix !== undefined && target.refPointerPrefix !== '') {
|
|
125
|
+
text = text.replace(/`_shared\/references\//g, '`' + target.refPointerPrefix + '_shared/references/');
|
|
126
|
+
}
|
|
127
|
+
writeOne(join(target.refsDir({ scope, projectDir, home }, s.name), full.relPath), text);
|
|
128
|
+
}
|
|
107
129
|
}
|
|
108
130
|
if (s.refs.length && target.refsDir) {
|
|
109
131
|
const refsRoot = target.refsDir({ scope, projectDir, home }, s.name);
|
|
@@ -111,7 +133,7 @@ export function installTo(target: Target, opts: InstallOptions): InstallResult {
|
|
|
111
133
|
}
|
|
112
134
|
}
|
|
113
135
|
for (const a of agents) {
|
|
114
|
-
const out = target.transformAgent(a.data, a.body);
|
|
136
|
+
const out = target.transformAgent({ ...a.data, ...(a.internal ? { 'internal-agent': 'true' } : {}) }, a.body);
|
|
115
137
|
if (out) writeOne(join(dirs.agentsDir, out.relPath), out.text);
|
|
116
138
|
if (target.transformAgentFull) {
|
|
117
139
|
const full = target.transformAgentFull(a.data, a.body);
|
|
@@ -119,6 +141,11 @@ export function installTo(target: Target, opts: InstallOptions): InstallResult {
|
|
|
119
141
|
}
|
|
120
142
|
}
|
|
121
143
|
|
|
144
|
+
if (sharedRefs.length) {
|
|
145
|
+
const sharedRoot = join(dirs.skillsDir, '_shared', 'references');
|
|
146
|
+
for (const r of sharedRefs) writeOne(join(sharedRoot, r.relPath), r.text);
|
|
147
|
+
}
|
|
148
|
+
|
|
122
149
|
if (target.postInstall) {
|
|
123
150
|
const post = target.postInstall({ scope, projectDir, home, dryRun, files: result.written });
|
|
124
151
|
result.written.push(...post.written);
|
|
@@ -144,3 +171,39 @@ export function removeInstalled(manifest: { files: string[] }, { dryRun = false
|
|
|
144
171
|
}
|
|
145
172
|
return removed;
|
|
146
173
|
}
|
|
174
|
+
|
|
175
|
+
function assertNotSymlink(file: string): void {
|
|
176
|
+
if (!existsSync(file)) return;
|
|
177
|
+
try {
|
|
178
|
+
if (lstatSync(file).isSymbolicLink()) throw new Error(`refusing to follow symlink: ${file}`);
|
|
179
|
+
} catch (e) {
|
|
180
|
+
if ((e as { code?: string }).code === 'ENOENT') return;
|
|
181
|
+
throw e;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const GITIGNORE_MARKER = '# mugiwara';
|
|
186
|
+
const GITIGNORE_BLOCK = `# mugiwara — audit trail is the product: commit reports/, results/, logs/, spec/, plans/.
|
|
187
|
+
# Ignore session state and regenerated files.
|
|
188
|
+
.mugiwara/state.json
|
|
189
|
+
.mugiwara/state-*.json
|
|
190
|
+
.mugiwara/config
|
|
191
|
+
.mugiwara/continue.md
|
|
192
|
+
.mugiwara/refs/
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
export function ensureProjectGitignore(projectDir: string, opts: { dryRun?: boolean } = {}): { appended: boolean; notes: string[] } {
|
|
196
|
+
const { dryRun = false } = opts;
|
|
197
|
+
const path = join(projectDir, '.gitignore');
|
|
198
|
+
assertNotSymlink(path);
|
|
199
|
+
if (existsSync(path) && readFileSync(path, 'utf8').includes(GITIGNORE_MARKER)) {
|
|
200
|
+
return { appended: false, notes: [] };
|
|
201
|
+
}
|
|
202
|
+
const existing = existsSync(path) ? readFileSync(path, 'utf8') : '';
|
|
203
|
+
const separator = existing.length && !existing.endsWith('\n') ? '\n' : '';
|
|
204
|
+
if (!dryRun) {
|
|
205
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
206
|
+
writeFileSync(path, existing + separator + GITIGNORE_BLOCK);
|
|
207
|
+
}
|
|
208
|
+
return { appended: true, notes: [`.gitignore ${dryRun ? 'would append' : 'appended'} mugiwara audit-trail block`] };
|
|
209
|
+
}
|
package/src/mission.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/mission.ts
|
|
2
2
|
// Mission-state helpers for the mugiwara CLI (installer + reset only).
|
|
3
|
-
import { existsSync, rmSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { existsSync, rmSync, readFileSync, readdirSync, mkdirSync, appendFileSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
|
|
6
6
|
function activeActor(projectDir: string): string | null {
|
|
@@ -30,10 +30,12 @@ export function resetMission(projectDir: string, keepLogs: boolean, force?: bool
|
|
|
30
30
|
const p = join(root, dir);
|
|
31
31
|
if (existsSync(p)) { rmSync(p, { recursive: true, force: true }); removed.push(dir); }
|
|
32
32
|
}
|
|
33
|
-
// mission state files
|
|
34
|
-
for (const f of
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
// mission state files — state.json + branch-specific state-*.json
|
|
34
|
+
for (const f of readdirSync(root)) {
|
|
35
|
+
if (/^state(-.+)?\.json$/.test(f)) {
|
|
36
|
+
const p = join(root, f);
|
|
37
|
+
if (existsSync(p)) { rmSync(p); removed.push(f); }
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
if (!keepLogs) {
|
|
39
41
|
const p = join(root, 'logs');
|
|
@@ -46,3 +48,113 @@ export function resetMission(projectDir: string, keepLogs: boolean, force?: bool
|
|
|
46
48
|
}
|
|
47
49
|
return { removed, kept };
|
|
48
50
|
}
|
|
51
|
+
|
|
52
|
+
export function archiveMission(projectDir: string, mission: string, opts: { dryRun?: boolean } = {}): { report: string | null; removed: string[]; kept: string[]; index?: string } {
|
|
53
|
+
const { dryRun = false } = opts;
|
|
54
|
+
const root = join(projectDir, '.mugiwara');
|
|
55
|
+
// mission allowlist — same as savepoint.sh / mission-report.sh. Dot-only
|
|
56
|
+
// names (".", "..") would resolve upward through join(...,"..") and let
|
|
57
|
+
// rmSync reach state.json/config outside the mission dir.
|
|
58
|
+
if (!mission || /[^a-zA-Z0-9._-]/.test(mission) || /^\.+$/.test(mission)) throw new Error(`invalid mission name "${mission}" (allowlist: [a-zA-Z0-9._-], not a dot-path)`);
|
|
59
|
+
const removed: string[] = [];
|
|
60
|
+
const kept: string[] = [];
|
|
61
|
+
|
|
62
|
+
// A file belongs to this mission when stripping the optional YYYY-MM-DD-
|
|
63
|
+
// prefix leaves `<mission>.md` or `<mission>-<suffix>.md`. Covers both the
|
|
64
|
+
// bare names and the date-prefixed names the prose writes (audit-trail.md).
|
|
65
|
+
const belongs = (f: string): boolean => {
|
|
66
|
+
const base = f.replace(/^\d{4}-\d{2}-\d{2}-/, '');
|
|
67
|
+
return base === `${mission}.md` || base.startsWith(`${mission}-`);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// locate the report (the archive target that must survive). Reports are
|
|
71
|
+
// date-prefixed (`reports/YYYY-MM-DD-<mission>.md`); compare the stripped
|
|
72
|
+
// mission name so `bar-foo.md` is not mistaken for mission `foo`.
|
|
73
|
+
let report: string | null = null;
|
|
74
|
+
const reportsDir = join(root, 'reports');
|
|
75
|
+
if (existsSync(reportsDir)) {
|
|
76
|
+
const f = readdirSync(reportsDir).find(n => {
|
|
77
|
+
const m = n.match(/^(\d{4}-\d{2}-\d{2})-(.+)\.md$/);
|
|
78
|
+
return !!m && m[2] === mission;
|
|
79
|
+
});
|
|
80
|
+
if (f) report = join('reports', f);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// remove per-mission wave intermediates from results/<mission>/, EXCEPT
|
|
84
|
+
// 06-closure.md and 07-pr-verdict.md (PR material + closure stay)
|
|
85
|
+
const resultsDir = join(root, 'results', mission);
|
|
86
|
+
if (existsSync(resultsDir)) {
|
|
87
|
+
for (const f of readdirSync(resultsDir)) {
|
|
88
|
+
if (f === '06-closure.md' || f === '07-pr-verdict.md') { kept.push(join('results', mission, f)); continue; }
|
|
89
|
+
const p = join(resultsDir, f);
|
|
90
|
+
if (!dryRun) rmSync(p, { recursive: true, force: true });
|
|
91
|
+
removed.push(join('results', mission, f));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// spec, review, issues, per-mission decision log — bare + date-prefixed
|
|
96
|
+
const specDir = join(root, 'spec');
|
|
97
|
+
if (existsSync(specDir)) {
|
|
98
|
+
for (const f of readdirSync(specDir)) {
|
|
99
|
+
if (!belongs(f)) continue;
|
|
100
|
+
const p = join(specDir, f);
|
|
101
|
+
if (!dryRun) rmSync(p);
|
|
102
|
+
removed.push(join('spec', f));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
for (const dir of ['review', 'issues']) {
|
|
107
|
+
const d = join(root, dir);
|
|
108
|
+
if (!existsSync(d)) continue;
|
|
109
|
+
for (const f of readdirSync(d)) {
|
|
110
|
+
if (!belongs(f)) continue;
|
|
111
|
+
const p = join(d, f);
|
|
112
|
+
if (!dryRun) rmSync(p, { force: true });
|
|
113
|
+
removed.push(join(dir, f));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const logsDir = join(root, 'logs');
|
|
118
|
+
if (existsSync(logsDir)) {
|
|
119
|
+
for (const f of readdirSync(logsDir)) {
|
|
120
|
+
if (!belongs(f)) continue;
|
|
121
|
+
const p = join(logsDir, f);
|
|
122
|
+
if (!dryRun) rmSync(p);
|
|
123
|
+
removed.push(join('logs', f));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// continue.md is a session handoff — only remove it if it belongs to THIS
|
|
128
|
+
// mission (its content references the mission name); otherwise leave it.
|
|
129
|
+
const cont = join(root, 'continue.md');
|
|
130
|
+
if (existsSync(cont)) {
|
|
131
|
+
try {
|
|
132
|
+
if (readFileSync(cont, 'utf8').includes(mission)) {
|
|
133
|
+
if (!dryRun) rmSync(cont);
|
|
134
|
+
removed.push('continue.md');
|
|
135
|
+
}
|
|
136
|
+
} catch { /* unreadable — leave it */ }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// kept: report + the audit-trail survivors
|
|
140
|
+
if (report) kept.push(report);
|
|
141
|
+
for (const k of ['plans', 'config', 'state.json', join('logs', 'lessons.md')]) {
|
|
142
|
+
if (existsSync(join(root, k))) kept.push(k);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// summary index: append one line per archived mission (retention aid),
|
|
146
|
+
// idempotently — never duplicate a line for an already-indexed mission.
|
|
147
|
+
let index: string | undefined;
|
|
148
|
+
const indexFile = join(root, 'reports', 'index.md');
|
|
149
|
+
const line = `- ${mission} — ${new Date().toISOString().slice(0, 10)}${report ? ` → ${report}` : ''}\n`;
|
|
150
|
+
if (!dryRun) {
|
|
151
|
+
mkdirSync(join(root, 'reports'), { recursive: true });
|
|
152
|
+
const existing = existsSync(indexFile) ? readFileSync(indexFile, 'utf8') : '';
|
|
153
|
+
if (!existing.split(/\r?\n/).some(l => l.startsWith(`- ${mission} —`))) {
|
|
154
|
+
const header = existing ? '' : '# Mission index\n\n';
|
|
155
|
+
appendFileSync(indexFile, header + line);
|
|
156
|
+
}
|
|
157
|
+
index = join('reports', 'index.md');
|
|
158
|
+
}
|
|
159
|
+
return { report, removed, kept, index };
|
|
160
|
+
}
|
package/src/targets/claude.ts
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
// src/targets/claude.ts
|
|
2
|
-
import { existsSync, readFileSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, copyFileSync, chmodSync, readdirSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { stringifyFrontmatter, type FrontmatterData } from '../frontmatter.ts';
|
|
6
6
|
import type { Target } from '../installer.ts';
|
|
7
7
|
|
|
8
8
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const
|
|
9
|
+
const HOOKS_SRC = join(here, '..', '..', 'hooks');
|
|
10
|
+
const COMMANDS_SRC = join(here, '..', '..', '.claude', 'commands');
|
|
11
|
+
|
|
12
|
+
// Claude Code has no path-scoped permission. write-scope maps to a partial
|
|
13
|
+
// `tools:` list: artifacts agents lose Edit (cannot modify existing source)
|
|
14
|
+
// but keep Write (must create .mugiwara/**); source agents get the default set.
|
|
15
|
+
function toolsFromScope(scope?: string): string | undefined {
|
|
16
|
+
if (scope === 'artifacts') return 'Read, Grep, Glob, Write, Bash, WebFetch, WebSearch';
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
10
19
|
|
|
11
20
|
export const target: Target = {
|
|
12
21
|
id: 'claude',
|
|
13
22
|
label: 'Claude Code',
|
|
14
23
|
native: true,
|
|
24
|
+
refPointerPrefix: '../',
|
|
15
25
|
paths({ scope, projectDir, home }) {
|
|
16
26
|
const root = scope === 'global' ? join(home, '.claude') : join(projectDir, '.claude');
|
|
17
27
|
return { skillsDir: join(root, 'skills'), agentsDir: join(root, 'agents') };
|
|
@@ -25,6 +35,10 @@ export const target: Target = {
|
|
|
25
35
|
transformAgent(data: FrontmatterData, body: string) {
|
|
26
36
|
const fm: FrontmatterData = { name: data.name, description: data.description };
|
|
27
37
|
if (data.tools) fm.tools = data.tools;
|
|
38
|
+
else {
|
|
39
|
+
const generated = toolsFromScope(data['write-scope']);
|
|
40
|
+
if (generated) fm.tools = generated;
|
|
41
|
+
}
|
|
28
42
|
return { relPath: `${data.name}.md`, text: stringifyFrontmatter(fm, body) };
|
|
29
43
|
},
|
|
30
44
|
refsDir({ scope, projectDir, home }, skillName: string) {
|
|
@@ -32,15 +46,37 @@ export const target: Target = {
|
|
|
32
46
|
return join(root, 'skills', skillName, 'references');
|
|
33
47
|
},
|
|
34
48
|
postInstall({ scope, projectDir, home, dryRun }) {
|
|
35
|
-
// Wire
|
|
49
|
+
// Wire hook scripts (SessionStart + UserPromptSubmit) into the installed .claude dir.
|
|
36
50
|
const root = scope === 'global' ? join(home, '.claude') : join(projectDir, '.claude');
|
|
37
|
-
const
|
|
51
|
+
const written: string[] = [];
|
|
52
|
+
const notes: string[] = [];
|
|
38
53
|
if (dryRun) return { written: [], notes: [] };
|
|
39
|
-
if (existsSync(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
if (existsSync(HOOKS_SRC)) {
|
|
55
|
+
for (const f of readdirSync(HOOKS_SRC)) {
|
|
56
|
+
if (!f.endsWith('.ts')) continue;
|
|
57
|
+
const dst = join(root, 'hooks', f);
|
|
58
|
+
if (!existsSync(dst)) {
|
|
59
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
60
|
+
copyFileSync(join(HOOKS_SRC, f), dst);
|
|
61
|
+
// /bin/sh executes hooks via shebang — a non-executable copy is a
|
|
62
|
+
// "Permission denied" at first user prompt. chmod every hook file.
|
|
63
|
+
chmodSync(dst, 0o755);
|
|
64
|
+
written.push(dst);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Port the /mugiwara commands into the installed .claude dir.
|
|
69
|
+
if (existsSync(COMMANDS_SRC)) {
|
|
70
|
+
const dstDir = join(root, 'commands');
|
|
71
|
+
mkdirSync(dstDir, { recursive: true });
|
|
72
|
+
for (const f of readdirSync(COMMANDS_SRC)) {
|
|
73
|
+
if (!f.endsWith('.md')) continue;
|
|
74
|
+
const src = join(COMMANDS_SRC, f);
|
|
75
|
+
const dst = join(dstDir, f);
|
|
76
|
+
if (!existsSync(dst)) { copyFileSync(src, dst); written.push(dst); }
|
|
77
|
+
else notes.push(`existing command kept: ${dst}`);
|
|
78
|
+
}
|
|
43
79
|
}
|
|
44
|
-
return { written
|
|
80
|
+
return { written, notes };
|
|
45
81
|
},
|
|
46
82
|
};
|
package/src/targets/generic.ts
CHANGED
|
@@ -44,7 +44,7 @@ export function makeGeneric(opts: {
|
|
|
44
44
|
if (stubOnly) {
|
|
45
45
|
return {
|
|
46
46
|
relPath: `agent-${data.name}.md`,
|
|
47
|
-
text: `# Agent: ${data.name}\n\n> ${data.description}\n\nSkills: ${data.skills ?? ''}. Read \`.mugiwara/refs/${data.name}.md\` when embodying this role.`,
|
|
47
|
+
text: `# Agent: ${data.name}\n\n> ${data.description}\n\nSkills: ${data.skills ?? ''}. Read \`.mugiwara/refs/${data.name}.md\` when embodying this role.\n\nOnly zoro-execution and brook-healing may modify source code.\nReturn your output to luffy-orchestrator; do not choose the next step.`,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
return { relPath: `agent-${data.name}.md`, text: `# Agent: ${data.name}\n\n> ${data.description}\n\nSkills used: ${data.skills ?? ''}\n\n${body}` };
|
package/src/targets/opencode.ts
CHANGED
|
@@ -20,26 +20,45 @@ const CREW: Record<string, CrewConfig> = {
|
|
|
20
20
|
'usopp-brainstorm': { color: '#f59e0b', temperature: 0.6, steps: 15 },
|
|
21
21
|
'nami-planner': { color: '#f97316', temperature: 0.2, steps: 15 },
|
|
22
22
|
'zoro-execution': { color: '#22c55e', temperature: 0.1, steps: 30 },
|
|
23
|
-
'chopper-checkpoint': { color: '#3b82f6', temperature: 0.1,
|
|
24
|
-
'sanji-quality': { color: '#a855f7', temperature: 0.1,
|
|
25
|
-
'franky-gates': { color: '#06b6d4', temperature: 0.1,
|
|
26
|
-
'robin-reviewer': { color: '#8b5cf6', temperature: 0.2,
|
|
27
|
-
'jinbe-security': { color: '#6366f1', temperature: 0.2,
|
|
23
|
+
'chopper-checkpoint': { color: '#3b82f6', temperature: 0.1, steps: 15 },
|
|
24
|
+
'sanji-quality': { color: '#a855f7', temperature: 0.1, steps: 10 },
|
|
25
|
+
'franky-gates': { color: '#06b6d4', temperature: 0.1, steps: 10 },
|
|
26
|
+
'robin-reviewer': { color: '#8b5cf6', temperature: 0.2, steps: 15 },
|
|
27
|
+
'jinbe-security': { color: '#6366f1', temperature: 0.2, steps: 15 },
|
|
28
28
|
'brook-healing': { color: '#ec4899', temperature: 0.1, steps: 20 },
|
|
29
|
-
'skeptic-verifier': { color: '#64748b', temperature: 0.1,
|
|
29
|
+
'skeptic-verifier': { color: '#64748b', temperature: 0.1, steps: 12 },
|
|
30
30
|
'eval-runner': { color: '#14b8a6', temperature: 0.2, steps: 15 },
|
|
31
31
|
'resume-coordinator': { color: '#d97706', temperature: 0.2, steps: 10 },
|
|
32
32
|
'memory-keeper': { color: '#d946ef', temperature: 0.2, steps: 8 },
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
// write-scope is the single source of truth (content/agents/*.md frontmatter).
|
|
36
|
+
// The path boundary (artifacts vs source) IS expressible in opencode:
|
|
37
|
+
// permission.edit accepts glob/pattern -> action, last match wins. Artifacts
|
|
38
|
+
// agents get deny-all-edit except .mugiwara/**; source agents (zoro, brook)
|
|
39
|
+
// get full edit allow. Derived at install time from the frontmatter field.
|
|
40
|
+
function permissionFromScope(scope: string | undefined): Record<string, string | Record<string, string>> | undefined {
|
|
41
|
+
if (scope === 'source') return { edit: 'allow' };
|
|
42
|
+
if (scope === 'artifacts') return { edit: { '*': 'deny', '.mugiwara/**': 'allow' } };
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function agentFrontmatter(name: string, description: string, writeScope?: string) {
|
|
36
47
|
const crew = CREW[name];
|
|
37
48
|
const lines = [`description: ${description}`, `mode: all`];
|
|
38
49
|
if (crew) {
|
|
39
50
|
lines.push(`color: '${crew.color}'`, `temperature: ${crew.temperature}`, `steps: ${crew.steps}`);
|
|
40
|
-
|
|
51
|
+
const perm = permissionFromScope(writeScope);
|
|
52
|
+
if (perm) {
|
|
41
53
|
lines.push('permission:');
|
|
42
|
-
for (const [k, v] of Object.entries(
|
|
54
|
+
for (const [k, v] of Object.entries(perm)) {
|
|
55
|
+
if (typeof v === 'string') {
|
|
56
|
+
lines.push(` ${k}: ${v}`);
|
|
57
|
+
} else {
|
|
58
|
+
lines.push(` ${k}:`);
|
|
59
|
+
for (const [pk, pv] of Object.entries(v)) lines.push(` "${pk}": ${pv}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
63
|
}
|
|
45
64
|
return lines.join('\n');
|
|
@@ -49,6 +68,7 @@ export const target: Target = {
|
|
|
49
68
|
id: 'opencode',
|
|
50
69
|
label: 'opencode',
|
|
51
70
|
native: true,
|
|
71
|
+
refPointerPrefix: '../',
|
|
52
72
|
paths({ scope, projectDir, home }) {
|
|
53
73
|
const root = scope === 'global' ? join(home, '.config', 'opencode') : join(projectDir, '.opencode');
|
|
54
74
|
return { skillsDir: join(root, 'skills'), agentsDir: join(root, 'agents') };
|
|
@@ -60,7 +80,8 @@ export const target: Target = {
|
|
|
60
80
|
};
|
|
61
81
|
},
|
|
62
82
|
transformAgent(data: FrontmatterData, body: string) {
|
|
63
|
-
const
|
|
83
|
+
const desc = data['internal-agent'] === 'true' ? `[INTERNAL] ${data.description}` : data.description;
|
|
84
|
+
const fm = agentFrontmatter(data.name, desc, data['write-scope']);
|
|
64
85
|
return { relPath: `${data.name}.md`, text: `---\n${fm}\n---\n${body}` };
|
|
65
86
|
},
|
|
66
87
|
refsDir({ scope, projectDir, home }, skillName: string) {
|
package/docs/concepts/agents.md
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# The Crew — 14 Agents
|
|
2
|
-
|
|
3
|
-
Every agent is a focused specialist. The main thread embodies each role inline
|
|
4
|
-
using its skill; you can also summon any member directly. "Dispatch" below
|
|
5
|
-
means "route the mission to this role."
|
|
6
|
-
|
|
7
|
-
The front door is the `using-mugiwara` skill — load it for crew overview.
|
|
8
|
-
Slash command: `/using-mugiwara`.
|
|
9
|
-
|
|
10
|
-
| Agent | Crew member | Role | Summon for |
|
|
11
|
-
|-------|-------------|------|------------|
|
|
12
|
-
| `luffy-orchestrator` | Luffy | Captain — 5-way triage, check-ins, decisions, closure | mission start, wave boundaries, escalations |
|
|
13
|
-
| `usopp-brainstorm` | Usopp | Critical friend — interrogates, researches, no rubber-stamps | vague ideas, direction, options |
|
|
14
|
-
| `nami-planner` | Nami | Planner — interview-first, full-context scan, scaled plans | turning an idea into an execution plan |
|
|
15
|
-
| `zoro-execution` | Zoro | Executor — inline sequential tasks, parallel worker batches, evidence per task | executing an approved plan |
|
|
16
|
-
| `chopper-checkpoint` | Chopper | Auditor — verify-everything, deduped re-runs, failure ledger | auditing a wave's results |
|
|
17
|
-
| `sanji-quality` | Sanji | Quality — discover real tooling, format/lint/test | after checkpoint passes |
|
|
18
|
-
| `franky-gates` | Franky | Gates — coverage, build, Definition of Done, binary verdicts | after quality checks |
|
|
19
|
-
| `robin-reviewer` | Robin | Reviewer — doubt-driven diff review, breaking-change map first | after gates pass |
|
|
20
|
-
| `jinbe-security` | Jinbe | Security — STRIDE, OWASP, secrets, injection, dependencies | security audit of a diff |
|
|
21
|
-
| `brook-healing` | Brook | Healer — reads the ledger, root-cause fixes, ≤3 cycles | any wave produced failures |
|
|
22
|
-
| `skeptic-verifier` | Skeptic | Adversarial verifier — doubts every output, does NOT validate | high-stakes verdicts, plans, reviews |
|
|
23
|
-
| `eval-runner` | Eval Runner | Harness tester — task suites, judge-agent comparison | verifying mugiwara itself works |
|
|
24
|
-
| `resume-coordinator` | Resume Coordinator | Resumer — rebuilds state from `.mugiwara/`, continues never restarts | context loss, new session mid-mission |
|
|
25
|
-
| `memory-keeper` | Memory Keeper | Institutional memory — surfaces past lessons, captures new ones | mission start + closure |
|
|
26
|
-
|
|
27
|
-
## How to summon
|
|
28
|
-
|
|
29
|
-
Say a crew member's name in your request:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
> Chopper, audit the last wave against the plan
|
|
33
|
-
> Nami, plan this out
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Luffy still records the route and its reason, and direct calls do not skip
|
|
37
|
-
check-ins. The harness stays coherent either way.
|
|
38
|
-
|
|
39
|
-
## Who never does what
|
|
40
|
-
|
|
41
|
-
- **Luffy** never implements code.
|
|
42
|
-
- **Chopper** never fixes findings — reports them.
|
|
43
|
-
- **Skeptic** never validates — doubts.
|
|
44
|
-
- **Robin/Jinbe** never implement — findings to Brook.
|
|
45
|
-
- Crew members never dispatch each other. Workers are subagents, never crew.
|
|
46
|
-
|
|
47
|
-
## The crew ships whole
|
|
48
|
-
|
|
49
|
-
Every install gets all 14 agents and all 26 skills. No project-type selection —
|
|
50
|
-
the harness routes each task to the right specialist.
|
|
51
|
-
|
|
52
|
-
See [skills.md](skills.md) for the 26 techniques, or
|
|
53
|
-
[workflow.md](workflow.md) for the pipeline.
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Audit Trail
|
|
2
|
-
|
|
3
|
-
Every artifact the Mugiwara crew produces — what writes it, when, and how to
|
|
4
|
-
read it as a reviewer.
|
|
5
|
-
|
|
6
|
-
## The artifacts
|
|
7
|
-
|
|
8
|
-
| Artifact | Path | Written by | When | For |
|
|
9
|
-
|----------|------|-----------|------|-----|
|
|
10
|
-
| **Plan doc** | `.mugiwara/plans/YYYY-MM-DD-<mission>.md` | Nami (planning) | Wave 2 | Zero-context executor — waves, tasks, criteria, risk |
|
|
11
|
-
| **Spec** | `.mugiwara/spec/YYYY-MM-DD-<mission>.md` | Usopp (brainstorm) / Luffy (spec bridge) | Wave 0–1 | Bridge from idea to plan — goal, acceptance, constraints |
|
|
12
|
-
| **State** | `.mugiwara/state.json` | `scripts/savepoint.sh` | Every wave boundary | Computed mission state: lane, wave, files, blockers, token budget, evidence paths |
|
|
13
|
-
| **Decision log** | `.mugiwara/logs/YYYY-MM-DD-<mission>.md` | Luffy (orchestrator) | Every wave | Route reason, check-in verdicts, mode flips, decisions |
|
|
14
|
-
| **Blocker ledger** | `.mugiwara/issues/YYYY-MM-DD-<mission>-blockers.md` | Any agent | On blocker hit | Row per blocker: wave, task, symptom, attempted, help-needed |
|
|
15
|
-
| **Todo list** | `.mugiwara/results/<mission>-todos.md` | Zoro (execution) | Wave 3 | Checkbox per task, checked with evidence pointer |
|
|
16
|
-
| **Audit report** | `.mugiwara/results/YYYY-MM-DD-<mission>-audit.md` | Chopper (checkpoint) | Wave 4 | Per-task evidence, commit hygiene, parallel-conflict, honest classification |
|
|
17
|
-
| **Quality report** | `.mugiwara/results/YYYY-MM-DD-<mission>-quality.md` | Sanji (quality) | Wave 5 | Formatter/linter/unit/user-test results |
|
|
18
|
-
| **Gate verdict** | `.mugiwara/results/YYYY-MM-DD-<mission>-gates.md` | Franky (gates) | Wave 6 | Coverage thresholds from config, build exit, DoD verdict |
|
|
19
|
-
| **Review findings** | `.mugiwara/review/YYYY-MM-DD-<mission>-review.md` | Robin (review) | Wave 7 | Severity-tagged: path:line → problem → fix |
|
|
20
|
-
| **Security report** | `.mugiwara/review/YYYY-MM-DD-<mission>-security.md` | Jinbe (security) | Wave 7 | STRIDE, OWASP mapping, checklist, CVSS severity |
|
|
21
|
-
| **Heal report** | `.mugiwara/results/YYYY-MM-DD-<mission>-heal.md` | Brook (healing) | Wave 8 | Fixed list, escalated list, updated ledger |
|
|
22
|
-
| **Closure report** | `.mugiwara/results/YYYY-MM-DD-<mission>-closure.md` | Luffy (orchestrator) | Wave 9 | Mission summary, per-wave outcomes, deferred items, lessons |
|
|
23
|
-
| **Mission report** | `.mugiwara/reports/YYYY-MM-DD-<mission>.md` | `scripts/mission-report.sh` | Wave 9 | Human-readable summary: what changed, gates, state, token cost |
|
|
24
|
-
| **PR verdict** | `.mugiwara/results/YYYY-MM-DD-<mission>-pr-verdict.md` | Luffy (orchestrator) | Wave 9 | Ready PR summary block for the user to open the PR |
|
|
25
|
-
| **Trace** | `.mugiwara/results/<mission>-trace.md` | Resume coordinator | Every dispatch | Dispatch → outcome — drives resume (legacy; state.json preferred) |
|
|
26
|
-
| **Lessons ledger** | `.mugiwara/logs/lessons.md` | Memory Keeper | Cross-mission | One row per real lesson, append-only, all actors share |
|
|
27
|
-
| **Evidence logs** | `.mugiwara/results/<label>-<hash>.log` | `scripts/evidence.sh` | On demand | Command stdout/stderr capture with timestamp and exit code |
|
|
28
|
-
|
|
29
|
-
## How to read as a reviewer
|
|
30
|
-
|
|
31
|
-
1. **Start with the mission report** (`reports/`) — one file, what changed, gates, token cost.
|
|
32
|
-
2. **Check the gate verdict** (`results/<mission>-gates.md`) — coverage from config, build, DoD. Any FAIL needs explanation.
|
|
33
|
-
3. **Spot-check the audit report** (`results/<mission>-audit.md`) — did Chopper re-run checks or accept claims? Every criterion gets a command run + evidence row.
|
|
34
|
-
4. **Review findings count** (`review/`) — how many blocker/major/minor? Were they healed? Check the heal report for closure.
|
|
35
|
-
5. **State.json** for raw numbers — lane, wave, files, blockers open, heal cycle, token budget status (ok/warn/stop).
|
|
36
|
-
|
|
37
|
-
## What stays after cleanup
|
|
38
|
-
|
|
39
|
-
After Wave 9 closure (run via `mugiwara-ship` cleanup procedure):
|
|
40
|
-
|
|
41
|
-
**Kept** (audit trail + PR material):
|
|
42
|
-
- `config` — runtime config
|
|
43
|
-
- `plans/<mission>.md` — clean plan doc
|
|
44
|
-
- `results/<mission>-closure.md` — closure report
|
|
45
|
-
- `results/<mission>-pr-verdict.md` — PR material
|
|
46
|
-
- `reports/<mission>.md` — mission report
|
|
47
|
-
- `state.json` — final mission state (unless another actor's mission is active)
|
|
48
|
-
- `logs/lessons.md` — cross-mission lessons
|
|
49
|
-
- `backup/`, `manifest.json` — harness config
|
|
50
|
-
|
|
51
|
-
**Deleted** (consumed/superseded):
|
|
52
|
-
- `spec/<mission>.md` — consumed by planning
|
|
53
|
-
- `results/<mission>-todos.md` — consumed
|
|
54
|
-
- `results/<mission>-audit.md` — superseded by closure
|
|
55
|
-
- `results/<mission>-quality.md` — consumed
|
|
56
|
-
- `results/<mission>-gates.md` — consumed
|
|
57
|
-
- `results/<mission>-heal.md` — consumed
|
|
58
|
-
- `results/<mission>-trace.md` — consumed (state.json is canonical)
|
|
59
|
-
- `review/<mission>-review.md` — consumed
|
|
60
|
-
- `review/<mission>-security.md` — consumed
|
|
61
|
-
- `issues/<mission>-blockers.md` — consumed
|
|
62
|
-
- `logs/<mission>.md` — decision log, per-mission
|
|
63
|
-
|
|
64
|
-
Cleanup lists candidates first (dry-run), then deletes. A mission is only
|
|
65
|
-
closed after cleanup runs.
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Positioning
|
|
2
|
-
|
|
3
|
-
What mugiwara is and when to use something else.
|
|
4
|
-
|
|
5
|
-
## What mugiwara is
|
|
6
|
-
|
|
7
|
-
**Mugiwara is the governance layer for AI-assisted engineering work.** Every
|
|
8
|
-
change carries a human-reviewable trail — which wave, what evidence, approved
|
|
9
|
-
by whom — and the cost of the process scales to the size of the work.
|
|
10
|
-
|
|
11
|
-
- **Lane sizing** — process scales from zero waves (typo) to nine (auth
|
|
12
|
-
migration), computed from the diff by `scripts/lane.sh`, not guessed.
|
|
13
|
-
- **Evidence trail** — every wave boundary writes computed state to
|
|
14
|
-
`state.json`. No wave passes on a spoken claim. `scripts/evidence.sh` wraps
|
|
15
|
-
check commands and captures output.
|
|
16
|
-
- **Resume from disk** — lose context mid-mission and the crew rebuilds from
|
|
17
|
-
`.mugiwara/` instead of restarting.
|
|
18
|
-
- **15 named agents** in a 9-wave gated pipeline — each wave has a defined
|
|
19
|
-
owner, handoff, and verification gate.
|
|
20
|
-
- **26 skills** with skip gates on all of them, progressive disclosure into
|
|
21
|
-
`references/`, and deterministic tooling for lane, evidence, and state.
|
|
22
|
-
|
|
23
|
-
## What mugiwara refuses
|
|
24
|
-
|
|
25
|
-
- **A runtime or daemon.** Orchestration stays in the harness. Pure markdown.
|
|
26
|
-
- **Auto-merge or auto-deploy.** Human review at the PR is the terminal gate.
|
|
27
|
-
- **Unattended marathon mode.** Mugiwara runs inline by default — you watch
|
|
28
|
-
every wave. Subagents only for parallel work.
|
|
29
|
-
- **Skill-count growth.** 26 is the ceiling; a new skill replaces an old one.
|
|
30
|
-
- **Head-to-head feature scorecards.** The compliance matrix replaces them.
|
|
31
|
-
|
|
32
|
-
## When to use something else
|
|
33
|
-
|
|
34
|
-
- **Deep autonomous marathon runs.** If you want an agent to disappear for
|
|
35
|
-
hours on subagent-driven builds with minimal visibility, superpowers'
|
|
36
|
-
`subagent-driven-development` is built for exactly that.
|
|
37
|
-
- **Reference-encyclopedia depth.** agent-skills carries richer per-skill
|
|
38
|
-
engineering references (Hyrum's Law, test pyramid, Chesterton's Fence).
|
|
39
|
-
- **A runtime service.** If you need API-driven, deployable agent crews, use a
|
|
40
|
-
framework (LangGraph, CrewAI).
|
|
41
|
-
- **A single mega-prompt.** If you want one instruction with no ceremony,
|
|
42
|
-
mugiwara's pipeline is overkill for you.
|
|
43
|
-
|
|
44
|
-
## Reproducible facts
|
|
45
|
-
|
|
46
|
-
Generated from `content/` and `scripts/validate-content.ts`:
|
|
47
|
-
|
|
48
|
-
| Metric | Value |
|
|
49
|
-
|--------|:-----:|
|
|
50
|
-
| Skills | 26 |
|
|
51
|
-
| Agents | 15 |
|
|
52
|
-
| Index (all descriptions) | ~10k chars (~2.5k tokens) |
|
|
53
|
-
| Avg skill size | ~1.2k tokens |
|
|
54
|
-
| Skills with skip gate | 26/26 |
|
|
55
|
-
| References/ files | growing |
|
|
56
|
-
| Evals | 11 cases |
|
|
57
|
-
|
|
58
|
-
*Figures from Aug 2026. Recalculate with `bun scripts/validate-content.ts --check-manifest`.*
|