@bongos/core 1.19.637 → 1.19.638
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/.bongos-core.json +53 -43
- package/.claude/skills/builder-sequence/SKILL.md +2 -2
- package/.claude/skills/design/SKILL.md +2 -2
- package/docs/adr/0274-one-kernel-three-role-packs.md +55 -0
- package/docs/adr/README.md +1 -0
- package/docs/file-map.md +5 -4
- package/docs/module-api-changelog.md +2 -0
- package/docs/onboarding/slash-commands.md +2 -2
- package/docs/packs/artist.md +78 -0
- package/docs/packs/engineer.md +107 -0
- package/docs/packs/ideator.md +125 -0
- package/modules/lifecycle/ship-card.js +19 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/claim.js +21 -9
- package/scripts/gds/discipline-modes.json +8 -8
- package/scripts/gds/fitness.js +6 -0
- package/scripts/gds/publish-manifest.js +9 -0
- package/scripts/gds/role-pack-guard.js +121 -0
- package/src/module-api.js +1 -1
- package/tests/edit_hints.mjs +1 -1
- package/tests/fitness.mjs +96 -0
- package/tests/idea_ideate_full.mjs +10 -4
- package/tests/module-scope-map.mjs +4 -3
- package/tests/publish_manifest.mjs +2 -1
- package/tests/ship_card.mjs +18 -4
- package/.claude/skills/dev/SKILL.md +0 -49
- package/.claude/skills/ideate/SKILL.md +0 -164
- package/.claude/skills/paint/SKILL.md +0 -71
package/tests/fitness.mjs
CHANGED
|
@@ -57,6 +57,102 @@ test('CLAUDE.md char budget is ratcheted and ordered (target < ceiling, live fil
|
|
|
57
57
|
assert.equal(r.hardFail, false, 'the live CLAUDE.md must be under the char ceiling (ratchet locked in)');
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
// --- the role packs (task 1002990 / ADR 0274) --------------------------------
|
|
61
|
+
//
|
|
62
|
+
// This guard is the ONLY place a broken pack path can surface: claim.js reads the
|
|
63
|
+
// role registry fail-open so it can never break a granted claim, which means an
|
|
64
|
+
// entry pointing at a missing file degrades to silence — the craft's label prints
|
|
65
|
+
// and its playbook never loads. The ADR rests the whole hard-fail argument on that,
|
|
66
|
+
// so an untested guard would undermine its own rationale. Hence both legs, the same
|
|
67
|
+
// pair every sibling guard here carries: the live tree is clean, AND the check
|
|
68
|
+
// actually catches the failure rather than being a no-op.
|
|
69
|
+
const rolePacks = require(path.join(ROOT, 'scripts', 'gds', 'role-pack-guard.js'));
|
|
70
|
+
|
|
71
|
+
test('role packs: the live registry resolves and every pack is under budget', () => {
|
|
72
|
+
const r = rolePacks.checkRolePacks();
|
|
73
|
+
assert.equal(r.hardFail, false, r.violations.join('\n'));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('role pack budget is ratcheted and ordered (target < ceiling)', () => {
|
|
77
|
+
assert.ok(rolePacks.PACK_CHAR_TARGET < rolePacks.PACK_CHAR_HARD_MAX, 'target must sit below the hard ceiling');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('role pack guard actually CATCHES a missing pack, a pointerless entry, and a short roster (not a no-op)', () => {
|
|
81
|
+
const real = fs;
|
|
82
|
+
const withRegistry = (modes) => ({
|
|
83
|
+
readFileSync: (p, e) => (String(p).includes('discipline-modes.json') ? JSON.stringify({ modes }) : real.readFileSync(p, e)),
|
|
84
|
+
existsSync: (p) => (String(p).includes('__gone__') ? false : real.existsSync(p)),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// (1) the silent runtime failure: a pack path that resolves to nothing.
|
|
88
|
+
const missing = rolePacks.checkRolePacks(withRegistry({
|
|
89
|
+
engineer: { pack: 'docs/packs/__gone__.md', directive: 'x' },
|
|
90
|
+
artist: { pack: 'docs/packs/artist.md', directive: 'x' },
|
|
91
|
+
ideator: { pack: 'docs/packs/ideator.md', directive: 'x' },
|
|
92
|
+
}));
|
|
93
|
+
assert.equal(missing.hardFail, true, 'a pack that is not in the tree must hard-fail');
|
|
94
|
+
assert.ok(missing.violations.some((v) => /__gone__/.test(v) && /not in the tree/.test(v)), 'the violation must name the unresolvable path');
|
|
95
|
+
|
|
96
|
+
// (2) an entry routing a claim to no playbook at all.
|
|
97
|
+
const pointerless = rolePacks.checkRolePacks(withRegistry({
|
|
98
|
+
engineer: { pack: 'docs/packs/engineer.md', directive: 'x' },
|
|
99
|
+
artist: { pack: 'docs/packs/artist.md', directive: 'x' },
|
|
100
|
+
ideator: { pack: 'docs/packs/ideator.md', directive: 'x' },
|
|
101
|
+
ui: { directive: 'x' },
|
|
102
|
+
}));
|
|
103
|
+
assert.equal(pointerless.hardFail, true, 'an entry with neither pack nor skill must hard-fail');
|
|
104
|
+
assert.ok(pointerless.violations.some((v) => /'ui'/.test(v) && /neither/.test(v)));
|
|
105
|
+
|
|
106
|
+
// (3) a craft quietly dropped back into the kernel — the split's own shape.
|
|
107
|
+
const short = rolePacks.checkRolePacks(withRegistry({
|
|
108
|
+
engineer: { pack: 'docs/packs/engineer.md', directive: 'x' },
|
|
109
|
+
artist: { pack: 'docs/packs/artist.md', directive: 'x' },
|
|
110
|
+
ideator: { skill: 'ideate', directive: 'x' },
|
|
111
|
+
}));
|
|
112
|
+
assert.equal(short.hardFail, true, 'fewer than three packs must hard-fail');
|
|
113
|
+
assert.ok(short.violations.some((v) => /only 2 craft/.test(v)));
|
|
114
|
+
|
|
115
|
+
// (4) an over-budget pack — the "CI budgets each pack" half of the criterion.
|
|
116
|
+
const fat = rolePacks.checkRolePacks({
|
|
117
|
+
readFileSync: (p, e) => {
|
|
118
|
+
if (String(p).includes('discipline-modes.json')) {
|
|
119
|
+
return JSON.stringify({ modes: {
|
|
120
|
+
engineer: { pack: 'docs/packs/engineer.md', directive: 'x' },
|
|
121
|
+
artist: { pack: 'docs/packs/artist.md', directive: 'x' },
|
|
122
|
+
ideator: { pack: 'docs/packs/ideator.md', directive: 'x' },
|
|
123
|
+
} });
|
|
124
|
+
}
|
|
125
|
+
return 'x'.repeat(rolePacks.PACK_CHAR_HARD_MAX + 1);
|
|
126
|
+
},
|
|
127
|
+
existsSync: () => true,
|
|
128
|
+
});
|
|
129
|
+
assert.equal(fat.hardFail, true, 'a pack over the char ceiling must hard-fail');
|
|
130
|
+
assert.ok(fat.violations.some((v) => /hard ceiling/.test(v)));
|
|
131
|
+
|
|
132
|
+
// …and the guard is not simply always-red: the real tree passes (leg 1 above),
|
|
133
|
+
// and an unreadable registry is itself the failure rather than a free pass.
|
|
134
|
+
const unreadable = rolePacks.checkRolePacks({
|
|
135
|
+
readFileSync: () => { throw new Error('boom'); },
|
|
136
|
+
existsSync: () => true,
|
|
137
|
+
});
|
|
138
|
+
assert.equal(unreadable.hardFail, true, 'an unreadable registry must fail, not fail open like claim.js');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// The ship card mirrors the registry by hand — it cannot require a core script
|
|
142
|
+
// across the module boundary, which is why claim.js and ship-card.js have always
|
|
143
|
+
// carried the map twice (task 1003487 was that duplication drifting). A test is the
|
|
144
|
+
// shared source they cannot have: rename a pack and this fails instead of the hall
|
|
145
|
+
// shipping a button that opens nothing.
|
|
146
|
+
test('ship-card routing agrees with the role registry, entry for entry', () => {
|
|
147
|
+
const registry = JSON.parse(fs.readFileSync(path.join(ROOT, 'scripts', 'gds', 'discipline-modes.json'), 'utf8')).modes;
|
|
148
|
+
const card = require(path.join(ROOT, 'modules', 'lifecycle', 'ship-card.js'));
|
|
149
|
+
for (const [discipline, mode] of Object.entries(registry)) {
|
|
150
|
+
const cmd = card.buildCardModel({ stage: 'claimed', taskId: 1, discipline, brand: { currency: 'credits' } }).action.cmd;
|
|
151
|
+
if (mode.pack) assert.ok(cmd.includes(mode.pack), `${discipline}: card says "${cmd}" but the registry names ${mode.pack}`);
|
|
152
|
+
else if (mode.skill) assert.equal(cmd, `/${mode.skill}`, `${discipline}: card and registry disagree on the skill`);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
60
156
|
test('nested CLAUDE.md present for every high-traffic dir', () => {
|
|
61
157
|
const r = fitness.checkNestedDocsPresent();
|
|
62
158
|
assert.equal(r.hardFail, false, r.violations.join('\n'));
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
// tests/idea_ideate_full.mjs
|
|
2
2
|
//
|
|
3
|
-
// task 1002931 (BV1.R155, goal 1000062) —
|
|
4
|
-
// conversationally.
|
|
3
|
+
// task 1002931 (BV1.R155, goal 1000062) — the ideator's playbook authors a Full
|
|
4
|
+
// Idea conversationally.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
6
|
+
// WHERE THAT PLAYBOOK LIVES (task 1002990). It used to be the /ideate skill. The
|
|
7
|
+
// kernel/pack split moved it into the Ideator role pack and deleted the skill, so
|
|
8
|
+
// this suite now reads docs/packs/ideator.md. Every contract below is unchanged —
|
|
9
|
+
// the file moved, the promises did not — and pointing the suite at the new home is
|
|
10
|
+
// what stops the split from silently dropping the guard with the skill.
|
|
11
|
+
//
|
|
12
|
+
// A pack is a prompt, so the thing to pin is the PROMPT'S CONTRACT. Two
|
|
7
13
|
// done-when clauses, and both are checkable:
|
|
8
14
|
//
|
|
9
15
|
// 1. "indistinguishable in the database from one authored in the hall" — so the
|
|
@@ -30,7 +36,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
30
36
|
|
|
31
37
|
const require = createRequire(import.meta.url);
|
|
32
38
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
33
|
-
const SKILL = fs.readFileSync(path.join(ROOT, '
|
|
39
|
+
const SKILL = fs.readFileSync(path.join(ROOT, 'docs/packs/ideator.md'), 'utf8');
|
|
34
40
|
// Prose assertions run against a WHITESPACE-NORMALISED copy. Markdown is hard-
|
|
35
41
|
// wrapped, so any phrase long enough to be worth asserting will eventually
|
|
36
42
|
// straddle a newline — and a regex that does not allow for that fails on a
|
|
@@ -231,9 +231,10 @@ test('methodology joined the roster (task 1002989) — the instruction surfaces
|
|
|
231
231
|
const covers = (touch) => gsc.scopeSubset(['methodology'], [touch]).ok;
|
|
232
232
|
for (const touch of [
|
|
233
233
|
'CLAUDE.md', // the kernel half of the split (1002990)
|
|
234
|
-
'
|
|
235
|
-
'
|
|
236
|
-
'
|
|
234
|
+
'docs/packs/engineer.md', // the three role packs the split authored (1002990)
|
|
235
|
+
'docs/packs/artist.md',
|
|
236
|
+
'docs/packs/ideator.md',
|
|
237
|
+
'.claude/skills/status/SKILL.md', // the skills floor no module claims
|
|
237
238
|
'.claude/rules/content-charter.md', // pre-carved for task 1003687
|
|
238
239
|
'docs/adr/0264-the-ten-working-areas.md', // the ADR library
|
|
239
240
|
'docs/handoff-template.md',
|
|
@@ -77,7 +77,8 @@ const PUBLISH = [
|
|
|
77
77
|
'docs/handoff-template.md', // portable session-handoff format
|
|
78
78
|
'docs/project-context.template.md', // the neutral scaffold (NOT the OTB-filled one)
|
|
79
79
|
'config/design-tokens.schema.json', // generic contract schema
|
|
80
|
-
'.claude/skills/
|
|
80
|
+
'.claude/skills/status/SKILL.md',
|
|
81
|
+
'docs/packs/engineer.md', // the role packs the kernel/pack split moved the methodology into (task 1002990)
|
|
81
82
|
'package.json',
|
|
82
83
|
'Dockerfile',
|
|
83
84
|
'.env.local.example',
|
package/tests/ship_card.mjs
CHANGED
|
@@ -201,14 +201,28 @@ test('claimed: neutral tone, scope rows, discipline action, brief in dropdown',
|
|
|
201
201
|
assert.equal(row(m, 'Estimate'), '~2h');
|
|
202
202
|
assert.equal(row(m, 'Touches'), '4 files');
|
|
203
203
|
assert.equal(row(m, 'Value'), undefined); // no value summary pre-work
|
|
204
|
-
assert.equal(m.action.cmd, '/
|
|
204
|
+
assert.equal(m.action.cmd, 'Read docs/packs/engineer.md and start the work');
|
|
205
205
|
const html = card.renderCardHtml(m);
|
|
206
206
|
assert.match(html, /Extend the card to every stage\./); // brief in dropdown
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
209
|
+
// The card must open the SAME playbook the claim just named, or it reintroduces the
|
|
210
|
+
// 1003487 divergence. Since task 1002990 the three core crafts have no slash command
|
|
211
|
+
// left to open — /dev, /paint and /ideate were deleted with the kernel/pack split —
|
|
212
|
+
// so the card points at the pack file; a module-contributed discipline still routes
|
|
213
|
+
// to its skill. A '/' prefix on a core craft here means a dead command in the hall.
|
|
214
|
+
test('claimed action routes by discipline — core crafts to their pack, modules to their skill', () => {
|
|
215
|
+
const cmdFor = (discipline) => card.buildCardModel({ stage: 'claimed', taskId: 1, discipline, brand: BRAND }).action.cmd;
|
|
216
|
+
assert.equal(cmdFor('artist'), 'Read docs/packs/artist.md and start the work');
|
|
217
|
+
assert.equal(cmdFor('ideator'), 'Read docs/packs/ideator.md and start the work');
|
|
218
|
+
assert.equal(cmdFor('ui'), '/design');
|
|
219
|
+
// An unknown or unset discipline falls back to the Engineer pack, exactly as it
|
|
220
|
+
// used to fall back to /dev — engineering is the project's default loop.
|
|
221
|
+
assert.equal(cmdFor('unclassified'), 'Read docs/packs/engineer.md and start the work');
|
|
222
|
+
assert.equal(cmdFor(undefined), 'Read docs/packs/engineer.md and start the work');
|
|
223
|
+
for (const d of ['engineer', 'artist', 'ideator']) {
|
|
224
|
+
assert.ok(!cmdFor(d).startsWith('/'), `${d} must not be routed to a slash command — /dev, /paint and /ideate no longer exist`);
|
|
225
|
+
}
|
|
212
226
|
});
|
|
213
227
|
|
|
214
228
|
// ---- review ----
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dev
|
|
3
|
-
description: The engineering session — the operating playbook for engineer-discipline work (code, infra, Bongos itself, bugs, performance). Triggers when the user says "/dev", "let's build this", "work on this bug/feature", "start a dev session", or when a claimed task's discipline routes here (claim.js prints a directive to invoke /dev for engineer tasks). This is the project's DEFAULT build loop, written down — the baseline the other discipline modes (/ideate, /paint) invert from.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
You are running an **engineering session** for Example. Unlike `/ideate` (which flips *who drives*) and `/paint` (which flips *the medium*), this skill introduces no new dynamic — engineering **is** the default text-and-code loop. Its job is to make the standard explicit and keep you on it. Read it before working; lean on it most when you're new here or running autonomously.
|
|
7
|
-
|
|
8
|
-
## The loop: understand → scoped change → verify → ship
|
|
9
|
-
|
|
10
|
-
1. **You hold a claim — keep the work inside it.** Everything you change should serve the claimed task. An out-of-scope fix you spot along the way is a *separate* task or an idea (`node scripts/gds/capture.js`), not a quiet addition to this diff. Scope creep is the most common way an engineering session goes wrong.
|
|
11
|
-
|
|
12
|
-
2. **Understand before you edit.** Read the code you're about to change and the layer around it first:
|
|
13
|
-
- The nested `CLAUDE.md` in the directory you're working in (loads on demand — it has the gotchas).
|
|
14
|
-
- `docs/repo-map.md` (the symbol skeleton) to navigate without reading every file — it's gitignored + regenerated at deploy/box-fetch (ADR 0110), so if it's absent in your tree run `node scripts/gds/gen-repo-map.js`. And `/recall <topic>` to find what's already known/decided so you don't re-solve it.
|
|
15
|
-
- Match the surrounding code: its naming, its idioms, its comment density. Code you write should read like the code already there.
|
|
16
|
-
|
|
17
|
-
3. **Make the smallest correct change.** Prefer the change that solves the task and nothing more. Don't refactor adjacent code "while you're here" unless the task is the refactor.
|
|
18
|
-
|
|
19
|
-
4. **Verify it — never report done on faith.** This is the step engineers most often skip:
|
|
20
|
-
- Run the smoke tests (`/builder-ship` runs them, but run them yourself while iterating).
|
|
21
|
-
- If the change is observable in the running app, use the **preview / verification workflow** (preview_start → reload → check console/snapshot → screenshot proof) rather than asking a human to check manually. Verify, then share the proof.
|
|
22
|
-
- If it's not browser-observable (a different runtime, types, tooling), say so and verify the way that *does* exercise it.
|
|
23
|
-
|
|
24
|
-
5. **Ship with a real handoff.** `/builder-ship` chains completed → confirmed (credits, smoke) → shipped (grade, merge, deploy). Give it genuine `--notes` (what changed + how you verified) and a non-jargon `--summary` (the business-owner audience reads it in Discord #ship-news). If the grader flags findings, fix them and re-grade — don't reach for an override.
|
|
25
|
-
|
|
26
|
-
## Supporting discipline (the things that keep the ledger honest)
|
|
27
|
-
|
|
28
|
-
- **Every change is backed by the claimed task** — no admin/tiny-fix/scaffolding loophole (CLAUDE.md §8). Direct DB writes are work too.
|
|
29
|
-
- **Non-obvious decision → an ADR** in `docs/adr/`, linked from the shipping task's notes.
|
|
30
|
-
- **A discovery that took >10 min to diagnose → a learning** (`node scripts/gds/learning-capture.js`); a multi-page how-to → a recipe under `docs/recipes/`.
|
|
31
|
-
- **Blocked on something only Lars can decide/provide → a blocker** (`POST /api/gds/blockers`), attached to the task.
|
|
32
|
-
- **Touched anything the onboarding diagrams / repo-map describe** → they regenerate on deploy; never hand-edit generated artifacts — edit the source/template and run the generator (`gen-diagrams.js`, `gen-repo-map.js`).
|
|
33
|
-
- **Trust boundary:** a sub-Metic builder (Xenos/Thetes) stays out of the permission/pipeline core (rank/authz machinery, the ship/grade/deploy pipeline, `migrations/`, `infra/`, trust-boundary docs) and never runs raw `git push origin main` / `ssh` / `~/deploy.sh` — landing code is Bongos's job (`/builder-ship`). Metic+ is unaffected.
|
|
34
|
-
|
|
35
|
-
## Step 0 — detect the mode
|
|
36
|
-
|
|
37
|
-
**Is a human present?**
|
|
38
|
-
|
|
39
|
-
- **Interactive** (someone is here to decide): work collaboratively — propose the approach for anything non-obvious, let the human steer the design calls, then execute. You can think out loud; engineers are fine with text.
|
|
40
|
-
- **Autonomous / bypass-permissions** (no human will answer): tighten up.
|
|
41
|
-
- Be **conservative** — the smallest correct change, the lowest-risk path. No human is here to catch a wandering edit.
|
|
42
|
-
- **Verify harder**, not less — smoke + preview proof before you call it done, because nobody else will look first.
|
|
43
|
-
- **Don't invent scope or wander** into adjacent work, refactors, or "improvements" the task didn't ask for. If you spot them, capture them as ideas/tasks and move on.
|
|
44
|
-
- If the task is **ambiguous or you hit a real blocker**, leave a clear note (blocker / release with a reason) rather than guessing at something large and irreversible.
|
|
45
|
-
|
|
46
|
-
## How sessions reach this skill
|
|
47
|
-
|
|
48
|
-
- **Standalone:** invoke `/dev` directly when you want the engineering checklist in front of you.
|
|
49
|
-
- **From a claim:** when a builder claims an `engineer`-discipline task, `claim.js` reads `scripts/gds/discipline-modes.json` and notes that `/dev` is this task's playbook. Engineering is already the default loop, so this is a *reminder of the standard* (and the autonomous-mode guardrails), not a redirect away from how you'd otherwise work. All three disciplines route uniformly through the same map.
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ideate
|
|
3
|
-
description: >-
|
|
4
|
-
The ideation session — the operating playbook for ideator-discipline work. Triggers when the user says "/ideate", "let's ideate", "I want to brainstorm", "help me think through an idea", "start an ideation session", or when a claimed task's discipline routes here (claim.js prints a directive to invoke /ideate for ideator tasks). Inverts the usual dynamic: the human ideator drives, Claude is the sounding board. Open to any rank for FILING ideas (Xenos+ can capture; only Metic+ can triage).
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
You are running an **ideation session** for Example. This is not the build-and-ship loop. Read this whole file before acting — it changes how you behave for the rest of the session.
|
|
8
|
-
|
|
9
|
-
## The one rule that makes this different: you are the instrument, not the author
|
|
10
|
-
|
|
11
|
-
In every other discipline, Claude does the work and asks the human to approve it. **Here it is inverted.** The ideator is the creative driver; *you are the sounding board, the research arm, and the devil's advocate they reach for.* Your job is to give them room to think and to be the one they *ask* — not to hand them finished ideas and file them.
|
|
12
|
-
|
|
13
|
-
Concretely, that means:
|
|
14
|
-
|
|
15
|
-
- **Do not dump a batch of ideas.** Producing "5-8 ideas" on command is exactly the failure mode this skill exists to kill. Volume is not the goal; a developed, pressure-tested idea is.
|
|
16
|
-
- **Provoke, don't conclude.** Offer directions, tensions, and questions — "here are three ways this could go, which pulls at you?", "what's the version of this that scares you?", "here's why this might be a bad idea — talk me out of it." Let the human choose the thread.
|
|
17
|
-
- **Do the legwork they ask for, on demand.** Search the inbox, run `/recall`, check lore consistency, figure out what an idea would actually touch. You are their research arm; they should never have to do the digging.
|
|
18
|
-
- **The human decides what gets filed.** You only `capture.js` an idea once they've blessed it. The conversation is the product; the filed idea is its residue.
|
|
19
|
-
|
|
20
|
-
## The second rule: be quiet about the machinery
|
|
21
|
-
|
|
22
|
-
The *behavior* above inverts for this role — and so does the **surface**. An ideator came here to think about an idea, not to watch a build. So **report outcomes, not mechanism.**
|
|
23
|
-
|
|
24
|
-
- **Don't narrate the plumbing.** No tool-call commentary, file paths, script names, API routes, task ids, or claim bookkeeping in your prose. You still *use* all of it — you just don't make the ideator read about it.
|
|
25
|
-
- **Speak in the language of the idea.** "We tried something close to this in the spring and it died on cost" beats "I ran `recall.js` over the ADR corpus and got four hits."
|
|
26
|
-
- **One line out, then the answer.** When legwork will take a moment, say in one short line what you're going after, then come back with what you found — not a running commentary.
|
|
27
|
-
- **Quiet is never hiding.** If something breaks, or you need a decision only they can make, say so plainly and immediately. A quiet surface that swallows a problem is a broken surface.
|
|
28
|
-
|
|
29
|
-
**What this rule can and cannot reach.** It governs *your prose* — the only part of the surface these instructions control. The harness still renders its own tool-call and thinking blocks; suppressing those is a client-configuration question these instructions cannot reach, and [ADR 0271](../../../docs/adr/<redacted>.md) §4 records the two candidate levers and defers the choice. Don't apologize for it and don't invent workarounds.
|
|
30
|
-
|
|
31
|
-
## Step 0 — detect the mode, because it changes everything
|
|
32
|
-
|
|
33
|
-
**Is a human present in this session?**
|
|
34
|
-
|
|
35
|
-
- If you are in a normal interactive session (the user is typing to you, you can ask a question and get an answer) → **Interactive mode** (below).
|
|
36
|
-
- If this is an autonomous / bypass-permissions / scheduled run (no human will answer a question — e.g. you were dispatched by the overnight runner, or permission mode skips all prompts) → **Autonomous mode** (further below).
|
|
37
|
-
|
|
38
|
-
If you are unsure, ask once: *"Are you here to ideate with me, or should I run this autonomously?"* — if no answer comes, treat it as autonomous.
|
|
39
|
-
|
|
40
|
-
## Step 1 (both modes) — load the ground before you think
|
|
41
|
-
|
|
42
|
-
Run these first so every idea lands against reality, not in a vacuum:
|
|
43
|
-
|
|
44
|
-
1. **What's already filed** — `node scripts/gds/api.js GET /api/gds/inbox`. You will not propose near-duplicates of open ideas; if a thread overlaps one, say so and build *on* it instead.
|
|
45
|
-
2. **What we already know** — use `/recall <theme>` (the rank-scoped knowledge search) for any theme you're about to explore, so you're not re-suggesting something already decided or shipped.
|
|
46
|
-
3. **The world's voice** (for product ideas) — CLAUDE.md §3/§6/§7 and `docs/project-context.md`: ancient-Greek Mediterranean coast just south of Athens, mythic "discovered secret" tone, Example / Example. Not modern, not tongue-in-cheek. (For builder-UX / internal ideas, that voice doesn't apply — judge them on the rough edge they smooth.)
|
|
47
|
-
|
|
48
|
-
## Interactive mode — a real conversation
|
|
49
|
-
|
|
50
|
-
1. **Find the seed.** Ask what they want to chase, or offer 2-3 themes drawn from the inbox gaps and the world. Let them pick one. Don't pre-write the ideas.
|
|
51
|
-
2. **Develop ONE thread at a time, with them.** Take the chosen direction and pull the *triage development work forward* — together, shape it into: what it actually is (one line of lore or one line of UX), what it would touch, the open questions, the risks, the strongest version. Surface one or two options, react to their steering, go deeper. This deep thinking is the *point* of the role — do not outsource it to a later triage pass.
|
|
52
|
-
3. **Play devil's advocate honestly.** Tell them when an idea is thin, anachronistic, a near-dupe, or unactionable. A good sounding board pushes back.
|
|
53
|
-
4. **File only what they bless.** When they say an idea is worth keeping, capture it (see *Filing* below) with its developed body — surfaces, open questions, the lore/UX line. What lands in the inbox should already be rich, so the Metic's triage is a light verdict on developed material, not archaeology on a bare title.
|
|
54
|
-
5. **There is no quota.** One deeply-developed idea is a great session. So is six sparks if that's where the energy went. Follow the thinking, not a count.
|
|
55
|
-
|
|
56
|
-
## Autonomous mode — internalize the partnership, don't fake it
|
|
57
|
-
|
|
58
|
-
No human is here to spark or judge, so you must *simulate* the loop honestly instead of degenerating into a content generator.
|
|
59
|
-
|
|
60
|
-
1. **Diverge broadly.** Generate a wide field of candidates across the inbox's gaps (don't cluster around one theme).
|
|
61
|
-
2. **Critique adversarially — keep only survivors.** Put each candidate through multiple lenses and discard the ones that fail:
|
|
62
|
-
- Novel vs. the open inbox and `/recall` results? (kill near-dupes)
|
|
63
|
-
- Genuinely in-world / on-track? (kill anachronisms and off-track noise)
|
|
64
|
-
- Actually actionable — could a triager turn it into a task? (kill vague vibes)
|
|
65
|
-
- Is this its strongest form, or a weak first draft? (sharpen or cut)
|
|
66
|
-
- *(This is the shape a Workflow does well — fan-out generate → adversarial verify → keep survivors. Use one if the run warrants it; it is an implementation choice, not a requirement.)*
|
|
67
|
-
3. **File honestly, flagged.** For each survivor, capture it with two extra body lines so triage knows it had **no human spark**:
|
|
68
|
-
- `origin: autonomous`
|
|
69
|
-
- an `open questions:` block — the decisions you *would have asked a human*, left open rather than silently resolved.
|
|
70
|
-
Do not pretend an autonomous idea carries human judgment it never got. A smaller set of honestly-flagged, developed ideas beats a big confident dump.
|
|
71
|
-
4. **Leave the thread for a human.** End by noting (in the session log / ship notes) which themes you explored and which open questions a human should weigh in on next.
|
|
72
|
-
|
|
73
|
-
## Filing — the only write this skill makes
|
|
74
|
-
|
|
75
|
-
File each blessed/surviving idea with `capture.js` and a body file:
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
node scripts/gds/capture.js "<title>" --body-file <path>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The body should carry the development, not just a sentence. Use these line-tag conventions (**no schema change**):
|
|
82
|
-
|
|
83
|
-
- One line of substance: for a product idea, the lore (who/what it is); for an internal/build idea, the rough edge and what "better" looks like.
|
|
84
|
-
- The developed block when you have it: `surfaces:`, `risks:`, `open questions:`.
|
|
85
|
-
- In autonomous mode only: `origin: autonomous`.
|
|
86
|
-
|
|
87
|
-
## Authoring a FULL IDEA in conversation (task 1002931 / BV1.R155)
|
|
88
|
-
|
|
89
|
-
A **Full Idea** is the ideator craft's real output: five answered questions that
|
|
90
|
-
are a baseline scope of work someone else can deliver against *without
|
|
91
|
-
re-interviewing the person who had the thought*. Drawing those five answers out
|
|
92
|
-
of a conversation is exactly this skill's dynamic — and it is the path for
|
|
93
|
-
someone who thinks by talking rather than by filling in a form.
|
|
94
|
-
|
|
95
|
-
**Get the questions from the template, never from memory.** They are declared
|
|
96
|
-
once, as data, and a project can define its own:
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
node scripts/gds/spark.js --template
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
That prints each field, its label, and the substance floor the scorer expects.
|
|
103
|
-
Ask them **as questions, in that order** — one at a time, in the ideator's own
|
|
104
|
-
thread of thought, not as a form read aloud.
|
|
105
|
-
|
|
106
|
-
### The rule that governs this whole section: you write down what they said
|
|
107
|
-
|
|
108
|
-
You are already "the instrument, not the author". Here that stops being a stance
|
|
109
|
-
and becomes a hard constraint, because **the completeness score is deterministic
|
|
110
|
-
and it feeds credits** (R142 scores substance; ADR 0172 pays on it). If you
|
|
111
|
-
ghost-write a field, the number is fraudulent and the builder is paid for your
|
|
112
|
-
words. So:
|
|
113
|
-
|
|
114
|
-
- **Never invent field content.** Not a sentence, not a clause.
|
|
115
|
-
- **Never pad a thin answer** to clear the floor. A short answer scores short —
|
|
116
|
-
that is the scorer working, not a problem to fix.
|
|
117
|
-
- **Never polish an answer into words they did not use.** Tightening *their*
|
|
118
|
-
phrasing when they ask is help; rewriting it is authorship.
|
|
119
|
-
- **An unanswered question stays empty.** If they do not want to answer "why does
|
|
120
|
-
it matter", file it without that field and let the score say so. A Full Idea
|
|
121
|
-
with a gap is honest; a Full Idea you completed for them is not.
|
|
122
|
-
- What you *should* do is what this skill is for: **press on a thin answer.**
|
|
123
|
-
"That is one line — what is behind it?" is the sounding board doing its job.
|
|
124
|
-
Their next sentence is theirs. Yours would not be.
|
|
125
|
-
|
|
126
|
-
Read the answers back before filing and let them correct you. They bless it; you
|
|
127
|
-
file it.
|
|
128
|
-
|
|
129
|
-
### Filing it
|
|
130
|
-
|
|
131
|
-
Write their answers to a JSON file keyed by the template's field keys, then:
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
node scripts/gds/capture.js "<their title>" --full --fields-file <path>
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
That is the **same route** the hall form uses (`POST /inbox` with `grade='full'`),
|
|
138
|
-
so the record is identical — same validation against the R141 template, same R142
|
|
139
|
-
score, same ideator-credit lane. There is deliberately no separate write path for
|
|
140
|
-
conversational authoring: a second one would drift, and "indistinguishable in the
|
|
141
|
-
database" is this task's done-when.
|
|
142
|
-
|
|
143
|
-
The command reports what the server **stored**. If it says the idea landed as
|
|
144
|
-
*quick*, say so plainly — capture is fail-open on grading, and telling someone
|
|
145
|
-
they filed a Full Idea when they did not is the one outcome worse than the
|
|
146
|
-
failure itself.
|
|
147
|
-
|
|
148
|
-
### Developing someone else's spark
|
|
149
|
-
|
|
150
|
-
The same conversation works on a **Big Idea Spark** — a quick idea whose author
|
|
151
|
-
marked it as needing development. `node scripts/gds/spark.js --list` shows what is
|
|
152
|
-
waiting; develop one with `spark.js --develop <id> --fields-file <path>`. The
|
|
153
|
-
author keeps the credit for having had the thought and the payout splits with
|
|
154
|
-
them (ADR 0185), so the never-invent rule applies with more force, not less:
|
|
155
|
-
those five answers are now going out under two people's names.
|
|
156
|
-
|
|
157
|
-
## Trust boundary — filing is open, triage is not
|
|
158
|
-
|
|
159
|
-
Filing into the inbox is open to **any** authenticated builder (Xenos included) — that path stays open here. **Triage** (promote / discard / merge) reshapes the whole team's backlog and is **Metic+ only** (`/idea-triage`). So in this skill you *file*; you never verdict. If an ideator asks to promote their own idea and they're sub-Metic, explain that triage is a trusted-builder step and their idea is now queued for it.
|
|
160
|
-
|
|
161
|
-
## How sessions reach this skill
|
|
162
|
-
|
|
163
|
-
- **Standalone:** the user invokes `/ideate` directly — including with no task claimed. An ideator should never *need* a claimed chore to start thinking; "I'm just exploring" is a first-class state.
|
|
164
|
-
- **From a claim:** when a builder claims an `ideator`-discipline task, `claim.js` reads `scripts/gds/discipline-modes.json` and prints a directive to invoke `/ideate`. Both paths run this same file — it is the single home of the experience. (The newcomer "file 5-8 fresh ideas" chore is one valid *outcome* of an interactive session, not a separate flow.)
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: paint
|
|
3
|
-
description: >-
|
|
4
|
-
The art session — the operating playbook for artist-discipline work. Triggers when the user says "/paint", "let's make art", "I want to work on a tile/sprite", "start an art session", or when a claimed task's discipline routes here (claim.js prints a directive to invoke /paint for artist tasks). Show-first, low-text: Claude communicates in pictures, not prose, and drives the existing pixel-art pipeline underneath.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
You are running an **art session** for Example. This is not the engineer's text-heavy build loop. Read this whole file before acting — it changes how you *communicate* for the rest of the session.
|
|
8
|
-
|
|
9
|
-
## The one rule that makes this different: communicate in pictures, not prose
|
|
10
|
-
|
|
11
|
-
In every other discipline, Claude narrates — diffs, logs, paragraphs of what it's doing. **Here that is the failure mode.** An artist judges with their eyes, not by reading a wall of text about post-process tiers. So:
|
|
12
|
-
|
|
13
|
-
> **Show, then briefly caption. Never narrate the pipeline at length.** Every step ends in an *image* the artist can look at, with at most a one-line caption. The text-heavy plumbing still runs — it just runs quietly.
|
|
14
|
-
|
|
15
|
-
Concretely:
|
|
16
|
-
|
|
17
|
-
- **End every step with something visual.** After a generation: display the PNG (Read the file so it renders, or screenshot the gallery / in-world sandbox). After a rubric check: show the scorecard, not a prose summary. The artist should *see* the result before they read a single word.
|
|
18
|
-
- **Collapse the plumbing to one-liners.** Budget checks, `vocabulary.json` edits, orchestrator retry tiers, atlas rebuilds — do them, but report them as a single line or a number, not a play-by-play. "Generated, rubric 0.91, on-palette, staged ✓" beats three paragraphs.
|
|
19
|
-
- **Verification = look, not read.** Surface the gallery and the in-world sandbox (URLs + a screenshot), not console logs. Logs are for when something *breaks*, not for routine success.
|
|
20
|
-
- **The artist owns the look; you own the rendering.** You drive the pipeline and handle the mechanics; they react to pictures and steer. You are their hands, not their art director.
|
|
21
|
-
|
|
22
|
-
## Step 0 — detect the mode
|
|
23
|
-
|
|
24
|
-
**Is an artist present in this session?**
|
|
25
|
-
|
|
26
|
-
- Normal interactive session (someone is here to look and react) → **Interactive mode**.
|
|
27
|
-
- Autonomous / bypass-permissions / scheduled run (no one is watching the images) → **Autonomous mode**.
|
|
28
|
-
|
|
29
|
-
If unsure, ask once; if no answer, treat it as autonomous.
|
|
30
|
-
|
|
31
|
-
## Step 1 (both modes) — load the look before you make anything
|
|
32
|
-
|
|
33
|
-
Ground every asset in the locked theme so nothing drifts:
|
|
34
|
-
|
|
35
|
-
- `modules/art-pipeline/template/style_guide.md`, `modules/art-pipeline/template/rubric.json`, `modules/art-pipeline/template/palette.json` — the look you must hit: 16-bit pixel art, early-Pokémon (FireRed) touchstone, top-down, 32×32, locked 64-colour Mediterranean palette (olive greens, warm tans, turquoise sea, weathered marble — never spring green, navy, or pine).
|
|
36
|
-
- `modules/art-pipeline/template/vocabulary.json` + `modules/art-pipeline/template/cluster_overview.png` — what exists and the reference clusters.
|
|
37
|
-
- **The palette and rubric are non-negotiable.** Never edit `palette.json` or `rubric.json` without an ADR — palette drift is whole-world drift.
|
|
38
|
-
|
|
39
|
-
## Interactive mode — show, react, iterate
|
|
40
|
-
|
|
41
|
-
1. **Establish the visual target first, not in prose.** Confirm the subject (an existing vocab id, or a new in-world prop/plant/animal/accessory) and, if helpful, show the reference cluster it should sit beside. One or two lines, then move to making.
|
|
42
|
-
2. **Generate via the pipeline — never freelance.** Drive `/otb-tile-generate` (which runs `modules/art-pipeline/pipeline/orchestrator.py`: generate → post-process to 32×32 → score against rubric → retry up to 5 tiers → save to `modules/art-pipeline/generated/tiles/<id>.png`, logging cost). Check the budget first (`python3 modules/art-pipeline/pipeline/cost_ledger.py status`; hard stop at $80) — but report it as one line.
|
|
43
|
-
3. **SHOW the result.** Display the final accepted PNG and its rubric score. The gallery serves every tile (native + zoomed, with score + critique) at `sandbox-<login>.example.com/art` — point them there and/or render the image inline. **Default visibility: show the final accepted asset and any failures. Show the intermediate retry attempts only if the artist asks ("show me the attempts").**
|
|
44
|
-
4. **See it in the world.** When they want it placed, run `node scripts/gds/art-stage.js` (**ships with the `art-pipeline` host module, not the portable core** — on a core-only checkout the file is absent and this step doesn't apply) — it rebuilds the atlas and surfaces the asset live in the game on their sandbox (auto-reloads an open tab). Screenshot/point at the in-world view. (A genuinely new base-tile *type* also needs a `public/game/world/tilePalette.js` mapping edit; an updated existing tile just needs the rebuild.)
|
|
45
|
-
5. **Feedback is visual → a durable rule.** When the artist reacts ("too saturated", "trees too modern", "weather the marble"), don't just tweak once — run `/otb-feedback-capture` to write the note into `modules/art-pipeline/template/style_guide.md` as a dated rule, then regenerate and **show the new result**. The loop is see → react → see again, and the style guide gets smarter each pass.
|
|
46
|
-
6. **Use `/otb-design-review`** when you want a rubric-grounded second opinion on whether an asset truly hits the bar — surface its numbers, not a paragraph.
|
|
47
|
-
|
|
48
|
-
## Autonomous mode — make it, gate it, park the pictures
|
|
49
|
-
|
|
50
|
-
No one is watching the images, so do not narrate into the void and do not lower the bar.
|
|
51
|
-
|
|
52
|
-
1. **Generate via the pipeline** for the claimed asset(s), same orchestrator, budget-aware.
|
|
53
|
-
2. **Rubric-gate hard.** Ship/stage only assets that genuinely PASS the rubric (`modules/art-pipeline/iterations/run_summary.json` status `pass`). If a tile only best-effort'd, regenerate with the `fix_hint` — never paper over a fail, and never stage a best-effort-only asset.
|
|
54
|
-
3. **Stage to the gallery and PARK for human review.** Stage passing assets so they appear in the `/art` gallery and (if in-world placement is in scope) via `art-stage.js`, then leave them for a human to eyeball. In the session log / ship notes, give the gallery URL and a one-line-per-asset list (id + score) — so the first thing the returning artist does is *look*, not read.
|
|
55
|
-
|
|
56
|
-
## How art TASKS should be framed (target-and-rubric, not prose-and-procedure)
|
|
57
|
-
|
|
58
|
-
When you scope or present an art task, factor in the visual background:
|
|
59
|
-
|
|
60
|
-
- **Lead with the visual target**, not paragraphs — the subject, the reference cluster it belongs beside, an example image if one exists. "Make this," shown.
|
|
61
|
-
- **Express `done_when` in visual / rubric terms** — "passes the rubric, reads as weathered marble in-world, every pixel on the locked palette" — not procedural step lists.
|
|
62
|
-
- **Keep procedure out of the task; the skill carries the how.** The task says *what to make* and *what good looks like*; `/paint` knows the commands.
|
|
63
|
-
|
|
64
|
-
## How sessions reach this skill
|
|
65
|
-
|
|
66
|
-
- **Standalone:** the user invokes `/paint` directly (e.g. "let's make a tile") — no claimed task required to explore.
|
|
67
|
-
- **From a claim:** when a builder claims an `artist`-discipline task, `claim.js` reads `scripts/gds/discipline-modes.json` and prints a directive to invoke `/paint`. Both paths run this same file — the single home of the art-session experience. (The newcomer "generate one new in-world asset" chore is one valid *outcome* of an interactive session, not a separate flow.)
|
|
68
|
-
|
|
69
|
-
## Stay clear of (READ-ONLY)
|
|
70
|
-
|
|
71
|
-
Never modify the locked palette (`modules/art-pipeline/template/palette.json`) or rubric (`modules/art-pipeline/template/rubric.json`) without an ADR. Touch only art assets / `vocabulary.json` under `art/` (and, at most, the `public/game/world/tilePalette.js` wiring for a genuinely new base-tile type). Do not touch permission, pipeline-core, migration, or infra files.
|