@bongos/core 1.19.1032 → 1.19.1034
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 +322 -117
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/grade-audit/SKILL.md +1 -1
- package/.claude/skills/grade-recover/SKILL.md +2 -1
- package/.claude/skills/grader-health/SKILL.md +5 -1
- package/.claude/skills/merge-mode/SKILL.md +1 -1
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +15 -0
- package/docs/adr/0175-the-board-room-full-idea-ratification.md +3 -2
- package/docs/adr/0178-the-copy-desk-flag-and-queue.md +3 -3
- package/docs/adr/0188-patrol-runs-on-ci-not-the-server.md +2 -2
- package/docs/adr/0189-baseline-floors-and-the-freeze-detector.md +1 -1
- package/docs/adr/0233-a-copy-proposal-is-a-task-carrying-a-patch.md +1 -1
- package/docs/adr/0241-the-artist-gate-is-a-per-project-deploy-gate-that-reads-a-state.md +11 -3
- package/docs/adr/README.md +4 -4
- package/docs/api/openapi.json +1 -1
- package/docs/architecture.md +4 -3
- package/docs/canonical-permissions.md +2 -2
- package/docs/copy-inventory.md +34 -30
- package/docs/copy-registry.json +69 -33
- package/docs/file-map.md +4 -3
- package/docs/module-api-changelog.md +4 -0
- package/docs/recipes/autobongos-windows-host.md +3 -1
- package/docs/recipes/local-dev.md +45 -3
- package/docs/recipes/packaging-the-core.md +3 -1
- package/docs/recipes/redteam-patrol.md +2 -2
- package/docs/recipes/upgrading-the-core.md +1 -1
- package/modules/autonomy/cadence.js +52 -0
- package/modules/autonomy/gauge.js +57 -9
- package/modules/government/protected-surfaces.json +1 -0
- package/modules/grading/grade-engine.js +267 -0
- package/modules/grading/grader-subagent.js +4 -3
- package/modules/grading/grader-workers/index.js +67 -11
- package/modules/grading/grader-workers/worker-verdict.js +32 -2
- package/modules/grading/grader.js +109 -88
- package/modules/hall-ui/public/deploy.js +35 -0
- package/modules/hall-ui/public/project-settings.css +7 -0
- package/modules/hall-ui/records/builders-roster.md +10 -0
- package/modules/hall-ui/records/catalog.md +10 -0
- package/modules/hall-ui/records/collaboration.md +14 -0
- package/modules/hall-ui/records/goal-dependency-forest.md +11 -0
- package/modules/hall-ui/records/oversight-family.md +19 -0
- package/modules/hall-ui/records/panel-family.md +19 -0
- package/modules/hall-ui/records/reading-rooms.md +12 -0
- package/modules/hall-ui/records/record-family.md +13 -0
- package/modules/hall-ui/records/reference-room.md +9 -0
- package/modules/hall-ui/records/roster-and-ledger.md +9 -0
- package/modules/hall-ui/records/sky.md +23 -0
- package/modules/lifecycle/dependency-advisory.js +2 -1
- package/modules/lifecycle/routes/tasks.js +19 -4
- package/modules/lifecycle/ship-preflight.js +91 -0
- package/modules/provisioning/control-plane-guard.js +14 -13
- package/modules/provisioning/core-upgrade.js +30 -17
- package/modules/provisioning/public-refusal.js +44 -0
- package/modules/provisioning/routes/disconnect.js +2 -1
- package/modules/provisioning/routes/env-manifest.js +5 -4
- package/modules/provisioning/routes/provisioning.js +16 -15
- package/modules/provisioning/routes/repo-private.js +2 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +7481 -0
- package/scripts/gds/address-park-sweep.sh +3 -1
- package/scripts/gds/autobongos-run.js +91 -3
- package/scripts/gds/backfill-cost.js +20 -9
- package/scripts/gds/baseline-staleness.js +1 -1
- package/scripts/gds/claim.js +2 -2
- package/scripts/gds/credential-presence.js +281 -0
- package/scripts/gds/db-backup-nightly.sh +9 -4
- package/scripts/gds/db-backup-offsite.sh +4 -2
- package/scripts/gds/deploy-main-audit-gate.sh +11 -4
- package/scripts/gds/dev-lib.js +212 -5
- package/scripts/gds/dev.js +102 -50
- package/scripts/gds/doctor.js +3 -2
- package/scripts/gds/grade-correlation-audit.js +280 -0
- package/scripts/gds/grade-replay.js +237 -0
- package/scripts/gds/hooks/pre-push.js +7 -3
- package/scripts/gds/main-audit.js +19 -10
- package/scripts/gds/memory-map.js +3 -1
- package/scripts/gds/onboarding-config.js +3 -2
- package/scripts/gds/package-core.js +72 -1
- package/scripts/gds/plain-cards.js +4 -0
- package/scripts/gds/preflight.js +12 -4
- package/scripts/gds/provision-core-upgrade.js +282 -80
- package/scripts/gds/provision-repo-auth.js +15 -0
- package/scripts/gds/provision.js +1 -1
- package/scripts/gds/publish-credential-check.js +3 -0
- package/scripts/gds/push-main.js +14 -3
- package/scripts/gds/push-path-brief.js +3 -2
- package/scripts/gds/redteam-patrol.js +4 -4
- package/scripts/gds/release-notes.js +271 -0
- package/scripts/gds/run-routine.js +18 -5
- package/scripts/gds/run-unit-tests.js +14 -3
- package/scripts/gds/seed-board-room-tasks.js +1 -1
- package/scripts/gds/session-cost.js +12 -3
- package/scripts/gds/ship-deploy-target.js +11 -6
- package/scripts/gds/ship-flow.js +5 -3
- package/scripts/gds/ship-grade-steps.js +33 -0
- package/scripts/gds/ship-land.js +241 -16
- package/scripts/gds/ship-merge.js +3 -2
- package/scripts/gds/ship-preflight-steps.js +86 -11
- package/scripts/gds/ship.js +1 -1
- package/scripts/gds/stray-unit-sweep.sh +3 -1
- package/scripts/gds/upgrade-migrate.js +67 -0
- package/scripts/gds/upgrade.js +9 -7
- package/scripts/hall-preview/README.md +20 -3
- package/scripts/hall-preview/live-identity.js +1 -1
- package/scripts/hall-preview/refresh-fixtures.js +71 -11
- package/scripts/hall-preview/scrub-identity.js +296 -0
- package/src/bongos/routes/security.js +3 -3
- package/src/build-info.js +4 -2
- package/src/module-api.js +1 -1
- package/tests/adr_0089_scope.mjs +70 -0
- package/tests/adr_0162_citation.mjs +184 -0
- package/tests/autobongos_cadence.mjs +74 -0
- package/tests/autobongos_loop.mjs +114 -0
- package/tests/autonomy_gauge.mjs +56 -0
- package/tests/consumer_layout_boot.mjs +363 -31
- package/tests/core_upgrade_door.mjs +40 -6
- package/tests/core_upgrade_runner.mjs +329 -5
- package/tests/credential_presence.mjs +153 -0
- package/tests/db_backup_nightly.mjs +21 -3
- package/tests/db_backup_offsite.mjs +81 -0
- package/tests/deploy_audit_gate.mjs +5 -2
- package/tests/deploy_page_projects.mjs +63 -2
- package/tests/dev_lib.mjs +2 -1
- package/tests/dev_windows.mjs +324 -0
- package/tests/env_knobs_neutral_prefix.mjs +203 -0
- package/tests/fixtures/grade-replay/recorded-panel-grades.json +27 -0
- package/tests/government_protected_surfaces.mjs +10 -0
- package/tests/grade_correlation_audit.mjs +159 -0
- package/tests/grade_engine.mjs +249 -0
- package/tests/grade_engine_replay.mjs +99 -0
- package/tests/grader_prompt_window_bound.mjs +132 -0
- package/tests/grader_unbacked_score.mjs +194 -0
- package/tests/hall_preview_scrub.mjs +214 -0
- package/tests/hall_records.mjs +85 -0
- package/tests/helpers.mjs +25 -0
- package/tests/instance_db_migrated_on_code_move.mjs +8 -1
- package/tests/integration_parked_ratchet.mjs +24 -1
- package/tests/plain_cards.mjs +1 -1
- package/tests/provisioning_public_refusal.mjs +195 -0
- package/tests/publish_status_branch.mjs +128 -0
- package/tests/redteam_patrol.mjs +1 -1
- package/tests/release_notes.mjs +327 -0
- package/tests/shell_stat_portability.mjs +49 -0
- package/tests/ship_land_conflict.mjs +181 -0
- package/tests/ship_land_red_pr.mjs +236 -0
- package/tests/ship_preflight.mjs +226 -3
- package/tests/start_env_guard.mjs +16 -0
- package/tests/sweep_app_account.mjs +15 -2
- package/tests/upgrade.mjs +20 -1
- package/tests/upgrade_migrate.mjs +195 -0
package/docs/file-map.md
CHANGED
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
│ ├── sessions/ ← CORE-DOMAIN carve (BV1.R82, default-on): the session_records corpus + data plane (upload, cross-builder search/deep-dive), the BFG read-the-room scorer, session-pulse/stale-claim helpers. Registers no port — reached via HTTP POST to its own /sessions route; resolves the economy `reward` port for the cost-plus token reward. CLAUDE.md, module.json, routes/sessions.js, bfg.js, pulse.js.
|
|
135
135
|
│ ├── autonomy/ ← CORE-DOMAIN carve (BV1.R83, default-on): the MAS autonomy surfaces — the $0 deterministic autonomy gate (System 3, inert until armed), the conductor/architect CLIs, and the in-process routine timers (incl. the weekly peer-vote-tally poller). Registers no port; resolves the lifecycle `tallyPeerVotes` doorway. CLAUDE.md, module.json, routes/autonomy.js, autonomy.js.
|
|
136
136
|
│ ├── status-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R84, default-on): the public status dashboard at status.<apex>, moved from public-status/. NO routes/db/port — declares contributes.webSurfaces:[{host:"status.",dir:"public"}], served by the loader web-surface seam (moduleWebSurfaces → serve-internal). CLAUDE.md, module.json, public/{index.html,status.js,style.css,cursors/,snapshots/}.
|
|
137
|
-
│ ├── hall-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R85, default-on): the authenticated builders' hall at builders.<apex>, moved from public-builders/ (~13k LOC, the largest). NO routes/db/port — declares contributes.webSurfaces:[{host:"builders.",dir:"public"}] for discovery, but UNLIKE status-ui keeps its DEDICATED serving block in serve-internal (the /builders shim + canonical redirects + citizen/Archon page gates + asset-stamping + hall-widget injection), partitioned out of the generic web-surface loop and served from BUILDERS_DIR. CLAUDE.md, module.json, public/{index.html,builders.js,style.css,work,watch,gate,settings,ranks,sessions,primer,diagrams,atlas,...}.{html,js},cursors/,chime.wav. Four ARCHETYPE sheets sit beside the per-page ones: `record.css` (the task + idea records, task 1003305), `room.css` (the READING ROOMS — the primer + the diagrams index, task 1003306: the reading measure and rhythm, the table of contents, the progress hairline and the framed figure diagram-viewer.js upgrades on both pages), `oversight.css` (the OVERSIGHT family — government, watch, gate, task 1003469 (harbor was its fourth until task 1003890 removed the dev box): the row, the figure band inside a panel, the group head, the inline form, the grant toggle and the shared confirm modal; named oversight because the vocabulary wall bans "governance" on the government surface) and `panel.css` (the PANEL family — settings, profile, task 1003308 (pair was its third until task 1003890 removed the dev box): the row, the switch, the field with its label above, the chip control, the four voices and the sign-in gate; the hall's my-projects page was DELETED in the same task — "my projects" is the hub's user-level page, and the hall keeps no link or redirect; the family's fourth page `not-ready.html` was deleted by task 1003450, along with the emptied `requireNonXenosPage` gate that was the only thing redirecting to it). A page sheet then holds only what one page has and the others do not — `primer.css` the acknowledge gate, `diagrams.css` the legend strip, `gate.css` the hold reasons and file chips, `watch.css` the severities, the report reader and the grade trend, `settings.css` the rail layout, the group head, the token ladder and the voices grid, `profile.css` the identity band and the shelf, `people.css` the directory's identity cell (task 1003470 made the legacy door `/scouting` ship the same body and script as `/people`; task 1003440 then deleted the door — `scouting.html` and `scouting.states.json` are gone and the URL 301s to `/people`), `thinking.css` THE SKY's one sheet (task 1004231 / sky part 3 — `thinking.html` at `/thinking` is the prototype the owner adopted as the design of record, `docs/design/mocks/sky/`, built over `GET /sky` + `GET /sky/mine`; its script is the seven `sky-*.js` files on one shared `window.OTBSky`; it replaced THE ROOM of task 1004098, which survives as the list drawer, and the old `/sky` page, whose URL 301s here; `idea-objects.js` beside it is the shared five-object vocabulary).
|
|
137
|
+
│ ├── hall-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R85, default-on): the authenticated builders' hall at builders.<apex>, moved from public-builders/ (~13k LOC, the largest). NO routes/db/port — declares contributes.webSurfaces:[{host:"builders.",dir:"public"}] for discovery, but UNLIKE status-ui keeps its DEDICATED serving block in serve-internal (the /builders shim + canonical redirects + citizen/Archon page gates + asset-stamping + hall-widget injection), partitioned out of the generic web-surface loop and served from BUILDERS_DIR. CLAUDE.md, module.json, records/ (one file per page family — what each family's redesign settled; CLAUDE.md points at them, and a new record is a new file there so concurrent hall tasks stop colliding on one insertion point, task 1003499), public/{index.html,builders.js,style.css,work,watch,gate,settings,ranks,sessions,primer,diagrams,atlas,...}.{html,js},cursors/,chime.wav. Four ARCHETYPE sheets sit beside the per-page ones: `record.css` (the task + idea records, task 1003305), `room.css` (the READING ROOMS — the primer + the diagrams index, task 1003306: the reading measure and rhythm, the table of contents, the progress hairline and the framed figure diagram-viewer.js upgrades on both pages), `oversight.css` (the OVERSIGHT family — government, watch, gate, task 1003469 (harbor was its fourth until task 1003890 removed the dev box): the row, the figure band inside a panel, the group head, the inline form, the grant toggle and the shared confirm modal; named oversight because the vocabulary wall bans "governance" on the government surface) and `panel.css` (the PANEL family — settings, profile, task 1003308 (pair was its third until task 1003890 removed the dev box): the row, the switch, the field with its label above, the chip control, the four voices and the sign-in gate; the hall's my-projects page was DELETED in the same task — "my projects" is the hub's user-level page, and the hall keeps no link or redirect; the family's fourth page `not-ready.html` was deleted by task 1003450, along with the emptied `requireNonXenosPage` gate that was the only thing redirecting to it). A page sheet then holds only what one page has and the others do not — `primer.css` the acknowledge gate, `diagrams.css` the legend strip, `gate.css` the hold reasons and file chips, `watch.css` the severities, the report reader and the grade trend, `settings.css` the rail layout, the group head, the token ladder and the voices grid, `profile.css` the identity band and the shelf, `people.css` the directory's identity cell (task 1003470 made the legacy door `/scouting` ship the same body and script as `/people`; task 1003440 then deleted the door — `scouting.html` and `scouting.states.json` are gone and the URL 301s to `/people`), `thinking.css` THE SKY's one sheet (task 1004231 / sky part 3 — `thinking.html` at `/thinking` is the prototype the owner adopted as the design of record, `docs/design/mocks/sky/`, built over `GET /sky` + `GET /sky/mine`; its script is the seven `sky-*.js` files on one shared `window.OTBSky`; it replaced THE ROOM of task 1004098, which survives as the list drawer, and the old `/sky` page, whose URL 301s here; `idea-objects.js` beside it is the shared five-object vocabulary).
|
|
138
138
|
│ ├── lifecycle/ ← CORE-DOMAIN carve (BV1.R86, default-on): the build state machine — tasks · claims · versions · done-when · goals · dependencies · claim→ship→grade→credit · github-push + merge-lock + conflict-resolve + publish-reconciler. The LAST, most-coupled carve; registers the `lifecycle` kernel port (createTask, classifyTaskKind, tallyPeerVotes, work-tracking reads). CLAUDE.md, module.json, routes/{tasks,claims,versions,done-when,goals,dependencies,gate-approvals,analytics}.js, lifecycle.js, github-push.js, merge-lock.js, conflict-resolve.js, publish-reconciler.js, task-visuals.js + task-visual-db.js + routes/visuals.js (the optional ship-time visual, task 1003109 — the route file is NOT named task-*.js on purpose; see the module CLAUDE.md).
|
|
139
139
|
│ ├── copy-desk/ ← CORE-DOMAIN module (task 1003113 / R02 of goal 1000074, default-on): the COPY half of the design contract — ADR 0081 gave design TOKENS a repo-owned source of truth, text had none. Owns the FLAG (anyone in any role marks a string or a whole surface as needing an artist's attention, with a reason required in BOTH the route and a CHECK constraint) and the QUEUE an artist reads it from. READS R01's committed registry (docs/copy-registry.json, generated by scripts/gds/copy-inventory.js) and never writes it. NO LIVE CMS is the hard non-goal: no column here could hold replacement text, and copy_no_cms.mjs pins that. Key is `copy-desk`, not `copy` — the branding contract already owns a `copy` block, so the bare word reds the "core carries no module code" fitness check. R03 (task 1003114, ADR 0233) added the PROPOSAL: an artist writes the replacement wording and it becomes a Bongos task carrying a fenced copy-proposal patch — no row, NO second migration (a proposals table is the forbidden column with extra steps), and scripts/gds/copy-apply.js lands it as a real diff under a claim. CLAUDE.md, module.json, registry.js, flags.js, proposals.js, routes/copy-desk.js, migrations/copy_desk_001_flags.sql, tests/{copy_flags,copy_queue,copy_no_cms,copy_proposals}.mjs. Its hall surface lives with hall-ui (public/copy-desk.{html,js,css}), per the one-key-per-web-surface precedent.
|
|
140
140
|
│ ├── ui-design/ ← CORE-DOMAIN module (task 1003324 / ADR 0197, default-on): the design capability every builder on every instance gets — ships METHOD, never a world. Absorbs ADR 0081's layer: adapters/{claude-design,figma}/index.js (moved from src/ui/adapters/), scripts/{design-sync,figma-design-sync,validate-design}.js (moved from scripts/gds/, which keeps thin shims), docs/design-contract.md (moved from docs/). Declaration-only: contributes.skills design (the /design playbook, new) + design-sync + figma-design-sync; no routes/port/migrations, so disabling it touches no served surface. CLAUDE.md separates the platform FLOORS (the Fifteen Rule, the dark twins, no page :root, the 24px floor, AA in both modes, the kill switch) from the instance's WORLD (its packs + DESIGN.md). kit/ (task 1003320) is the look-before-you-ship kit: lib.js (the floors, the states/probes contracts, the action + expectation vocabularies, the WCAG maths, the stub spawner), serve.js (any surface through the doorway's real transforms + fixtures/), render.js (states × 1440/390/320 × dark/light, audited), probe.js (PASS/FAIL contracts), check-mock.js (platform rules + the instance's DESIGN.md taste bans, then the detector), tells.js (task 1003329 / ADR 0223: the anti-pattern detector as two tiers — floors FAIL, craft tells WARN, kit-ignore waivers per file; the rendered twins live in lib.js factsInPage), contrast.js + png.js; a page's <page>.states.json / <page>.probes.json sit BESIDE the surface (modules/public-landing/public/, modules/hall-ui/public/). Recipe: docs/recipes/ui-look-before-you-ship.md. skills/ (task 1003321 / ADR 0198) is the vendoring policy: policy.json (licence allowlist, verdicts that may land, sidecar fields, preamble markers), PREAMBLE.md (the platform preamble every vendored SKILL.md opens with), README.md (the roster — both origins scanned dangerous on 2026-08-28, landed as rebuild specs; nothing vendored — and the landing recipe); a landable copy goes under skills/vendor/<name>/ with PROVENANCE.md + LICENSE and is materialised into an instance's .claude/skills/ by claude-materialize.js step 1b. skills/<name>/ (task 1003325 / ADR 0220) are the in-house rebuilds from the specs, first-party and counted: design-taste-frontend (the default taste skill), design-taste-frontend-v1 (the earlier generation, kept distinct), high-end-visual-design (the polish pass), redesign-existing-projects (the in-place upgrade); each opens with the same preamble and carries a "Rebuilt from" section instead of a sidecar. impeccable/ (task 1003326 / ADR 0221) is the design-craft method as ONE skill with sub-commands: SKILL.md (the router, the menu, the craft floor, the bounded finish) + reference/<sub-command>.md (eighteen playbooks, one loaded per request); no hooks, no bypass agent, no telemetry, no live server. minimalist-ui/, industrial-brutalist-ui/, gpt-taste/, stitch-design-taste/ (task 1003327 / ADR 0230) are the four looks, composition grammars with no colours of their own: the palette is the instance's pack and the texture is a named entry in styles/; a substrate is an archetype that still ships both modes, gpt-taste's selection is derived from the route rather than rolled, and stitch-design-taste writes a DESIGN.md-shaped contract document whose thirteen are transcribed from the pack. image-to-code/, imagegen-frontend-web/, imagegen-frontend-mobile/, brandkit/ (task 1003328 / ADR 0222) are the image family under the hero-only rule: plates and hero objects only, the pair (JPEG dark plate + WebP alpha cutout) with a <file>.json sidecar beside each, through the instance's art pipeline key; the grove specimen's styles/grove/assets/ is the worked example. style/ (task 1003475 / ADR 0231) is the module's first FIRST-PARTY skill (no upstream, so a `## First party` section instead of `## Rebuilt from`): the /style session in which an owner authors their own look in four bounded steps, rendering the nearest library entries before asking, drafting inside the contract, retuning by measurement, and handing over the one-step adoption without ever writing config/branding.json. styles/ (task 1003323 / ADR 0219) is the style library: <name>/pack.json (the theme.ui overlay, exactly the fifteen) + DESIGN.md (the look's derived recipes, thirteen in lockstep with the pack) + mock.html (the specimen); chrome-world (pinned to the neutral pack), expedition, grove, blueprint (the first cool look, authored through /style at task 1003475); STYLE=<name> on the kit lays a look over the instance's pack through GDS_BRANDING_FILE; tests/ui_design_styles.mjs runs the world/cosmos/hall token suites once per alternate (UI_DESIGN_PACK). config/design-tokens.* + design-sources.json STAY in config/ as the host boundary; public-landing keeps its own key (first customer, not owner).
|
|
@@ -174,6 +174,7 @@
|
|
|
174
174
|
│ ├── ship.js ← resolve claim as shipped, award credits (`/builder-ship`); also uploads a secret-scrubbed session digest to the corpus (6D.1, ADR 0027); on a dev box runs the sandbox-first review gate before resolving (#927, ADR 0046)
|
|
175
175
|
│ ├── ship-visual.js ← the OPTIONAL `--visual <image> [--visual-alt "…"]` leg of a ship (task 1003109): screens the file BEFORE the claim resolves (bad input costs no claim), uploads it AFTER (a failed picture never fails a ship)
|
|
176
176
|
│ ├── package-core.js ← package the core as a versioned, installable artifact + pin manifest (`bongos package-core`; R84, ADR 0100 §1, [#1688](https://example.com/builders#/task/1688)): isPublishable() selection + mirror redaction + fail-closed no-leak gate → dist/bongos-core-<version>.{tgz,manifest.json}; version = src/module-api CORE_VERSION. Recipe: docs/recipes/packaging-the-core.md
|
|
177
|
+
│ ├── release-notes.js ← what each core release brought in (task 1004218): generated at pack time from the ref's HISTORY into the package's release-notes.json (exact per-release ranges, 1 MiB bound; package-core redacts its prose like a doc), read back by the upgrade runner for a from→to range; home of the one merge-summary parser
|
|
177
178
|
│ ├── surface.js ← who the CLI output is FOR: agent (default) or terminal (task 1003680). The `bongos` dispatcher sets BONGOS_SURFACE=terminal when a person types a verb; the skills and the card hook run `node scripts/gds/<verb>.js` directly and keep the agent card byte-identical. Never inferred from isTTY — a session's stdout is not a TTY either, so sniffing would invert it. Helpers: action() (/builder-ship N vs bongos ship N), taskRef(), strong()/em()/code(), table() (markdown vs aligned columns). Guarded by tests/cli_surface.mjs
|
|
178
179
|
│ ├── sandbox-stage.js ← stage the working tree on the live game preview (box OR local) for browser review before ship; resolvePreviewContext picks the context (`/builder-stage`; #927, ADR 0046; local: task 1056)
|
|
179
180
|
│ ├── local-preview.js ← builder CLI for the LOCAL sandbox: start/stop/status/restart/logs/url of the game-only preview at http://localhost:3100 (`npm run preview`; task 1056)
|
|
@@ -415,7 +416,7 @@ tests/
|
|
|
415
416
|
├── fix-task/SKILL.md ← /fix-task N — claim, fix (test-first), verify, and ship a single Bongos task by id end to end; defers to /builder-claim + /builder-ship for their own mechanics
|
|
416
417
|
├── goal-create/SKILL.md ← /goal-create — plan and create ONE goal (the module-scoped workspace between version and criteria, ADR 0086) in one session: <redacted>, scope wall, 2-4 criteria, seed tasks; also the auto-pickup when a task is created with no goal to live in (goal_advisory); Metic+ (Archon for a protected-module scope)
|
|
417
418
|
├── goal-review/SKILL.md ← /goal-review — walk the criterion review queue: each auto-flagged 'met — pending review' criterion gets confirm / reject / defer; confirming a goal's last criterion auto-achieves it (ADR 0086 §6); Metic+
|
|
418
|
-
├── grade-audit/SKILL.md ← /grade-audit — manual-cadence accountability sweep: override ledger (shipped-despite-fail, infra vs real, un-requested confirms named), dropped blocker/major findings on passes queued via capture.js with the advisory-Narc filter, runtime-blindness false-pass spot-check, outage roll-up → /grader-health; describes and queues only, never confirms (ADR
|
|
419
|
+
├── grade-audit/SKILL.md ← /grade-audit — manual-cadence accountability sweep: override ledger (shipped-despite-fail, infra vs real, un-requested confirms named), dropped blocker/major findings on passes queued via capture.js with the advisory-Narc filter, runtime-blindness false-pass spot-check, outage roll-up → /grader-health; describes and queues only, never confirms (ADR 0158 §2, task 1002657)
|
|
419
420
|
├── grade-recover/SKILL.md ← /grade-recover N — the 'my grade failed, now what' loop: diagnose outage vs fabricated fail vs genuine fail from the persisted grade, then run the right recovery (--regrade or the auditable override-request); adds no ship-path gate (ADR 0162, task 1002655)
|
|
420
421
|
├── grader-health/SKILL.md ← /grader-health — read-only grader health check: outage runs (n_unavailable streaks, outage-vs-rejection confirmation), pass-rate drift vs baseline, per-grade cost anomalies, stale model pins; emits exact --regrade remediation lines; optional --probe live calibration (Metic+, paid) (task 1002656)
|
|
421
422
|
├── idea-triage/SKILL.md ← /idea-triage — daily walk through the Bongos idea_inbox (promote / discard / merge); Metic+
|
|
@@ -462,7 +463,7 @@ tests/
|
|
|
462
463
|
├── peer-vote-tally/SKILL.md ← deterministic tally (`tally.js`) folding builder-on-builder peer votes at least 7 days old into karma_log rows (criterion C2) (restored in task 1003365; unscheduled in core — only redteam-weekly has a firing workflow; config/scheduled-routines.json records the intended cadence)
|
|
463
464
|
├── publish-watch/SKILL.md ← daily publish-lane check (task 1003916): compares every version the release lane ANNOUNCED in its own release commits against what the registry actually holds, and posts anything announced-but-never-delivered to Discord #ship-news. Exists because the 2026-09-13 outage (8 failed runs, 3 hours) was found by a person reading the npm version list — a failed run is one red row nobody watches, and the next merge erases the evidence. Silent on a healthy day by design; exit 2 (could not read) is distinct from exit 1 (found one).
|
|
464
465
|
├── rank-roles-audit/SKILL.md ← nightly deterministic check that every builder holds one of the four live ranks, so none silently resolves to zero permissions under the governance_002 backfill's INNER JOIN; detect-only, files one idea_inbox row and never repairs, and never fatal at boot (task 1002873; unscheduled in core — only redteam-weekly has a firing workflow; config/scheduled-routines.json records the intended cadence)
|
|
465
|
-
├── redteam-weekly/SKILL.md ← weekly deterministic red-team patrol (task 1003128): full-history gitleaks scan + dependency drift review (audit delta, cooldown, young pkgs, stale overrides) + action-pin check → files security reports (advisory, ADR
|
|
466
|
+
├── redteam-weekly/SKILL.md ← weekly deterministic red-team patrol (task 1003128): full-history gitleaks scan + dependency drift review (audit delta, cooldown, young pkgs, stale overrides) + action-pin check → files security reports (advisory, ADR 0158 §2). FIRED BY .github/workflows/redteam-patrol.yml, Mondays 06:17 UTC — `cadence: weekly` here and that cron must agree or fitness Check 25 (scripts/gds/routine-schedule.js) fails the gate (task 1003209, ADR 0188)
|
|
466
467
|
├── repo-simplify-sweep/SKILL.md ← weekly repo-cleanliness janitor — runs repo-metrics, files dead-code findings to idea_inbox, and auto-fixes only the narrow safe class (restored in task 1003365; unscheduled in core — only redteam-weekly has a firing workflow; config/scheduled-routines.json records the intended cadence)
|
|
467
468
|
├── security-review-weekly/SKILL.md ← weekly security-state review — stale vulnerability_reports, ageing security-tagged tasks, recent high/critical dependency alerts; one Archon broadcast when anything is stale, silent otherwise (restored in task 1003365; unscheduled in core — only redteam-weekly has a firing workflow; config/scheduled-routines.json records the intended cadence)
|
|
468
469
|
├── skill-usage-review/SKILL.md ← nightly skill-usage feedback loop — aggregates 24h of skill invocations into friction findings filed as `[skill-friction]` idea_inbox rows (restored in task 1003365; unscheduled in core — only redteam-weekly has a firing workflow; config/scheduled-routines.json records the intended cadence)
|
|
@@ -2543,5 +2543,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2543
2543
|
landed since 1.19.1030 with no explicit bump. run 36192093201. (task 1002620)
|
|
2544
2544
|
1.19.1032 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2545
2545
|
landed since 1.19.1031 with no explicit bump. run 36192968150. (task 1002620)
|
|
2546
|
+
1.19.1033 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2547
|
+
landed since 1.19.1032 with no explicit bump. run 36214617025. (task 1002620)
|
|
2548
|
+
1.19.1034 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2549
|
+
landed since 1.19.1033 with no explicit bump. run 36215757254. (task 1002620)
|
|
2546
2550
|
---------------------------------------------------------------------------
|
|
2547
2551
|
```
|
|
@@ -152,7 +152,9 @@ It is the machine's working copy, not a place to edit.
|
|
|
152
152
|
| Symptom | Where to look |
|
|
153
153
|
|---|---|
|
|
154
154
|
| Runner line says **Not checking in** | is the PC on? `...\autobongos-service.ps1 status` on the box |
|
|
155
|
-
| **Checking in** but nothing ever ships | the Gate page — is a goal allowlisted, and is the switch on? |
|
|
155
|
+
| **Checking in** but nothing ever ships | first the Gate page — is a goal allowlisted, and is the switch on? If both are on, the **gauge**: `autobongos-service.ps1 digest`, or `node scripts/gds/autonomy-gauge.js`. A `hold` with `unknown: true` means it cannot read your remaining capacity, and it will wait forever rather than guess |
|
|
156
|
+
| The log repeats `hold ... unknown: true` | the gauge has no reading it can vouch for. Open a **terminal** `claude` session on the box once — that writes it. A desktop-app session does not: the writer is a statusLine command, and only a terminal renders one |
|
|
157
|
+
| `hold` naming a **derived** gauge and a cap | working as designed. After the last real reading's window resets, the runner may do `AUTOBONGOS_DERIVED_TASK_CAP` tasks (default 2) before it wants a fresh reading. A terminal session lifts it |
|
|
156
158
|
| Shipping stopped after a while | the log: the runner backs off after three failures and probes; the reason is in the log |
|
|
157
159
|
| It keeps restarting | `status` shows the last result; the `====` banners in the log mark each start |
|
|
158
160
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> The one-command path from a freshly-cloned **standalone instance repo** (one whose
|
|
4
4
|
> `config/branding.json` points at `http://localhost:<port>`) to a running, signed-in
|
|
5
|
-
> instance on your Mac. This is the local counterpart of `bongos onboard` (which
|
|
5
|
+
> instance on your Mac, Linux or Windows machine. This is the local counterpart of `bongos onboard` (which
|
|
6
6
|
> stands an instance up in the **cloud**) — see [ADR 0149](../adr/0149-bongos-dev-local-launcher.md).
|
|
7
7
|
|
|
8
8
|
## TL;DR
|
|
@@ -26,8 +26,50 @@ it is safe (idempotent). Stop it with `bongos dev stop`.
|
|
|
26
26
|
brew install postgresql@16
|
|
27
27
|
brew services start postgresql@16 # bongos dev will also try to start it for you
|
|
28
28
|
```
|
|
29
|
-
- macOS
|
|
30
|
-
|
|
29
|
+
- macOS, Linux or Windows. On **Windows**, see the next section.
|
|
30
|
+
|
|
31
|
+
## On Windows
|
|
32
|
+
|
|
33
|
+
`bongos dev` runs natively on Windows (task 1002707). You need two installs, both one-time:
|
|
34
|
+
|
|
35
|
+
1. **Git for Windows** — [git-scm.com/download/win](https://git-scm.com/download/win). It
|
|
36
|
+
includes **Git Bash**, which `bongos dev` uses to run the migrations. You can run
|
|
37
|
+
`bongos dev` itself from Git Bash, PowerShell or Command Prompt.
|
|
38
|
+
2. **PostgreSQL** — the installer from
|
|
39
|
+
[postgresql.org/download/windows](https://www.postgresql.org/download/windows/). Keep the
|
|
40
|
+
default port (5432), and **note the password** it asks you to choose for the `postgres`
|
|
41
|
+
user. You do not need to add anything to PATH: `bongos dev` finds the installed tools
|
|
42
|
+
itself.
|
|
43
|
+
|
|
44
|
+
Then tell `bongos dev` that password and run it:
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
# PowerShell
|
|
48
|
+
$env:PGPASSWORD = "<the password you chose>"
|
|
49
|
+
npx bongos dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Git Bash
|
|
54
|
+
PGPASSWORD="<the password you chose>" npx bongos dev
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
To keep the password for next time, run `setx PGPASSWORD "<the password you chose>"` once
|
|
58
|
+
and open a new terminal.
|
|
59
|
+
|
|
60
|
+
What is different on Windows, and why:
|
|
61
|
+
|
|
62
|
+
- **The Postgres user is `postgres`.** The Windows installer creates only that one user, so
|
|
63
|
+
`bongos dev` uses it unless you set `PGUSER`. It never stops at a password prompt: a
|
|
64
|
+
missing or wrong password stops with a message saying what to set.
|
|
65
|
+
- **Postgres runs as a Windows service** (`postgresql-x64-<version>`), which normally starts
|
|
66
|
+
with Windows. If it is stopped, `bongos dev` tries to start it. Starting a service needs an
|
|
67
|
+
Administrator terminal; otherwise press Win+R, type `services.msc`, find the service, and
|
|
68
|
+
click Start.
|
|
69
|
+
- **WSL's bash is not used.** `C:\Windows\System32\bash.exe` runs Linux, which cannot reach a
|
|
70
|
+
Windows Postgres, so `bongos dev` looks for Git Bash instead.
|
|
71
|
+
- **Docker is the fallback.** If you would rather not install Postgres or Git, the Docker
|
|
72
|
+
path in [`self-host.md`](self-host.md) runs everything in containers.
|
|
31
73
|
|
|
32
74
|
## What `bongos dev` does (and why it's needed)
|
|
33
75
|
|
|
@@ -40,11 +40,13 @@ If the no-leak gate fails, it names the file + the residual literal. Fix the red
|
|
|
40
40
|
|
|
41
41
|
**The neutral floor** (task [#1002217](https://example.com/builders#/task/1002217), audit H4). Because the trunk carries no `config/branding.json`, the *branding-derived* redaction would strip nothing — so `package-core.js` always injects a fixed **`PRIOR_INSTANCE_FLOOR`** (prior-instance tokens/owners) into the doc-redaction + no-leak gate. Published **docs** are de-branded against it and the gate **fails closed** if a floor literal survives, even with no branding.json. **Functional** files still ship verbatim (the R88 fix) and are instead surfaced by the non-fatal `[leak-scan]` (task 1002220). To retire a new prior-instance token, add it to `PRIOR_INSTANCE_FLOOR` (kept in `package-core.js`, never in `mirror-redact.js` — that file's self-leak invariant forbids hardcoded literals).
|
|
42
42
|
|
|
43
|
+
**The release notes** (task 1004218). The tarball also carries `release-notes.json` at its root — what each release brought in, as the merge summaries its ships wrote — so the Deploy page on any project can say what an upgrade brings in without a core git checkout (no tenant box has one). It is the one file derived from the ref's **history** rather than from a committed file, built by [`scripts/gds/release-notes.js`](../../scripts/gds/release-notes.js): pinned in the manifest like every other file (so `--self-verify` reproduces it), its prose **redacted exactly like a doc** (the neutral floor applies — real summaries in the history name prior instances, and shipping them verbatim would fail the leak scan on every pack), and bounded at 1 MiB by dropping the oldest releases. **A shallow clone or a `--from-worktree` build ships without it**, printing `! release-notes.json not generated — <why>`; an upgrade onto such a version then says its notes are unavailable. CI packs at `fetch-depth: 0`, so every release it publishes carries them.
|
|
44
|
+
|
|
43
45
|
## Prove it boots (the standing PROVE-PUBLISH gates)
|
|
44
46
|
|
|
45
47
|
Two standing gates keep "a published core boots clean from a bare install" honest (task [#1002221](https://example.com/builders#/task/1002221), audit H1/H2):
|
|
46
48
|
|
|
47
|
-
- **`node scripts/gds/run-unit-tests.js --integration`** — the integration-smoke gate. Runs the heavier integration set (longer per-test budget), including [`tests/consumer_layout_boot.mjs`](../../tests/consumer_layout_boot.mjs), which packages the core, `npm install`s the `.tgz`, and boots `/healthz` from the real consumer layout.
|
|
49
|
+
- **`node scripts/gds/run-unit-tests.js --integration`** — the integration-smoke gate. Runs the heavier integration set (longer per-test budget), including [`tests/consumer_layout_boot.mjs`](../../tests/consumer_layout_boot.mjs), which packages the core, `npm install`s the `.tgz`, and boots `/healthz` from the real consumer layout. Since task 1002863 it also carries the database half: it installs the unpacked package from its **own shipped lockfile** with `npm ci`, runs `npm run migrate` from the consumer onto a brand-new **empty** database (and onto a second one with every optional module switched on), then boots the installed server against the first and reads a sentinel row back through `GET /api/bongos/public/versions`. It creates and drops those databases itself, so it needs a Postgres whose role may `CREATE DATABASE`; without one it prints SKIP lines, except under `CI=true`, where a missing Postgres fails the run. The `integration` job of [`.github/workflows/integration.yml`](../../.github/workflows/integration.yml) runs this set on every push to `main` (not per PR — a cost decision recorded in that file). The default `run-unit-tests.js` (no flag) stays the fast DB-free unit gate and *excludes* this set.
|
|
48
50
|
- **[`tests/pruned_lockfile_integrity.mjs`](../../tests/pruned_lockfile_integrity.mjs)** — a network-free unit guard (runs in the default gate every PR) that rebuilds the shipped pruned lockfile and asserts every registry package keeps a **well-formed, verbatim `integrity` hash**. This is the exact R88 regression (redaction once blanked those base64 hashes → `npm ci` could no longer verify) caught before a consumer's install ever fails.
|
|
49
51
|
|
|
50
52
|
## Consume + pin it (the R85 side)
|
|
@@ -55,7 +55,7 @@ files normally. This is opt-in on purpose — the patrol must not *require* a
|
|
|
55
55
|
long-lived token to be useful.
|
|
56
56
|
|
|
57
57
|
**Red means a finding was LOST, not that a finding exists.** Findings are
|
|
58
|
-
advisory (ADR
|
|
58
|
+
advisory (ADR 0158 §2), so a run that files three of them is a success:
|
|
59
59
|
|
|
60
60
|
| the run… | exit |
|
|
61
61
|
|---|---|
|
|
@@ -88,7 +88,7 @@ Reports land at `target: redteam-patrol/<class>` for Archon adjudication in the
|
|
|
88
88
|
red-team dashboard — confirm / dispute / link-fix, exactly like a
|
|
89
89
|
`/builder-redteam` filing (they share the pipeline and the bounty table; patrol
|
|
90
90
|
reports are machine-filed, so confirming one pays nobody). The fix is always an
|
|
91
|
-
ordinary task; the patrol never gates and never self-executes (ADR
|
|
91
|
+
ordinary task; the patrol never gates and never self-executes (ADR 0158 §2).
|
|
92
92
|
|
|
93
93
|
## Design boundaries
|
|
94
94
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
2. **bump the pin** — vendor the new `bongos-core-<version>.tgz` and rewrite the `"@bongos/core": "file:vendor/…"` dependency.
|
|
15
15
|
3. **`npm install`** — `node_modules/@bongos/core` becomes the new version.
|
|
16
16
|
3b. **verify the integrity pin** (task [#1002216](https://example.com/builders#/task/1002216)) — recompute `tree_sha256` over the installed core and check the vendored `.tgz` bytes against `tarball.sha256`, comparing to the trusted reference manifest (the committed `vendor/…manifest.json`; the installed inner manifest for `--registry`). Runs **before** migrate so a corrupted core never touches the DB. A **mismatch is fatal → rollback**; a missing reference warns (fatal with `--require-pin`); opt out with `--skip-pin-verify`.
|
|
17
|
-
4. **`npm run migrate`** — the core's `migrate.sh` applies additive `core_*` migrations (merged three-root: core + instance + modules).
|
|
17
|
+
4. **`npm run migrate`** — the core's `migrate.sh` applies additive `core_*` migrations (merged three-root: core + instance + modules). An instance whose `package.json` declares **no** `migrate` script — an adopted repo, since the adopt layer adds only the core dependency — runs the installed core's `scripts/migrate.sh` directly from the instance root instead, which is exactly what a scaffold's script runs; the pre-flight names it, so the dry run shows it (task [#1004274](https://example.com/builders#/task/1004274)). Before that fallback, such an instance failed here after the pin had moved and rolled back every time.
|
|
18
18
|
5. **materialize `.claude/`** — refresh skills/settings/hooks from the new core (`materializeClaude`), rewriting invocations to the `bongos` bin.
|
|
19
19
|
6. **restart** — `--service <unit>` or `--restart-cmd "<cmd>"`.
|
|
20
20
|
7. **verify** — installed version == target + the **mandatory post-restart health check** (task [#1002222](https://example.com/builders#/task/1002222)): a bump that restarts the service **requires `--health-url <url>`** (it can't report success without confirming the new core serves). Opt out explicitly with `--no-health-check`; a bump with no managed restart needs no URL (it reports the new core installed-but-unconfirmed). A still-failing health poll fails the bump (auto-rollback).
|
|
@@ -50,6 +50,30 @@ const CLASSES = ['progress', 'quiet', 'stopped', 'transient', 'systemic', 'unwor
|
|
|
50
50
|
// Only these advance the failure count toward `probing`.
|
|
51
51
|
const COUNTS_AS_FAILURE = new Set(['transient', 'systemic']);
|
|
52
52
|
|
|
53
|
+
// WORKER_RAN_FLOOR_S — below this, a worker did not do any work (task 1004179).
|
|
54
|
+
//
|
|
55
|
+
// A real Claude Code session that read a brief, touched a repo and produced a
|
|
56
|
+
// verdict does not finish in seconds. The observed broken shape was 2s with no
|
|
57
|
+
// cost recorded at all. The floor is generous on purpose: it only has to
|
|
58
|
+
// separate "the process died on startup" from "a session ran", and being wrong
|
|
59
|
+
// in the permissive direction costs one extra iteration, while being wrong in
|
|
60
|
+
// the strict direction would call a fast legitimate run breakage.
|
|
61
|
+
const WORKER_RAN_FLOOR_S = 30;
|
|
62
|
+
|
|
63
|
+
// workerNeverRan — the supervisor already decided the worker FAILED; this asks
|
|
64
|
+
// whether it ever started. Both conditions are required: a worker that burned
|
|
65
|
+
// real time or real tokens and then failed DID run and met something, which is
|
|
66
|
+
// a different fact that this must not swallow.
|
|
67
|
+
function workerNeverRan(row = {}) {
|
|
68
|
+
if (row.outcome !== 'worker_failed') return false;
|
|
69
|
+
if (row.spawn_error) return true; // it could not even be launched
|
|
70
|
+
const cost = Number(row.cost_usd);
|
|
71
|
+
const spentNothing = !Number.isFinite(cost) || cost <= 0;
|
|
72
|
+
const dur = Number(row.duration_s);
|
|
73
|
+
const tooFast = Number.isFinite(dur) && dur < WORKER_RAN_FLOOR_S;
|
|
74
|
+
return spentNothing && tooFast;
|
|
75
|
+
}
|
|
76
|
+
|
|
53
77
|
// SYSTEMIC_MARKERS — substrings that mean waiting will not help.
|
|
54
78
|
//
|
|
55
79
|
// A heuristic over an error string, which is a thing to be uneasy about, so the
|
|
@@ -86,6 +110,33 @@ function classifyEvent(row = {}) {
|
|
|
86
110
|
// counting it as such would hold a broken runner at full speed indefinitely.
|
|
87
111
|
if (row.verified === true) return { class: 'progress', detail: 'a task shipped and the ledger confirms it' };
|
|
88
112
|
if (row.ledger_shape === 'undetermined') return { class: 'transient', detail: 'the ledger could not be read back' };
|
|
113
|
+
// DID THE WORKER ACTUALLY RUN? (task 1004179, found by the 1003907 proof run.)
|
|
114
|
+
//
|
|
115
|
+
// Everything below this line assumes a worker that ran and met a real
|
|
116
|
+
// obstacle — a grader refusal, a red main, a task it could not finish. That
|
|
117
|
+
// is genuinely quiet: the machine is fine, a blocker was filed, the task is
|
|
118
|
+
// out of the pool, and moving to the next one is right.
|
|
119
|
+
//
|
|
120
|
+
// A worker that never got going is the opposite, and it was landing in the
|
|
121
|
+
// same bucket. On the Windows host every worker exited in ~2s with "worker
|
|
122
|
+
// output was not JSON" because its argv was corrupted; each run filed a
|
|
123
|
+
// blocker, parked a task, and was classed `quiet` — which neither trips nor
|
|
124
|
+
// forgives the failure count. consecutive_failures stayed 0, the mode stayed
|
|
125
|
+
// `full`, and the runner would have worked through the entire allowlisted
|
|
126
|
+
// goal at one task per five minutes, parking every one of them, while the
|
|
127
|
+
// hall showed it alive and allowed to work. It got through one task before a
|
|
128
|
+
// human stopped it.
|
|
129
|
+
//
|
|
130
|
+
// The queue-vs-runner distinction this module already draws is the same one:
|
|
131
|
+
// `unworkable_queue` is a healthy machine with nothing it can do, and must
|
|
132
|
+
// never escalate. A worker that cannot start is a BROKEN machine with plenty
|
|
133
|
+
// it should be doing, and must.
|
|
134
|
+
if (workerNeverRan(row)) {
|
|
135
|
+
return {
|
|
136
|
+
class: looksSystemic(reason) ? 'systemic' : 'transient',
|
|
137
|
+
detail: `the worker never ran (${row.outcome || 'worker_failed'}${Number.isFinite(Number(row.duration_s)) ? `, ${row.duration_s}s` : ''}, no cost recorded): ${String(row.reason || '').slice(0, 200)}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
89
140
|
// It ran, it did not ship. Not breakage — a blocker was filed and the task is
|
|
90
141
|
// out of the pool — but not progress either. Quiet keeps the runner at full
|
|
91
142
|
// speed so it moves on to the next task, which is the right response.
|
|
@@ -273,4 +324,5 @@ function shouldJumpWait(before, after) {
|
|
|
273
324
|
module.exports = {
|
|
274
325
|
CLASSES, COUNTS_AS_FAILURE, SYSTEMIC_MARKERS, DEFAULTS, START,
|
|
275
326
|
looksSystemic, classifyEvent, nextCadence, signalFingerprint, shouldJumpWait,
|
|
327
|
+
workerNeverRan, WORKER_RAN_FLOOR_S,
|
|
276
328
|
};
|
|
@@ -114,11 +114,14 @@ function readGauge(raw, nowEpochS, config = {}) {
|
|
|
114
114
|
|
|
115
115
|
const writtenAt = Number(raw.written_at);
|
|
116
116
|
if (!Number.isFinite(writtenAt)) return { known: false, reason: 'gauge file has no readable written_at' };
|
|
117
|
-
|
|
118
117
|
const ageS = nowEpochS - writtenAt;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
// NO FILE-LEVEL STALENESS BAIL (task 1004178). There used to be one here, and
|
|
119
|
+
// it short-circuited before the per-window logic below could run — which made
|
|
120
|
+
// the "staleness is per window, not per file" rule directly underneath it a
|
|
121
|
+
// dead letter for exactly the files that needed it. An old file whose windows
|
|
122
|
+
// have all turned over is not unknown; it is a file describing windows that
|
|
123
|
+
// have ended. The windows decide, and when none of them can, the return at the
|
|
124
|
+
// bottom says so with the file's age.
|
|
122
125
|
// A clock that ran backwards is not evidence either.
|
|
123
126
|
if (ageS < -60) return { known: false, ageS, reason: 'gauge is dated in the future — clock skew, treating as unknown' };
|
|
124
127
|
|
|
@@ -129,6 +132,26 @@ function readGauge(raw, nowEpochS, config = {}) {
|
|
|
129
132
|
// on a fresh written_at forever — "unknown" quietly becoming "headroom".
|
|
130
133
|
// Files written before observed_at existed fall back to written_at, which is
|
|
131
134
|
// exactly what they meant.
|
|
135
|
+
// AN AGED-OUT READING WHOSE WINDOW HAS SINCE RESET IS NOT STALE — IT IS
|
|
136
|
+
// SUPERSEDED (task 1004178, found by the 1003907 proof run).
|
|
137
|
+
//
|
|
138
|
+
// WHY: an unattended host cannot refresh this file at all — the writer is a
|
|
139
|
+
// statusLine, which only renders in a terminal session. The evidence and the
|
|
140
|
+
// full account are in modules/autonomy/CLAUDE.md; what matters here is the
|
|
141
|
+
// consequence: without this, the runner holds 30 minutes in and never resumes.
|
|
142
|
+
//
|
|
143
|
+
// The narrow fact that rescues it: when `now` is past a window's own
|
|
144
|
+
// `resets_at`, the window that reading described has ENDED, and the current
|
|
145
|
+
// one began at that reset with zero used. That is what a reset IS, not a
|
|
146
|
+
// guess — which is why this does not breach "unknown is never headroom":
|
|
147
|
+
// nothing is being assumed about the observation, it is being RETIRED.
|
|
148
|
+
//
|
|
149
|
+
// What IS assumed is that nobody else spent the new window. That is why a
|
|
150
|
+
// derived window is MARKED, and why the caller must bound how much work it
|
|
151
|
+
// does on one. The true boundary is also unknowable — these windows roll from
|
|
152
|
+
// first use, not from a fixed clock — so `resetsAt` on a derived window is a
|
|
153
|
+
// lower bound, and the seven-day PACE check is skipped rather than run
|
|
154
|
+
// against a boundary we invented.
|
|
132
155
|
const win = (w) => {
|
|
133
156
|
const o = raw[w];
|
|
134
157
|
if (!o || typeof o !== 'object') return null;
|
|
@@ -136,8 +159,14 @@ function readGauge(raw, nowEpochS, config = {}) {
|
|
|
136
159
|
const resets = Number(o.resets_at);
|
|
137
160
|
if (!Number.isFinite(used) || !Number.isFinite(resets)) return null;
|
|
138
161
|
const observedAt = Number.isFinite(Number(o.observed_at)) ? Number(o.observed_at) : writtenAt;
|
|
139
|
-
if (nowEpochS - observedAt
|
|
140
|
-
|
|
162
|
+
if (nowEpochS - observedAt <= c.staleAfterS) {
|
|
163
|
+
return { used, resetsAt: resets, observedAt, ageS: nowEpochS - observedAt, derived: false };
|
|
164
|
+
}
|
|
165
|
+
// Aged out. Superseded ONLY if its window has actually turned over.
|
|
166
|
+
if (nowEpochS >= resets) {
|
|
167
|
+
return { used: 0, resetsAt: resets, observedAt: resets, ageS: nowEpochS - resets, derived: true };
|
|
168
|
+
}
|
|
169
|
+
return null; // old, and its window is still running — no longer evidence
|
|
141
170
|
};
|
|
142
171
|
const fiveHour = win('five_hour');
|
|
143
172
|
const sevenDay = win('seven_day');
|
|
@@ -145,7 +174,7 @@ function readGauge(raw, nowEpochS, config = {}) {
|
|
|
145
174
|
// Both windows are optional in the source ("may be absent"), but with neither
|
|
146
175
|
// there is nothing to decide on.
|
|
147
176
|
if (!fiveHour && !sevenDay) {
|
|
148
|
-
return { known: false, ageS, reason:
|
|
177
|
+
return { known: false, ageS, reason: `gauge is ${Math.round(ageS / 60)}m old and no window has turned over since — absent or aged out, which is unknown, not headroom` };
|
|
149
178
|
}
|
|
150
179
|
return { known: true, ageS, fiveHour, sevenDay };
|
|
151
180
|
}
|
|
@@ -188,7 +217,9 @@ function decideCapacity({ gauge, now, config = {} } = {}) {
|
|
|
188
217
|
return { go: false, unknown: false, sleepUntil: g.sevenDay.resetsAt, window: 'seven_day',
|
|
189
218
|
reason: `seven-day window spent (${g.sevenDay.used.toFixed(1)}%) — sleeping to its reset` };
|
|
190
219
|
}
|
|
191
|
-
|
|
220
|
+
// A DERIVED seven-day window carries a boundary we inferred, so pacing it
|
|
221
|
+
// would measure progress through a week we guessed at. Skipped, not faked.
|
|
222
|
+
if (!g.sevenDay.derived && g.sevenDay.used > pace.allowedPct) {
|
|
192
223
|
const until = whenPaceAllows(g.sevenDay, c);
|
|
193
224
|
// Never propose a wake in the past, and never past the reset itself.
|
|
194
225
|
const sleepUntil = Math.min(Math.max(until, now + 1), g.sevenDay.resetsAt);
|
|
@@ -209,7 +240,24 @@ function decideCapacity({ gauge, now, config = {} } = {}) {
|
|
|
209
240
|
const bits = [];
|
|
210
241
|
if (g.fiveHour) bits.push(`5h ${g.fiveHour.used.toFixed(1)}%`);
|
|
211
242
|
if (g.sevenDay) bits.push(`7d ${g.sevenDay.used.toFixed(1)}%`);
|
|
212
|
-
|
|
243
|
+
// A derived window is reported as such all the way out, so a caller can bound
|
|
244
|
+
// the work it does on one and a reader can see which kind of "go" this is.
|
|
245
|
+
const derived = !!((g.fiveHour && g.fiveHour.derived) || (g.sevenDay && g.sevenDay.derived));
|
|
246
|
+
const detail = derived
|
|
247
|
+
? "the last reading's window has since reset, so it was retired rather than trusted"
|
|
248
|
+
: `gauge ${Math.round(g.ageS)}s old`;
|
|
249
|
+
// `derivedSince` is the reset the derived baseline stands on. The caller needs
|
|
250
|
+
// it because a derived window cannot be paced: a SEVEN-day window will almost
|
|
251
|
+
// never turn over during a night, so its stale reading is dropped and the
|
|
252
|
+
// weekly pace check — the one the module's own notes call the thing that
|
|
253
|
+
// actually binds a heavy week — does not run at all. A stale weekly figure
|
|
254
|
+
// cannot stand in for it either: usage only grows, so an under-reported value
|
|
255
|
+
// makes the check MORE permissive, which is the wrong direction to be wrong in.
|
|
256
|
+
// Bounding the work done since `derivedSince` is what replaces that pacing.
|
|
257
|
+
const derivedSince = derived
|
|
258
|
+
? Math.min(...[g.fiveHour, g.sevenDay].filter((w) => w && w.derived).map((w) => w.observedAt))
|
|
259
|
+
: null;
|
|
260
|
+
return { go: true, unknown: false, sleepUntil: null, derived, derivedSince, reason: `headroom (${bits.join(', ')}; ${detail})` };
|
|
213
261
|
}
|
|
214
262
|
|
|
215
263
|
module.exports = {
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
{ "glob": "modules/grading/grader-prompt.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
60
60
|
{ "glob": "modules/grading/grader-score.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
61
61
|
{ "glob": "modules/grading/grader-subagent.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
62
|
+
{ "glob": "modules/grading/grade-engine.js", "group": "pipeline", "why": "task 1002839. The central grading engine every work-type is graded through: it runs the deterministic route-rank and permission-path pre-passes and applies the deterministic veto, so editing it can switch off the protected-path gate for every grade at once." },
|
|
62
63
|
{ "glob": "modules/grading/grader-workers/", "group": "pipeline", "why": "the adversarial panel (Narc/Hacker/Quality/Efficiency) — blunting these blunts the gate" },
|
|
63
64
|
{ "glob": "modules/grading/grader-rubric.json", "group": "pipeline", "why": "the grader's scoring rubric (ADR 0058)" },
|
|
64
65
|
{ "glob": "scripts/gds/ship.js", "group": "pipeline", "why": "the ship lifecycle driver" },
|