@bongos/core 1.19.971 → 1.19.973
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 +116 -76
- package/docs/adr/0111-instance-hosting-provisioning-module.md +1 -0
- package/docs/adr/0323-hosting-is-three-shapes-and-we-are-not-the-landlord.md +1 -1
- package/docs/adr/0325-the-managed-fleet-control-plane-is-the-hub-we-already-run.md +1 -1
- package/docs/adr/0327-a-cloud-host-runs-on-the-owners-account-and-the-key-is-borrowed.md +107 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +1 -1
- package/docs/api-reference.md +1 -1
- package/docs/architecture.md +6 -6
- package/docs/branding-contract.md +1 -1
- package/docs/canonical-permissions.md +24 -24
- package/docs/copy-inventory.md +193 -187
- package/docs/copy-registry.json +320 -276
- package/docs/design/projects-hub-direction-v2.md +1 -1
- package/docs/design/vanilla-hall-ui-redesign-scope.md +2 -2
- package/docs/file-map.md +7 -7
- package/docs/handoff-template.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/docs/modules-contract.md +1 -1
- package/docs/onboarding/drachmae-and-karma.md +2 -2
- package/docs/packs/engineer.md +5 -5
- package/docs/packs/ideator.md +1 -1
- package/docs/recipes/README.md +1 -1
- package/docs/recipes/audit-replay.md +2 -2
- package/docs/recipes/gds-db-backup.md +3 -3
- package/docs/recipes/managed-settings-remote-control.md +9 -9
- package/docs/recipes/memory-sync-conflicts.md +2 -2
- package/docs/recipes/ops-gotchas.md +24 -5
- package/docs/recipes/overnight-builder.md +3 -3
- package/docs/recipes/parallel-goal-waves.md +3 -3
- package/docs/recipes/reranking-a-goals-board.md +2 -2
- package/docs/recipes/search-index-ingestion.md +1 -1
- package/docs/recipes/ship-and-regrade.md +2 -2
- package/docs/recipes/staging-environment.md +1 -1
- package/docs/recipes/windows-builders.md +1 -1
- package/modules/hall-ui/public/deploy.html +10 -5
- package/modules/hall-ui/public/deploy.js +199 -110
- package/modules/hall-ui/public/goals-page.js +6 -0
- package/modules/hall-ui/public/goals-render.js +16 -0
- package/modules/hall-ui/public/mine-lens.js +172 -0
- package/modules/hall-ui/public/project-settings.css +36 -0
- package/modules/hall-ui/public/work-summary.js +90 -0
- package/modules/hall-ui/public/work.css +50 -0
- package/modules/hall-ui/public/work.html +24 -0
- package/modules/hall-ui/public/work.js +38 -51
- package/modules/lifecycle/db-goals.js +20 -3
- package/modules/lifecycle/routes/goals.js +2 -2
- package/modules/provisioning/core-upgrade.js +61 -2
- package/modules/public-landing/public/contact.html +1 -1
- package/modules/public-landing/public/index.html +1 -1
- package/modules/public-landing/public/privacy.html +1 -1
- package/modules/public-landing/public/projects.html +1 -1
- package/modules/public-landing/public/terms.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/api-alias-caller-scan.js +47 -9
- package/scripts/gds/cloudbongos-token-isolation.conf +33 -0
- package/scripts/gds/fitness.js +3 -0
- package/scripts/gds/provision-core-upgrade.js +132 -1
- package/scripts/gds/run-unit-tests.js +14 -9
- package/scripts/gds/scope-roster-guard.js +118 -0
- package/scripts/hall-preview/server.js +5 -0
- package/src/bongos/module-scope-map.js +1 -0
- package/src/module-api.js +1 -1
- package/tests/api_alias_caller_ratchet.mjs +68 -2
- package/tests/core_upgrade_door.mjs +81 -0
- package/tests/core_upgrade_runner.mjs +132 -0
- package/tests/deploy_page_projects.mjs +234 -79
- package/tests/fitness_scope_roster.mjs +117 -0
- package/tests/goal_mine_lens.mjs +233 -0
- package/tests/goal_tier.mjs +30 -4
- package/tests/hall_mine_lens.mjs +381 -0
- package/tests/idea_spark_hall.mjs +101 -12
- package/tests/known_failing_ratchet.mjs +19 -9
- package/tests/landing_legal_pages.mjs +5 -1
- package/tests/projects_hub_pre_uat.mjs +12 -6
- package/tests/served_paths_shipped.mjs +36 -2
|
@@ -85,7 +85,7 @@ Every item is tagged as the builders tagged it: **given** (one of the eight), **
|
|
|
85
85
|
These were found by the test and page mappers and confirmed against the feeds; they belong to tasks 1003300 / 1003301, not to this round.
|
|
86
86
|
|
|
87
87
|
- **No feed carries a per-project hall address.** `clientBranding()` deliberately withholds domains and `{{buildersOrigin}}` is one value per instance, so "hall entry only where the hall address differs from the site address" needs a new field on `/api/bongos/projects/featured` (or `/my-projects`), e.g. `hall_origin`, null where the hall is at `<site>/builders`. On the apex the hall is `builders.cloudbongos.com` (differs); on a child it is `<site>/builders` (same).
|
|
88
|
-
- **No feed carries faces or a 30-day count.** The enrichment (`modules/platform-identity/project-stats.js`) returns `builders`, `tags`, `owner`, `owner_avatar`; the faces need the remote leaderboard's avatar rows kept (the count already comes from them), and `shipped_30d` needs the remote `/api/
|
|
88
|
+
- **No feed carries faces or a 30-day count.** The enrichment (`modules/platform-identity/project-stats.js`) returns `builders`, `tags`, `owner`, `owner_avatar`; the faces need the remote leaderboard's avatar rows kept (the count already comes from them), and `shipped_30d` needs the remote `/api/bongos/public/recent-shipped` (row-capped at 30, hence the `N+` rule). `art_url` is already on the feed and is read by nothing.
|
|
89
89
|
- **Tests that pin the retired chrome and must be retargeted in the build** (from `tests/projects_hub.mjs`, `tests/projects_hub_pre_uat.mjs`, `tests/landing_page.mjs`): the `Home` link (`projects_hub.mjs:40, 46, 48`), the hall pill's `data-link-hall href="{{buildersOrigin}}"` (`landing_page.mjs:214-220`, `projects_hub.mjs:105`), the `.shell .navrow` rule in cosmos (`projects_hub_pre_uat.mjs:203`), the card's slice rule (`projects_hub.mjs:487`: the first adjacent `</div></div>` ends the slice, so every new card region must be a direct child and the banner a bare `<img>`), the `<td>` count across the header, `#selfRow` and the row template if the glyph becomes a cell (`projects_hub.mjs:531-535`), and the singular `querySelector('[data-nav="mine"]')` at `projects.html:5307` (a `My projects` item with `data-nav="mine"` would be a second node; hide by `querySelectorAll` or hook it differently). The dropdown items keep `href="?view=map" data-nav="map"` (etc.) as adjacent attributes so `projects_hub.mjs:42-43` holds unchanged. A new bar-ground token goes into cosmos with both dark twins and a `PAIRS` row in `tests/cosmos_token_contrast.mjs`.
|
|
90
90
|
- **Copy.** Every string that changes on the built page re-runs `node scripts/gds/copy-inventory.js` (CI checks the registry).
|
|
91
91
|
|
|
@@ -82,7 +82,7 @@ One shell wraps every page, replacing both the header text-link stack and the pe
|
|
|
82
82
|
| **Content** | Scrollable view region | Right of sidebar, below top bar | max 1120px, gutter 24–32 | Only region that scrolls. One view at a time; centers past max. |
|
|
83
83
|
| **Footer** | Minimal meta line | End of content flow | auto | Reduced to sign-out + instance name; no lore. |
|
|
84
84
|
|
|
85
|
-
> **Seam preserved.** The shell is chrome only. The hall-widget registry (`dom-utils.js` · `contributeHallWidget`) and the `/api/
|
|
85
|
+
> **Seam preserved.** The shell is chrome only. The hall-widget registry (`dom-utils.js` · `contributeHallWidget`) and the `/api/bongos/*` reads are unchanged — widgets mount into view containers instead of one `<main>`.
|
|
86
86
|
|
|
87
87
|
---
|
|
88
88
|
|
|
@@ -268,7 +268,7 @@ Not layout, but it rides along. Most of this already flows through the brand pac
|
|
|
268
268
|
The hall has hard architectural constraints (see `modules/hall-ui/CLAUDE.md`). Placement changes are cheap only if they respect these.
|
|
269
269
|
|
|
270
270
|
- **Widget registry is the source of truth.** A fitness check (`scripts/gds/fitness.js checkHallSectionRegistry`) reds the build if a `<section class="scroll">` is hardcoded into `<main>`. Views must mount registered widgets, not inline them.
|
|
271
|
-
- **No framework, no build step.** Static HTML/CSS/JS polling `/api/
|
|
271
|
+
- **No framework, no build step.** Static HTML/CSS/JS polling `/api/bongos/*`. The shell is hand-rolled CSS + a small amount of JS — no framework may be introduced.
|
|
272
272
|
- **Dedicated serving block.** `src/bongos/serve-internal.js` serves this from `BUILDERS_DIR` with the subdomain rewrite shim, canonical redirects, page gates, and asset-stamping. New assets must carry the content-hash `?v=` stamp.
|
|
273
273
|
- **Server-side gates stay authoritative.** Hiding a sidebar item is cosmetic; `requireGovernancePage` and the sign-in redirects remain the real access control.
|
|
274
274
|
- **Brand pack drives copy.** Neutralizing voice = a neutral default pack + removing hardcoded lore, not English strings baked into markup.
|
package/docs/file-map.md
CHANGED
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
│ ├── box-dormant-reclaim.{service,timer} ← (#598) daily CONTROL-PLANE sweep: deprovision long-parked dev boxes
|
|
87
87
|
│ ├── box-intent-runner.{service,timer} ← (#701) 1-min CONTROL-PLANE runner: drain box_intents (auto-provision + wake-on-connect) via `box.js run-intents --apply`
|
|
88
88
|
│ ├── box-drift-reconcile.{service,timer} ← (#1289/ADR 0071) hourly CONTROL-PLANE sweep: repair DO⇄DB drift via `box.js reconcile-drift --apply` (kill zombie droplets, mark ghost rows destroyed)
|
|
89
|
-
│ ├── box-heartbeat.sh ← (#598) runs ON THE BOX: pings /api/
|
|
90
|
-
│ ├── box-report-terminal.sh ← (#760/ADR 0038) runs ON THE BOX: POSTs the box's web-terminal URL + basic-auth credential UP to /api/
|
|
89
|
+
│ ├── box-heartbeat.sh ← (#598) runs ON THE BOX: pings /api/bongos/box/heartbeat while in use, so the idle sweep measures activity not uptime
|
|
90
|
+
│ ├── box-report-terminal.sh ← (#760/ADR 0038) runs ON THE BOX: POSTs the box's web-terminal URL + basic-auth credential UP to /api/bongos/box/terminal so a Chromebook builder reads them from the web
|
|
91
91
|
│ ├── box-source-fetch.sh ← (#600/#898/ADR 0052) runs ON THE BOX post-clone: scope-aware source fetch (sparse starter / full) + idempotently installs & enables the box units (box-game-preview, box-terminal, close-box) on every fetch so existing boxes self-heal; also self-tests (task 843) — every cycle it black-box-probes box-terminal/cloudflared/box-game-preview + the terminal credential and restarts whatever's unhealthy, not just what's absent
|
|
92
92
|
│ ├── builder-box-cloud-init.yaml ← (#598/#599/#760) first-boot bootstrap: Docker + devcontainer up, Claude Code + ttyd + cloudflared on host, box-terminal.service + cloudflared.service + heartbeat cron wired (substituted by box.js)
|
|
93
93
|
│ ├── managed-settings.template.json ← (#599) Claude Desktop sshConfigs template (locked to one approved box); filled per-builder by gen-managed-settings.sh
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
│ ├── discord-channels.js ← Archon CLI: plan/apply the Discord channel layout via the API (ADR 0036, #727)
|
|
165
165
|
│ ├── setup.js ← one-time GitHub Device Flow → ~/.config/otb/gds-session.json
|
|
166
166
|
│ ├── start.js ← list claimable tasks + active claims (`/builder-start`)
|
|
167
|
-
│ ├── claim.js ← atomic POST /api/
|
|
167
|
+
│ ├── claim.js ← atomic POST /api/bongos/claims (`/builder-claim`); runs the worktree-per-claim guard (worktree-claim-guard.js) BEFORE the session check and the POST; prints the claim-time context pack incl. next-free ADR/migration numbers (V4.R26); printDisciplineMode() reads discipline-modes.json to route a claimed task to its playbook skill
|
|
168
168
|
│ ├── discipline-modes.json ← the ROLE REGISTRY read by claim.js: engineer/artist/ideator → their role pack under docs/packs/, module-contributed ui → the /design skill; absence of an entry = the default build-and-ship loop, fail-open at claim time — but scripts/gds/role-pack-guard.js hard-fails CI if an entry names a pack that is not in the tree ([#1267](https://example.com/builders#/task/1267))
|
|
169
169
|
│ ├── next-number.js ← deterministic next-free ADR + migration number from origin/main ∪ local working tree; supersedes the drift-prone claim-time DB counter (V4.R26, [#964](https://example.com/builders#/task/964)). `node scripts/gds/next-number.js [--json]`
|
|
170
170
|
│ ├── gen-repo-map.js ← Path B (ADR 0063, [#1224](https://example.com/builders#/task/1224)): zero-dep, deterministic symbol-skeleton generator → docs/repo-map.md + the generated factual block in each nested CLAUDE.md; ranks exported symbols by reference frequency. `--check` = CI gate; regenerated on deploy by ship.js regenerateRepoMap()
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
│ ├── me.js ← current builder profile + leaderboard
|
|
188
188
|
│ ├── goal.js ← goal board CLI: `list` (rollup per goal) + `show <id>` (criteria, tasks, waits-on, next claimable)
|
|
189
189
|
│ ├── seed-v3-tasks.js ← V3 Planning Session #1: 80 net-new GDS-V3 tasks (V3.R01–V3.R89) + 10 idea_inbox promotions; idempotent on source_ref
|
|
190
|
-
│ ├── backfill-cost.js ← read art ledger → POST /api/
|
|
190
|
+
│ ├── backfill-cost.js ← read art ledger → POST /api/bongos/cost (idempotent)
|
|
191
191
|
│ ├── smoke-write.sh ← write-path smoke (create→claim→ship round-trip)
|
|
192
192
|
│ ├── backup-dropin-sweep.sh ← (task 1003930) control-plane sweep: retires the temporary task-1003925 backup drop-in from each project whose pinned core carries the fix (1.19.750+), proving one backup succeeds without it first; survey by default, `--apply` to act; re-run after each pin moves
|
|
193
193
|
│ ├── stray-unit-sweep.sh ← (task 1003939) control-plane sweep: the ledger's torn-down slugs that still have a service/backup unit loaded or on disk (a torn-down project holding memory outside the ADR 0285 count); survey by default, `--apply` disables, removes, reloads, reset-failed's; DB/dumps/checkout/Caddy left alone
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
│ │ ├── catalog.js ← the browsable module catalog model (ADR 0167 / ADR 0107 §2/§3): `source` (which TREE ships it — core package vs instance, read off the loader's discovery root) + resolved author/origin `credit` with an `inferred` flag. The ONE builder behind both `GET /api/bongos/modules` and `bongos module list --catalog`, so the hall + CLI can't drift.
|
|
230
230
|
│ │ └── semver.js ← minimal semver `satisfies(version, range)` used by the loader (no npm dep).
|
|
231
231
|
│ ├── platform-server.js ← BONGOS-ONLY entrypoint (ADR 0062 R51, task 1190): boots Express + the shared internal surface (API + hall + status) with NO game in the process; the inverse of preview-server.js. `node src/platform-server.js`
|
|
232
|
-
│ ├── preview-server.js ← GAME-ONLY entrypoint for the per-box sandbox (ADR 0052): Phaser/Colyseus + tiles, NO /api/
|
|
232
|
+
│ ├── preview-server.js ← GAME-ONLY entrypoint for the per-box sandbox (ADR 0052): Phaser/Colyseus + tiles, NO /api/bongos
|
|
233
233
|
│ ├── seats.js ← in-process seat counter + EventEmitter
|
|
234
234
|
│ ├── rooms/
|
|
235
235
|
│ │ ├── WorldRoom.js ← singleton room: move + interact + identity
|
|
@@ -401,7 +401,7 @@ tests/
|
|
|
401
401
|
├── builder-exit/SKILL.md ← /builder-exit — gracefully offboard (or reactivate) a builder: release claims, seal session logs, drop rank to xenos
|
|
402
402
|
├── builder-key/SKILL.md ← /builder-key — list API-key status, render the visual 'key needed' callout for anything missing, drive the UI-first Settings add-flow + re-sync/confirm; never accepts a key pasted in chat (task 1391)
|
|
403
403
|
├── builder-reauth/SKILL.md ← /builder-reauth — refresh an expired Bongos CLI session the UI-first way (no terminal Device Flow)
|
|
404
|
-
├── builder-redteam/SKILL.md ← /builder-redteam — file a red-team / vulnerability report (severity, target, repro) to /api/
|
|
404
|
+
├── builder-redteam/SKILL.md ← /builder-redteam — file a red-team / vulnerability report (severity, target, repro) to /api/bongos/security
|
|
405
405
|
├── builder-release/SKILL.md ← /builder-release — abandon a claim (task returns to ready, no credits)
|
|
406
406
|
├── builder-sequence/SKILL.md ← /builder-sequence N — walk a whole dependency chain from one kickoff (claim → build → ship → next), one claim at a time; halts and reports on migration/security/protected-path/thin-spec/judgement tasks (scripts/gds/sequence.js, task 1002484)
|
|
407
407
|
├── builder-setup/SKILL.md ← /builder-setup — one-time GitHub Device Flow auth (Bongos); multi-builder-on-one-device gate
|
|
@@ -489,7 +489,7 @@ To install on a new machine, symlink each routine's directory under `~/.claude/s
|
|
|
489
489
|
├── session-start.js ← SessionStart: <redacted> .env.local into a fresh worktree, then chains onboarding-ship + rank-change greeting + memory pull
|
|
490
490
|
├── rank-change-greeting.js ← promotion/demotion greeting (V3.R28 #249); spawned by session-start.js, also runnable standalone
|
|
491
491
|
├── pull-memory.js ← memory pull-on-session-start (V3.R56 #275); spawned by session-start.js (kill-switches: OTB_MEMORY_PULL_OFF / OTB_SUBAGENT)
|
|
492
|
-
├── recall-hints.js ← SessionStart: when the session opens holding a claim, surface the top project-knowledge hits for that task via POST /api/
|
|
492
|
+
├── recall-hints.js ← SessionStart: when the session opens holding a claim, surface the top project-knowledge hits for that task via POST /api/bongos/search (#963/V4.R25, ADR 0060)
|
|
493
493
|
├── conductor.js ← UserPromptSubmit: MAS Conductor advisory + dispatch directive (#427/#439); self-gates on OTB_CONDUCTOR_OFF / OTB_SUBAGENT
|
|
494
494
|
├── session-cards.js ← UserPromptSubmit: deterministic delivery of READ-ONLY in-session cards (builder-start, status) — pre-renders the card + injects a one-step render directive (task 1288)
|
|
495
495
|
├── lifecycle-card.js ← PostToolUse (Bash|PowerShell): deterministic delivery of MUTATING lifecycle cards (claim/ship/release) — the write-side mirror of session-cards.js (task 1288)
|
package/docs/handoff-template.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
**New limitations / risks / blockers introduced this session:**
|
|
28
28
|
- {new V1 architecture limitation → added to limitations/current-version.md}
|
|
29
29
|
- {new ops gotcha → long-form recipe under docs/recipes/, OR short rule via `node scripts/gds/learning-capture.js`}
|
|
30
|
-
- {new blocker for Lars → POST /api/
|
|
30
|
+
- {new blocker for Lars → POST /api/bongos/blockers (the markdown file is frozen archive only)}
|
|
31
31
|
- {(or "none")}
|
|
32
32
|
|
|
33
33
|
**Generative ideas captured this session:**
|
|
@@ -2416,5 +2416,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2416
2416
|
landed since 1.19.969 with no explicit bump. run 35804568036. (task 1002620)
|
|
2417
2417
|
1.19.971 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2418
2418
|
landed since 1.19.970 with no explicit bump. run 35805746484. (task 1002620)
|
|
2419
|
+
1.19.972 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2420
|
+
landed since 1.19.971 with no explicit bump. run 35806478158. (task 1002620)
|
|
2421
|
+
1.19.973 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2422
|
+
landed since 1.19.972 with no explicit bump. run 35813381436. (task 1002620)
|
|
2419
2423
|
---------------------------------------------------------------------------
|
|
2420
2424
|
```
|
package/docs/modules-contract.md
CHANGED
|
@@ -296,7 +296,7 @@ Each module's `modules/<key>/CLAUDE.md` is the authoritative per-module referenc
|
|
|
296
296
|
| `isModuleEnabled(name)` | Gate a mount or feature. Throws on an unknown name (programmer error). |
|
|
297
297
|
| `enabledModules()` | The resolved on-set (an array of enabled module keys). |
|
|
298
298
|
| `enabledDisciplines()` | The union of `contributes.disciplines` across enabled modules. |
|
|
299
|
-
| `clientModules()` | `{ enabled: {…booleans}, disciplines: […] }` — injected into hall/status HTML as `window.__MODULES__` and served at `GET /api/
|
|
299
|
+
| `clientModules()` | `{ enabled: {…booleans}, disciplines: […] }` — injected into hall/status HTML as `window.__MODULES__` and served at `GET /api/bongos/public/modules`. Front-ends read it to hide UI sections for off modules. |
|
|
300
300
|
| `resolveModules(opts)` | The pure resolver (unit-tested, zero I/O). |
|
|
301
301
|
|
|
302
302
|
---
|
|
@@ -118,7 +118,7 @@ Builders are **uncapped by default** ([ADR 0085](../adr/0085-remove-default-per-
|
|
|
118
118
|
|
|
119
119
|
- **No default cap.** `monthly_budget_usd` is unset for most builders, which means uncapped. The MTD figure still resets at the start of each calendar month.
|
|
120
120
|
- A cap, when set, is there to **catch a runaway**, not to ration normal work — the **$50 default was removed** ([ADR 0085](../adr/0085-remove-default-per-builder-spend-cap.md)) because a new builder's own session cost crossed it within a day or two, freezing the very work it was meant to enable.
|
|
121
|
-
- An **Archon** can set or clear a specific builder's ceiling (`PATCH /api/
|
|
121
|
+
- An **Archon** can set or clear a specific builder's ceiling (`PATCH /api/bongos/builders/:id/budget`); clearing it (`null`) returns the builder to uncapped.
|
|
122
122
|
|
|
123
123
|
If a cap is set and you hit `over`, you're not in trouble — you've just reached the month's ceiling. Ask an Archon to raise or clear it if the work justifies it.
|
|
124
124
|
|
|
@@ -130,7 +130,7 @@ Karma (added in migration 040) is a **completely separate** counter from example
|
|
|
130
130
|
|
|
131
131
|
### How karma is earned (and lost)
|
|
132
132
|
|
|
133
|
-
- **Peer votes on confirmed work.** Builders upvote/downvote each other's confirmed tasks. Only **Metic-and-above** can cast a vote (`POST /api/
|
|
133
|
+
- **Peer votes on confirmed work.** Builders upvote/downvote each other's confirmed tasks. Only **Metic-and-above** can cast a vote (`POST /api/bongos/tasks/:id/vote` is rank-gated). Votes are **tallied weekly** into one net `peer_vote_weekly` karma entry per builder. There's an **anti-self-vote** guard and an anti-retaliation rule (a downvote can't dent your karma within the same week).
|
|
134
134
|
- **Proposal ratification.** When a criterion-proposal you made is ratified, you get **+3 karma** (`proposal_ratified`).
|
|
135
135
|
- **Idea promotion.** Promoting an idea into a real task awards karma to the capturer.
|
|
136
136
|
- **It can go down.** The [BFG](../adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md) good-citizenship corrections can apply a *non-positive* karma delta. Karma is a slower, more reflective signal than example — you can ship fast and still lose karma if you break things.
|
package/docs/packs/engineer.md
CHANGED
|
@@ -33,13 +33,13 @@ Engineering is the project's **default loop**, so this pack introduces no new dy
|
|
|
33
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
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
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/
|
|
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/bongos/tasks` or `node scripts/gds/capture.js`, then claim it.
|
|
37
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
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
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
40
|
- **Non-obvious decision → an ADR** in [`docs/adr/`](../adr/), linked from the shipping task's notes.
|
|
41
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/
|
|
42
|
+
- **Stuck on something only the owner can decide or provide → a blocker** (`POST /api/bongos/blockers`), with the `blocker_ref` attached to the task.
|
|
43
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
44
|
|
|
45
45
|
### Where an idea goes when it isn't this task
|
|
@@ -48,7 +48,7 @@ Engineering is the project's **default loop**, so this pack introduces no new dy
|
|
|
48
48
|
|
|
49
49
|
- Fits inside the existing claim → just ship it under that claim.
|
|
50
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/
|
|
51
|
+
- Bigger or out of scope → create a task via `POST /api/bongos/tasks` (status `backlog`), or capture it with `node scripts/gds/capture.js` for `idea_inbox` triage.
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
@@ -73,8 +73,8 @@ If this is an autonomous, bypass-permissions, or scheduled run and no one will a
|
|
|
73
73
|
|
|
74
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
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/
|
|
77
|
-
4. **Update the detail files** if anything changed: a new gotcha → a recipe or a captured learning; a new blocker → `POST /api/
|
|
76
|
+
3. **Review the `idea_inbox`** via `GET /api/bongos/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/bongos/blockers`; a decision → a new ADR.
|
|
78
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
79
|
|
|
80
80
|
If nothing changed in a section, leave it alone — don't churn.
|
package/docs/packs/ideator.md
CHANGED
|
@@ -39,7 +39,7 @@ If unsure, ask once: *"Are you here to ideate with me, or should I run this auto
|
|
|
39
39
|
|
|
40
40
|
So that every idea lands against reality rather than in a vacuum:
|
|
41
41
|
|
|
42
|
-
1. **What's already filed** — `node scripts/gds/api.js GET /api/
|
|
42
|
+
1. **What's already filed** — `node scripts/gds/api.js GET /api/bongos/inbox`. You will not propose near-duplicates of open ideas; if a thread overlaps one, say so and build *on* it.
|
|
43
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
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
45
|
|
package/docs/recipes/README.md
CHANGED
|
@@ -17,7 +17,7 @@ A "recipe" is not a limitation (something the project cannot do). It is a multi-
|
|
|
17
17
|
|
|
18
18
|
- Architectural decisions → [`docs/adr/`](../../docs/adr/)
|
|
19
19
|
- Things the project cannot do → `limitations/` (instance-side)
|
|
20
|
-
- Things stuck on the prompter's input → the blockers queue (`POST /api/
|
|
20
|
+
- Things stuck on the prompter's input → the blockers queue (`POST /api/bongos/blockers`, reviewed via `/blocker-review`)
|
|
21
21
|
|
|
22
22
|
## Read order while working
|
|
23
23
|
|
|
@@ -23,7 +23,7 @@ Run by an Archon when investigating an incident, a suspected compromise, or a "w
|
|
|
23
23
|
Notably absent — and worth knowing about so you can ask follow-up questions if needed:
|
|
24
24
|
|
|
25
25
|
- **GET requests** are not in `audit_log` (by design; high volume, low signal). Read patterns aren't part of this replay.
|
|
26
|
-
- **Builder rank changes** show up as `HTTP_PATCH route=/api/
|
|
26
|
+
- **Builder rank changes** show up as `HTTP_PATCH route=/api/bongos/builders/:id/rank` rows and as `CREDIT` rows when the rank change carries a example adjustment. The new rank value lives in `audit_log.request_body_redacted`.
|
|
27
27
|
- **Game-server WebSocket events** (movement, world state) live in `world_events` and are NOT included here — this script is Bongos-scoped. If a game-side investigation is needed, query `world_events` separately.
|
|
28
28
|
|
|
29
29
|
## Running the script
|
|
@@ -73,7 +73,7 @@ A "gap" is something the builder did that does NOT appear in the output. The rep
|
|
|
73
73
|
- **Direct DB writes via psql.** If an Archon runs `psql … UPDATE tasks SET …` directly, that bypasses the API and produces NO `audit_log` row. Mitigation: don't do that without documenting in the corresponding claim's `session_logs.notes_md`. (See CLAUDE.md §8 working rules — direct DB writes need a claim too.)
|
|
74
74
|
- **Game-server side effects** (player position updates, WorldRoom state). These intentionally live in `world_events` and are out of scope here; a separate game-side replay would be needed for that.
|
|
75
75
|
- **Webhooks / scheduled tasks** that act as a builder identity. Each scheduled task runs as `example-owner` (the droplet's service identity); its actions ARE captured as that builder's audit log entries, but a forensic reader needs to know to filter them by `route` shape (e.g. routes that no human ever hits).
|
|
76
|
-
- **Build-broadcast posts** to Discord `#ship-news` (`scripts/discord/`, webhook — replaced the retired Google Chat `scripts/chat/` on 2026-06-05). The broadcast itself is not in `audit_log`, but the *trigger* (which task shipped) IS, as a `POST /api/
|
|
76
|
+
- **Build-broadcast posts** to Discord `#ship-news` (`scripts/discord/`, webhook — replaced the retired Google Chat `scripts/chat/` on 2026-06-05). The broadcast itself is not in `audit_log`, but the *trigger* (which task shipped) IS, as a `POST /api/bongos/tasks/:id/ship`. So the chain is reconstructable: the audit-replay shows "X shipped at T"; the Discord `#ship-news` channel shows the broadcast went out shortly after.
|
|
77
77
|
|
|
78
78
|
If you find a class of action that produces NEITHER a row in any of the six tables NOR a record elsewhere, file it as a task — that's a real audit-trail gap.
|
|
79
79
|
|
|
@@ -265,9 +265,9 @@ gunzip -c "$DUMP" | sudo -u postgres psql -d example
|
|
|
265
265
|
# 4. Restart the app.
|
|
266
266
|
sudo systemctl start example
|
|
267
267
|
|
|
268
|
-
# 5. Smoke: hit /api/
|
|
269
|
-
curl -s https://example.com/api/
|
|
270
|
-
curl -s https://example.com/api/
|
|
268
|
+
# 5. Smoke: hit /api/bongos/healthz, /api/bongos/versions, /api/bongos/public/progress.
|
|
269
|
+
curl -s https://example.com/api/bongos/healthz
|
|
270
|
+
curl -s https://example.com/api/bongos/public/progress | jq '.progress[0]'
|
|
271
271
|
```
|
|
272
272
|
|
|
273
273
|
## Bug attachments — the state that is not in the database (task 1003918)
|
|
@@ -35,10 +35,10 @@ Both paths land the builder on the same box and the same `/workspace`. The choic
|
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
# macOS / Linux
|
|
38
|
-
curl -fsSL https://example.com/api/
|
|
38
|
+
curl -fsSL https://example.com/api/bongos/box/connect.sh | bash
|
|
39
39
|
# Windows (PowerShell)
|
|
40
|
-
irm https://example.com/api/
|
|
41
|
-
# Plain-text guide (no auth): https://example.com/api/
|
|
40
|
+
irm https://example.com/api/bongos/box/connect.ps1 | iex
|
|
41
|
+
# Plain-text guide (no auth): https://example.com/api/bongos/box/connect
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
The bootstrap (`infra/box-connect.sh` / `.ps1`, served by `GET /box/connect.sh|.ps1`)
|
|
@@ -191,10 +191,10 @@ No SSH and no pairing script - two API calls:
|
|
|
191
191
|
|
|
192
192
|
```bash
|
|
193
193
|
# 1. Get a box (provisions or wakes it; see Part 0 / #701):
|
|
194
|
-
POST /api/
|
|
194
|
+
POST /api/bongos/box/ensure
|
|
195
195
|
|
|
196
196
|
# 2. Poll until the box has reported its terminal up:
|
|
197
|
-
GET /api/
|
|
197
|
+
GET /api/bongos/box/terminal
|
|
198
198
|
# -> {"url": "https://<id>.trycloudflare.com", "credential": "<redacted>"}
|
|
199
199
|
```
|
|
200
200
|
|
|
@@ -276,7 +276,7 @@ The build is unit- and smoke-covered, but the loop crosses real hardware + a hum
|
|
|
276
276
|
**Leg A — quick tunnel (zero secrets).**
|
|
277
277
|
|
|
278
278
|
1. Provision a box for a test builder: `node scripts/gds/box.js onboard <login> --apply` (builder must have a registered SSH key, or `--allow-no-keys`). Confirm cloud-init finished: SSH in and `cloud-init status --wait` → `done`; `systemctl is-active box-terminal cloudflared` → `active`.
|
|
279
|
-
2. Confirm the box published its terminal: `tail /tmp/box-report-terminal.log` should show `terminal access reported`. Then as the builder: `GET /api/
|
|
279
|
+
2. Confirm the box published its terminal: `tail /tmp/box-report-terminal.log` should show `terminal access reported`. Then as the builder: `GET /api/bongos/box/terminal` (or `/builder-box`) → returns `{ url: https://<id>.trycloudflare.com, credential }`.
|
|
280
280
|
3. Open the `url` in a browser. Basic-auth as **`otb`** + the `credential`. You should land in a `/workspace` shell.
|
|
281
281
|
4. In that terminal run `claude`. Complete the browser `/login` (trust is pre-seeded, [#824](https://example.com/builders#/task/824) — accept once if still prompted) and Trusted-Devices enrollment. Confirm an interactive session starts. **This is the leg `claude rc` could never do** ([#745](https://example.com/builders#/task/745)).
|
|
282
282
|
5. Inside that session, run **`/remote-control`** (the slash command, NOT `claude rc`). Confirm it prints a pairing link; open the link and confirm the Claude web/mobile app drives the box (ADR 0040, verified live 2026-06-07).
|
|
@@ -299,7 +299,7 @@ The build is unit- and smoke-covered, but the loop crosses real hardware + a hum
|
|
|
299
299
|
|
|
300
300
|
## Part 3 — The box-heartbeat cron
|
|
301
301
|
|
|
302
|
-
The cloud-init also wires `infra/box-heartbeat.sh` as a 5-minute cron job. This pings `/api/
|
|
302
|
+
The cloud-init also wires `infra/box-heartbeat.sh` as a 5-minute cron job. This pings `/api/bongos/box/heartbeat` while the box is in active use (interactive SSH session or CPU load > 0.2). Silence = the idle-suspend sweep ([#598](https://example.com/builders#/task/598)) is free to park the box.
|
|
303
303
|
|
|
304
304
|
Without this cron the idle sweep measures **uptime** instead of **activity** and may park a box someone is actively using. Always verify it's wired:
|
|
305
305
|
|
|
@@ -323,7 +323,7 @@ from Bongos at boot and on a 10-minute cron, via `infra/box-source-fetch.sh`
|
|
|
323
323
|
1. The box reads the builder's Bongos session token (it appears after they authenticate
|
|
324
324
|
Claude Code / run `/builder-reauth` — so the **first clone lands after the builder
|
|
325
325
|
connects**, not at boot).
|
|
326
|
-
2. It calls `GET /api/
|
|
326
|
+
2. It calls `GET /api/bongos/box/source-access`. Bongos checks the builder's **live**
|
|
327
327
|
rank + status (ADR 0016 — unforgeable from the box):
|
|
328
328
|
- **403 `SOURCE_ACCESS_REVOKED`** — builder demoted below the floor or deactivated.
|
|
329
329
|
The script cuts the credentialed remote (box-side clawback); `box.js reconcile`
|
|
@@ -400,7 +400,7 @@ bash infra/gen-managed-settings.sh alice > /tmp/alice-managed-settings.json
|
|
|
400
400
|
# 4. For thin-device (Chromebook) path: the web terminal is ready automatically
|
|
401
401
|
# (box-terminal.service + cloudflared.service start at boot; box-report-terminal
|
|
402
402
|
# publishes the URL + credential to Bongos within ~1 min)
|
|
403
|
-
# Builder self-serves: POST /api/
|
|
403
|
+
# Builder self-serves: POST /api/bongos/box/ensure, then poll GET /api/bongos/box/terminal
|
|
404
404
|
# -> open the url, basic-auth as user 'otb' with the returned credential, run: claude
|
|
405
405
|
# -> then /remote-control to drive the box from the Claude app (ADR 0040)
|
|
406
406
|
|
|
@@ -12,8 +12,8 @@ Memory is **local-first, server-canonical on ship**. There are exactly two sync
|
|
|
12
12
|
|
|
13
13
|
| Trigger | Direction | What happens |
|
|
14
14
|
|---|---|---|
|
|
15
|
-
| `/builder-ship` succeeds ([#274](https://example.com/builders#/task/274) R55) | **push** local → server | `POST /api/
|
|
16
|
-
| `SessionStart` / `/builder-start` ([#275](https://example.com/builders#/task/275) R56) | **pull** server → local | client reports its newest local `mtime`; `GET /api/
|
|
15
|
+
| `/builder-ship` succeeds ([#274](https://example.com/builders#/task/274) R55) | **push** local → server | `POST /api/bongos/memory/sync` upserts each local memory file into `builder_memory`. Every file is written unconditionally — the **last push to land wins**. |
|
|
16
|
+
| `SessionStart` / `/builder-start` ([#275](https://example.com/builders#/task/275) R56) | **pull** server → local | client reports its newest local `mtime`; `GET /api/bongos/memory/since?mtime=…` returns files the server holds that are **newer**; client writes them over local copies. |
|
|
17
17
|
|
|
18
18
|
The stored `mtime` is the client's reported file mtime and is **advisory** — used only by the pull side's newer-than check. The server's own `updated_at` (trigger-maintained) is the authority for "when did this row actually change." A client cannot win a conflict by forging a future mtime: an unparseable mtime is normalized to `NULL`, and the server clock governs.
|
|
19
19
|
|
|
@@ -87,6 +87,25 @@ Organized by topic, not chronology. New entries go in the matching section; crea
|
|
|
87
87
|
|
|
88
88
|
---
|
|
89
89
|
|
|
90
|
+
## systemd
|
|
91
|
+
|
|
92
|
+
### The web tier is blocked from the cloud tokens by a drop-in — don't "tidy" it away
|
|
93
|
+
|
|
94
|
+
`/etc/systemd/system/cloudbongos.service.d/<redacted>.conf` carries `InaccessiblePaths=/etc/cloudbongos/box.env`, so the internet-facing process cannot read the DigitalOcean and Cloudflare tokens (ADR 0327 §5, task 1004176). The repo copy is `scripts/gds/cloudbongos-token-isolation.conf`.
|
|
95
|
+
|
|
96
|
+
Without it the file is plain mode 600 owned by `lars` and the web tier runs as `lars`, so it *could* read them — ADR 0111 §2's boundary is real in the code but was not enforced by the kernel. Deleting the drop-in silently restores that exposure.
|
|
97
|
+
|
|
98
|
+
**Verifying it needs the service's own user, not root.** A mode-000 over-mount is bypassed by `CAP_DAC_OVERRIDE`, so a root read succeeds and makes a working configuration look like it did nothing:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
PID=$(systemctl show -p MainPID --value cloudbongos)
|
|
102
|
+
sudo nsenter -t "$PID" -m -- setpriv --reuid=lars --regid=lars --clear-groups \
|
|
103
|
+
cat /etc/cloudbongos/box.env # must FAIL
|
|
104
|
+
sudo -u lars cat /etc/cloudbongos/box.env >/dev/null # must SUCCEED (runners need it)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Inside the namespace the file lists as `---------- 1 root root 0`. The runner units load it via `EnvironmentFile=` in the host namespace and are unaffected.
|
|
108
|
+
|
|
90
109
|
## SSH + droplet
|
|
91
110
|
|
|
92
111
|
### Don't `apt-get upgrade` in a plain SSH session
|
|
@@ -181,7 +200,7 @@ Organized by topic, not chronology. New entries go in the matching section; crea
|
|
|
181
200
|
|
|
182
201
|
### PowerShell 5.1 turns a clean `node scripts/gds/*.js` exit into a false failure
|
|
183
202
|
|
|
184
|
-
- **Symptom:** Running `node scripts/gds/api.js GET /api/
|
|
203
|
+
- **Symptom:** Running `node scripts/gds/api.js GET /api/bongos/me 2>&1` (or the same on `claim.js`/`ship.js`) inside a PowerShell 5.1 session reports failure — `$?` is `$false` and the stderr line surfaces as a `NativeCommandError` — even though node exited 0 and the JSON on stdout is exactly right.
|
|
185
204
|
- **Root cause:** `api.js` prints its status banner to stderr unconditionally, by design (stdout stays clean JSON for piping); `claim.js`/`ship.js` also write diagnostics to stderr during a normal run. PS 5.1 wraps any stderr output from a native command into an `ErrorRecord` once the two streams are merged with `2>&1`, and sets `$?` false regardless of the actual exit code.
|
|
186
205
|
- **Fix:** Never merge streams on these calls. Prefer `scripts/gds/api.ps1` (a thin wrapper that discards stderr and writes clean JSON to stdout, safe to pipe into `ConvertFrom-Json`), or call `node scripts/gds/api.js ...` plain, with no `2>&1`.
|
|
187
206
|
- **Why it bites:** The exit code and JSON body are both fine — only the redirection is wrong — so the failure looks like a real API error and wastes time chasing a phantom bug in the call itself.
|
|
@@ -209,17 +228,17 @@ Organized by topic, not chronology. New entries go in the matching section; crea
|
|
|
209
228
|
- **Root cause (one known class, fixed):** the grader read a `null` baseline because the task had empty `touches[]`, so it diffed against nothing and "saw" zero files. Fixed in [#536](https://example.com/builders#/task/536) — the grader baseline is now derived from `git merge-base` independent of `touches[]`. If you hit a *different* false-negative class, treat the below as the general escape hatch.
|
|
210
229
|
- **The process (canonical — works at any rank):**
|
|
211
230
|
1. The **stuck builder** (any rank, incl. Xenos) files an override request — this is the one builder-rank-available escape hatch:
|
|
212
|
-
`POST /api/
|
|
231
|
+
`POST /api/bongos/tasks/:id/override-request` with `{ "rationale": "<≥20 chars: why the grade is wrong>" }`.
|
|
213
232
|
This is *not* routing around the trust boundary — Xenos are allowed to file; only the decision is privileged.
|
|
214
|
-
2. An **Archon** reviews the open queue (`GET /api/
|
|
215
|
-
`POST /api/
|
|
233
|
+
2. An **Archon** reviews the open queue (`GET /api/bongos/override-requests?status=open`) and decides:
|
|
234
|
+
`POST /api/bongos/override-requests/:id/decide` with `{ "decision": "approve", "note": "..." }`.
|
|
216
235
|
3. On approve, the task flips `completed → confirmed` and **both the credit AND the ship attribution (`shipped_by`) land with the original requester**, never the approving Archon ([#538](https://example.com/builders#/task/538)). The whole exchange is permanently audited in `task_override_requests` (requester, decider, rationale, decision note, timestamps).
|
|
217
236
|
- **Do NOT** use `POST /tasks/:id/confirm` to unstick *another* builder's task — it credits + attributes to the *caller* (the Archon), not the original builder. `/confirm` is for the shipping builder's own `--skip-grade` path. The override-request → approve flow is the correct tool when the work was someone else's.
|
|
218
237
|
- **Why it bites:** the grader defaults to fail (by design — it's adversarial), so a false-negative looks identical to a real rejection. The fix is a documented, audited human-in-the-loop appeal, not a grader bypass — and the appeal pays the right person.
|
|
219
238
|
|
|
220
239
|
### A task sits at `confirmed` and every sweep logs `pr_not_landed` for a PR GitHub says is MERGED
|
|
221
240
|
|
|
222
|
-
- **Symptom:** `journalctl -u <instance>.service | grep publish-reconciler` shows the same task in the `dispositions:` line sweep after sweep as `pr_not_landed`, while `gh pr view <n>` reports `MERGED` with green checks. Only a manual `POST /api/
|
|
241
|
+
- **Symptom:** `journalctl -u <instance>.service | grep publish-reconciler` shows the same task in the `dispositions:` line sweep after sweep as `pr_not_landed`, while `gh pr view <n>` reports `MERGED` with green checks. Only a manual `POST /api/bongos/tasks/<id>/ship` clears it. Observed live 2026-08-12 (task 1002695 / PR 91, 18 min across 4 sweeps).
|
|
223
242
|
- **Read the disposition first.** Since task 1002724 the line carries the probe detail — `1002695:pr_not_landed(deploy=unavailable http=403 pr=91 …)` — so you can tell the three cases apart without a shell:
|
|
224
243
|
- `deploy=pending` — a real deploy is in flight. Correct; wait.
|
|
225
244
|
- `deploy=unavailable http=403` — **the server's GitHub token cannot read Actions.** The probe is blind, not waiting. The sweep now falls back to the git-history land proof and lands the task anyway (a blind probe must not outrank main's history), but the underlying token permission is still worth fixing: grant the App/PAT `actions:read` so the deploy gate is real again. On a repo with no `deploy-prod.yml` at all, a token that CAN read Actions gets a clean 404 → `unconfigured` → the merge is the land.
|
|
@@ -25,12 +25,12 @@ Parallel runs several tasks at once in **separate isolated worktrees**. It gets
|
|
|
25
25
|
|
|
26
26
|
> "Run overnight-builder, **parallel 3**, 6-hour budget, stop at $80."
|
|
27
27
|
|
|
28
|
-
The runner only fills parallel slots with tasks explicitly flagged **`parallel_safe = true`** (and, as always, with non-overlapping file footprints). Flag a task parallel-safe at creation (`parallel_safe: true` in `POST /api/
|
|
28
|
+
The runner only fills parallel slots with tasks explicitly flagged **`parallel_safe = true`** (and, as always, with non-overlapping file footprints). Flag a task parallel-safe at creation (`parallel_safe: true` in `POST /api/bongos/tasks`) or after the fact:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
TOKEN=$(node -e "console.log(require(require('os').homedir()+'/.config/otb/pms-session.json').token)")
|
|
32
32
|
curl -sS -X PATCH -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
|
|
33
|
-
-d '{"parallel_safe": true}' https://example.com/api/
|
|
33
|
+
-d '{"parallel_safe": true}' https://example.com/api/bongos/tasks/<id>
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
In parallel mode each worker stops at `confirmed` (verified, not yet paid — [ADR 0120](../adr/0120-pay-on-land-and-builder-owned-rebase-gate.md) books credits at land) and the runner lands the merges **one at a time** — concurrent merges to `main` are never allowed. Credits land as each merge completes.
|
|
@@ -40,7 +40,7 @@ In parallel mode each worker stops at `confirmed` (verified, not yet paid — [A
|
|
|
40
40
|
The end-of-run report buckets everything; the only things needing you are:
|
|
41
41
|
|
|
42
42
|
- **Parked — needs merge** (`confirmed`): a ship passed quality review but hasn't landed yet. The server reconciler sweeps these to `shipped` on its own within ~5 min — re-check the report before acting. Only if one is *still* parked after that does it need **`/merge-mode`** by hand (a conflict the server couldn't auto-resolve).
|
|
43
|
-
- **Parked — needs grade review** (`completed`): the quality grader failed or flaked (it flakes ~1 in 3). Eyeball the change; if it's good, manually confirm it (`POST /api/
|
|
43
|
+
- **Parked — needs grade review** (`completed`): the quality grader failed or flaked (it flakes ~1 in 3). Eyeball the change; if it's good, manually confirm it (`POST /api/bongos/tasks/:id/confirm`, archon-only).
|
|
44
44
|
- **Released with feedback**: the runner couldn't finish these and put them back in the queue with a note (a captured learning) explaining why — so the next builder, you or it, doesn't start from zero. Nothing to do unless you want to unblock them.
|
|
45
45
|
|
|
46
46
|
Everything under **Shipped** is already merged and deployed.
|
|
@@ -17,8 +17,8 @@ Dependencies tell you what must **ship** first. They tell you nothing about what
|
|
|
17
17
|
Start by pulling the real graph — status, `dependencies[]`, `dependents[]`, and `requires_rank` for every task on the goal:
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
node scripts/gds/api.js GET "/api/
|
|
21
|
-
node scripts/gds/api.js GET "/api/
|
|
20
|
+
node scripts/gds/api.js GET "/api/bongos/tasks?goal_id=<goal>&limit=100"
|
|
21
|
+
node scripts/gds/api.js GET "/api/bongos/tasks/<id>" # includes dependencies + dependents
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
> **Gotcha (cost us ~40 minutes).** The generated API client wraps responses as `{status, ok, data:{...}}`. Reading `res.tasks` gives `undefined` and every dependency array silently looks empty — which reads as "this goal has no dependencies at all". Unwrap `.data` first. An empty dependency graph should make you suspicious, not relieved.
|
|
@@ -64,7 +64,7 @@ Concurrent bound claims from one machine **used to be impossible**: the app-laye
|
|
|
64
64
|
**Use the batch endpoint**, which was built for exactly this:
|
|
65
65
|
|
|
66
66
|
```
|
|
67
|
-
node scripts/gds/api.js POST /api/
|
|
67
|
+
node scripts/gds/api.js POST /api/bongos/claims/batch \
|
|
68
68
|
--body-file batch.json # {"task_ids":[111,222,333],"bind_session":false}
|
|
69
69
|
```
|
|
70
70
|
|
|
@@ -35,7 +35,7 @@ Three rules that did the most work in practice:
|
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
echo '{"priority":2}' > /tmp/p.json
|
|
38
|
-
node scripts/gds/api.js PATCH /api/
|
|
38
|
+
node scripts/gds/api.js PATCH /api/bongos/tasks/1002884 --body-file /tmp/p.json
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Two things to know before you batch this:
|
|
@@ -54,7 +54,7 @@ Core reaches a live instance only through a release plus a pin move (gate 3, [`c
|
|
|
54
54
|
Generate the statements from a checked map rather than typing ids, keep it in one transaction, and **write the revert first** — the prior values are only recoverable if you captured them before the write:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
node scripts/gds/api.js GET '/api/
|
|
57
|
+
node scripts/gds/api.js GET '/api/bongos/tasks?goal_id=<goal>&limit=200' --quiet > before.json
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
Then group the ids by target tier and emit one `UPDATE` per tier, guarded to the goal and to open statuses so a concurrent ship cannot be clobbered:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
How the `search_chunks` index (the recall layer, [ADR 0060](../adr/0060-gds-retrieval-layer.md)) gets populated from repo markdown, and how to operate it. Read before touching `scripts/gds/search-ingest-md.js` or the deploy hook.
|
|
4
4
|
|
|
5
|
-
> The query side is [`modules/memory/search.js`](../../modules/memory/search.js) + [`POST /api/
|
|
5
|
+
> The query side is [`modules/memory/search.js`](../../modules/memory/search.js) + [`POST /api/bongos/search`](../../modules/memory/routes/search.js) ([#949](https://example.com/builders#/task/949)); rank/owner scoping + its isolation suite are [#950](https://example.com/builders#/task/950). Ingestion has two halves: **repo markdown** (this recipe's first sections — [#947](https://example.com/builders#/task/947), the deploy hook) and **DB prose** (the [DB-prose nightly](#db-prose-nightly-timer) section below — [#948](https://example.com/builders#/task/948), a systemd timer).
|
|
6
6
|
|
|
7
7
|
## What it does
|
|
8
8
|
|
|
@@ -35,7 +35,7 @@ node scripts/gds/ship.js <task-id> --regrade
|
|
|
35
35
|
|
|
36
36
|
This re-runs **ONLY the grade step** against the committed diff, with **no claim required**:
|
|
37
37
|
|
|
38
|
-
1. **Eligibility** — the task must be at `completed`, and you must either have *last held the claim* or be an **Archon**. (The ownership data comes from the `last_claim` field on `GET /api/
|
|
38
|
+
1. **Eligibility** — the task must be at `completed`, and you must either have *last held the claim* or be an **Archon**. (The ownership data comes from the `last_claim` field on `GET /api/bongos/tasks/:id`; the gate is `evaluateRegradeEligibility` in `ship.js`.)
|
|
39
39
|
2. **Preflight** — your work must be committed (the grader reads committed history, not your working tree) and your local ship/grade tooling must be current with `main` (a stale `grader.js`/`ship.js` silently fails the same way — the [#662](https://example.com/builders#/task/662) lesson). `--force` overrides the freshness checks.
|
|
40
40
|
3. **Empty-diff guard** — the grader reads committed history, so an empty committed diff aborts cleanly.
|
|
41
41
|
4. **Grade** — runs the subagent grader and POSTs to the rank-open `/tasks/:id/grade` endpoint. `applyGrade` promotes `completed → confirmed` and awards credits on pass (idempotent — re-grading after the credit already landed is a no-op).
|
|
@@ -60,7 +60,7 @@ node scripts/gds/ship.js 600 --regrade # re-grades the committed diff; on pass
|
|
|
60
60
|
Only if the grade was genuinely *wrong* (not "I don't want to fix it"):
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
curl -X POST -H "Authorization: Bearer <token>" https://example.com/api/
|
|
63
|
+
curl -X POST -H "Authorization: Bearer <token>" https://example.com/api/bongos/tasks/<id>/confirm
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
This writes a `task_grades` row with `grader_kind='lars'` so the audit trail shows it was a manual override. Prefer `--regrade`.
|
|
@@ -182,7 +182,7 @@ The things that ARE separated (process, port, DB, OAuth app, env, chat webhook)
|
|
|
182
182
|
```bash
|
|
183
183
|
# Full staging smoke from a laptop
|
|
184
184
|
HOST=https://staging.example.com
|
|
185
|
-
for path in /healthz /api/
|
|
185
|
+
for path in /healthz /api/bongos/healthz /api/bongos/public/versions; do
|
|
186
186
|
status=$(curl -o /dev/null -sS -w '%{http_code}' "${HOST}${path}")
|
|
187
187
|
printf " %-40s %s\n" "${HOST}${path}" "${status}"
|
|
188
188
|
done
|
|
@@ -183,7 +183,7 @@ you see a ship-call failure from older tooling, check `GET /tasks/<id>` before r
|
|
|
183
183
|
|
|
184
184
|
## `git fetch` / `git push` / `ls-remote` fail here BY DESIGN
|
|
185
185
|
|
|
186
|
-
- This machine holds no GitHub push credential (ADR 0031 §6 / ADR 0055). The scan found 22 `git fetch` attempts in three days, all wasted. Landing is server-mediated: `/builder-ship` uploads a bundle and the server pushes, opens the PR and lands it. To see whether work reached GitHub use `GET /api/
|
|
186
|
+
- This machine holds no GitHub push credential (ADR 0031 §6 / ADR 0055). The scan found 22 `git fetch` attempts in three days, all wasted. Landing is server-mediated: `/builder-ship` uploads a bundle and the server pushes, opens the PR and lands it. To see whether work reached GitHub use `GET /api/bongos/tasks/:id/publish-status`, never a raw git probe. To base a new worktree on fresh main, `node scripts/gds/worktree.js add <task-id> --base origin/main` (worktree.js fetches through the sanctioned path).
|
|
187
187
|
|
|
188
188
|
## A worktree without `node_modules` fails 300+ tests — and the count is not the signal
|
|
189
189
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Deploy — {{worldName}}</title>
|
|
7
|
-
<meta name="description" content="Move this
|
|
7
|
+
<meta name="description" content="Move this project onto a newer core and read back the version its box actually serves — the deploy gate, without a shell or an ssh key.">
|
|
8
8
|
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
|
|
9
9
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
-
<link rel="stylesheet" href="/builders/style.css?v=2026-09-
|
|
11
|
+
<link rel="stylesheet" href="/builders/style.css?v=2026-09-23-changelist1">
|
|
12
12
|
<link rel="stylesheet" href="/builders/oversight.css">
|
|
13
13
|
<link rel="stylesheet" href="/builders/project-settings.css">
|
|
14
14
|
</head>
|
|
@@ -36,10 +36,15 @@
|
|
|
36
36
|
<!-- The honest framing, and the one thing a reader must not misread:
|
|
37
37
|
shipping work and deploying it are different acts. "Merged" does not
|
|
38
38
|
mean visible (ADR 0137's three gates); this page is the third one. -->
|
|
39
|
+
<!-- The page is about THIS project and no other (task 1004171) — every other
|
|
40
|
+
project's upgrade is offered in its own hall, so a page that listed them
|
|
41
|
+
would be the wrong surface as well as the wrong count. -->
|
|
39
42
|
<p class="scroll__lede">
|
|
40
43
|
Merging work does not put it in front of anyone. This is the step that does:
|
|
41
|
-
it moves this
|
|
42
|
-
|
|
44
|
+
it moves this project onto a newer core, waits for its box to answer, and
|
|
45
|
+
puts it back if it does not. Every project has this control in its own hall,
|
|
46
|
+
this platform included — so what you see below is one project, the one whose
|
|
47
|
+
hall you are in.
|
|
43
48
|
</p>
|
|
44
49
|
<!-- One mount, written by deploy.js. Nothing here is authored as markup with
|
|
45
50
|
a version in it: every number on this page is a reading the control plane
|
|
@@ -59,6 +64,6 @@
|
|
|
59
64
|
<script src="/builders/palette.js" defer></script>
|
|
60
65
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
61
66
|
<script src="/builders/hall-kit.js"></script>
|
|
62
|
-
<script src="/builders/deploy.js?v=2026-09-
|
|
67
|
+
<script src="/builders/deploy.js?v=2026-09-23-changelist1"></script>
|
|
63
68
|
</body>
|
|
64
69
|
</html>
|