@ionivetech/mugiwara 0.5.1 → 0.5.3
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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/.claude-plugin/plugin.json +64 -0
- package/.claude-plugin/sync.sh +18 -0
- package/.codex-plugin/plugin.json +18 -0
- package/.cursor-plugin/plugin.json +19 -0
- package/.kimi-plugin/plugin.json +18 -0
- package/.opencode/commands/mugiwara.md +13 -7
- package/.opencode/commands/using-mugiwara.md +26 -0
- package/.opencode/plugins/mugiwara-helpers.mjs +90 -0
- package/.opencode/plugins/mugiwara.mjs +10 -107
- package/AGENTS.md +183 -0
- package/GEMINI.md +12 -0
- package/README.md +86 -56
- package/content/agents/luffy-orchestrator.md +1 -1
- package/content/agents/zoro-execution.md +1 -1
- package/content/skills/mugiwara-execution/SKILL.md +2 -5
- package/content/skills/{mugiwara-proof-order/SKILL.md → mugiwara-execution/references/tdd.md} +4 -7
- package/content/skills/using-mugiwara/SKILL.md +52 -0
- package/dist/mugiwara.js +35 -4
- package/docs/adoption-guide.md +1 -1
- package/docs/agents.md +5 -3
- package/docs/claude-setup.md +1 -1
- package/docs/developer-onboarding.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/index.md +1 -1
- package/docs/install-antigravity.md +45 -0
- package/docs/install-claude.md +75 -0
- package/docs/install-cli.md +103 -0
- package/docs/install-codex.md +44 -0
- package/docs/install-copilot.md +45 -0
- package/docs/install-cursor.md +45 -0
- package/docs/install-gemini.md +44 -0
- package/docs/install-kimi.md +45 -0
- package/docs/install-opencode.md +129 -0
- package/docs/install-pi.md +46 -0
- package/docs/install.md +53 -0
- package/docs/opencode-setup.md +1 -1
- package/docs/skills.md +1 -1
- package/evals/cases/routing-claim-audit.json +1 -1
- package/evals/cases/routing-using-mugiwara.json +25 -0
- package/evals/floor.json +1 -1
- package/gemini-extension.json +6 -0
- package/hooks/hooks.json +11 -0
- package/hooks/mugiwara-mode-tracker.ts +80 -0
- package/hooks/session-start.ts +1 -1
- package/package.json +13 -2
- package/plugin.json +15 -0
- package/src/targets/opencode.ts +39 -3
- package/.opencode/commands/mugiwara-mode.md +0 -6
- package/content/agents/using-mugiwara.md +0 -44
- package/content/skills/mugiwara-proof-order/references/proof-order-examples.md +0 -62
- package/evals/cases/routing-proof-order.json +0 -25
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// hooks/mugiwara-mode-tracker.ts — UserPromptSubmit hook: intercepts
|
|
3
|
+
// /mugiwara <mode> commands in Claude Code chat and writes .mugiwara/config.
|
|
4
|
+
// Same logic as the OpenCode plugin's chat.message hook, standalone for
|
|
5
|
+
// Claude Code's hook process model.
|
|
6
|
+
//
|
|
7
|
+
// Input: JSON on stdin with { prompt: "..." }
|
|
8
|
+
// Output: JSON on stdout with { prompt: "..." } (pass-through)
|
|
9
|
+
|
|
10
|
+
const VALID_MODES = new Set(['guided', 'semi', 'auto']);
|
|
11
|
+
|
|
12
|
+
function parseModeChange(promptRaw: string): string | null {
|
|
13
|
+
if (typeof promptRaw !== 'string') return null;
|
|
14
|
+
let prompt = promptRaw.trim();
|
|
15
|
+
const wrapped = /^(["'`])([\s\S]*)\1$/.exec(prompt);
|
|
16
|
+
if (wrapped) prompt = wrapped[2].trim();
|
|
17
|
+
prompt = prompt.toLowerCase();
|
|
18
|
+
if (!prompt) return null;
|
|
19
|
+
|
|
20
|
+
const tplSet = /^(?:set |)mugiwara mode:[ \t]*(\S*)/.exec(prompt);
|
|
21
|
+
if (tplSet && VALID_MODES.has(tplSet[1])) return tplSet[1];
|
|
22
|
+
|
|
23
|
+
const slashMode = /^\/(?:mugiwara[-\s]?)?mode[ \t]+(\S*)/.exec(prompt);
|
|
24
|
+
if (slashMode && VALID_MODES.has(slashMode[1])) return slashMode[1];
|
|
25
|
+
|
|
26
|
+
const slashMain = /^\/mugiwara[ \t]+(\S*)/.exec(prompt);
|
|
27
|
+
if (slashMain && VALID_MODES.has(slashMain[1])) return slashMain[1];
|
|
28
|
+
|
|
29
|
+
const natural = /^mugiwara mode[ \t]+(\S*)/.exec(prompt);
|
|
30
|
+
if (natural && VALID_MODES.has(natural[1])) return natural[1];
|
|
31
|
+
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from 'node:fs';
|
|
36
|
+
import { homedir, tmpdir } from 'node:os';
|
|
37
|
+
import { dirname, join } from 'node:path';
|
|
38
|
+
|
|
39
|
+
function applyModeChange(mode: string) {
|
|
40
|
+
if (!VALID_MODES.has(mode)) return;
|
|
41
|
+
const cwd = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
42
|
+
const dir = join(cwd, '.mugiwara');
|
|
43
|
+
const file = join(dir, 'config');
|
|
44
|
+
mkdirSync(dir, { recursive: true });
|
|
45
|
+
const lines: string[] = [];
|
|
46
|
+
if (existsSync(file)) {
|
|
47
|
+
for (const line of readFileSync(file, 'utf8').split(/\r?\n/)) {
|
|
48
|
+
const t = line.trim();
|
|
49
|
+
if (t.startsWith('mode=')) continue;
|
|
50
|
+
lines.push(line);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
lines.push(`mode=${mode}`);
|
|
54
|
+
const body = lines.filter((_l, i) => !(lines[i] === '' && (i === lines.length - 1 || i === 0))).join('\n') + '\n';
|
|
55
|
+
const tmp = join(tmpdir(), `mugiwara-config-${process.pid}-${Date.now()}.tmp`);
|
|
56
|
+
writeFileSync(tmp, body);
|
|
57
|
+
renameSync(tmp, file);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// main
|
|
61
|
+
async function main() {
|
|
62
|
+
let input = '';
|
|
63
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
64
|
+
if (!input.trim()) { process.stdout.write(JSON.stringify({ prompt: '' })); return; }
|
|
65
|
+
|
|
66
|
+
let parsed: { prompt?: string };
|
|
67
|
+
try { parsed = JSON.parse(input); } catch { parsed = { prompt: input }; }
|
|
68
|
+
const prompt = parsed.prompt ?? '';
|
|
69
|
+
|
|
70
|
+
const change = parseModeChange(prompt);
|
|
71
|
+
if (change) applyModeChange(change);
|
|
72
|
+
|
|
73
|
+
// pass-through — always return the prompt unchanged
|
|
74
|
+
process.stdout.write(JSON.stringify({ prompt }));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch(() => {
|
|
78
|
+
// silent — hook must never block the conversation
|
|
79
|
+
process.stdout.write(JSON.stringify({ prompt: '' }));
|
|
80
|
+
});
|
package/hooks/session-start.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
console.log(
|
|
4
4
|
JSON.stringify({
|
|
5
5
|
additionalContext:
|
|
6
|
-
"Mugiwara crew available. The workflow auto-activates for non-trivial requests (no need to call `/using-mugiwara` at session start; it is optional and routes to the right crew member). The crew runs inline in the main thread — Never Task-dispatch a crew member. Subagents only for [PARALLEL] task batches, concurrent review/security, and independent re-run checks. Checkpoint reports at wave/stage boundaries. Mode: guided / semi / auto (see .mugiwara/config). See skills/mugiwara-workflow."
|
|
6
|
+
"Mugiwara crew available. The workflow auto-activates for non-trivial requests (no need to call `/using-mugiwara` at session start; it is optional and routes to the right crew member). The crew runs inline in the main thread — Never Task-dispatch a crew member. Subagents only for [PARALLEL] task batches, concurrent review/security, and independent re-run checks. Checkpoint reports at wave/stage boundaries. Mode: guided / semi / auto (see .mugiwara/config). Switch with `/mugiwara <mode>`. See skills/mugiwara-workflow."
|
|
7
7
|
})
|
|
8
8
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ionivetech/mugiwara",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "The Straw Hat crew of AI agents and skills: brainstorm, plan, execute, checkpoint, quality, gates, review, security, self-healing. Installs into Claude Code, opencode, Copilot, Gemini, Codex, Cursor, Kimi, pi, Windsurf, Cline, Kilo, Antigravity.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,16 @@
|
|
|
22
22
|
"evals",
|
|
23
23
|
"scripts",
|
|
24
24
|
".opencode",
|
|
25
|
+
".claude-plugin",
|
|
26
|
+
".codex-plugin",
|
|
27
|
+
".cursor-plugin",
|
|
28
|
+
".kimi-plugin",
|
|
29
|
+
".agents",
|
|
25
30
|
"hooks",
|
|
31
|
+
"gemini-extension.json",
|
|
32
|
+
"GEMINI.md",
|
|
33
|
+
"AGENTS.md",
|
|
34
|
+
"plugin.json",
|
|
26
35
|
"README.md",
|
|
27
36
|
"LICENSE"
|
|
28
37
|
],
|
|
@@ -43,7 +52,8 @@
|
|
|
43
52
|
"evals": "bun scripts/run-evals.ts",
|
|
44
53
|
"retrieval-eval": "bun scripts/retrieval-eval.ts",
|
|
45
54
|
"sync-version": "bun scripts/sync-version.ts",
|
|
46
|
-
"gate": "bun run typecheck && bun run test && bun run build && bun scripts/validate-content.ts --check-manifest --check-docs && bun scripts/run-evals.ts && bun scripts/retrieval-eval.ts",
|
|
55
|
+
"gate": "bun run typecheck && bun run test && bun run build && bun scripts/validate-content.ts --check-manifest --check-docs && bun run verify-pack && bun scripts/run-evals.ts && bun scripts/retrieval-eval.ts",
|
|
56
|
+
"verify-pack": "npm pack --dry-run 2>&1 | grep -q 'ionivetech-mugiwara' && echo '✓ npm package clean' || (echo '✗ npm pack failed' && exit 1)",
|
|
47
57
|
"prepack": "bun run build && bun run sync-version"
|
|
48
58
|
},
|
|
49
59
|
"keywords": [
|
|
@@ -66,6 +76,7 @@
|
|
|
66
76
|
],
|
|
67
77
|
"devDependencies": {
|
|
68
78
|
"@types/node": "^26.2.0",
|
|
79
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
69
80
|
"typescript": "^7.0.2",
|
|
70
81
|
"vitest": "^4.1.10"
|
|
71
82
|
}
|
package/plugin.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mugiwara",
|
|
3
|
+
"description": "The Straw Hat crew of AI agents and skills: brainstorm, plan, execute, checkpoint, quality, gates, review, security, healing.",
|
|
4
|
+
"version": "0.5.3",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "ionive"
|
|
7
|
+
},
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": "https://github.com/ionivetech/mugiwara",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"agents",
|
|
12
|
+
"skills",
|
|
13
|
+
"workflow"
|
|
14
|
+
]
|
|
15
|
+
}
|
package/src/targets/opencode.ts
CHANGED
|
@@ -3,6 +3,43 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { stringifyFrontmatter, type FrontmatterData } from '../frontmatter.ts';
|
|
4
4
|
import type { Target } from '../installer.ts';
|
|
5
5
|
|
|
6
|
+
type CrewConfig = {
|
|
7
|
+
color: string;
|
|
8
|
+
temperature: number;
|
|
9
|
+
steps: number;
|
|
10
|
+
permission?: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const CREW: Record<string, CrewConfig> = {
|
|
14
|
+
'luffy-orchestrator': { color: '#ef4444', temperature: 0.2, steps: 15 },
|
|
15
|
+
'usopp-brainstorm': { color: '#f59e0b', temperature: 0.6, steps: 15 },
|
|
16
|
+
'nami-planner': { color: '#f97316', temperature: 0.2, steps: 15 },
|
|
17
|
+
'zoro-execution': { color: '#22c55e', temperature: 0.1, steps: 30 },
|
|
18
|
+
'chopper-checkpoint': { color: '#3b82f6', temperature: 0.1, permission: { edit: 'deny' }, steps: 15 },
|
|
19
|
+
'sanji-quality': { color: '#a855f7', temperature: 0.1, permission: { edit: 'deny' }, steps: 10 },
|
|
20
|
+
'franky-gates': { color: '#06b6d4', temperature: 0.1, permission: { edit: 'deny' }, steps: 10 },
|
|
21
|
+
'robin-reviewer': { color: '#8b5cf6', temperature: 0.2, permission: { edit: 'deny' }, steps: 15 },
|
|
22
|
+
'jinbe-security': { color: '#6366f1', temperature: 0.2, permission: { edit: 'deny' }, steps: 15 },
|
|
23
|
+
'brook-healing': { color: '#ec4899', temperature: 0.1, steps: 20 },
|
|
24
|
+
'skeptic-verifier': { color: '#64748b', temperature: 0.1, permission: { edit: 'deny' }, steps: 12 },
|
|
25
|
+
'eval-runner': { color: '#14b8a6', temperature: 0.2, steps: 15 },
|
|
26
|
+
'resume-coordinator': { color: '#d97706', temperature: 0.2, steps: 10 },
|
|
27
|
+
'memory-keeper': { color: '#d946ef', temperature: 0.2, steps: 8 },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function agentFrontmatter(name: string, description: string) {
|
|
31
|
+
const crew = CREW[name];
|
|
32
|
+
const lines = [`description: ${description}`, `mode: all`];
|
|
33
|
+
if (crew) {
|
|
34
|
+
lines.push(`color: '${crew.color}'`, `temperature: ${crew.temperature}`, `steps: ${crew.steps}`);
|
|
35
|
+
if (crew.permission) {
|
|
36
|
+
lines.push('permission:');
|
|
37
|
+
for (const [k, v] of Object.entries(crew.permission)) lines.push(` ${k}: ${v}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return lines.join('\n');
|
|
41
|
+
}
|
|
42
|
+
|
|
6
43
|
export const target: Target = {
|
|
7
44
|
id: 'opencode',
|
|
8
45
|
label: 'opencode',
|
|
@@ -18,9 +55,8 @@ export const target: Target = {
|
|
|
18
55
|
};
|
|
19
56
|
},
|
|
20
57
|
transformAgent(data: FrontmatterData, body: string) {
|
|
21
|
-
const fm
|
|
22
|
-
|
|
23
|
-
return { relPath: `${data.name}.md`, text: stringifyFrontmatter(fm, body) };
|
|
58
|
+
const fm = agentFrontmatter(data.name, data.description);
|
|
59
|
+
return { relPath: `${data.name}.md`, text: `---\n${fm}\n---\n${body}` };
|
|
24
60
|
},
|
|
25
61
|
refsDir({ scope, projectDir, home }, skillName: string) {
|
|
26
62
|
const root = scope === 'global' ? join(home, '.config', 'opencode') : join(projectDir, '.opencode');
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: using-mugiwara
|
|
3
|
-
description: Front-door router. Classifies missions, routes to specialist. Never implements.
|
|
4
|
-
skills: mugiwara-workflow, mugiwara-orchestration, mugiwara-pr
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Using Mugiwara (Front Door)
|
|
8
|
-
|
|
9
|
-
The easy entry point to the crew. Say "use mugiwara" or invoke `using-mugiwara` — you do not need to remember agent names. Embodied inline by the main thread; returns the route, never dispatches a crew member.
|
|
10
|
-
|
|
11
|
-
## Auto-activation
|
|
12
|
-
|
|
13
|
-
The workflow auto-activates for non-trivial requests — you do NOT need to call `using-mugiwara` at session start. This agent is an OPTIONAL explicit router: use it for a "how do I use mugiwara?" explanation or to route a mission by hand. For ANY non-trivial request, check before responding: if the mugiwara workflow could apply, run it — invoke the skill and start Wave 0 triage. Do not skip the check ("this is just a question", "I'll just do this one thing first", "I can explore first"). Process first: the crew workflow, then the specialized skill.
|
|
14
|
-
|
|
15
|
-
## Experience
|
|
16
|
-
|
|
17
|
-
Front-door router, 20 years of triage. Abilities: fast 5-way classification, knowing exactly which specialist to send, no-implementation discipline.
|
|
18
|
-
|
|
19
|
-
## What to do
|
|
20
|
-
|
|
21
|
-
1. **If the user asks how mugiwara works** — summarize in a few lines: the crew (Luffy gates, Nami plans, Zoro executes, Chopper audits, Brook heals), the workspace (`.mugiwara/`), and that every non-trivial mission starts with Luffy triage. Point to `mugiwara-workflow` for the full pipeline.
|
|
22
|
-
2. **If the user gives a mission or task** — classify it (Trivial / Explicit / Exploratory / Open-ended / Ambiguous) and route:
|
|
23
|
-
- Clear, small, well-understood → route to `nami-planner` directly (or `zoro-execution` if a plan already exists).
|
|
24
|
-
- Vague idea, needs direction, research, or options → route to `usopp-brainstorm`.
|
|
25
|
-
- Anything else / not sure → route to `luffy-orchestrator` (full 5-way triage + check-ins).
|
|
26
|
-
- Specialized asks map directly: review → `robin-reviewer`, security → `jinbe-security`, fix failures → `brook-healing`, audit → `chopper-checkpoint`, resume → `resume-coordinator`, past lessons → `memory-keeper`.
|
|
27
|
-
3. **Record the route** in the decision log (`.mugiwara/logs/YYYY-MM-DD-<mission>.md`) with a one-line reason — the harness stays coherent even when the entry was `using-mugiwara`. Read the active mode from `.mugiwara/config` (project then global config, missing = guided) and mention it in the route record so the session starts on the right level. Never write into the plan doc.
|
|
28
|
-
|
|
29
|
-
## Rules
|
|
30
|
-
|
|
31
|
-
1. Follow `mugiwara-workflow` and `mugiwara-orchestration` for the pipeline; this agent only routes.
|
|
32
|
-
2. Never start implementation yourself — you are the front door, not a doer.
|
|
33
|
-
3. Ambiguous → default to `luffy-orchestrator`, never guess a specialist.
|
|
34
|
-
4. Direct calls do not skip Luffy's check-ins on the mission that follows.
|
|
35
|
-
|
|
36
|
-
## Output
|
|
37
|
-
|
|
38
|
-
Route decision + reason, written to the decision log (`.mugiwara/logs/YYYY-MM-DD-<mission>.md`). If no mission yet, a short "how to use" summary to the user.
|
|
39
|
-
|
|
40
|
-
## Red flags
|
|
41
|
-
|
|
42
|
-
- Implementing code instead of routing.
|
|
43
|
-
- Guessing a specialist for an ambiguous request instead of sending it to Luffy.
|
|
44
|
-
- Starting a mission without recording the route.
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Proof Order Examples
|
|
2
|
-
|
|
3
|
-
The test's proof value comes from WHEN it runs, not that it exists.
|
|
4
|
-
|
|
5
|
-
## Why order matters
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
❌ Write implementation → Write test → Test passes immediately
|
|
9
|
-
The test never demonstrated it could catch the bug.
|
|
10
|
-
You cannot prove the test is testing the right thing.
|
|
11
|
-
|
|
12
|
-
✅ Write test (red) → Watch it fail → Write implementation → Test passes (green)
|
|
13
|
-
The red phase proves the test catches the absence of the feature.
|
|
14
|
-
The green phase proves the feature satisfies the test.
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Example: password validation
|
|
18
|
-
|
|
19
|
-
```ts
|
|
20
|
-
// RED — test first, watch it fail
|
|
21
|
-
describe('validatePassword', () => {
|
|
22
|
-
it('rejects passwords shorter than 8 characters', () => {
|
|
23
|
-
expect(validatePassword('short')).toBe(false);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// FAIL: validatePassword is not defined
|
|
28
|
-
|
|
29
|
-
// GREEN — minimal impl
|
|
30
|
-
function validatePassword(pw: string): boolean {
|
|
31
|
-
return pw.length >= 8;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// REFACTOR — while green
|
|
35
|
-
function validatePassword(pw: string): boolean {
|
|
36
|
-
if (pw.length < 8) return false;
|
|
37
|
-
if (!/[A-Z]/.test(pw)) return false;
|
|
38
|
-
if (!/[0-9]/.test(pw)) return false;
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Anti-pattern: test after implementation
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
// Code already written, then test added later:
|
|
47
|
-
function formatCurrency(amount: number): string {
|
|
48
|
-
return `$${amount.toFixed(2)}`;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Test passes immediately — proves nothing:
|
|
52
|
-
it('formats currency', () => {
|
|
53
|
-
expect(formatCurrency(10)).toBe('$10.00'); // green on first run
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The fix: comment out the implementation, watch the test fail, then uncomment.
|
|
58
|
-
If the test still passes with implementation removed, the test is wrong.
|
|
59
|
-
|
|
60
|
-
## Rule
|
|
61
|
-
|
|
62
|
-
A test that passes on first run has proven nothing. Discard the implementation and redo test-first, or comment it out and prove the test actually fails before restoring.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "routing-proof-order",
|
|
3
|
-
"skill": "mugiwara-proof-order",
|
|
4
|
-
"trigger": {
|
|
5
|
-
"positive": [
|
|
6
|
-
{ "prompt": "write the test first before implementing the function", "top_k": 3 },
|
|
7
|
-
{ "prompt": "use TDD — red green refactor for this feature", "top_k": 3 },
|
|
8
|
-
{ "prompt": "prove the behavior with a failing test, then implement", "top_k": 3 }
|
|
9
|
-
],
|
|
10
|
-
"negative": [
|
|
11
|
-
{ "prompt": "run the existing unit test suite that was written last week" },
|
|
12
|
-
{ "prompt": "run the acceptance tests defined by the user" }
|
|
13
|
-
]
|
|
14
|
-
},
|
|
15
|
-
"behavioral": [
|
|
16
|
-
{
|
|
17
|
-
"task": "Implement a new utility function. Write the test first, then the implementation, then refactor.",
|
|
18
|
-
"rubric": [
|
|
19
|
-
"follows RED-GREEN-REFACTOR discipline",
|
|
20
|
-
"writes the test before the implementation",
|
|
21
|
-
"one test = one behavior"
|
|
22
|
-
]
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|