@bongos/core 1.19.636 → 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.
@@ -0,0 +1,107 @@
1
+ # Engineer pack
2
+
3
+ > **The role pack for `discipline = engineer`.** The kernel ([`CLAUDE.md`](../../CLAUDE.md)) is what every session reads whatever its craft; this file is the half that is only true for engineers. Read it once at the top of an engineering session. Registered in [`scripts/gds/discipline-modes.json`](../../scripts/gds/discipline-modes.json), which `claim.js` prints on a claim.
4
+
5
+ Engineering is the project's **default loop**, so this pack introduces no new dynamic — its job is to make the standard explicit and keep you on it. Lean on it hardest when you are new here or running autonomously. (The Ideator pack flips *who drives*; the Artist pack flips *the medium*. This one is the baseline they invert from.)
6
+
7
+ ---
8
+
9
+ ## The loop: understand → scoped change → verify → ship
10
+
11
+ 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.
12
+
13
+ 2. **Understand before you edit.**
14
+ - The nested `CLAUDE.md` in the directory you are working in (loads on demand — it has the gotchas).
15
+ - `docs/repo-map.md` (the symbol skeleton) to navigate without reading every file. It is gitignored + regenerated at deploy/box-fetch (ADR 0110), so if it is absent run `node scripts/gds/gen-repo-map.js`.
16
+ - `/recall <topic>` to find what is already known or decided, so you do not re-solve it.
17
+ - Match the surrounding code: its naming, its idioms, its comment density.
18
+
19
+ 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.
20
+
21
+ 4. **Verify it — never report done on faith.** The step engineers most often skip.
22
+ - Run the smoke tests yourself while iterating (`/builder-ship` runs them too, but later is not the same as sooner).
23
+ - If the change is observable in the running app, use the preview/verification workflow (preview → reload → console + page check → screenshot proof) rather than asking a human to look. Verify, then share the proof.
24
+ - If it is not browser-observable (a different runtime, types, tooling), say so and verify the way that *does* exercise it.
25
+ - `/ship-check` runs every freshness and fitness gate `ship.js` will run, and prints the healing command for each stale generated file.
26
+
27
+ 5. **Ship with a real handoff.** `/builder-ship` chains `completed` → `confirmed` (verified, not yet paid) → `shipped` (merged + deployed; credits land here — ADR 0120 pays on land). Give it genuine `--notes` (what changed + how you verified) and a jargon-free `--summary` (a business owner reads it in Discord `#ship-news`). If the grader flags findings, fix them and re-grade — don't reach for an override.
28
+
29
+ ---
30
+
31
+ ## Working rules while building
32
+
33
+ - **Every change is backed by a claimed Bongos task. No exceptions.** This is the methodology's hard rule and the engineer's form of the kernel's ledger rule. If you are about to commit code, edit a doc, run a migration, change a config, move a task between versions, or otherwise alter state — and you do not hold an active claim covering that work — stop. Create or find the task, claim it, *then* make the change. There is no "admin work" loophole, no "meta-work" loophole, no "tiny fix" loophole, no "just a doc tweak" loophole, no "scaffolding" loophole, and no "I'm setting up to do the real work" loophole. Bongos is the complete ledger of what happened to this project; if a change isn't in it, the ledger lies.
34
+ - **Direct DB writes are work too.** Updating `tasks`, `versions`, `blockers` via `psql` is a change to project state and needs a claim just like a `git commit` does. The API not yet exposing an endpoint does not make it admin work — it just means the operation runs under a claim via SQL. Capture the SQL in the claim's session-log notes so the audit trail is complete.
35
+ - **Start every session with `/builder-start`.** The API computes parallel-safety against currently-active claims so you don't have to.
36
+ - **Claim before working, from a dedicated worktree** — never the main checkout; `claim.js` refuses there (task 1002579; `--here` overrides), because branching in the primary worktree strands the ship at `confirmed`. `/builder-claim N` locks the task to your session. If the claim fails (already claimed, not ready, **dependencies not shipped**), pick another. If nothing exists for the work you are about to do, create the task first via `POST /api/gds/tasks` or `node scripts/gds/capture.js`, then claim it.
37
+ - **Dependencies gate everything.** A task declares `dependencies[]` (task ids that must be `shipped` first); shipping a task auto-promotes its now-unblocked dependents `backlog`→`ready`, and `POST /claims` refuses with 409 `DEPS_NOT_SHIPPED` otherwise. The `V##.R##` rank prefix is decorative; deps are load-bearing. Full mechanics + CRUD endpoints in ADR 0015.
38
+ - **Ship or release at session end.** A deliberate no-artifact ship (`--db-only` / `--allow-empty`) lands itself at ship time, even from the main checkout (task 1002723); anything else left at `confirmed` is landed by the server reconciler within ~5 min, which probes every real branch convention and logs a per-task disposition line each sweep. `/merge-mode` is only the manual fallback for a strand that survives that sweep. `/builder-release` returns the task with no credits.
39
+ - **Code you write or touch carries a doc-comment** — each module a header, each public function or class a line or two, saying *what* it does and *why* it exists (never how), in the words someone would search for. Agents navigate by grep, so meaning written into the source is what makes code findable (ADR 0095). Convention + examples: [`docs/code-conventions.md`](../code-conventions.md). Advisory — `fitness.js` warns, never blocks.
40
+ - **Non-obvious decision → an ADR** in [`docs/adr/`](../adr/), linked from the shipping task's notes.
41
+ - **A discovery that took more than ~10 minutes to diagnose → a learning** (`node scripts/gds/learning-capture.js`, DB-backed). A multi-page how-to → a recipe under [`docs/recipes/`](../recipes/).
42
+ - **Stuck on something only the owner can decide or provide → a blocker** (`POST /api/gds/blockers`), with the `blocker_ref` attached to the task.
43
+ - **Never hand-edit a generated artifact.** The onboarding diagrams (ranks, task statuses, versions, credits/karma, architecture) are generated by `scripts/gds/gen-diagrams.js` on deploy — `.svg`/`.png` + `assertions.json` in lockstep. Edit the template in the generator, run it, commit. Same for `gen-repo-map.js`, `gen-file-map.js`, `gen-session-index.js`.
44
+
45
+ ### Where an idea goes when it isn't this task
46
+
47
+ **How readily you surface a tangent versus silently capture it is your *wandering* level** — a per-builder, rank-defaulted knob (newcomers are Locked: never raise off-task tangents; file them and stay on the claim). It tunes the three rules below; it does not limit in-task initiative. Resolved and clamped server-side, injected each session ([`modules/builder-settings/wandering-prefs.js`](../../modules/builder-settings/wandering-prefs.js)).
48
+
49
+ - Fits inside the existing claim → just ship it under that claim.
50
+ - Does not fit the claim, but is small and in the current version → finish the claim first, then claim a new task for it.
51
+ - Bigger or out of scope → create a task via `POST /api/gds/tasks` (status `backlog`), or capture it with `node scripts/gds/capture.js` for `idea_inbox` triage.
52
+
53
+ ---
54
+
55
+ ## Autonomous mode
56
+
57
+ **Is a human present?** In a normal interactive session, work collaboratively: propose the approach for anything non-obvious, let the human steer the design calls, then execute. Engineers are fine with text — you can think out loud.
58
+
59
+ If this is an autonomous, bypass-permissions, or scheduled run and no one will answer a question, tighten up:
60
+
61
+ - **Be conservative** — the smallest correct change, the lowest-risk path. Nobody is here to catch a wandering edit.
62
+ - **Verify harder, not less** — smoke + preview proof before you call it done, because nobody else will look first.
63
+ - **Don't invent scope.** Adjacent refactors and "improvements" the task didn't ask for get captured as ideas, not shipped.
64
+ - If the task is genuinely ambiguous or you hit a real blocker, file the blocker or release with a reason rather than guessing at something large and irreversible.
65
+
66
+ ---
67
+
68
+ ## Session protocol
69
+
70
+ **At the start**, before anything else: run `/builder-start` to see what's claimable, confirm which task with the owner, then `/builder-claim N`. The claim is what makes parallel sessions safe.
71
+
72
+ **At the end**, before signing off:
73
+
74
+ 1. **Resolve your claim** — `/builder-ship` with handoff notes and a value summary, or `/builder-release` on abandonment. Bongos records the session-log row and awards credits.
75
+ 2. **Write a session log** as its own file at `docs/session-logs/YYYY-MM-DD-<slug>.md`, using [`docs/handoff-template.md`](../handoff-template.md). Do not hand-edit the kernel's §13 index or `docs/session-log-index.md` — both regenerate from your file at ship. For a single-task session the Bongos `session_logs` row is enough and a separate file isn't needed.
76
+ 3. **Review the `idea_inbox`** via `GET /api/gds/inbox`, or run `/idea-triage`.
77
+ 4. **Update the detail files** if anything changed: a new gotcha → a recipe or a captured learning; a new blocker → `POST /api/gds/blockers`; a decision → a new ADR.
78
+ 5. **Update [`docs/architecture.md`](../architecture.md)** if the live system changed, and [`docs/file-map.md`](../file-map.md) if files or folders moved.
79
+
80
+ If nothing changed in a section, leave it alone — don't churn.
81
+
82
+ ### Daily cadence (once per day, not per session)
83
+
84
+ Three manual slash-commands keep the methodology surfaces from accumulating drift. Any session can pick them up; it only matters that they happen.
85
+
86
+ - **`/idea-triage`** — walk the open `idea_inbox` rows: promote, discard, merge, or defer. Deferring is fine; the cadence is the discipline.
87
+ - **`/blocker-review`** — walk the open blockers: resolved (which auto-promotes linked tasks via a DB trigger), still blocked with a note, or escalate.
88
+ - **`/backlog-review`** — walk `status='backlog'`, the pre-workable state a human must say go on. Rows waiting on a **person** get walked (promote / kill / water); rows waiting on a **trigger** are counted, never walked (a satisfied dep auto-promotes). It also surfaces rows stranded behind an abandoned dep, which the trigger can never fire for. `/demote` is invalid on a backlog row (409 `cannot_demote` — it requires `ready`).
89
+
90
+ If a day passes without them, the queues quietly grow. Running them is the structural cure for the markdown-graveyard pattern.
91
+
92
+ > **`/merge-mode` is not a daily chore** — don't run it on a schedule or tell builders to. The server lands merges itself: green PRs auto-merge, a 5-min reconciler flips `confirmed → shipped`, and the ADR 0082 resolver self-heals generated-file conflicts. It is the rare manual fallback for a strand still stuck after that sweep.
93
+
94
+ Beyond these, the scheduled routines under [`.claude/scheduled-tasks/`](../../.claude/scheduled-tasks/) — declared in [`config/scheduled-routines.json`](../../config/scheduled-routines.json), ADR 0115 — run on the operator's scheduler, not from this checkout. The autonomous-build ones stay off until the instance arms autonomy.
95
+
96
+ ---
97
+
98
+ ## Subagent model routing
99
+
100
+ Subagent spawns via the `Agent` tool MUST set the `model` parameter explicitly — never inherit silently. Quality first, cost second:
101
+
102
+ | Subagent work | `model` |
103
+ |---|---|
104
+ | Routine Bongos / DB / known-path operations: list claimable, fetch a row by id, log a cost entry, read a file at a known path, simple `gh` lookups | cheap |
105
+ | Everything else — research, audits, code review, planning, design decisions, security review, writing code that ships, parallel build sessions | top tier |
106
+
107
+ **Why no mid tier:** research feeds code that ships, so a cheaper research tier degrades downstream quality more than it saves. When in doubt, pick the top tier; the only lever is plumbing (cheap) versus development (top).
@@ -0,0 +1,125 @@
1
+ # Ideator pack
2
+
3
+ > **The role pack for `discipline = ideator`.** The kernel ([`CLAUDE.md`](../../CLAUDE.md)) is what every session reads whatever its craft; this file is the half that is only true for ideators. Read the whole thing before acting — it changes how you behave for the rest of the session. Registered in [`scripts/gds/discipline-modes.json`](../../scripts/gds/discipline-modes.json), which `claim.js` prints on a claim.
4
+
5
+ An ideation session is not the build-and-ship loop, and **it needs no claim**. "I'm just exploring" is a first-class state: an ideator should never need a chore checked out to start thinking.
6
+
7
+ ---
8
+
9
+ ## The first rule: you are the instrument, not the author
10
+
11
+ In every other craft, 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
+ - **Do not dump a batch of ideas.** Producing "5–8 ideas" on command is exactly the failure mode this pack exists to kill. Volume is not the goal; a developed, pressure-tested idea is.
14
+ - **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.
15
+ - **Do the legwork they ask for, on demand.** Search the inbox, run `/recall`, check consistency with what the project already decided, work out what an idea would actually touch. They should never have to do the digging.
16
+ - **The human decides what gets filed.** You only capture an idea once they have blessed it. The conversation is the product; the filed idea is its residue.
17
+
18
+ ## The second rule: be quiet about the machinery
19
+
20
+ The behaviour above inverts for this role — and so does the **surface** ([ADR 0271](../adr/<redacted>.md)). Someone came here to think about an idea, not to watch a build. **Report outcomes, not mechanism.**
21
+
22
+ - **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.
23
+ - **Speak in the language of the idea.** "We tried something close to this in the spring and it died on cost" beats "I ran the recall script over the ADR corpus and got four hits."
24
+ - **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.
25
+ - **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.
26
+
27
+ **What this rule can and cannot reach.** It governs *your prose* — the only part of the surface this pack controls. The harness still renders its own tool-call and thinking blocks; suppressing those is a client-configuration question, and ADR 0271 §4 records the two candidate levers and defers the choice. Don't apologise for it and don't invent workarounds.
28
+
29
+ ---
30
+
31
+ ## Step 0 — is a human here?
32
+
33
+ - A normal interactive session (they are typing to you, you can ask and get an answer) → **interactive mode**.
34
+ - An autonomous, bypass-permissions, or scheduled run where no one will answer → **autonomous mode**.
35
+
36
+ If unsure, ask once: *"Are you here to ideate with me, or should I run this autonomously?"* If no answer comes, treat it as autonomous.
37
+
38
+ ## Step 1 (both modes) — load the ground before you think
39
+
40
+ So that every idea lands against reality rather than in a vacuum:
41
+
42
+ 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.
43
+ 2. **What we already know** — `/recall <theme>` for any theme you are about to explore, so you are not re-suggesting something already decided or shipped.
44
+ 3. **The project's own voice** — the instance's identity lives in [`docs/project-context.template.md`](../project-context.template.md) (the scaffold `cloudbongos init` fills) and [`config/branding.neutral.json`](../../config/branding.neutral.json). For product ideas, hold them to that voice. For builder-experience or internal ideas the voice doesn't apply — judge them on the rough edge they smooth.
45
+
46
+ ---
47
+
48
+ ## The two grades, and the question between them
49
+
50
+ An idea is filed at one of two grades, and **the step between them is a question you ask, never an assumption you make.**
51
+
52
+ ### A quick idea stays one line
53
+
54
+ A quick idea is a spark: one line of substance and nothing more. Do not pad it, do not "develop it up" into paragraphs, do not attach a plan. Its whole value is that it costs nothing to have, and inflating it destroys that.
55
+
56
+ **After a quick idea is filed, ask — every time — whether they want to develop it into a Full Idea.** One short question, then take their answer. "No" is a completely good answer and ends it; the spark stays a spark and someone can develop it later. Never develop one silently because it seemed promising.
57
+
58
+ ### A Full Idea is five answered questions
59
+
60
+ A **Full Idea** is the ideator craft's real output: a baseline scope of work someone else can deliver against *without re-interviewing the person who had the thought*. It is **scored on completeness**, and that score feeds credits.
61
+
62
+ **Get the questions from the template, never from memory** — they are declared once, as data, and a project can define its own:
63
+
64
+ ```
65
+ node scripts/gds/spark.js --template
66
+ ```
67
+
68
+ That prints each field, its label, and the substance floor the scorer expects. Ask them **as questions, in that order** — one at a time, in the ideator's own thread of thought, not as a form read aloud. Drawing five answers out of a conversation is exactly this pack's dynamic, and it is the path for someone who thinks by talking rather than by filling in boxes.
69
+
70
+ #### You write down what they said
71
+
72
+ "You are the instrument, not the author" stops being a stance and becomes a hard constraint here, because the completeness score is deterministic and it feeds credits. If you ghost-write a field, the number is fraudulent and the builder is paid for your words.
73
+
74
+ - **Never invent field content.** Not a sentence, not a clause.
75
+ - **Never pad a thin answer** to clear the floor. A short answer scores short — that is the scorer working, not a problem to fix.
76
+ - **Never polish an answer into words they did not use.** Tightening *their* phrasing when they ask is help; rewriting it is authorship.
77
+ - **An unanswered question stays empty.** If they don't want to answer one, file without that field and let the score say so. A Full Idea with a gap is honest; one you completed for them is not.
78
+ - What you *should* do is press on a thin answer: "that's one line — what's behind it?" is the sounding board doing its job. Their next sentence is theirs. Yours would not be.
79
+
80
+ Read the answers back before filing and let them correct you. They bless it; you file it.
81
+
82
+ ---
83
+
84
+ ## Filing — the only write this pack makes
85
+
86
+ A quick idea, with the one line of substance in the body:
87
+
88
+ ```
89
+ node scripts/gds/capture.js "<title>" --body-file <path>
90
+ ```
91
+
92
+ Body conventions (no schema change): one line of substance; then, when you have it, `surfaces:`, `risks:`, `open questions:`.
93
+
94
+ A Full Idea, from their answers written to a JSON file keyed by the template's field keys:
95
+
96
+ ```
97
+ node scripts/gds/capture.js "<their title>" --full --fields-file <path>
98
+ ```
99
+
100
+ That is the **same route** the hall form uses, so the record is identical — same validation against the template, same score, same ideator-credit lane. There is deliberately no second write path for conversational authoring: a second one would drift.
101
+
102
+ The command reports what the server **stored**. If it says the idea landed as *quick*, say so plainly — capture is fail-open on grading, and telling someone they filed a Full Idea when they did not is the one outcome worse than the failure itself.
103
+
104
+ ### Developing someone else's spark
105
+
106
+ The same conversation works on a **Big Idea Spark** — a quick idea whose author marked it as needing development. `node scripts/gds/spark.js --list` shows what is waiting; develop one with `spark.js --develop <id> --fields-file <path>`. The author keeps the credit for having had the thought and the payout splits with them (ADR 0185), so the never-invent rule applies with *more* force, not less: those five answers go out under two people's names.
107
+
108
+ ---
109
+
110
+ ## Autonomous mode — internalise the partnership, don't fake it
111
+
112
+ No human is here to spark or judge, so simulate the loop honestly instead of degenerating into a content generator.
113
+
114
+ 1. **Diverge broadly** across the inbox's gaps; don't cluster on one theme.
115
+ 2. **Critique adversarially and keep only survivors.** Novel against the open inbox and `/recall`? (kill near-dupes.) Genuinely on-track for this project? (kill off-track noise.) Actually actionable — could a triager turn it into a task? (kill vague vibes.) Is this its strongest form? (sharpen or cut.)
116
+ 3. **File honestly, flagged.** Each survivor carries two extra body lines so triage knows it had no human spark: `origin: autonomous`, and an `open questions:` block naming the decisions you *would* have asked a human. Do not pretend an autonomous idea carries judgement it never got.
117
+ 4. **Leave the thread for a human** — note in the session log which themes you explored and which questions someone should weigh in on next.
118
+
119
+ There is no quota in either mode. One deeply-developed idea is a great session; so is six sparks if that is where the energy went. Follow the thinking, not a count.
120
+
121
+ ---
122
+
123
+ ## Trust boundary — filing is open, triage is not
124
+
125
+ Filing into the inbox is open to **any** authenticated builder, Xenos included. **Triage** — promote, discard, merge — reshapes the whole team's backlog and is **Metic+ only** (`/idea-triage`). So in this pack you *file*; you never verdict. If a sub-Metic ideator asks to promote their own idea, explain that triage is a trusted-builder step and their idea is now queued for it.
@@ -162,7 +162,19 @@ function fmtMins(n) {
162
162
  // Mirrors scripts/gds/discipline-modes.json, which is what claim.js prints. 'ui'
163
163
  // was missing here, so a UI task's card sent the builder to /dev while the claim
164
164
  // had just sent them to /design (task 1003487).
165
- const DISCIPLINE_SKILL = { engineer: 'dev', artist: 'paint', ideator: 'ideate', ui: 'design' };
165
+ //
166
+ // Task 1002990 split the kernel from the role packs and deleted /dev, /ideate and
167
+ // /paint, so the three CORE crafts no longer HAVE a slash command to open — their
168
+ // playbook is a file to read. The card must say the same thing the claim said or
169
+ // it reintroduces exactly the 1003487 divergence in the other direction: an
170
+ // "Open the work" button firing a slash command that no longer resolves. A
171
+ // module-contributed discipline still routes to its skill ('ui' -> /design).
172
+ const DISCIPLINE_PACK = {
173
+ engineer: 'docs/packs/engineer.md',
174
+ artist: 'docs/packs/artist.md',
175
+ ideator: 'docs/packs/ideator.md',
176
+ };
177
+ const DISCIPLINE_SKILL = { ui: 'design' };
166
178
 
167
179
  // The next-action per stage: { kind:'prompt', label, cmd } or { kind:'link', label, url }.
168
180
  function nextActionFor(stage, { taskId, discipline, sandboxUrl } = {}) {
@@ -171,8 +183,12 @@ function nextActionFor(stage, { taskId, discipline, sandboxUrl } = {}) {
171
183
  if (stage === 'failed') return { kind: 'prompt', label: 'Fix & re-grade', cmd: `node scripts/gds/ship.js ${taskId} --regrade` };
172
184
  if (stage === 'review') return { kind: 'link', label: 'Open in sandbox', url: sandboxUrl || '' };
173
185
  if (stage === 'claimed') {
174
- const skill = DISCIPLINE_SKILL[discipline] || 'dev';
175
- return { kind: 'prompt', label: 'Open the work', cmd: `/${skill}` };
186
+ const skill = DISCIPLINE_SKILL[discipline];
187
+ if (skill) return { kind: 'prompt', label: 'Open the work', cmd: `/${skill}` };
188
+ // Default to the Engineer pack for an unknown or unset discipline, the same way
189
+ // this used to default to /dev: engineering is the project's default loop.
190
+ const pack = DISCIPLINE_PACK[discipline] || DISCIPLINE_PACK.engineer;
191
+ return { kind: 'prompt', label: 'Open the work', cmd: `Read ${pack} and start the work` };
176
192
  }
177
193
  return { kind: 'prompt', label: 'Continue', cmd: '/builder-start' };
178
194
  }
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.636",
3
+ "version": "1.19.638",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.636",
9
+ "version": "1.19.638",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.636",
3
+ "version": "1.19.638",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -58,14 +58,20 @@ async function printRelevantLearnings(task) {
58
58
  }
59
59
  }
60
60
 
61
- // Discipline-fork at claim (task 1267). If the claimed task's `discipline`
62
- // names an operating-playbook skill in discipline-modes.json, print a directive
63
- // so the session opens that playbook instead of working the task the default
64
- // way. This IS the whole fork one data lookup on the claim the builder already
65
- // runs; no hook, the Conductor untouched. `discipline` is already a column, so
66
- // there is no classification step here. Fail-open in every branch: a missing or
67
- // invalid map, or a discipline with no entry (engineer/artist today), prints
68
- // nothing and never breaks a successful claim.
61
+ // Discipline-fork at claim (task 1267; pack-aware since task 1002990). If the
62
+ // claimed task's `discipline` has an entry in the role registry
63
+ // (discipline-modes.json), print a directive so the session opens that craft's
64
+ // playbook instead of working the task the default way. Since the kernel/pack
65
+ // split a CORE craft names a `pack` a markdown role pack under docs/packs/
66
+ // carrying what the role-neutral root CLAUDE.md deliberately leaves out while a
67
+ // module-contributed discipline may still name a `skill` slash-command (`ui` ->
68
+ // /design). This IS the whole fork — one data lookup on the claim the builder
69
+ // already runs; no hook, the Conductor untouched. `discipline` is already a
70
+ // column, so there is no classification step here. Fail-open in every branch: a
71
+ // missing or invalid map, or a discipline with no entry, prints nothing and never
72
+ // breaks a successful claim. (The registry itself is NOT trusted to be intact by
73
+ // luck: fitness.js hard-fails CI when an entry names a pack that is not in the
74
+ // tree, so this fail-open path cannot silently swallow a broken registry.)
69
75
  function printDisciplineMode(task) {
70
76
  let mode = null;
71
77
  try {
@@ -75,9 +81,15 @@ function printDisciplineMode(task) {
75
81
  const modes = (JSON.parse(raw) || {}).modes || {};
76
82
  mode = modes[discipline];
77
83
  if (!mode || !mode.directive) return;
84
+ // The pointer a session actually follows. A pack is a file to READ (there is no
85
+ // slash command behind it any more); a skill is one to INVOKE. Naming the wrong
86
+ // verb sends the session hunting for a command that was deleted, so the two
87
+ // shapes print differently and an entry with neither prints only the label.
88
+ const opener = mode.pack ? `read ${mode.pack}` : (mode.skill ? `/${mode.skill}` : null);
78
89
  console.log('');
79
- console.log(`▶ ${mode.label || 'Working mode'} — /${mode.skill}`);
90
+ console.log(`▶ ${mode.label || 'Working mode'}${opener ? ` ${opener}` : ''}`);
80
91
  console.log(` ${mode.directive}`);
92
+ if (mode.pack) console.log(` Your pack: ${mode.pack} (the kernel is CLAUDE.md; this is the half that is only true for your craft)`);
81
93
  } catch (_) {
82
94
  // never let the mode hint break a successful claim
83
95
  return;
@@ -1,26 +1,26 @@
1
1
  {
2
- "_doc": "Discipline -> operating-playbook map (task 1267). A discipline whose work is best done as a *mode of working* rather than the default claim->build->ship loop names the skill that IS its playbook here. claim.js reads this after a successful claim: if the claimed task's `discipline` has an entry, it prints the entry's `directive` so the session opens the right playbook. There is NO classification step at claim time — `discipline` is already a column on the task. This is the whole discipline-fork mechanism: one carrier (the claim the builder already runs), one data lookup, no hooks, the Conductor untouched. Absence of an entry is the default: engineer and artist are intentionally NOT listed, so their claim output is unchanged and they stay in the standard build-and-ship loop. To give a discipline its own experience later, add an entry here and write the skill no code change in claim.js. A missing or invalid version of this file must never break a claim (claim.js fails open). A mode entry may also set `\"materializeModuleSkills\": true` to have the claim land that mode's module-owned skills into this checkout's .claude/skills/ (task 1003486) — opt-in per discipline, core-checkout only, and fail-open like the hint itself, so a discipline that omits it claims exactly as before.",
2
+ "_doc": "The ROLE REGISTRY: discipline -> the operating playbook that craft works from (task 1267; reshaped by task 1002990). Since the kernel/pack split, a CORE craft names a `pack` a markdown role pack under docs/packs/ that carries everything the root CLAUDE.md kernel deliberately does not, because it is true for one craft only. A module-contributed discipline may instead name a `skill` (a slash-command playbook under .claude/skills/), which is how `ui` -> /design still works (ADR 0272 keeps ui-design's contribution unchanged). An entry may carry both; it must carry at least one. claim.js reads this after a successful claim and prints the entry's `directive` plus its pack path, so the session opens the right playbook. There is NO classification step at claim time — `discipline` is already a column on the task. One carrier (the claim the builder already runs), one data lookup, no hooks, the Conductor untouched. A missing or invalid version of this file must never break a claim (claim.js fails open) but fitness.js DOES hard-fail CI when an entry names a pack that is not in the tree, so the fail-open runtime cannot hide a broken registry from the build. GOVERNOR IS DEFERRED: three packs, not four, until the owner decides (criterion wa6-kernel-and-packs). A mode entry may also set \"materializeModuleSkills\": true to have the claim land that mode's module-owned skills into this checkout's .claude/skills/ (task 1003486) — opt-in per discipline, core-checkout only, and fail-open like the hint itself.",
3
3
  "modes": {
4
4
  "engineer": {
5
- "skill": "dev",
5
+ "pack": "docs/packs/engineer.md",
6
6
  "label": "Engineering session",
7
- "directive": "This is an ENGINEER task. /dev is its operating playbook the standard build loop, written down: understand the code before editing -> make the smallest correct, scoped change -> VERIFY it (smoke tests + the preview/verification workflow when observable) -> /builder-ship with real notes. Engineering is already the default way you'd work, so this is a reminder of the standard (and the autonomous-mode guardrails: be conservative, verify hard, don't wander), not a redirect. Open /dev if you want the checklist or you're running autonomously."
7
+ "directive": "This is an ENGINEER task. Read the Engineer pack now, before working — it is the operating playbook for this craft and the only place the standard build loop is written down: understand the code before editing -> make the smallest correct, scoped change -> VERIFY it (smoke tests + the preview/verification workflow when observable) -> /builder-ship with real notes. Engineering is already the default way you'd work, so the pack is the standard made explicit (plus the autonomous-mode guardrails: be conservative, verify hard, don't wander), not a redirect."
8
8
  },
9
9
  "ideator": {
10
- "skill": "ideate",
10
+ "pack": "docs/packs/ideator.md",
11
11
  "label": "Ideation session",
12
- "directive": "This is an IDEATOR task. To work it, invoke the /ideate skillthat skill is the operating playbook for ideation, and it is the only place the experience is defined. It inverts the usual dynamic: you (the human ideator) are the creative driver and Claude is your sounding board / research arm / devil's advocate, not a content generator filing ideas on command. If no human is present (autonomous / bypass-permissions), /ideate runs a self-adversarial divergence-and-critique loop instead of dumping a fixed batch. Open /ideate now rather than working this task the default way. THE SURFACE, not just the behavior (ADR 0271): an ideator session is QUIET about its own machinery. Report outcomes, not mechanism — do not narrate tool calls, file paths, script names, API routes or task/claim bookkeeping unless they ask or something actually failed. Speak in the language of the idea, not the plumbing. If a step breaks, say plainly what broke and what you need — quiet never means hiding a problem."
12
+ "directive": "This is an IDEATOR task. Read the Ideator pack now and work from it it is the operating playbook for ideation and the only place the experience is defined. It inverts the usual dynamic: you (the human ideator) are the creative driver and Claude is your sounding board / research arm / devil's advocate, not a content generator filing ideas on command. Quick ideas stay ONE LINE, and after one is filed Claude asks whether to develop it into a Full Idea — five questions, drawn out of the conversation in the ideator's own words and scored on completeness. If no human is present (autonomous / bypass-permissions), the pack runs a self-adversarial divergence-and-critique loop instead of dumping a fixed batch. THE SURFACE, not just the behavior (ADR 0271): an ideator session is QUIET about its own machinery. Report outcomes, not mechanism — do not narrate tool calls, file paths, script names, API routes or task/claim bookkeeping unless they ask or something actually failed. Speak in the language of the idea, not the plumbing. If a step breaks, say plainly what broke and what you need — quiet never means hiding a problem."
13
13
  },
14
14
  "artist": {
15
- "skill": "paint",
15
+ "pack": "docs/packs/artist.md",
16
16
  "label": "Art session",
17
- "directive": "This is an ARTIST task. To work it, invoke the /paint skillthat skill is the operating playbook for art sessions, and it is the only place the experience is defined. It is show-first / low-text: Claude communicates in pictures (display the generated tile, the /art gallery at sandbox-<login>.<instance-apex>/art, and the in-world sandbox), not paragraphs about what the pipeline did. It drives the existing pixel-art pipeline (otb-tile-generate / otb-design-review / otb-feedback-capture / art-stage.js) and keeps the locked palette + rubric sacred. If no human is present (autonomous / bypass-permissions), /paint generates, rubric-gates hard, stages passing assets to the gallery, and parks the visuals for human review. Open /paint now rather than working this task the default way; the gallery is at sandbox-<login>.<instance-apex>/art."
17
+ "directive": "This is an ARTIST task. Read the Artist pack now and work from it it is the operating playbook for art sessions and the only place the experience is defined. It is show-first and low-text: communicate in pictures and rendered surfaces, not paragraphs about what ran. Interpret as little as possible — take the brief literally, you are the artist's hands and not their art director — and arrive precalculated: load the look, have the options already rendered, never open with a form of intake questions. The artist's subject is how the project LOOKS AND READS, which is core (ADR 0272); a pixel-art or asset pipeline is a host module the pack drives only when the instance ships one. If no human is present (autonomous / bypass-permissions), make it, gate it hard, stage the passes and park the visuals for human review."
18
18
  },
19
19
  "ui": {
20
20
  "skill": "design",
21
21
  "materializeModuleSkills": true,
22
22
  "label": "UI design session",
23
- "directive": "This is a UI task — interface DESIGN work (layout, wireframes, design systems, Figma / Claude-Design), split out of the pixel-art `artist` lane (ADR 0079). To work it, invoke the /design skill — the operating playbook for UI-design sessions, the only place the experience is defined. Like /paint it is show-first: communicate in mock-ups and rendered screens, not paragraphs about layout decisions — stage the change on your sandbox preview (/builder-stage) and look at the real interface before shipping. Keep the locked branding (config/branding.json) and the existing component conventions of the surface you touch (modules/status-ui, modules/hall-ui, public/game/ui). If no human is present (autonomous / bypass-permissions), produce the design, stage it for review, and park the screens rather than shipping interface changes blind. Open /design now rather than working this task the default way."
23
+ "directive": "This is a UI task — interface DESIGN work (layout, wireframes, design systems, Figma / Claude-Design), split out of the pixel-art `artist` lane (ADR 0079) and kept as a module-contributed discipline by ADR 0272. To work it, invoke the /design skill — the operating playbook for UI-design sessions, the only place the experience is defined. Like the Artist pack it is show-first: communicate in mock-ups and rendered screens, not paragraphs about layout decisions — stage the change on your sandbox preview (/builder-stage) and look at the real interface before shipping. Keep the locked branding (config/branding.json) and the existing component conventions of the surface you touch (modules/status-ui, modules/hall-ui, public/game/ui). If no human is present (autonomous / bypass-permissions), produce the design, stage it for review, and park the screens rather than shipping interface changes blind. Open /design now rather than working this task the default way."
24
24
  }
25
25
  }
26
26
  }
@@ -1342,6 +1342,12 @@ function checkSkillFrontmatter() {
1342
1342
  const CHECKS = [
1343
1343
  checkCoreHostBoundary,
1344
1344
  checkClaudeMdBudget,
1345
+ // Check 32 — task 1002990 / criterion wa6-kernel-and-packs: the root CLAUDE.md is
1346
+ // now a role-neutral KERNEL and each craft's playbook lives in a pack under
1347
+ // docs/packs/. claim.js resolves the pack through the role registry and fails
1348
+ // OPEN, so a pack path that points at nothing is invisible at runtime — CI is the
1349
+ // only place a hollowed-out role can be caught. Rationale in that file.
1350
+ require('./role-pack-guard.js').checkRolePacks,
1345
1351
  checkSkillFrontmatter,
1346
1352
  checkNestedDocsPresent,
1347
1353
  checkRankGuards,
@@ -55,7 +55,14 @@ const { cliClient, API_BASE } = require('./cli-lib');
55
55
  // not a GDS github_login, and every builder shares one commit email — so the
56
56
  // author NAME is the only distinguishing signal, and an unresolved name is
57
57
  // 'needs a human glance', not 'definitely a violation'.
58
- function analyzeCommits(commits, rankByIdentity, { strict = false } = {}) {
58
+ //
59
+ // `registry` is the protected-surface matcher, defaulting to the real one. It
60
+ // is a parameter for the same reason `rankByIdentity` is: this analyzer is pure
61
+ // and its callers supply its inputs. Tests inject a MIXED-FLOOR fixture through
62
+ // it — the real registry floors every surface at 'metic' today, so without the
63
+ // seam the per-hit floor comparison below is untestable and would silently rot
64
+ // back into a global-minimum test. The CLI never passes it.
65
+ function analyzeCommits(commits, rankByIdentity, { strict = false, registry = ppc } = {}) {
59
66
  const findings = [];
60
67
  for (const c of commits || []) {
61
68
  // #863-followup (finding #5): we no longer blanket-skip merges. For a
@@ -67,28 +74,46 @@ function analyzeCommits(commits, rankByIdentity, { strict = false } = {}) {
67
74
  // changes are still attributed to their feature commits (no double-count);
68
75
  // but a merge that smuggles a protected change is now caught and attributed
69
76
  // to the MERGE author.
70
- const hits = ppc.matchProtected(c.files || []);
77
+ const hits = registry.matchProtected(c.files || []);
71
78
  if (hits.length === 0) continue;
72
79
 
73
80
  const rank = resolveRank(c, rankByIdentity);
74
81
  const fileList = hits.map((h) => h.file).join(', ');
75
82
  if (rank == null) {
83
+ const need = strictestFloorLabel(hits, registry);
76
84
  findings.push({
77
85
  severity: strict ? 'blocker' : 'review',
78
86
  sha: c.sha,
79
87
  author: c.authorName,
80
88
  rank: null,
81
89
  files: hits.map((h) => h.file),
82
- summary: `commit ${short(c.sha)} by '${c.authorName}' touched permission-sensitive path(s) [${fileList}] but the author could not be resolved to a GDS rank. Verify it is Metic+ work.`,
90
+ summary: `commit ${short(c.sha)} by '${c.authorName}' touched permission-sensitive path(s) [${fileList}] but the author could not be resolved to a GDS rank. Verify it is ${need}+ work.`,
83
91
  });
84
- } else if (ppc.isBelowFloor(rank)) {
92
+ continue;
93
+ }
94
+
95
+ // Each hit is judged against ITS OWN registry floor — not against the
96
+ // registry's global minimum. `isBelowFloor` tests the lowest floor any
97
+ // surface declares, which is identical only while every surface floors at
98
+ // the same rank (true today). The moment governance RAISES one surface's
99
+ // floor, a global-minimum test silently downgrades that raise back to the
100
+ // minimum here — in the one layer that catches a raw `git push origin main`
101
+ // (task 1003191; the cooperative layers already compare per-hit via
102
+ // checkPermissionPaths). Unknown ranks stay non-blocking, as before: an
103
+ // unresolvable rank is the `rank == null` case above.
104
+ const tier = registry.tierOf(rank);
105
+ const below = tier === null ? [] : hits.filter((h) => tier < registry.RANK_TIER[h.floor]);
106
+ if (below.length > 0) {
107
+ const need = strictestFloorLabel(below, registry);
108
+ const belowList = below.map((h) => `${h.file} (floor ${h.floor})`).join(', ');
85
109
  findings.push({
86
110
  severity: 'blocker',
87
111
  sha: c.sha,
88
112
  author: c.authorName,
89
113
  rank,
90
- files: hits.map((h) => h.file),
91
- summary: `commit ${short(c.sha)} by '${c.authorName}' (rank '${rank}', below Metic) modified permission-sensitive path(s) [${fileList}] — this is the SEC #863 violation class. It must be reverted and re-landed by a Metic+ builder if genuinely needed.`,
114
+ files: below.map((h) => h.file),
115
+ floors: below.map((h) => h.floor),
116
+ summary: `commit ${short(c.sha)} by '${c.authorName}' (rank '${rank}') modified permission-sensitive path(s) [${belowList}] whose registry floor it does not clear — this is the SEC #863 violation class. It must be reverted and re-landed by a ${need}+ builder if genuinely needed.`,
92
117
  });
93
118
  }
94
119
  }
@@ -115,6 +140,16 @@ function short(sha) {
115
140
  return String(sha || '').slice(0, 9);
116
141
  }
117
142
 
143
+ // The highest rank floor demanded by a set of protected hits, title-cased for
144
+ // prose ('Metic', 'Archon'). What a reader has to clear to own the whole commit
145
+ // — so a finding names the floor that actually governs it rather than a
146
+ // hardcoded 'Metic+' that a governance floor raise would make a lie.
147
+ function strictestFloorLabel(hits, registry) {
148
+ const floors = hits.map((h) => h.floor);
149
+ const top = floors.reduce((a, b) => (registry.RANK_TIER[b] > registry.RANK_TIER[a] ? b : a), floors[0]);
150
+ return top ? top.charAt(0).toUpperCase() + top.slice(1) : 'Metic';
151
+ }
152
+
118
153
  // ---------- git + API glue (CLI) ----------
119
154
 
120
155
  function git(args) {
@@ -124,6 +124,15 @@ const PUBLISH_ALLOWLIST = [
124
124
  'docs/file-map.md',
125
125
  'docs/repo-map.md',
126
126
  'docs/handoff-template.md', // the portable session-handoff format (methodology)
127
+ // The ROLE PACKS (task 1002990). docs/ is default-deny, and these are not
128
+ // documentation ABOUT the methodology — they ARE it: since the kernel/pack split
129
+ // the root CLAUDE.md is role-neutral and everything a craft actually works from
130
+ // lives here. scripts/gds/discipline-modes.json ships (scripts/ is allowlisted)
131
+ // and names these paths, so omitting them would release a core whose every claim
132
+ // prints a pack path that resolves to nothing on the instance — the exact silent
133
+ // failure scripts/gds/role-pack-guard.js exists to make loud. The registry and
134
+ // this line are only ever added or removed together.
135
+ 'docs/packs/',
127
136
  'docs/canonical-permissions.md', // the rank-ladder reference IS the methodology (sanitized)
128
137
  'docs/project-context.template.md', // the neutral scaffold `cloudbongos init` fills (NOT the OTB-filled one)
129
138
  '.claude/skills/', // the methodology slash-commands (hooks/settings are denied below)