@bongos/core 1.19.715 → 1.19.724

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.
Files changed (414) hide show
  1. package/.bongos-core.json +472 -407
  2. package/.claude/skills/backlog-review/SKILL.md +3 -3
  3. package/.claude/skills/blocker-review/SKILL.md +1 -1
  4. package/.claude/skills/blocker-solve/SKILL.md +2 -2
  5. package/.claude/skills/builder-reauth/SKILL.md +1 -1
  6. package/.claude/skills/builder-redteam/SKILL.md +1 -1
  7. package/.claude/skills/builder-ship/SKILL.md +1 -1
  8. package/.claude/skills/builder-start/SKILL.md +1 -1
  9. package/.claude/skills/design/SKILL.md +2 -2
  10. package/.claude/skills/feedback/SKILL.md +1 -1
  11. package/.claude/skills/goal-create/SKILL.md +1 -1
  12. package/.claude/skills/goal-review/SKILL.md +2 -2
  13. package/.claude/skills/idea-triage/SKILL.md +5 -5
  14. package/.claude/skills/merge-mode/SKILL.md +4 -4
  15. package/.claude/skills/new-project/SKILL.md +17 -17
  16. package/.claude/skills/planning-session/SKILL.md +11 -11
  17. package/.claude/skills/recall/SKILL.md +2 -2
  18. package/.claude/skills/strand-fix/SKILL.md +1 -1
  19. package/.devcontainer/README.md +2 -2
  20. package/CONTRIBUTING.md +2 -2
  21. package/GOVERNANCE.md +4 -4
  22. package/clients/bongos-client/README.md +1 -1
  23. package/clients/bongos-client/bongos-client.global.js +4 -0
  24. package/clients/bongos-client/index.cjs +4 -0
  25. package/clients/bongos-client/index.d.ts +5 -0
  26. package/clients/bongos-client/index.mjs +4 -0
  27. package/config/branding.neutral.json +4 -2
  28. package/docs/adr/0001-stack-choice-single-vps.md +2 -2
  29. package/docs/adr/0002-digitalocean-over-hetzner.md +1 -1
  30. package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
  31. package/docs/adr/0009-autotile-architecture.md +1 -1
  32. package/docs/adr/0011-terrain-id-rendering-model.md +3 -3
  33. package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +1 -1
  34. package/docs/adr/0014-families-canonical-over-vocabulary.md +1 -1
  35. package/docs/adr/0015-task-dependencies-and-auto-promotion.md +1 -1
  36. package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +1 -1
  37. package/docs/adr/0018-three-rank-model-goes-live.md +3 -3
  38. package/docs/adr/0020-security-model-public-stub.md +9 -9
  39. package/docs/adr/0021-per-builder-skill-model-preferences.md +2 -2
  40. package/docs/adr/0022-secrets-policy.md +5 -5
  41. package/docs/adr/0024-cloneable-repo-local-first-memory.md +3 -3
  42. package/docs/adr/0024-multi-agent-system-architecture.md +10 -10
  43. package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +1 -1
  44. package/docs/adr/0025-structured-criterion-task-link.md +1 -1
  45. package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +13 -13
  46. package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +14 -14
  47. package/docs/adr/0029-status-page-outage-resilience.md +1 -1
  48. package/docs/adr/0030-builders-hall-live-updates.md +1 -1
  49. package/docs/adr/0031-cloud-dev-environments-for-builders.md +7 -7
  50. package/docs/adr/0032-discord-mirror-of-gds.md +3 -3
  51. package/docs/adr/0033-discord-bot-service-principal.md +4 -4
  52. package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
  53. package/docs/adr/0035-builder-onboarding-three-paths.md +4 -4
  54. package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +1 -1
  55. package/docs/adr/0037-discord-channel-management.md +1 -1
  56. package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +5 -5
  57. package/docs/adr/0039-setup-first-onboarding-ux.md +6 -6
  58. package/docs/adr/0040-remote-control-default-browser-onramp.md +3 -3
  59. package/docs/adr/0041-temporary-grader-bypass-killswitch.md +2 -2
  60. package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +5 -5
  61. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +2 -2
  62. package/docs/adr/0044-mediterranean-palette-replacement.md +1 -1
  63. package/docs/adr/0044-per-box-live-game-preview.md +1 -1
  64. package/docs/adr/0046-sandbox-first-review-gate.md +1 -1
  65. package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +1 -1
  66. package/docs/adr/0049-split-parallel-safety-contract.md +1 -1
  67. package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +2 -2
  68. package/docs/adr/0051-full-session-transcript-corpus.md +2 -2
  69. package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +1 -1
  70. package/docs/adr/0053-scoped-dev-box-session.md +1 -1
  71. package/docs/adr/0054-session-token-reward-cost-plus.md +7 -7
  72. package/docs/adr/0055-server-mediated-branch-publish.md +2 -2
  73. package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +3 -3
  74. package/docs/adr/0057-container-cost-ledger.md +1 -1
  75. package/docs/adr/0057-discord-archon-approval-channels.md +2 -2
  76. package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +6 -6
  77. package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +11 -11
  78. package/docs/adr/0060-gds-retrieval-layer.md +3 -3
  79. package/docs/adr/0061-context-layer-decomposition.md +2 -2
  80. package/docs/adr/0062-medusa-instance-model-decoupling.md +5 -5
  81. package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +2 -2
  82. package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +3 -3
  83. package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +5 -5
  84. package/docs/adr/0066-generated-file-map-sections.md +2 -2
  85. package/docs/adr/0067-session-start-fast-forward-pull.md +1 -1
  86. package/docs/adr/0068-shared-art-key-for-newcomers.md +1 -1
  87. package/docs/adr/0069-hall-live-channel-sse-decouple.md +3 -3
  88. package/docs/adr/0070-deterministic-session-card-delivery.md +1 -1
  89. package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +2 -2
  90. package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +2 -2
  91. package/docs/adr/0072-dev-box-code-staleness-visibility.md +2 -2
  92. package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +3 -3
  93. package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +2 -2
  94. package/docs/adr/0076-in-session-deterministic-compaction.md +2 -2
  95. package/docs/adr/0077-content-addressed-llm-cache.md +2 -2
  96. package/docs/adr/0078-deterministic-first-cron.md +3 -3
  97. package/docs/adr/0079-value-gated-autonomous-engagement.md +2 -2
  98. package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +3 -3
  99. package/docs/adr/0081-tool-agnostic-design-layer.md +3 -3
  100. package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +2 -2
  101. package/docs/adr/0083-modular-architecture-strangler-build-plan.md +3 -3
  102. package/docs/adr/0085-remove-default-per-builder-spend-cap.md +2 -2
  103. package/docs/adr/0086-goal-scoped-work-hierarchy.md +15 -15
  104. package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +5 -5
  105. package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +1 -1
  106. package/docs/adr/0088-consistent-character-generative-animation.md +5 -5
  107. package/docs/adr/0089-modular-multi-model-adversarial-grader.md +15 -15
  108. package/docs/adr/0090-metic-task-authoring.md +8 -8
  109. package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +3 -3
  110. package/docs/adr/0092-hosting-module-and-on-prem-target.md +11 -11
  111. package/docs/adr/0093-tranche-2-core-carve-sequence.md +5 -5
  112. package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +1 -1
  113. package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +6 -6
  114. package/docs/adr/0095-cross-agent-context-management.md +5 -5
  115. package/docs/adr/0096-require-reward-before-workable.md +5 -5
  116. package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +2 -2
  117. package/docs/adr/0097-retroactive-reward-backfill.md +4 -4
  118. package/docs/adr/0098-public-mirror-publish-manifest.md +3 -3
  119. package/docs/adr/0099-delayed-redacted-mirror-export.md +1 -1
  120. package/docs/adr/0100-two-repo-instance-model.md +6 -6
  121. package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +9 -9
  122. package/docs/adr/0102-finish-bounding-the-kernel.md +1 -1
  123. package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +6 -6
  124. package/docs/adr/0103-gdsv4-bongos-consolidation.md +3 -3
  125. package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +3 -3
  126. package/docs/adr/0105-instance-seed-migrations-out-of-core.md +2 -2
  127. package/docs/adr/0106-goal-owner-manager-authority.md +2 -2
  128. package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +6 -6
  129. package/docs/adr/0108-instance-composition-configurable-root.md +6 -6
  130. package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +3 -3
  131. package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +1 -1
  132. package/docs/adr/0111-instance-hosting-provisioning-module.md +18 -18
  133. package/docs/adr/0112-private-goals-invitations-join-requests.md +7 -7
  134. package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +1 -1
  135. package/docs/adr/0114-instance-docs-discovery-contract.md +4 -4
  136. package/docs/adr/0115-scheduled-routines-portability.md +1 -1
  137. package/docs/adr/0117-api-versioning-and-deprecation-policy.md +1 -1
  138. package/docs/adr/0118-api-contract-source-of-truth-code-first.md +1 -1
  139. package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +2 -2
  140. package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +1 -1
  141. package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +3 -3
  142. package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +1 -1
  143. package/docs/adr/0124-typed-api-response-bodies.md +2 -2
  144. package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +2 -2
  145. package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +3 -3
  146. package/docs/adr/0127-cross-box-fleet-observability.md +1 -1
  147. package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +3 -3
  148. package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +4 -4
  149. package/docs/adr/0130-provision-remote-exec-over-ssh.md +4 -4
  150. package/docs/adr/0131-rank-scoped-skill-visibility.md +2 -2
  151. package/docs/adr/0132-cohost-fleet-control-plane-migration.md +2 -2
  152. package/docs/adr/0133-github-app-manifest-onboarding-signin.md +1 -1
  153. package/docs/adr/0134-private-first-npm-distribution.md +3 -3
  154. package/docs/adr/0135-module-upstream-submission-interim-queue.md +1 -1
  155. package/docs/adr/0136-update-channel-subscription-policy.md +2 -2
  156. package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +6 -6
  157. package/docs/adr/0138-bundled-module-deps-declared-per-module.md +4 -4
  158. package/docs/adr/0142-project-context-is-prose-only.md +2 -2
  159. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +2 -2
  160. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +2 -2
  161. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +2 -2
  162. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +4 -4
  163. package/docs/adr/0147-standalone-live-docs-regen.md +1 -1
  164. package/docs/adr/0149-bongos-dev-local-launcher.md +1 -1
  165. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +3 -3
  166. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +20 -20
  167. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +2 -2
  168. package/docs/adr/0152-metic-task-abandonment.md +7 -7
  169. package/docs/adr/0153-sequential-chain-runner.md +1 -1
  170. package/docs/adr/0154-goal-owner-criterion-authoring.md +7 -7
  171. package/docs/adr/0155-adopt-private-repo-widen-oauth-scope.md +2 -2
  172. package/docs/adr/0156-user-set-display-name-wins.md +1 -1
  173. package/docs/adr/0157-archon-is-rank-and-identity-only.md +10 -10
  174. package/docs/adr/0158-choke-point-verdict-taxonomy.md +1 -1
  175. package/docs/adr/0159-merge-gate-reconciliation.md +1 -1
  176. package/docs/adr/0160-main-audit-repo-verifiable-caller.md +1 -1
  177. package/docs/adr/0161-publish-on-merge.md +2 -2
  178. package/docs/adr/0163-legacy-display-name-resolution.md +1 -1
  179. package/docs/adr/0165-instances-hookless-by-default.md +1 -1
  180. package/docs/adr/0166-module-maintenance-and-deprecation-policy.md +3 -3
  181. package/docs/adr/0167-gate-trust-link-agpl-default.md +2 -2
  182. package/docs/adr/0167-module-catalog-source-vs-provenance.md +3 -3
  183. package/docs/adr/0169-bongos-serve-server-bring-up.md +1 -1
  184. package/docs/adr/0171-profile-rollup-join-and-consent.md +1 -1
  185. package/docs/adr/0172-editable-rank-roles-substrate-axis.md +2 -2
  186. package/docs/adr/0172-per-craft-compensation-ideator-credit-lane.md +4 -4
  187. package/docs/adr/0173-legacy-multi-ship-shortfall-not-backfilled.md +1 -1
  188. package/docs/adr/0174-government-terminology-ranks-not-roles.md +1 -1
  189. package/docs/adr/0177-goal-membership-kind.md +3 -3
  190. package/docs/adr/0178-the-copy-desk-flag-and-queue.md +1 -1
  191. package/docs/adr/0179-board-membership-predicate-grammar.md +1 -1
  192. package/docs/adr/0181-teardown-state-gate-and-address-retention.md +1 -1
  193. package/docs/adr/0182-project-visibility-two-axes.md +1 -1
  194. package/docs/adr/0183-criteria-close-themselves.md +1 -1
  195. package/docs/adr/0184-ship-requires-an-assurance.md +1 -1
  196. package/docs/adr/0185-spark-handoff-credit-split.md +1 -1
  197. package/docs/adr/0186-per-project-idea-templates.md +1 -1
  198. package/docs/adr/0187-collab-four-decisions.md +1 -1
  199. package/docs/adr/0187-oauth-handshake-cookie-lifetime.md +1 -1
  200. package/docs/adr/0188-patrol-runs-on-ci-not-the-server.md +2 -2
  201. package/docs/adr/0189-baseline-floors-and-the-freeze-detector.md +2 -2
  202. package/docs/adr/0191-majority-and-the-author-who-may-not-decide-alone.md +1 -1
  203. package/docs/adr/0192-a-category-orients-and-authorises-nothing.md +2 -2
  204. package/docs/adr/0193-pause-task-scoped-box-slices.md +1 -1
  205. package/docs/adr/0195-adr-numbers-are-checked-like-migration-numbers.md +2 -2
  206. package/docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md +2 -2
  207. package/docs/adr/0197-the-ui-design-module.md +1 -1
  208. package/docs/adr/0198-third-party-skill-vendoring-policy.md +1 -1
  209. package/docs/adr/0203-doorway-changelog-out-of-module-api.md +2 -2
  210. package/docs/adr/0204-the-apex-is-dark-only.md +2 -2
  211. package/docs/adr/0205-federated-checkin-needs-the-hubs-own-signin-witness.md +1 -1
  212. package/docs/adr/0206-own-scoped-session-revocation-no-absolute-ceiling.md +1 -1
  213. package/docs/adr/0207-connections-implementation-departures-and-honest-limits.md +1 -1
  214. package/docs/adr/0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md +2 -2
  215. package/docs/adr/0209-one-budget-for-the-account-existence-oracle.md +1 -1
  216. package/docs/adr/0210-scouting-graduates-on-an-instance-asserted-owner-claim.md +1 -1
  217. package/docs/adr/0212-connections-on-the-profile-surface-and-addressing.md +1 -1
  218. package/docs/adr/0213-platform-terms-acceptance-is-the-hubs-own-witness.md +2 -2
  219. package/docs/adr/0215-the-recruiter-sliver-is-a-ceiling-not-a-step.md +6 -6
  220. package/docs/adr/0216-a-fake-pool-interpreter-must-fail-loudly-not-silently-ignore.md +2 -2
  221. package/docs/adr/0217-rank-gates-inviting-not-viewing.md +1 -1
  222. package/docs/adr/0218-the-apex-root-web-surface.md +2 -2
  223. package/docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md +1 -1
  224. package/docs/adr/0220-an-in-house-rebuilt-skill-is-a-first-party-skill.md +1 -1
  225. package/docs/adr/0221-the-impeccable-method-is-one-skill-with-sub-command-playbooks.md +2 -2
  226. package/docs/adr/0222-the-image-family-under-the-hero-only-rule.md +2 -2
  227. package/docs/adr/0223-the-detector-is-two-tiers-in-the-kit.md +3 -3
  228. package/docs/adr/0224-module-skills-reach-the-core-checkout-as-untracked-self-ignored-copies.md +1 -1
  229. package/docs/adr/0225-privacy-suppresses-cross-project-surfaces-only.md +1 -1
  230. package/docs/adr/0226-one-stale-timer-reporting-degrades-enforcement-refuses.md +1 -1
  231. package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
  232. package/docs/adr/0230-a-look-skill-is-a-composition-grammar-the-palette-is-the-pack.md +1 -1
  233. package/docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md +2 -2
  234. package/docs/adr/0232-rot-is-derived-not-swept-and-water-is-the-only-new-verb.md +2 -2
  235. package/docs/adr/0233-a-copy-proposal-is-a-task-carrying-a-patch.md +2 -2
  236. package/docs/adr/0234-idea-routing-capture-time-promotion-landing-matrix-homeless-inbox.md +2 -2
  237. package/docs/adr/0235-a-fix-category-is-kindbug-under-a-goal-no-column-required.md +11 -11
  238. package/docs/adr/0236-many-ideas-one-task-the-lineage-key-is-the-pair.md +5 -5
  239. package/docs/adr/0237-a-starter-bundle-is-a-preset-over-the-always-on-core-keyed-by-declared-type.md +5 -5
  240. package/docs/adr/0238-the-join-door-is-a-provisioning-settings-policy-key.md +1 -1
  241. package/docs/adr/0239-a-recommendation-is-a-table-that-carries-its-own-reason.md +4 -4
  242. package/docs/adr/0240-a-skipped-module-picker-stores-nothing-and-resolves-the-bundle-on-read.md +4 -4
  243. package/docs/adr/0241-the-artist-gate-is-a-per-project-deploy-gate-that-reads-a-state.md +1 -1
  244. package/docs/adr/0242-a-cascade-is-a-declaration-table-on-the-event-that-already-exists.md +2 -2
  245. package/docs/adr/0243-a-bundle-adjustment-belongs-to-the-bundle-not-the-advice-about-it.md +4 -4
  246. package/docs/adr/0244-a-catalog-search-is-a-view-over-the-rows-never-an-edit-to-the-selection.md +3 -3
  247. package/docs/adr/0245-the-way-back-into-an-optional-step-is-that-step-s-own-answer-route.md +7 -7
  248. package/docs/adr/0246-catalog-membership-is-a-projection-not-a-federation-side-effect.md +1 -1
  249. package/docs/adr/0247-the-join-door-is-one-composed-answer-and-dark-matter-has-no-live-verdict-yet.md +2 -2
  250. package/docs/adr/0248-a-hub-project-s-owner-is-the-provisioning-row-carried-on-a-port.md +3 -3
  251. package/docs/adr/0249-the-invite-step-is-the-done-panel-s-first-act-not-a-rail-step.md +3 -3
  252. package/docs/adr/0250-strict-versioning-the-version-boundary-is-the-scope-gate.md +6 -6
  253. package/docs/adr/0251-a-suggestion-of-who-to-invite-is-a-recruiting-surface-and-owes-the-opt-out.md +5 -5
  254. package/docs/adr/0252-the-self-hosted-visibility-report-is-a-pull-and-auto-appear-buys-a-retraction-lever.md +19 -19
  255. package/docs/adr/0253-the-takedown-lever-has-two-writers-and-provenance-is-a-column.md +2 -2
  256. package/docs/adr/0254-a-relayed-link-is-contained-downward-or-it-is-not-published.md +6 -6
  257. package/docs/adr/0255-a-public-lists-ordering-is-part-of-its-payload.md +2 -2
  258. package/docs/adr/0256-the-visibility-ceiling-is-the-sign-in-gate-too-and-the-reader-moves-to-the-composer.md +3 -3
  259. package/docs/adr/0257-auth-resolves-before-the-hall-mounts-anything.md +1 -1
  260. package/docs/adr/0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md +1 -1
  261. package/docs/adr/0259-a-projects-departure-from-the-public-list-is-public.md +7 -7
  262. package/docs/adr/0260-the-application-is-the-consent-and-the-echo-is-the-gate.md +4 -4
  263. package/docs/adr/0261-a-preselect-always-carries-a-reason-the-bundle-summary-is-the-floor.md +1 -1
  264. package/docs/adr/0262-a-bug-never-lands-in-the-inbox.md +1 -1
  265. package/docs/adr/0263-how-a-version-closes.md +3 -3
  266. package/docs/adr/0264-the-ten-working-areas.md +3 -3
  267. package/docs/adr/0265-work-with-no-goal-and-the-order-the-cut-needs.md +5 -5
  268. package/docs/adr/0266-the-board-room-is-its-own-surface-reachable-by-whoever-may-vote.md +2 -2
  269. package/docs/adr/0267-unanimity-and-the-revise-and-re-sit-loop.md +1 -1
  270. package/docs/adr/0268-the-constitution-comes-from-two-roots.md +3 -3
  271. package/docs/adr/0269-the-cli-session-store-is-host-keyed-at-a-fixed-anchor.md +1 -1
  272. package/docs/adr/0270-rank-floor-derives-without-a-prediction.md +2 -2
  273. package/docs/adr/0271-the-ideator-surface-is-two-halves.md +3 -3
  274. package/docs/adr/0272-a-craft-is-an-identity-not-a-toolchain.md +4 -4
  275. package/docs/adr/0273-hall-nav-can-gate-on-a-permission.md +1 -1
  276. package/docs/adr/0274-one-kernel-three-role-packs.md +1 -1
  277. package/docs/adr/0275-one-source-for-a-written-role-responsibility.md +1 -1
  278. package/docs/adr/0276-the-skill-listing-budget-cannot-hold-every-trigger.md +1 -1
  279. package/docs/adr/0277-a-box-is-in-use-only-while-a-human-is-attached.md +1 -1
  280. package/docs/adr/0278-a-gated-project-still-takes-applications.md +2 -2
  281. package/docs/adr/0279-an-upgrade-is-proven-by-the-served-version-not-the-health-check.md +1 -1
  282. package/docs/adr/0280-the-unattended-lane-may-drive-a-co-tenant-because-the-roster-is-the-decision.md +1 -1
  283. package/docs/adr/0281-an-instance-identity-is-its-own-unix-account-and-pg-role.md +2 -2
  284. package/docs/adr/README.md +294 -294
  285. package/docs/api/openapi.json +72 -5
  286. package/docs/api-reference.md +8 -2
  287. package/docs/architecture.md +22 -22
  288. package/docs/branding-contract.md +5 -5
  289. package/docs/canonical-permissions.md +22 -22
  290. package/docs/design/hall-direction-v2.md +3 -3
  291. package/docs/design/landing-page-direction-v2.md +1 -1
  292. package/docs/design/projects-hub-direction-v2.md +1 -1
  293. package/docs/file-map.md +3 -1
  294. package/docs/module-api-changelog.md +34 -1
  295. package/docs/modules-contract.md +25 -25
  296. package/docs/onboarding/browser-terminal-guide.md +1 -1
  297. package/docs/onboarding/diagrams/README.md +3 -3
  298. package/docs/onboarding/drachmae-and-karma.md +13 -13
  299. package/docs/onboarding/primer.md +7 -7
  300. package/docs/packs/artist.md +1 -1
  301. package/docs/packs/ideator.md +1 -1
  302. package/docs/project-context.template.md +3 -3
  303. package/docs/recipes/builder-box-lifecycle.md +5 -5
  304. package/docs/recipes/claude-design-loop.md +1 -1
  305. package/docs/recipes/core-release-pipeline.md +55 -14
  306. package/docs/recipes/figma-design-loop.md +1 -1
  307. package/docs/recipes/gds-db-backup.md +2 -2
  308. package/docs/recipes/instance-deploy.md +2 -2
  309. package/docs/recipes/instance-service-restart.md +3 -3
  310. package/docs/recipes/local-dev.md +2 -2
  311. package/docs/recipes/managed-settings-remote-control.md +3 -3
  312. package/docs/recipes/memory-backup.md +4 -4
  313. package/docs/recipes/memory-sync-conflicts.md +2 -2
  314. package/docs/recipes/multi-builder-merge.md +2 -2
  315. package/docs/recipes/ops-gotchas.md +4 -4
  316. package/docs/recipes/overnight-builder.md +1 -1
  317. package/docs/recipes/packaging-the-core.md +6 -6
  318. package/docs/recipes/private-npm-distribution.md +5 -5
  319. package/docs/recipes/search-index-ingestion.md +3 -3
  320. package/docs/recipes/self-host.md +5 -5
  321. package/docs/recipes/server-bring-up.md +1 -1
  322. package/docs/recipes/ship-and-regrade.md +2 -2
  323. package/docs/recipes/standalone-live-docs.md +1 -1
  324. package/docs/recipes/ui-look-before-you-ship.md +1 -1
  325. package/docs/recipes/upgrading-the-core.md +2 -2
  326. package/docs/recipes/work-on-a-task-from-your-dev-box.md +6 -6
  327. package/docs/research/cursor-competitive-analysis.md +3 -3
  328. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +7 -7
  329. package/migrations/core_240_artist_gate_indexes.sql +48 -0
  330. package/migrations/core_240_goal_members_drop_legacy_role.sql +79 -0
  331. package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
  332. package/modules/lifecycle/cascade.js +37 -9
  333. package/modules/lifecycle/db-claims.js +5 -2
  334. package/modules/lifecycle/db-goals.js +4 -3
  335. package/modules/lifecycle/db-overrides.js +117 -4
  336. package/modules/lifecycle/db-tasks.js +63 -0
  337. package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +12 -4
  338. package/modules/lifecycle/module.json +2 -1
  339. package/modules/lifecycle/pg-constraint-fail.js +49 -0
  340. package/modules/lifecycle/routes/artist-gate.js +101 -0
  341. package/modules/lifecycle/routes/claims.js +13 -1
  342. package/modules/lifecycle/routes/lifecycle.js +6 -0
  343. package/modules/lifecycle/routes/task-write-routes.js +7 -0
  344. package/modules/lifecycle/routes/tasks.js +24 -0
  345. package/modules/lifecycle/task-classifier.js +10 -1
  346. package/modules/lifecycle/tests/cascade.mjs +43 -0
  347. package/modules/provisioning/provisioning.js +79 -3
  348. package/modules/provisioning/routes/provisioning.js +6 -1
  349. package/modules/provisioning/tests/provisioning.mjs +8 -8
  350. package/modules/security/secret-scrub.js +40 -4
  351. package/modules/status-ui/public/README.md +1 -1
  352. package/modules/ui-design/docs/design-contract.md +2 -2
  353. package/modules/ui-design/kit/README.md +1 -1
  354. package/modules/ui-design/kit/serve.js +1 -0
  355. package/modules/ui-design/skills/README.md +6 -6
  356. package/modules/ui-design/skills/brandkit/SKILL.md +1 -1
  357. package/modules/ui-design/skills/design-taste-frontend/SKILL.md +1 -1
  358. package/modules/ui-design/skills/design-taste-frontend-v1/SKILL.md +1 -1
  359. package/modules/ui-design/skills/gpt-taste/SKILL.md +1 -1
  360. package/modules/ui-design/skills/high-end-visual-design/SKILL.md +1 -1
  361. package/modules/ui-design/skills/image-to-code/SKILL.md +1 -1
  362. package/modules/ui-design/skills/imagegen-frontend-mobile/SKILL.md +1 -1
  363. package/modules/ui-design/skills/imagegen-frontend-web/SKILL.md +1 -1
  364. package/modules/ui-design/skills/impeccable/SKILL.md +1 -1
  365. package/modules/ui-design/skills/industrial-brutalist-ui/SKILL.md +1 -1
  366. package/modules/ui-design/skills/minimalist-ui/SKILL.md +1 -1
  367. package/modules/ui-design/skills/redesign-existing-projects/SKILL.md +1 -1
  368. package/modules/ui-design/skills/stitch-design-taste/SKILL.md +1 -1
  369. package/modules/ui-design/skills/style/SKILL.md +2 -2
  370. package/modules/ui-design/styles/README.md +3 -3
  371. package/modules/ui-design/styles/blueprint/DESIGN.md +1 -1
  372. package/modules/ui-design/styles/chrome-world/DESIGN.md +1 -1
  373. package/package-lock.json +2 -2
  374. package/package.json +1 -1
  375. package/scripts/gds/audit-rank-roles.js +172 -0
  376. package/scripts/gds/build-cli-package.js +1 -0
  377. package/scripts/gds/claim.js +94 -9
  378. package/scripts/gds/fitness.js +8 -8
  379. package/scripts/gds/go-live.js +139 -5
  380. package/scripts/gds/land-watch.js +13 -5
  381. package/scripts/gds/mirror-redact.js +13 -2
  382. package/scripts/gds/package-core.js +11 -3
  383. package/scripts/gds/release.js +55 -0
  384. package/scripts/gds/ship-land.js +10 -2
  385. package/scripts/gds/ship-regen.js +41 -8
  386. package/scripts/gds/start.js +7 -4
  387. package/scripts/gds/worktree-claim-guard.js +27 -1
  388. package/scripts/public-mirror-export.js +17 -4
  389. package/src/bongos/api-errors.js +9 -0
  390. package/src/bongos/artist-gate.js +204 -0
  391. package/src/branding.js +15 -0
  392. package/src/module-api.js +34 -1
  393. package/tests/api_path_404.mjs +28 -0
  394. package/tests/artist_gate.mjs +234 -0
  395. package/tests/artist_gate_release.mjs +283 -0
  396. package/tests/artist_gate_route.mjs +174 -0
  397. package/tests/box_scope_predicate.mjs +117 -0
  398. package/tests/claim_error_surface.mjs +163 -1
  399. package/tests/cli_exit_no_abort.mjs +256 -3
  400. package/tests/currency_label.mjs +11 -4
  401. package/tests/go_live.mjs +144 -0
  402. package/tests/main_worktree_busy_reason.mjs +167 -0
  403. package/tests/membership_kind_lockstep.mjs +88 -0
  404. package/tests/mirror_redact.mjs +14 -0
  405. package/tests/module_api.mjs +6 -0
  406. package/tests/provision_settings_apply.mjs +13 -5
  407. package/tests/provisioning_settings.mjs +11 -7
  408. package/tests/provisioning_settings_apply.mjs +4 -4
  409. package/tests/provisioning_settings_env.mjs +59 -7
  410. package/tests/public_mirror_export.mjs +12 -0
  411. package/tests/rank_roles_audit.mjs +114 -0
  412. package/tests/scrubber_corpus.mjs +70 -2
  413. package/tests/start_rebase_warning.mjs +50 -0
  414. package/tests/task_field_bounds_match_db.mjs +140 -0
@@ -1,6 +1,6 @@
1
1
  # `modules/ui-design/styles/` — the style library: looks as branding packs
2
2
 
3
- A **look** is something a builder or an instance owner picks for a new surface or a whole instance. The library ships looks as **branding packs** ([task 1003323](https://cloudbongos.com/builders#/task/1003323), [ADR 0219](../../../docs/adr/<redacted>.md)): the thirteen colours and the two font stacks of `theme.ui` (the fifteen host-overridable tokens, [ADR 0062 §3](../../../docs/adr/<redacted>.md) / [ADR 0196](../../../docs/adr/<redacted>.md)), a `DESIGN.md` of the look's derived recipes in the frontmatter shape the chrome world uses, and one specimen mock. **Never a fork of a sheet.** The drift tests already prove every served sheet reads only the contract, so a look that needs a sixteenth token is a contract change and an ADR, not a style.
3
+ A **look** is something a builder or an instance owner picks for a new surface or a whole instance. The library ships looks as **branding packs** ([task 1003323](https://cloudbongos.com/builders#/task/1003323), [ADR 0219](../../../docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md)): the thirteen colours and the two font stacks of `theme.ui` (the fifteen host-overridable tokens, [ADR 0062 §3](../../../docs/adr/0062-medusa-instance-model-decoupling.md) / [ADR 0196](../../../docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md)), a `DESIGN.md` of the look's derived recipes in the frontmatter shape the chrome world uses, and one specimen mock. **Never a fork of a sheet.** The drift tests already prove every served sheet reads only the contract, so a look that needs a sixteenth token is a contract change and an ADR, not a style.
4
4
 
5
5
  ## The catalogue
6
6
 
@@ -8,7 +8,7 @@ A **look** is something a builder or an instance owner picks for a new surface o
8
8
  |---|---|---|---|
9
9
  | `chrome-world` | the neutral pack, byte for byte | The canonical entry: one iridescent chrome sculpture in a black void, pale grey paper in light, one warm salmon that lights only the pressable and the live. Its recipes are the repo-root [`DESIGN.md`](../../../DESIGN.md); [`chrome-world/DESIGN.md`](chrome-world/DESIGN.md) points there. | the world round's pick (task 1003296 → 1003298) |
10
10
  | `expedition` | warm paper, lamp yellow, Archivo | A printed field journal: a halftone screen over the paper, hairline frames instead of a grid, big heavy uppercase headlines, the yellow as a fill only. [`expedition/DESIGN.md`](expedition/DESIGN.md) | `docs/design/mocks/world/natgeo-editorial` (kept in round 1) |
11
- | `blueprint` | cool grey-blue paper, cyanotype blue, slate green, IBM Plex Sans | A drafting table under north light: a faint graph lattice on the ground, compartments registered to the board with a crosshair tick at a 2px cut edge, the display voice in sentence case, every figure mono and tabular, one cyanotype blue on what is pressable, a slate green for what was measured and a rust pencil for what went wrong. The library's first cool look. [`blueprint/DESIGN.md`](blueprint/DESIGN.md) | authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/<redacted>.md)) |
11
+ | `blueprint` | cool grey-blue paper, cyanotype blue, slate green, IBM Plex Sans | A drafting table under north light: a faint graph lattice on the ground, compartments registered to the board with a crosshair tick at a 2px cut edge, the display voice in sentence case, every figure mono and tabular, one cyanotype blue on what is pressable, a slate green for what was measured and a rust pencil for what went wrong. The library's first cool look. [`blueprint/DESIGN.md`](blueprint/DESIGN.md) | authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) |
12
12
  | `grove` | pale sage, tan, sea green, Nunito | A sculpted paper garden: soft corners on everything that holds content, tinted shadows, the sea as a slab a whole band sits on, the tan as the one lit thing. [`grove/DESIGN.md`](grove/DESIGN.md) | `docs/design/mocks/world/organic-cards` (kept in round 1) |
13
13
 
14
14
  The owner looked at both alternates on the sheet on 2026-09-01 and kept them ("styles look good for a start"). Both alternates were **retuned against the contract**, which is a measurement and not a taste: a pack's thirteen are laid through three sheets that already exist (the landing's `world.css`, the hub's `cosmos.css`, the hall's `style.css`) and every pair those sheets paint must clear AA under it. The grove's sage ground lifted and its inks deepened until the hub's fixed status vocabulary and the hall's chips cleared; the expedition's `ink-faint` deepened one step. What a pack cannot carry is **dark**: the contract is light values only, and every sheet's dark tier is its own black, which a look reaches through its accent and its faces. So the grove's green dark ground stays in the world round's mock and does not travel.
@@ -51,7 +51,7 @@ SURFACE=modules/ui-design/styles/expedition STYLE=expedition node modules/ui-des
51
51
 
52
52
  ## Adding a look
53
53
 
54
- The steps below are the manual path. The **`/style` session** ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/<redacted>.md)) walks them with an owner instead: it renders the nearest entries before it asks anything, drafts inside the contract, retunes against the same measurements below with a failure-to-fix table, and hands over the one-step adoption without taking it. `blueprint` was authored that way.
54
+ The steps below are the manual path. The **`/style` session** ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) walks them with an owner instead: it renders the nearest entries before it asks anything, drafts inside the contract, retunes against the same measurements below with a failure-to-fix table, and hands over the one-step adoption without taking it. `blueprint` was authored that way.
55
55
 
56
56
  1. Make the dir with the three files; start from the alternate nearest to it.
57
57
  2. `node modules/ui-design/kit/contrast.js --pack <name>` until the floor is clean; then `node --test tests/ui_design_styles.mjs`, which runs the world / cosmos / hall suites under the pack and tells you the exact pair that fails. Tune the thirteen, never the sheets.
@@ -75,7 +75,7 @@ components:
75
75
 
76
76
  # Style: The Blueprint
77
77
 
78
- **Origin.** Authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../../docs/adr/<redacted>.md)) from a two-line brief: *"a drafting table under north light, cool paper and graphite; one cyanotype blue on what is pressable, a rust pencil for what went wrong."* The library's three existing looks are all warm and all carry a warm accent (salmon, lamp yellow, tan), so the search step found no near neighbour and the session drafted rather than adapted. The retune against the contract took one pass: the pack floor and all three token suites cleared on the first measurement, which is what a cool ground and a deep graphite ink buy you. The candidate's own dark ground does not travel, as with every look: a pack carries light values only.
78
+ **Origin.** Authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) from a two-line brief: *"a drafting table under north light, cool paper and graphite; one cyanotype blue on what is pressable, a rust pencil for what went wrong."* The library's three existing looks are all warm and all carry a warm accent (salmon, lamp yellow, tan), so the search step found no near neighbour and the session drafted rather than adapted. The retune against the contract took one pass: the pack floor and all three token suites cleared on the first measurement, which is what a cool ground and a deep graphite ink buy you. The candidate's own dark ground does not travel, as with every look: a pack carries light values only.
79
79
 
80
80
  ## Overview
81
81
 
@@ -30,7 +30,7 @@ rounded:
30
30
 
31
31
  # Style: The Chrome World (the canonical look)
32
32
 
33
- This is the look Cloud Bongos itself runs on and the **first entry** of the style library ([task 1003323](https://cloudbongos.com/builders#/task/1003323)). It is the canonical one in a precise sense: its `pack.json` is byte-for-byte the `theme.ui` block of [`config/branding.neutral.json`](../../../../config/branding.neutral.json), the neutral pack every instance resolves over, and its recipes are **not restated here**. The world's derived tiers, faces, materials, motion grammar, components, Do's and Don'ts and accessibility floors are the repo-root [`DESIGN.md`](../../../../DESIGN.md), recorded from the built landing ([ADR 0196](../../../../docs/adr/<redacted>.md)). Read that file; this one only holds the thirteen so the catalogue's lockstep test has something to hold.
33
+ This is the look Cloud Bongos itself runs on and the **first entry** of the style library ([task 1003323](https://cloudbongos.com/builders#/task/1003323)). It is the canonical one in a precise sense: its `pack.json` is byte-for-byte the `theme.ui` block of [`config/branding.neutral.json`](../../../../config/branding.neutral.json), the neutral pack every instance resolves over, and its recipes are **not restated here**. The world's derived tiers, faces, materials, motion grammar, components, Do's and Don'ts and accessibility floors are the repo-root [`DESIGN.md`](../../../../DESIGN.md), recorded from the built landing ([ADR 0196](../../../../docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md)). Read that file; this one only holds the thirteen so the catalogue's lockstep test has something to hold.
34
34
 
35
35
  ## What this entry is for
36
36
 
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.715",
3
+ "version": "1.19.724",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.715",
9
+ "version": "1.19.724",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.715",
3
+ "version": "1.19.724",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ // scripts/gds/audit-rank-roles.js — does the live builder roster hold ONLY the
3
+ // four live ranks? (task 1002873)
4
+ //
5
+ // WHY. `migrations/023`'s CHECK on `builders.rank` still admits twelve legacy
6
+ // values beyond the four live ranks. `governance_002_seed_and_backfill.sql`
7
+ // backfills roles with an INNER JOIN from `builders.rank` to the four seeded
8
+ // `governance_roles`, so a builder sitting on a legacy rank gets NO role row and
9
+ // resolves to ZERO permissions: admitted by threshold under `requireRank`, locked
10
+ // out of everything under the resolver. They are not told why, and nothing about
11
+ // their account looks wrong.
12
+ //
13
+ // That divergence is deliberate — ADR 0151 chose fail-closed, and
14
+ // `tests/governance_parity.mjs` asserts it is strictly a tightening. What was
15
+ // missing is the VERIFICATION. governance_002's comment says "none exist today —
16
+ // verified", a point-in-time manual check that nothing re-runs; the parity test
17
+ // is DB-free by necessity (the unit gate has no Postgres) and says so in the
18
+ // repo; and R114's live proof ran on a scratch DB holding only the four seeded
19
+ // rank-roles, so the production roster was never queried.
20
+ //
21
+ // THIS IS THE RE-RUNNABLE HALF, and it is deliberately NOT fatal at boot. Idea
22
+ // 1000622 records that trap: an assertion that throws on startup turns a data
23
+ // problem on one instance into an outage. This is a standalone read-only script
24
+ // for a nightly/deploy-time caller — it exits 1 so a caller can act, and nothing
25
+ // in the server's boot path requires it.
26
+ //
27
+ // It reports rather than repairs, and that is a decision, not an omission:
28
+ // rewriting somebody's rank is an authority change, and it belongs to an operator
29
+ // who can see who the account is — not to a sweep.
30
+ //
31
+ // node scripts/gds/audit-rank-roles.js [--json] [--file-idea]
32
+ //
33
+ // Exit codes:
34
+ // 0 every builder holds a live rank
35
+ // 1 at least one builder holds a rank the governance backfill cannot match
36
+ // 2 could not read the roster (no session / network / route absent)
37
+ //
38
+ // `--file-idea` is what makes this a SURFACE rather than another thing nobody
39
+ // runs — the same shape diagram-drift/check.js uses, spawning capture.js so idea
40
+ // filing has one implementation. Without it a nightly deterministic run that exits
41
+ // 1 reports into a log nobody reads, which is the exact criticism this task makes
42
+ // of the status quo.
43
+
44
+ const path = require('node:path');
45
+ const { spawnSync } = require('node:child_process');
46
+ const fs = require('node:fs');
47
+ const os = require('node:os');
48
+ const { cliClient, requireSession, cliExit } = require('./cli-lib');
49
+ const { LIVE_RANK_LADDER } = require('../../src/bongos/db-kernel.js');
50
+
51
+ // findRanksWithoutRoles — the PURE half. Given roster rows and the live ladder,
52
+ // which builders hold a rank that `governance_002`'s INNER JOIN cannot match?
53
+ //
54
+ // Pure + exported because this is the only altitude the repo can test: the unit
55
+ // gate has no Postgres, which is exactly why the gap this script closes went
56
+ // unverified for so long. A DB-free test of the decision is not a consolation
57
+ // prize here — it is the thing that can actually run in CI.
58
+ //
59
+ // A row with NO rank at all counts: NULL fails the INNER JOIN the same way a
60
+ // legacy value does, and reads as "fine" in every UI that renders a blank.
61
+ function findRanksWithoutRoles(rows, liveRanks = LIVE_RANK_LADDER) {
62
+ const live = new Set(liveRanks);
63
+ return (Array.isArray(rows) ? rows : [])
64
+ .filter((b) => b && !live.has(b.rank))
65
+ .map((b) => ({
66
+ id: b.id != null ? String(b.id) : null,
67
+ // The login is what an operator needs to act; it is already visible to any
68
+ // caller authorised to read the roster, so this adds no exposure.
69
+ github_login: b.github_login || null,
70
+ rank: b.rank === undefined ? null : b.rank,
71
+ status: b.status || null,
72
+ }));
73
+ }
74
+
75
+ // summarize — the rank histogram, so a CLEAN run still says what it looked at.
76
+ // A green check that prints nothing is indistinguishable from one that read
77
+ // nothing, which is the failure mode this whole task is about.
78
+ function summarize(rows) {
79
+ const counts = new Map();
80
+ for (const b of Array.isArray(rows) ? rows : []) {
81
+ const key = b && b.rank ? b.rank : '(none)';
82
+ counts.set(key, (counts.get(key) || 0) + 1);
83
+ }
84
+ return [...counts.entries()].sort((a, b) => b[1] - a[1]);
85
+ }
86
+
87
+ // Spawn capture.js rather than POSTing here, so idea filing keeps one
88
+ // implementation (the diagram-drift/check.js precedent). Best-effort: a failure to
89
+ // file must not turn a successful audit into a crash — the exit code and stdout
90
+ // still carry the finding.
91
+ function fileIdea(offenders) {
92
+ const body = [
93
+ `${offenders.length} builder(s) hold a rank with no matching governance_roles row.`,
94
+ '',
95
+ 'They resolve to ZERO permissions — admitted by rank threshold under requireRank,',
96
+ 'refused by the permission resolver, and given no reason (ADR 0151 fail-closed).',
97
+ '',
98
+ ...offenders.map((o) => `- builder ${o.id}${o.github_login ? ` (${o.github_login})` : ''} rank=${o.rank === null ? '(none)' : o.rank} status=${o.status || '?'}`),
99
+ '',
100
+ 'Fix: move each to a live rank through the normal rank-change path, which rotates',
101
+ 'the governance role in the same transaction. Not auto-repaired: changing a rank is',
102
+ 'an authority decision, and a sweep is the wrong actor for it.',
103
+ '',
104
+ 'Filed by scripts/gds/audit-rank-roles.js (task 1002873).',
105
+ ].join('\n');
106
+ const tmp = path.join(os.tmpdir(), `rank-roles-audit-${process.pid}.md`);
107
+ try {
108
+ fs.writeFileSync(tmp, body, 'utf8');
109
+ const r = spawnSync(
110
+ process.execPath,
111
+ [path.join(__dirname, 'capture.js'),
112
+ `[rank-roles] ${offenders.length} builder(s) on a rank with no governance role`,
113
+ '--kind', 'bug', '--body-file', tmp],
114
+ { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 60_000 }
115
+ );
116
+ if (r.status !== 0) console.error('audit-rank-roles: capture.js failed to file the idea — the exit code above still carries the finding.');
117
+ } catch (e) {
118
+ console.error(`audit-rank-roles: could not file the idea (${(e && e.message) || e}) — the exit code above still carries the finding.`);
119
+ } finally {
120
+ try { fs.rmSync(tmp, { force: true }); } catch (_) { /* best-effort */ }
121
+ }
122
+ }
123
+
124
+ async function main() {
125
+ const json = process.argv.includes('--json');
126
+ await requireSession();
127
+ const api = await cliClient();
128
+ const r = await api.request('GET', '/builders/roster');
129
+ if (!r.ok) {
130
+ console.error(`audit-rank-roles: could not read the roster (HTTP ${r.status}).`);
131
+ console.error(' Needs a session with builder.roster.read. Nothing was checked — do NOT read this as a pass.');
132
+ return cliExit(2);
133
+ }
134
+ // The roster query has no WHERE on `builders`, so this covers every row,
135
+ // INACTIVE ONES INCLUDED. That matters: a deactivated builder on a legacy rank
136
+ // is exactly the row a future CHECK-narrowing migration would fail to apply over.
137
+ const rows = (r.data && (r.data.builders || r.data.roster || r.data)) || [];
138
+ const offenders = findRanksWithoutRoles(rows);
139
+ const histogram = summarize(rows);
140
+
141
+ if (json) {
142
+ console.log(JSON.stringify({ checked: rows.length, live_ranks: LIVE_RANK_LADDER, histogram, offenders }, null, 2));
143
+ return cliExit(offenders.length ? 1 : 0);
144
+ }
145
+
146
+ console.log(`audit-rank-roles: ${rows.length} builder row(s) checked against the live ladder [${LIVE_RANK_LADDER.join(', ')}]`);
147
+ for (const [rank, n] of histogram) console.log(` ${String(rank).padEnd(12)} ${n}`);
148
+ if (!offenders.length) {
149
+ console.log('\n✓ every builder holds a live rank — the governance backfill can match all of them.');
150
+ return cliExit(0);
151
+ }
152
+ console.log(`\n✗ ${offenders.length} builder(s) hold a rank with no matching governance role.`);
153
+ console.log(' They resolve to ZERO permissions: admitted by rank threshold, refused by the resolver,');
154
+ console.log(' and nothing tells them why (ADR 0151 fail-closed).');
155
+ for (const o of offenders) {
156
+ console.log(` - builder ${o.id}${o.github_login ? ` (${o.github_login})` : ''} rank=${o.rank === null ? '(none)' : o.rank} status=${o.status || '?'}`);
157
+ }
158
+ console.log('\n This is a BUILDER NEED, not an outage: move each to a live rank with the normal');
159
+ console.log(' rank-change path so the governance role rotates in the same transaction.');
160
+ console.log(' Deliberately not repaired here — changing a rank is an authority decision.');
161
+ if (process.argv.includes('--file-idea')) fileIdea(offenders);
162
+ return cliExit(1);
163
+ }
164
+
165
+ if (require.main === module) {
166
+ main().catch((err) => {
167
+ console.error('audit-rank-roles:', (err && err.message) || err);
168
+ cliExit(2);
169
+ });
170
+ }
171
+
172
+ module.exports = { findRanksWithoutRoles, summarize };
@@ -64,6 +64,7 @@ const FILES = [
64
64
  'scripts/gds/recall.js',
65
65
  'scripts/gds/cost.js',
66
66
  'scripts/gds/release.js',
67
+ 'scripts/gds/worktree-claim-guard.js', // release.js warns through it; pure, zero requires
67
68
 
68
69
  // Get onto a real environment without installing one: the cloud dev box.
69
70
  'scripts/gds/shell.js',
@@ -10,7 +10,7 @@
10
10
  const { execSync } = require('node:child_process');
11
11
  const fs = require('node:fs');
12
12
  const path = require('node:path');
13
- const { cliClient, requireSession, fmtTouches, printOnboardingNudge, rewardPolicy, costPlusOnlyNote, detectWorktreeName } = require('./cli-lib');
13
+ const { cliClient, requireSession, fmtTouches, printOnboardingNudge, rewardPolicy, costPlusOnlyNote, detectWorktreeName, cliExit } = require('./cli-lib');
14
14
  const { nextNumbers, padAdr, padMig } = require('./next-number');
15
15
  const { CORE_NS } = require('./migration-namespace');
16
16
  const { contextPack, formatContextPack, resolveWorktreeRoot } = require('./context-pack');
@@ -147,10 +147,44 @@ function enforceWorktreeClaim(taskId, { allowMainCheckout }) {
147
147
  allowMainCheckout,
148
148
  taskId,
149
149
  });
150
- if (d.verdict === 'allow') return;
150
+ if (d.verdict === 'allow') return tree;
151
151
  for (const line of d.lines) console.error(line);
152
152
  if (d.verdict === 'refuse') process.exit(2);
153
153
  console.error('');
154
+ return tree;
155
+ }
156
+
157
+ // task 1002592 — a failed worktree DETECTION reaches the builder disguised as a
158
+ // claim CONFLICT, and that disguise is the whole of the original bug report.
159
+ // When detectWorktreeName() yields nothing the claim goes up with
160
+ // worktree_name: null; the server's one-active-claim guard keys on the WORKING
161
+ // TREE, so an unnamed claim falls back to the per-session compare and a
162
+ // genuinely-parallel worktree is refused as a duplicate. The builder then hunts
163
+ // for a claim conflict that does not exist.
164
+ //
165
+ // Only speak when null is WRONG. In the main checkout null is the documented
166
+ // correct answer and the refusal is genuine, so a note there would send the next
167
+ // reader down precisely the wrong path — that distinction is the fix, not a
168
+ // detail of it.
169
+ function worktreeDetectionNote(ctx, taskId) {
170
+ // The caller must have actually PROBED the tree. Without that this cannot tell
171
+ // "detection failed" from "nobody looked", and guessing would hang a worktree
172
+ // warning on every refusal rendered by a caller that never had tree info —
173
+ // including every pre-existing one. Absence of knowledge is not evidence.
174
+ if (!ctx || !('worktree' in ctx)) return [];
175
+ const { worktree, isMainCheckout } = ctx;
176
+ if (worktree) return []; // named fine — the refusal is genuine
177
+ if (isMainCheckout === true) return []; // null is correct here
178
+ const why = isMainCheckout === false
179
+ ? 'this IS a linked worktree, so a name was expected'
180
+ : 'this tree is not recognisable as the main checkout either';
181
+ return [
182
+ ` ⚠ This session could not name its worktree — auto-detect returned nothing, and ${why}.`,
183
+ ' An unnamed claim is compared per-SESSION instead of per-worktree, so a real parallel',
184
+ ' worktree is refused as a duplicate. That is very likely what you are looking at, and',
185
+ ' it is a path-detection problem, not a claim conflict. Name it explicitly to rule it out:',
186
+ ` node scripts/gds/claim.js ${taskId} --worktree <name>`,
187
+ ];
154
188
  }
155
189
 
156
190
  function captureHeadSha() {
@@ -247,7 +281,25 @@ function claimErrorInfo(r) {
247
281
  // string), so every branch below silently missed and the refusal printed as
248
282
  // `[object Object]`. Pure (no console / no process.exit) + exported so it can be
249
283
  // unit-tested against the real envelope shapes. Returns { lines, exit }.
250
- function formatClaimFailure(r, taskId) {
284
+ //
285
+ // task 1002592: server-supplied prose (a task title, a flag reason, a hint) is
286
+ // echoed to the operator's terminal by the branches below. It is our own API, so
287
+ // this is hygiene rather than a live threat — but an unbounded string can carry
288
+ // control characters that repaint a terminal, and a runaway one can bury the
289
+ // guidance it was meant to add. Clip to one line, strip C0/C1 controls, cap length.
290
+ const MAX_LISTED_TASKS = 20;
291
+ function clip(s, max = 160) {
292
+ if (s == null) return '';
293
+ // eslint-disable-next-line no-control-regex
294
+ const flat = String(s).replace(/[--Ÿ]+/g, ' ').trim();
295
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
296
+ }
297
+
298
+ // task 1002592: `ctx` carries what the CALLER knows about the tree
299
+ // ({ worktree, isMainCheckout }) so the session-claim branch can tell a real
300
+ // conflict apart from a failed worktree detection. Optional and defaulted — the
301
+ // function stays pure and every existing caller/test keeps working.
302
+ function formatClaimFailure(r, taskId, ctx) {
251
303
  const lines = [];
252
304
  const { code, message, d } = claimErrorInfo(r);
253
305
 
@@ -271,6 +323,7 @@ function formatClaimFailure(r, taskId) {
271
323
  ? `Run /builder-ship ${n} (or /builder-release ${n}) first, or open a fresh worktree/session for this task.`
272
324
  : 'Ship or release the in-flight claim, or start a fresh worktree/session.')}`);
273
325
  lines.push(' One claim per session keeps each ship isolated (task 1642). To work tasks in PARALLEL, open a separate worktree/session per task — each holds its own single claim — or use the hall work board’s multi-select bulk-claim.');
326
+ lines.push(...worktreeDetectionNote(ctx, taskId));
274
327
  return { lines, exit: 1 };
275
328
  }
276
329
  if (code === 'newcomer_must_ship_first') {
@@ -294,6 +347,26 @@ function formatClaimFailure(r, taskId) {
294
347
  lines.push(` ${d.what_to_do || `Run /builder-ship ${n || '<task>'} (or /builder-release ${n || '<task>'}) first, claim from a separate worktree, or claim with {"bind_session":false} (an unbound claim always coexists).`}`);
295
348
  return { lines, exit: 1 };
296
349
  }
350
+ // task 1002592: ADR 0120 part 3's owed-rebase gate refuses EVERY new claim, so
351
+ // it is the refusal a builder is most stuck behind — and it was the only one
352
+ // with no branch here, printing as a bare `[REBASE_REQUIRED]: REBASE_REQUIRED`
353
+ // code echo. The server builds a full way-forward menu for it
354
+ // (rebaseRequiredHint, task 1003768 — /strand-fix leads because it is the one
355
+ // exit that works with no GitHub push credential, the DOCUMENTED default
356
+ // posture) and this surface dropped it on the floor. Name the owed tasks, then
357
+ // print the server's menu.
358
+ if (code === 'REBASE_REQUIRED') {
359
+ const owed = (d.rebaseTasks || d.rebase_tasks || []).slice(0, MAX_LISTED_TASKS);
360
+ lines.push(owed.length
361
+ ? `Your queue is gated — ${owed.length} confirmed task(s) are waiting on your rebase:`
362
+ : 'Your queue is gated — a confirmed task is waiting on your rebase.');
363
+ for (const t of owed) {
364
+ lines.push(` - task ${t.id}${t.title ? ` ${clip(t.title)}` : ''}`);
365
+ if (t.reason) lines.push(` flagged: ${clip(t.reason)}`);
366
+ }
367
+ lines.push(` ${clip(d.hint, 600) || 'Clear it with /strand-fix N, or rebase the branch and re-ship — or /builder-release it to give up on one.'}`);
368
+ return { lines, exit: 1 };
369
+ }
297
370
  if (code === 'ALREADY_CLAIMED') {
298
371
  lines.push(`Task #${taskId} was just claimed by another session. Try a different task.`);
299
372
  return { lines, exit: 1 };
@@ -356,6 +429,11 @@ function formatClaimFailure(r, taskId) {
356
429
  }
357
430
  // Fallback — still readable: the message + code, never a raw [object Object].
358
431
  lines.push(`Claim failed (${r ? r.status : '?'})${code ? ` [${code}]` : ''}${message ? `: ${message}` : ''}.`);
432
+ // task 1002592: whatever the code, if the server sent a way forward, PRINT it.
433
+ // REBASE_REQUIRED sat in this fallback with a fully-formed hint in its body and
434
+ // nothing rendered it. The branches above stay the curated wording; this is the
435
+ // floor, so the next unmapped code can never be mute the same way.
436
+ if (d && d.hint) lines.push(` ${clip(d.hint, 600)}`);
359
437
  return { lines, exit: 1 };
360
438
  }
361
439
 
@@ -488,7 +566,7 @@ async function main() {
488
566
  // task 1002579: worktree-per-claim, enforced BEFORE anything happens — before
489
567
  // the session check, before the POST. The whole point is that the builder
490
568
  // learns at claim time, not from a stranded ship hours later.
491
- enforceWorktreeClaim(taskId, { allowMainCheckout: args.includes(ESCAPE_FLAG) });
569
+ const tree = enforceWorktreeClaim(taskId, { allowMainCheckout: args.includes(ESCAPE_FLAG) });
492
570
  await requireSession();
493
571
  const wIdx = args.indexOf('--worktree');
494
572
  // Explicit --worktree always wins; otherwise auto-detect a linked worktree so
@@ -527,7 +605,7 @@ async function main() {
527
605
  if (outcome === 'retry') {
528
606
  r = await postClaim();
529
607
  } else if (outcome === 'stop') {
530
- process.exit(1); // everything already printed; no claim landed
608
+ return cliExit(1); // everything already printed; no claim landed
531
609
  }
532
610
  }
533
611
  if (r.status === 201) {
@@ -651,9 +729,16 @@ async function main() {
651
729
  }
652
730
  // Any non-201 comes here. formatClaimFailure normalizes the R01 error envelope
653
731
  // and renders the refusal as guidance (task 1476) — one place, unit-tested.
654
- const failure = formatClaimFailure(r, taskId);
732
+ const failure = formatClaimFailure(r, taskId, {
733
+ worktree,
734
+ isMainCheckout: tree ? tree.isMainCheckout : null,
735
+ });
655
736
  for (const line of failure.lines) console.error(line);
656
- process.exit(failure.exit);
737
+ // task 1002592: this exit runs immediately after the claim request, which is
738
+ // exactly where Windows aborts teardown — "Assertion failed: !(handle->flags &
739
+ // UV_HANDLE_CLOSING)" — turning a refusal's intended exit 1 into 127. Measured
740
+ // 3/3 aborting before this change. Set the code, let the loop drain (1002734).
741
+ cliExit(failure.exit);
657
742
  }
658
743
 
659
744
  // Only auto-run when invoked directly (`node claim.js …`); a `require()` (the
@@ -661,8 +746,8 @@ async function main() {
661
746
  if (require.main === module) {
662
747
  main().catch((err) => {
663
748
  console.error('fatal:', err);
664
- process.exit(1);
749
+ cliExit(1);
665
750
  });
666
751
  }
667
752
 
668
- module.exports = { formatClaimFailure, claimErrorInfo, goalMembershipOfferPlan, materializeModeSkills };
753
+ module.exports = { formatClaimFailure, claimErrorInfo, goalMembershipOfferPlan, materializeModeSkills, worktreeDetectionNote };
@@ -520,17 +520,17 @@ const KERNEL_FILES = [
520
520
  // KERNEL (already in the module-scope-map kernel key) and imports only the
521
521
  // kernel (instance-config) + node built-ins, so it joins the roster cleanly.
522
522
  'src/bongos/repo-info.js',
523
- // task 1002331 (ADR 0182 D6 / ADR 0247): the project's composed join/apply door —
524
- // a deterministic classifier over three policy values, the same category as
523
+ // task 1002331 (ADR 0182 D6 / ADR 0247): the project's composed join/apply door — a
524
+ // deterministic classifier over three policy values, the same category as
525
525
  // route-rank-check.js and goal-scope-check.js above (a trust decision the doorway
526
526
  // hands to modules so no module re-derives it). The doorway re-exports it, so
527
527
  // leaving it off this roster reads as a kernel->non-kernel leak; it imports only
528
- // branding.js, instance-config.js and logger.js — all on this roster — so
529
- // joining costs nothing and buys the import-direction guarantee on the file that
530
- // decides who may knock. (Task 1003579 removed its require of auth-admission.js
531
- // and moved joinabilityMode the other way: the gate now reads the composed door,
532
- // so the reader had to sit with the composer or the two files would have cycled.)
533
- 'src/bongos/project-door.js',
528
+ // branding.js, instance-config.js and logger.js — all on this roster — so joining
529
+ // costs nothing and buys the import-direction guarantee on the file that decides
530
+ // who may knock. (Task 1003579 moved joinabilityMode the other way: the gate reads
531
+ // the composed door, so reader and composer had to sit together or the two would
532
+ // cycle.) The ARTIST GATE joins for the same reason task 1003575, ADR 0241.
533
+ 'src/bongos/project-door.js', 'src/bongos/artist-gate.js',
534
534
  ];
535
535
 
536
536
  // Kernel files exempt from the no-module-keys scan (Check 10) because naming a