@ionivetech/mugiwara 0.6.2 → 0.6.4
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 +1 -1
- 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 +42 -10
- package/.opencode/commands/mugiwara-execute.md +1 -1
- package/.opencode/commands/mugiwara-heal.md +1 -1
- package/.opencode/commands/mugiwara-plan.md +1 -1
- package/.opencode/commands/mugiwara-review.md +1 -1
- package/.opencode/commands/mugiwara-security.md +1 -1
- package/.opencode/commands/mugiwara-ship.md +1 -1
- package/.opencode/mugiwara-helpers.mjs +1 -1
- package/.opencode/plugins/mugiwara.mjs +62 -20
- package/AGENTS.md +16 -5
- package/README.md +67 -15
- package/content/agents/brook-healing.md +1 -1
- package/content/agents/chopper-checkpoint.md +1 -1
- package/content/agents/eval-runner.md +1 -1
- package/content/agents/franky-gates.md +1 -1
- package/content/agents/jinbe-security.md +1 -1
- package/content/agents/memory-keeper.md +1 -1
- package/content/agents/nami-planner.md +2 -2
- package/content/agents/resume-coordinator.md +11 -11
- package/content/agents/robin-reviewer.md +1 -1
- package/content/agents/sanji-quality.md +1 -1
- package/content/agents/skeptic-verifier.md +1 -1
- package/content/agents/usopp-brainstorm.md +2 -2
- package/content/agents/zoro-execution.md +3 -3
- package/content/skills/mugiwara-agent-security/SKILL.md +1 -18
- package/content/skills/mugiwara-agent-security/references/checklist.md +20 -0
- package/content/skills/mugiwara-brainstorm/SKILL.md +7 -1
- package/content/skills/mugiwara-execution/SKILL.md +14 -13
- package/content/skills/mugiwara-execution/references/resume-batching.md +4 -4
- package/content/skills/mugiwara-healing/SKILL.md +2 -37
- package/content/skills/mugiwara-healing/references/workers.md +38 -0
- package/content/skills/mugiwara-orchestration/SKILL.md +11 -8
- package/content/skills/mugiwara-orchestration/references/check-ins.md +26 -7
- package/content/skills/mugiwara-orchestration/references/closure.md +9 -0
- package/content/skills/mugiwara-orchestration/references/triage-escalation.md +9 -12
- package/content/skills/mugiwara-planning/SKILL.md +7 -11
- package/content/skills/mugiwara-planning/references/plan-template.md +4 -4
- package/content/skills/mugiwara-pr/SKILL.md +11 -19
- package/content/skills/mugiwara-pr/references/verdict-format.md +31 -0
- package/content/skills/mugiwara-resume/SKILL.md +37 -22
- package/content/skills/mugiwara-ship/SKILL.md +1 -23
- package/content/skills/mugiwara-ship/references/cleanup.md +25 -0
- package/content/skills/mugiwara-workflow/SKILL.md +7 -3
- package/content/skills/mugiwara-workflow/references/workspace-layout.md +11 -3
- package/content/skills/using-mugiwara/SKILL.md +1 -1
- package/dist/mugiwara.js +138 -42
- package/gemini-extension.json +1 -1
- package/hooks/session-start.ts +113 -2
- package/package.json +3 -3
- package/plugin.json +1 -1
- package/references/multi-actor.md +39 -14
- package/references/skill-versioning.md +3 -3
- package/references/token-budget.md +1 -1
- package/references/wave-banners.md +75 -0
- package/scripts/evidence.sh +9 -0
- package/scripts/gate-selftest.ts +154 -0
- package/scripts/lane-base.ts +114 -0
- package/scripts/lane.sh +5 -3
- package/scripts/lib/lane-base.sh +19 -0
- package/scripts/lib/patterns.sh +21 -0
- package/scripts/mission-report.sh +21 -5
- package/scripts/savepoint.sh +170 -56
- package/scripts/setup-fixtures.ts +108 -0
- package/scripts/validate-content.ts +61 -0
- package/src/cli.ts +5 -1
- package/src/installer.ts +70 -8
- package/src/mission.ts +37 -19
- package/src/targets/opencode.ts +34 -6
package/src/mission.ts
CHANGED
|
@@ -4,12 +4,23 @@ import { existsSync, rmSync, readFileSync, readdirSync, mkdirSync, appendFileSyn
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
|
|
6
6
|
function activeActor(projectDir: string): string | null {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
// state now lives at .mugiwara/state/<mission>/[member].json — scan the
|
|
8
|
+
// latest state file for its actor
|
|
9
|
+
const stateDir = join(projectDir, '.mugiwara', 'state');
|
|
10
|
+
if (!existsSync(stateDir)) return null;
|
|
11
|
+
const missions = readdirSync(stateDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name);
|
|
12
|
+
let latest: { actor: string; updated: number } | null = null;
|
|
13
|
+
for (const mission of missions) {
|
|
14
|
+
const d = join(stateDir, mission);
|
|
15
|
+
for (const f of readdirSync(d).filter(f => f.endsWith('.json'))) {
|
|
16
|
+
try {
|
|
17
|
+
const s = JSON.parse(readFileSync(join(d, f), 'utf8'));
|
|
18
|
+
const t = Date.parse(s.updated_at || '') || 0;
|
|
19
|
+
if (!latest || t > latest.updated) latest = { actor: s.actor || null, updated: t };
|
|
20
|
+
} catch { /* corrupt — skip */ }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return latest ? latest.actor : null;
|
|
13
24
|
}
|
|
14
25
|
|
|
15
26
|
export function resetMission(projectDir: string, keepLogs: boolean, force?: boolean): { removed: string[]; kept: string[]; blocked?: string } {
|
|
@@ -30,7 +41,12 @@ export function resetMission(projectDir: string, keepLogs: boolean, force?: bool
|
|
|
30
41
|
const p = join(root, dir);
|
|
31
42
|
if (existsSync(p)) { rmSync(p, { recursive: true, force: true }); removed.push(dir); }
|
|
32
43
|
}
|
|
33
|
-
// mission state
|
|
44
|
+
// mission state + continue folders — state/<mission>/, continue/<mission>/
|
|
45
|
+
for (const dir of ['state', 'continue']) {
|
|
46
|
+
const p = join(root, dir);
|
|
47
|
+
if (existsSync(p)) { rmSync(p, { recursive: true, force: true }); removed.push(dir); }
|
|
48
|
+
}
|
|
49
|
+
// legacy flat state files — state.json + branch-specific state-*.json
|
|
34
50
|
for (const f of readdirSync(root)) {
|
|
35
51
|
if (/^state(-.+)?\.json$/.test(f)) {
|
|
36
52
|
const p = join(root, f);
|
|
@@ -81,7 +97,8 @@ export function archiveMission(projectDir: string, mission: string, opts: { dryR
|
|
|
81
97
|
}
|
|
82
98
|
|
|
83
99
|
// step results 01..05 + todos.md are evidence — kept; archive removes
|
|
84
|
-
//
|
|
100
|
+
// step results 01..05 + todos.md are evidence — kept; archive removes
|
|
101
|
+
// only spec/review/issues/logs + continue/<mission>/ + state/<mission>/
|
|
85
102
|
const resultsDir = join(root, 'results', mission);
|
|
86
103
|
if (existsSync(resultsDir)) {
|
|
87
104
|
for (const f of readdirSync(resultsDir)) {
|
|
@@ -121,21 +138,22 @@ export function archiveMission(projectDir: string, mission: string, opts: { dryR
|
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
140
|
|
|
124
|
-
// continue
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
141
|
+
// continue/<mission>/ is a session handoff — remove this mission's folder
|
|
142
|
+
const contDir = join(root, 'continue', mission);
|
|
143
|
+
if (existsSync(contDir)) {
|
|
144
|
+
if (!dryRun) rmSync(contDir, { recursive: true, force: true });
|
|
145
|
+
removed.push(join('continue', mission));
|
|
146
|
+
}
|
|
147
|
+
// state/<mission>/ — remove this mission's computed state (archived)
|
|
148
|
+
const stateDir = join(root, 'state', mission);
|
|
149
|
+
if (existsSync(stateDir)) {
|
|
150
|
+
if (!dryRun) rmSync(stateDir, { recursive: true, force: true });
|
|
151
|
+
removed.push(join('state', mission));
|
|
134
152
|
}
|
|
135
153
|
|
|
136
154
|
// kept: report + the audit-trail survivors
|
|
137
155
|
if (report) kept.push(report);
|
|
138
|
-
for (const k of ['plans', 'config',
|
|
156
|
+
for (const k of ['plans', 'config', join('logs', 'lessons.md')]) {
|
|
139
157
|
if (existsSync(join(root, k))) kept.push(k);
|
|
140
158
|
}
|
|
141
159
|
|
package/src/targets/opencode.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/targets/opencode.ts
|
|
2
|
-
import { existsSync, readdirSync, copyFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { existsSync, readdirSync, copyFileSync, mkdirSync, readFileSync } 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';
|
|
@@ -7,6 +7,7 @@ import type { Target } from '../installer.ts';
|
|
|
7
7
|
|
|
8
8
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const COMMANDS_SRC = join(here, '..', '..', '.opencode', 'commands');
|
|
10
|
+
const BANNER_TABLE = join(here, '..', '..', 'references', 'wave-banners.md');
|
|
10
11
|
|
|
11
12
|
type CrewConfig = {
|
|
12
13
|
color: string;
|
|
@@ -15,23 +16,46 @@ type CrewConfig = {
|
|
|
15
16
|
permission?: Record<string, string>;
|
|
16
17
|
};
|
|
17
18
|
|
|
19
|
+
// Colors are fallbacks — the wave-banners table is the source of truth.
|
|
20
|
+
// Temperature/steps stay here (runtime tuning, not banner material).
|
|
18
21
|
const CREW: Record<string, CrewConfig> = {
|
|
19
22
|
'luffy-orchestrator': { color: '#ef4444', temperature: 0.2, steps: 15 },
|
|
20
|
-
'usopp-brainstorm': { color: '#
|
|
23
|
+
'usopp-brainstorm': { color: '#b45309', temperature: 0.6, steps: 15 },
|
|
21
24
|
'nami-planner': { color: '#f97316', temperature: 0.2, steps: 15 },
|
|
22
25
|
'zoro-execution': { color: '#22c55e', temperature: 0.1, steps: 30 },
|
|
23
|
-
'chopper-checkpoint': { color: '#
|
|
24
|
-
'sanji-quality': { color: '#
|
|
26
|
+
'chopper-checkpoint': { color: '#60a5fa', temperature: 0.1, steps: 15 },
|
|
27
|
+
'sanji-quality': { color: '#facc15', temperature: 0.1, steps: 10 },
|
|
25
28
|
'franky-gates': { color: '#06b6d4', temperature: 0.1, steps: 10 },
|
|
26
29
|
'robin-reviewer': { color: '#8b5cf6', temperature: 0.2, steps: 15 },
|
|
27
30
|
'jinbe-security': { color: '#6366f1', temperature: 0.2, steps: 15 },
|
|
28
|
-
'brook-healing': { color: '#
|
|
31
|
+
'brook-healing': { color: '#2dd4bf', temperature: 0.1, steps: 20 },
|
|
29
32
|
'skeptic-verifier': { color: '#64748b', temperature: 0.1, steps: 12 },
|
|
30
33
|
'eval-runner': { color: '#14b8a6', temperature: 0.2, steps: 15 },
|
|
31
34
|
'resume-coordinator': { color: '#d97706', temperature: 0.2, steps: 10 },
|
|
32
35
|
'memory-keeper': { color: '#d946ef', temperature: 0.2, steps: 8 },
|
|
33
36
|
};
|
|
34
37
|
|
|
38
|
+
// Crew colors from the wave-banners table (single source of truth). Returns
|
|
39
|
+
// {} on any failure — callers fall back to the CREW map. Same table shape as
|
|
40
|
+
// the opencode plugin parses: | agent-id | role | hex | ansi-256 | emoji |
|
|
41
|
+
function readBannerColors(): Record<string, string> {
|
|
42
|
+
try {
|
|
43
|
+
if (!existsSync(BANNER_TABLE)) return {};
|
|
44
|
+
const text = readFileSync(BANNER_TABLE, 'utf8');
|
|
45
|
+
// null-prototype + CRLF-tolerant: agent ids are trusted repo content, but
|
|
46
|
+
// a future `__proto__` id must never write the object's prototype
|
|
47
|
+
const colors: Record<string, string> = Object.create(null);
|
|
48
|
+
for (const m of text.matchAll(/^\| ([\w-]+) \| [^|]+ \| (#[0-9a-f]{6}) \| (\d+) \| (\S+) \|\r?$/gm)) {
|
|
49
|
+
colors[m[1]] = m[2];
|
|
50
|
+
}
|
|
51
|
+
return colors;
|
|
52
|
+
} catch {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const BANNER_COLORS = readBannerColors();
|
|
58
|
+
|
|
35
59
|
// write-scope is the single source of truth (content/agents/*.md frontmatter),
|
|
36
60
|
// but it is a RULE for user-facing crew agents: they run inline in the main
|
|
37
61
|
// thread, so a runtime permission bound to the active-agent identity would
|
|
@@ -50,8 +74,12 @@ function permissionFromScope(scope: string | undefined): Record<string, string |
|
|
|
50
74
|
function agentFrontmatter(name: string, description: string, internal: boolean, writeScope?: string) {
|
|
51
75
|
const crew = CREW[name];
|
|
52
76
|
const lines = [`description: ${description}`, `mode: all`];
|
|
77
|
+
// color: wave-banners table wins; CREW fallback for agents the table lacks.
|
|
78
|
+
// temperature/steps only exist for CREW members (runtime tuning).
|
|
79
|
+
const color = BANNER_COLORS[name] ?? crew?.color;
|
|
80
|
+
if (color) lines.push(`color: '${color}'`);
|
|
53
81
|
if (crew) {
|
|
54
|
-
lines.push(`
|
|
82
|
+
lines.push(`temperature: ${crew.temperature}`, `steps: ${crew.steps}`);
|
|
55
83
|
const perm = internal ? permissionFromScope(writeScope) : undefined;
|
|
56
84
|
if (perm) {
|
|
57
85
|
lines.push('permission:');
|