@bongos/core 1.21.175 → 1.21.177

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 (1719) hide show
  1. package/.bongos-core.json +3371 -1636
  2. package/.claude/skills/ask-for-help/SKILL.md +4 -4
  3. package/.claude/skills/backlog-review/SKILL.md +1 -1
  4. package/.claude/skills/blocker-review/SKILL.md +2 -2
  5. package/.claude/skills/blocker-solve/SKILL.md +4 -4
  6. package/.claude/skills/bongos-feedback/SKILL.md +1 -1
  7. package/.claude/skills/bug-triage/SKILL.md +8 -8
  8. package/.claude/skills/builder-backup/SKILL.md +3 -3
  9. package/.claude/skills/builder-claim/SKILL.md +5 -5
  10. package/.claude/skills/builder-cost/SKILL.md +5 -5
  11. package/.claude/skills/builder-end/SKILL.md +6 -6
  12. package/.claude/skills/builder-exit/SKILL.md +2 -2
  13. package/.claude/skills/builder-key/SKILL.md +6 -6
  14. package/.claude/skills/builder-reauth/SKILL.md +4 -4
  15. package/.claude/skills/builder-redteam/SKILL.md +3 -3
  16. package/.claude/skills/builder-release/SKILL.md +3 -3
  17. package/.claude/skills/builder-sequence/SKILL.md +8 -8
  18. package/.claude/skills/builder-setup/SKILL.md +4 -4
  19. package/.claude/skills/builder-ship/SKILL.md +7 -7
  20. package/.claude/skills/builder-stage/SKILL.md +8 -8
  21. package/.claude/skills/builder-start/SKILL.md +4 -4
  22. package/.claude/skills/collab-review/SKILL.md +5 -5
  23. package/.claude/skills/design/SKILL.md +6 -4
  24. package/.claude/skills/design-sync/SKILL.md +3 -3
  25. package/.claude/skills/figma-design-sync/SKILL.md +4 -4
  26. package/.claude/skills/fix-task/SKILL.md +8 -8
  27. package/.claude/skills/goal-close/SKILL.md +9 -9
  28. package/.claude/skills/goal-create/SKILL.md +18 -18
  29. package/.claude/skills/grade-recover/SKILL.md +8 -8
  30. package/.claude/skills/grade-sweep/SKILL.md +15 -15
  31. package/.claude/skills/idea-triage/SKILL.md +15 -15
  32. package/.claude/skills/merge-mode/SKILL.md +14 -14
  33. package/.claude/skills/new-project/SKILL.md +5 -5
  34. package/.claude/skills/owner-review/SKILL.md +1 -1
  35. package/.claude/skills/planning-session/SKILL.md +15 -15
  36. package/.claude/skills/priority-session/SKILL.md +6 -6
  37. package/.claude/skills/read-session-export/SKILL.md +3 -3
  38. package/.claude/skills/recall/SKILL.md +7 -7
  39. package/.claude/skills/scan-before-install/SKILL.md +3 -3
  40. package/.claude/skills/session-handoff/SKILL.md +1 -1
  41. package/.claude/skills/ship-check/SKILL.md +3 -3
  42. package/.claude/skills/status/SKILL.md +3 -3
  43. package/.claude/skills/strand-fix/SKILL.md +6 -6
  44. package/.claude/skills/worktree-clean/SKILL.md +4 -4
  45. package/.gitattributes +12 -32
  46. package/GOVERNMENT.md +1 -1
  47. package/README.md +8 -8
  48. package/bin/bongos.js +23 -23
  49. package/clients/bongos-client/README.md +2 -2
  50. package/clients/bongos-client/bongos-client.global.js +22 -4
  51. package/clients/bongos-client/index.cjs +22 -4
  52. package/clients/bongos-client/index.d.ts +33 -4
  53. package/clients/bongos-client/index.mjs +21 -3
  54. package/config/branding.neutral.json +1 -1
  55. package/config/design-tokens.schema.json +1 -1
  56. package/config/modules.neutral.json +1 -3
  57. package/config/scheduled-routines.json +3 -8
  58. package/docs/adr/0029-status-page-outage-resilience.md +6 -6
  59. package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +1 -1
  60. package/docs/adr/0093-tranche-2-core-carve-sequence.md +1 -1
  61. package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
  62. package/docs/adr/0294-cli-sessions-do-not-expire.md +1 -1
  63. package/docs/adr/0383-sessions-end-after-ten-idle-days.md +35 -0
  64. package/docs/adr/0384-the-raise-page-is-a-hub-module-builders-edit-in-place.md +31 -0
  65. package/docs/adr/README.md +2 -0
  66. package/docs/api/openapi.json +606 -44
  67. package/docs/api-reference.md +25 -12
  68. package/docs/architecture.md +8 -7
  69. package/docs/canonical-permissions.md +4 -4
  70. package/docs/copy-inventory.md +1370 -1411
  71. package/docs/copy-registry.json +2136 -2536
  72. package/docs/design/demonolith-plan.md +6 -6
  73. package/docs/design/modular-architecture/00-research-report.md +1 -1
  74. package/docs/design/project-startup-direction.md +2 -2
  75. package/docs/design/projects-hub-direction-v2.md +1 -1
  76. package/docs/design/reviews/hall-v2/README.md +2 -2
  77. package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
  78. package/docs/file-map.md +92 -96
  79. package/docs/handoff-template.md +5 -5
  80. package/docs/module-api-changelog.md +7 -3
  81. package/docs/modules-contract.md +8 -7
  82. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +1 -1
  83. package/docs/onboarding/diagrams/02-rank-ladder.mmd +1 -1
  84. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +1 -1
  85. package/docs/onboarding/diagrams/04-architecture.mmd +1 -1
  86. package/docs/onboarding/diagrams/05-versioning.mmd +1 -1
  87. package/docs/onboarding/diagrams/README.md +5 -9
  88. package/docs/onboarding/diagrams/assertions.json +3 -3
  89. package/docs/onboarding/slash-commands.md +2 -2
  90. package/docs/packs/artist.md +4 -4
  91. package/docs/packs/engineer.md +11 -10
  92. package/docs/packs/ideator.md +7 -7
  93. package/docs/page-inventory.json +20 -1
  94. package/docs/page-readings.json +4387 -4603
  95. package/docs/recipes/README.md +1 -1
  96. package/docs/recipes/audit-replay.md +4 -4
  97. package/docs/recipes/autobongos-windows-host.md +6 -6
  98. package/docs/recipes/bongos-cli-release.md +2 -2
  99. package/docs/recipes/claude-design-loop.md +7 -7
  100. package/docs/recipes/core-release-pipeline.md +19 -19
  101. package/docs/recipes/failed-ship-recovery-proof.md +2 -2
  102. package/docs/recipes/figma-design-loop.md +6 -6
  103. package/docs/recipes/gds-db-backup.md +9 -9
  104. package/docs/recipes/instance-deploy.md +3 -3
  105. package/docs/recipes/instance-first-run.md +1 -1
  106. package/docs/recipes/multi-builder-merge.md +2 -2
  107. package/docs/recipes/ops-gotchas.md +13 -10
  108. package/docs/recipes/packaging-the-core.md +6 -6
  109. package/docs/recipes/parallel-goal-waves.md +4 -4
  110. package/docs/recipes/private-npm-distribution.md +9 -9
  111. package/docs/recipes/redteam-patrol.md +5 -5
  112. package/docs/recipes/render-pilot.md +2 -2
  113. package/docs/recipes/reranking-a-goals-board.md +2 -2
  114. package/docs/recipes/search-index-ingestion.md +5 -5
  115. package/docs/recipes/self-host.md +1 -1
  116. package/docs/recipes/ship-and-regrade.md +4 -4
  117. package/docs/recipes/staging-environment.md +1 -1
  118. package/docs/recipes/standalone-live-docs.md +1 -1
  119. package/docs/recipes/ui-look-before-you-ship.md +2 -2
  120. package/docs/recipes/upgrading-the-core.md +11 -11
  121. package/docs/recipes/windows-builders.md +18 -18
  122. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +6 -6
  123. package/docs/research/task-network-map-readability.md +3 -3
  124. package/migrations/core_278_builder_tester_tag.sql +18 -0
  125. package/migrations/core_279_bongos_shipper_new_scripts_path.sql +13 -0
  126. package/modules/agents/lib/answer-hold.js +1 -1
  127. package/modules/agents/lib/gate.js +1 -1
  128. package/modules/agents/lib/validate.js +1 -1
  129. package/modules/autonomy/db.js +9 -0
  130. package/modules/autonomy/gauge.js +1 -1
  131. package/modules/autonomy/governor-docket.js +2 -2
  132. package/modules/autonomy/module.json +2 -2
  133. package/modules/autonomy/pollers/daily-checks.js +262 -0
  134. package/modules/autonomy/pollers/routine-timers.js +9 -7
  135. package/modules/autonomy/rank-roles.js +64 -0
  136. package/modules/autonomy/routes/autonomy.js +3 -3
  137. package/modules/autonomy/server-schedule.js +37 -0
  138. package/modules/builder-settings/interaction-prefs.js +1 -1
  139. package/modules/builder-settings/render-prefs.js +1 -1
  140. package/modules/builder-settings/routes/settings.js +1 -1
  141. package/modules/builder-settings/skill-prefs.js +2 -2
  142. package/modules/builder-settings/wandering-prefs.js +2 -2
  143. package/modules/copy-desk/module.json +2 -2
  144. package/modules/copy-desk/page-data.js +5 -5
  145. package/modules/copy-desk/page-decisions.js +13 -1
  146. package/modules/copy-desk/proposals.js +4 -4
  147. package/modules/copy-desk/registry.js +2 -2
  148. package/modules/copy-desk/routes/copy-desk-release.js +119 -0
  149. package/modules/copy-desk/routes/copy-desk.js +3 -12
  150. package/modules/copy-desk/skills/tweak/SKILL.md +12 -12
  151. package/modules/copy-desk/tests/copy_flags.mjs +1 -1
  152. package/modules/copy-desk/tests/copy_no_cms.mjs +7 -3
  153. package/modules/copy-desk/tests/copy_proposals.mjs +2 -2
  154. package/modules/copy-desk/tests/copy_queue.mjs +1 -1
  155. package/modules/design-styles/skills/README.md +4 -4
  156. package/modules/design-styles/skills/imagegen-frontend-mobile/SKILL.md +1 -1
  157. package/modules/design-styles/skills/imagegen-frontend-web/SKILL.md +1 -1
  158. package/modules/discord/bug-attachments.js +1 -1
  159. package/modules/discord/ship-broadcast.js +1 -1
  160. package/modules/economy/achievements.js +49 -7
  161. package/modules/economy/cost-classify.js +6 -6
  162. package/modules/economy/cost-report.js +1 -1
  163. package/modules/economy/cost.js +1 -1
  164. package/modules/economy/credits.js +2 -1
  165. package/modules/economy/idea-size.js +2 -2
  166. package/modules/economy/reward.js +2 -0
  167. package/modules/economy/routes/cost.js +1 -1
  168. package/modules/economy/streak.js +43 -4
  169. package/modules/government/asks.js +1 -1
  170. package/modules/government/board.js +19 -2
  171. package/modules/government/catalog.js +3 -0
  172. package/modules/government/migrations/government_033_idea_vote.sql +46 -0
  173. package/modules/government/protected-surfaces.json +48 -47
  174. package/modules/government/recommendations.js +6 -2
  175. package/modules/government/routes/government.js +1 -1
  176. package/modules/grading/generated-provenance.js +13 -5
  177. package/modules/grading/grade-engine.js +1 -1
  178. package/modules/grading/grader-rubric.json +1 -1
  179. package/modules/grading/grader-score.js +1 -1
  180. package/modules/grading/grader-workers/index.js +1 -1
  181. package/modules/grading/grader.js +1 -1
  182. package/modules/grading/routes/grade.js +1 -1
  183. package/modules/hall-ui/public/atlas.html +5 -7
  184. package/modules/hall-ui/public/atlas.js +1 -1
  185. package/modules/hall-ui/public/atlas.states.json +1 -1
  186. package/modules/hall-ui/public/blockers.css +9 -0
  187. package/modules/hall-ui/public/blockers.html +4 -4
  188. package/modules/hall-ui/public/blockers.js +29 -30
  189. package/modules/hall-ui/public/board-room.css +5 -17
  190. package/modules/hall-ui/public/board-room.html +5 -6
  191. package/modules/hall-ui/public/board-room.js +41 -23
  192. package/modules/hall-ui/public/board-room.states.json +1 -1
  193. package/modules/hall-ui/public/brand-apply.js +1 -1
  194. package/modules/hall-ui/public/brand-holes.js +1 -1
  195. package/modules/hall-ui/public/builders.js +40 -86
  196. package/modules/hall-ui/public/city-decide.js +18 -4
  197. package/modules/hall-ui/public/city.html +1 -1
  198. package/modules/hall-ui/public/collab.html +1 -1
  199. package/modules/hall-ui/public/commands.html +6 -9
  200. package/modules/hall-ui/public/copy-desk.html +1 -1
  201. package/modules/hall-ui/public/copy-desk.js +2 -2
  202. package/modules/hall-ui/public/craft-mode.js +4 -0
  203. package/modules/hall-ui/public/deploy.html +6 -2
  204. package/modules/hall-ui/public/deploy.js +21 -13
  205. package/modules/hall-ui/public/diagrams.css +1 -1
  206. package/modules/hall-ui/public/diagrams.html +5 -8
  207. package/modules/hall-ui/public/diagrams.states.json +1 -1
  208. package/modules/hall-ui/public/drachmae.html +3 -7
  209. package/modules/hall-ui/public/fleet.html +3 -2
  210. package/modules/hall-ui/public/fleet.js +0 -4
  211. package/modules/hall-ui/public/gate.html +7 -7
  212. package/modules/hall-ui/public/gate.js +58 -77
  213. package/modules/hall-ui/public/goal-map.html +1 -1
  214. package/modules/hall-ui/public/goals-page.js +5 -5
  215. package/modules/hall-ui/public/goals-render.js +10 -11
  216. package/modules/hall-ui/public/goals.css +10 -0
  217. package/modules/hall-ui/public/goals.html +14 -7
  218. package/modules/hall-ui/public/government.html +3 -5
  219. package/modules/hall-ui/public/government.js +1 -5
  220. package/modules/hall-ui/public/hall-render.js +117 -57
  221. package/modules/hall-ui/public/hall-widgets.js +11 -11
  222. package/modules/hall-ui/public/idea.html +1 -1
  223. package/modules/hall-ui/public/ideas.html +3 -1
  224. package/modules/hall-ui/public/ideas.js +1 -0
  225. package/modules/hall-ui/public/index.html +12 -6
  226. package/modules/hall-ui/public/index.states.json +1 -1
  227. package/modules/hall-ui/public/mine-lens.js +1 -1
  228. package/modules/hall-ui/public/modules.html +7 -10
  229. package/modules/hall-ui/public/modules.js +0 -2
  230. package/modules/hall-ui/public/my-agents.html +1 -1
  231. package/modules/hall-ui/public/palette.js +5 -5
  232. package/modules/hall-ui/public/primer.html +4 -9
  233. package/modules/hall-ui/public/profile-connections.js +10 -2
  234. package/modules/hall-ui/public/profile-roles.js +3 -10
  235. package/modules/hall-ui/public/profile.html +12 -10
  236. package/modules/hall-ui/public/profile.js +13 -17
  237. package/modules/hall-ui/public/project-settings.html +3 -4
  238. package/modules/hall-ui/public/project-settings.js +0 -3
  239. package/modules/hall-ui/public/ranks.html +5 -11
  240. package/modules/hall-ui/public/ranks.js +6 -8
  241. package/modules/hall-ui/public/roadmap.css +0 -2
  242. package/modules/hall-ui/public/roadmap.html +1 -1
  243. package/modules/hall-ui/public/roadmap.js +16 -51
  244. package/modules/hall-ui/public/roster.html +1 -1
  245. package/modules/hall-ui/public/sessions.html +6 -8
  246. package/modules/hall-ui/public/sessions.js +7 -7
  247. package/modules/hall-ui/public/settings.html +1 -1
  248. package/modules/hall-ui/public/shell-trail.js +1 -1
  249. package/modules/hall-ui/public/shell.js +17 -17
  250. package/modules/hall-ui/public/street-deck.css +2 -1
  251. package/modules/hall-ui/public/street-deck.js +10 -2
  252. package/modules/hall-ui/public/street-desk.js +16 -5
  253. package/modules/hall-ui/public/street.html +1 -1
  254. package/modules/hall-ui/public/studio-lib.js +4 -0
  255. package/modules/hall-ui/public/studio.css +2 -0
  256. package/modules/hall-ui/public/studio.html +1 -1
  257. package/modules/hall-ui/public/studio.js +27 -1
  258. package/modules/hall-ui/public/style.css +43 -26
  259. package/modules/hall-ui/public/task-detail.js +10 -7
  260. package/modules/hall-ui/public/task.css +2 -0
  261. package/modules/hall-ui/public/task.html +3 -1
  262. package/modules/hall-ui/public/task.js +23 -7
  263. package/modules/hall-ui/public/thinking.html +1 -1
  264. package/modules/hall-ui/public/tweak-editor.html +1 -1
  265. package/modules/hall-ui/public/vote-control.js +208 -0
  266. package/modules/hall-ui/public/watch.html +3 -5
  267. package/modules/hall-ui/public/watch.js +5 -4
  268. package/modules/hall-ui/public/welcome-boot.css +130 -0
  269. package/modules/hall-ui/public/welcome-boot.js +334 -0
  270. package/modules/hall-ui/public/welcome-day.webp +0 -0
  271. package/modules/hall-ui/public/welcome-night.webp +0 -0
  272. package/modules/hall-ui/public/work-summary.js +1 -1
  273. package/modules/hall-ui/public/work.css +1 -0
  274. package/modules/hall-ui/public/work.html +3 -1
  275. package/modules/hall-ui/public/work.js +2 -1
  276. package/modules/hall-ui/records/accomplishments.md +16 -0
  277. package/modules/hall-ui/records/hall-ask-card.md +9 -0
  278. package/modules/hall-ui/records/karma-vote-control.md +13 -0
  279. package/modules/hall-ui/records/oversight-family.md +1 -1
  280. package/modules/hall-ui/records/profile-connections.md +2 -0
  281. package/modules/hall-ui/records/profile-roles.md +1 -1
  282. package/modules/hall-ui/records/reading-rooms.md +1 -1
  283. package/modules/hall-ui/records/welcome-tower.md +50 -0
  284. package/modules/ideas/migrations/ideas_011_idea_votes.sql +31 -0
  285. package/modules/ideas/projection.js +1 -1
  286. package/modules/ideas/routes/blockers.js +3 -3
  287. package/modules/ideas/routes/inbox.js +29 -1
  288. package/modules/ideas/routes/ratify-goal.js +1 -1
  289. package/modules/ideas/routing.js +1 -1
  290. package/modules/ideas/templates.js +1 -1
  291. package/modules/ideas/trail-descent.js +1 -1
  292. package/modules/ideas/trail-size.js +1 -1
  293. package/modules/ideas/votes.js +93 -0
  294. package/modules/lifecycle/abandon-leftovers.js +1 -1
  295. package/modules/lifecycle/cascade.js +1 -1
  296. package/modules/lifecycle/conflict-resolve.js +13 -21
  297. package/modules/lifecycle/criterion-ref.js +1 -1
  298. package/modules/lifecycle/db-analytics.js +57 -4
  299. package/modules/lifecycle/db-deps-criteria.js +1 -1
  300. package/modules/lifecycle/db-ship.js +2 -2
  301. package/modules/lifecycle/db-tasks.js +2 -2
  302. package/modules/lifecycle/db-versions.js +1 -1
  303. package/modules/lifecycle/db.js +2 -0
  304. package/modules/lifecycle/dead-deps.js +3 -3
  305. package/modules/lifecycle/dependency-advisory.js +3 -3
  306. package/modules/lifecycle/goal-category.js +1 -1
  307. package/modules/lifecycle/goal-forest.js +1 -1
  308. package/modules/lifecycle/goal-task-relevance-advisory.js +1 -1
  309. package/modules/lifecycle/kickoff-checklist.js +1 -1
  310. package/modules/lifecycle/kickoff-seed.js +1 -1
  311. package/modules/lifecycle/lifecycle.js +2 -0
  312. package/modules/lifecycle/merge-reach.js +29 -15
  313. package/modules/lifecycle/missing-dep-classify.js +3 -3
  314. package/modules/lifecycle/module.json +2 -1
  315. package/modules/lifecycle/page-tweak-approve.js +85 -1
  316. package/modules/lifecycle/page-tweak-hold.js +1 -1
  317. package/modules/lifecycle/publish-reconciler.js +1 -2
  318. package/modules/lifecycle/rot.js +1 -1
  319. package/modules/lifecycle/routes/artist-gate.js +1 -1
  320. package/modules/lifecycle/routes/gate-approvals.js +22 -1
  321. package/modules/lifecycle/routes/goals.js +1 -1
  322. package/modules/lifecycle/routes/task-route-helpers.js +1 -1
  323. package/modules/lifecycle/routes/task-votes.js +54 -0
  324. package/modules/lifecycle/routes/task-write-routes.js +1 -1
  325. package/modules/lifecycle/routes/tasks.js +2 -2
  326. package/modules/lifecycle/routes/versions.js +2 -2
  327. package/modules/lifecycle/ship-card.js +4 -4
  328. package/modules/lifecycle/ship-preflight.js +1 -1
  329. package/modules/lifecycle/task-classifier.js +1 -1
  330. package/modules/lifecycle/task-status.js +1 -1
  331. package/modules/lifecycle/task-visual-db.js +1 -1
  332. package/modules/memory/learnings.js +1 -1
  333. package/modules/memory/pollers/search-index.js +2 -2
  334. package/modules/memory/routes/learnings.js +1 -1
  335. package/modules/memory/routes/memory.js +1 -1
  336. package/modules/memory/search.js +2 -2
  337. package/modules/npm-release/release.js +1 -1
  338. package/modules/onboarding/howto-moments.js +1 -1
  339. package/modules/onboarding/newcomer-restock.js +3 -3
  340. package/modules/onboarding/onboarding.js +1 -1
  341. package/modules/pixel-art/skills/otb-tile-generate/SKILL.md +1 -1
  342. package/modules/platform-identity/origin-containment.js +1 -1
  343. package/modules/platform-identity/publish-gate.js +1 -1
  344. package/modules/platform-identity/tests/platform-identity.mjs +1 -1
  345. package/modules/provisioning/capacity.js +1 -1
  346. package/modules/provisioning/core-upgrade.js +15 -9
  347. package/modules/provisioning/credential-preflight.js +3 -3
  348. package/modules/provisioning/disconnect.js +1 -1
  349. package/modules/provisioning/dns-resolves.js +1 -1
  350. package/modules/provisioning/module.json +1 -1
  351. package/modules/provisioning/onboard-plan.js +1 -1
  352. package/modules/provisioning/paid-shape-gate.js +2 -2
  353. package/modules/provisioning/planet-physics.js +11 -2
  354. package/modules/provisioning/pollers/liveness-sweep.js +1 -1
  355. package/modules/provisioning/pollers/runner-drift-notify.js +5 -5
  356. package/modules/provisioning/provisioning.js +2 -2
  357. package/modules/provisioning/render-lookup.js +1 -1
  358. package/modules/provisioning/render-standup.js +3 -3
  359. package/modules/provisioning/repo-private.js +1 -1
  360. package/modules/provisioning/routes/callback-page.js +1 -1
  361. package/modules/provisioning/routes/core-upgrade.js +23 -3
  362. package/modules/provisioning/routes/provisioning.js +2 -2
  363. package/modules/provisioning/routes/render-standup.js +1 -1
  364. package/modules/provisioning/routes/repo-private.js +1 -1
  365. package/modules/provisioning/soft-limits.js +1 -1
  366. package/modules/provisioning/starter-bundles.js +4 -2
  367. package/modules/provisioning/tests/provisioning.mjs +1 -1
  368. package/modules/public-landing/public/account.html +4 -6
  369. package/modules/public-landing/public/assets/cosmos.css +13 -6
  370. package/modules/public-landing/public/connections.html +4 -6
  371. package/modules/public-landing/public/contact.html +4 -6
  372. package/modules/public-landing/public/guild.html +4 -6
  373. package/modules/public-landing/public/index.html +11 -9
  374. package/modules/public-landing/public/invitations.html +4 -6
  375. package/modules/public-landing/public/privacy.html +4 -6
  376. package/modules/public-landing/public/projects.html +168 -46
  377. package/modules/public-landing/public/terms.html +4 -6
  378. package/modules/raise/content/copy.json +40 -0
  379. package/modules/raise/content/nda.html +39 -0
  380. package/modules/raise/content/settings.json +49 -0
  381. package/modules/raise/db.js +95 -0
  382. package/modules/raise/migrations/raise_001_tables.sql +71 -0
  383. package/modules/raise/module.json +28 -0
  384. package/modules/raise/page.js +194 -0
  385. package/modules/raise/public/edit.js +152 -0
  386. package/modules/raise/public/favicon.svg +1 -0
  387. package/modules/raise/public/logo-ink.svg +1 -0
  388. package/modules/raise/public/logo-night.svg +1 -0
  389. package/modules/raise/public/mode.js +8 -0
  390. package/modules/raise/public/raise.css +234 -0
  391. package/modules/raise/public/raise.js +91 -0
  392. package/modules/raise/raise.js +174 -0
  393. package/modules/raise/routes/raise.js +152 -0
  394. package/modules/raise/views/gate.html +39 -0
  395. package/modules/raise/views/nda.html +21 -0
  396. package/modules/raise/views/page.html +133 -0
  397. package/modules/raise/web.js +72 -0
  398. package/modules/render-deploy/deploys.js +1 -1
  399. package/modules/render-deploy/render.js +2 -2
  400. package/modules/security/secret-scrub.js +3 -3
  401. package/modules/security/security.js +1 -1
  402. package/modules/security/tests/artifact_scan.mjs +1 -1
  403. package/modules/security/tests/mirror.mjs +1 -1
  404. package/modules/security/tests/scan_store.mjs +1 -1
  405. package/modules/sessions/db.js +2 -2
  406. package/modules/sessions/pulse.js +2 -2
  407. package/modules/sessions/routes/sessions.js +1 -1
  408. package/modules/specialities/specialities.js +1 -1
  409. package/modules/status-ui/public/README.md +3 -4
  410. package/modules/status-ui/public/index.html +5 -31
  411. package/modules/status-ui/public/status.js +6 -174
  412. package/modules/status-ui/public/style.css +4 -133
  413. package/modules/ui-design/docs/design-contract.md +3 -3
  414. package/modules/ui-design/kit/README.md +1 -1
  415. package/modules/ui-design/kit/serve.js +13 -4
  416. package/modules/ui-design/scripts/design-sync.js +1 -1
  417. package/modules/ui-design/scripts/figma-design-sync.js +1 -1
  418. package/modules/ui-design/scripts/validate-design.js +1 -1
  419. package/package-lock.json +27 -11
  420. package/package.json +2 -3
  421. package/release-notes.json +186 -0
  422. package/scripts/bongos/CLAUDE.md +15 -0
  423. package/scripts/bongos/abandon.js +137 -0
  424. package/scripts/bongos/accessibility-replay.js +195 -0
  425. package/scripts/bongos/address-park-sweep.sh +91 -0
  426. package/scripts/bongos/adopt-detect.js +123 -0
  427. package/scripts/bongos/adopt-import.js +111 -0
  428. package/scripts/bongos/adopt-preflight.js +187 -0
  429. package/scripts/bongos/adr-namespace.js +273 -0
  430. package/scripts/bongos/agent-invoke.js +689 -0
  431. package/scripts/bongos/agents-sync.js +502 -0
  432. package/scripts/bongos/api-alias-caller-scan.js +256 -0
  433. package/scripts/bongos/api-artifacts.js +91 -0
  434. package/scripts/bongos/api.js +86 -0
  435. package/scripts/bongos/api.ps1 +26 -0
  436. package/scripts/bongos/architect-audit.js +294 -0
  437. package/scripts/bongos/artifact-audit.js +326 -0
  438. package/scripts/bongos/artifact-format.js +203 -0
  439. package/scripts/bongos/ask.js +231 -0
  440. package/scripts/bongos/audit-authorship.sh +324 -0
  441. package/scripts/bongos/audit-deps.js +189 -0
  442. package/scripts/bongos/audit-gate.js +121 -0
  443. package/scripts/bongos/audit-rank-roles.js +131 -0
  444. package/scripts/bongos/audit-replay.sh +205 -0
  445. package/scripts/bongos/autobongos-digest.js +123 -0
  446. package/scripts/bongos/autobongos-grade-cap.js +187 -0
  447. package/scripts/bongos/autobongos-loop.js +210 -0
  448. package/scripts/bongos/autobongos-run.js +1361 -0
  449. package/scripts/bongos/autobongos-service.cmd +50 -0
  450. package/scripts/bongos/autobongos-service.ps1 +270 -0
  451. package/scripts/bongos/autobongos-tweak-lane.js +262 -0
  452. package/scripts/bongos/autobongos-verify.js +618 -0
  453. package/scripts/bongos/autonomy-gate.js +135 -0
  454. package/scripts/bongos/autonomy-gauge-statusline.js +124 -0
  455. package/scripts/bongos/autonomy-gauge.js +84 -0
  456. package/scripts/bongos/backfill-cost.js +176 -0
  457. package/scripts/bongos/backfill-disciplines.js +144 -0
  458. package/scripts/bongos/backfill-session-earnings.js +123 -0
  459. package/scripts/bongos/backfill-session-types.js +87 -0
  460. package/scripts/bongos/backfill-sessions.js +411 -0
  461. package/scripts/bongos/backfill-subagent-rewards.js +485 -0
  462. package/scripts/bongos/backfill-task-rewards.js +413 -0
  463. package/scripts/bongos/backlog-review.js +399 -0
  464. package/scripts/bongos/backup-dropin-sweep.sh +95 -0
  465. package/scripts/bongos/backup.js +116 -0
  466. package/scripts/bongos/baseline-staleness.js +217 -0
  467. package/scripts/bongos/bfg-principal-token.js +65 -0
  468. package/scripts/bongos/bug-attachment-audit.js +149 -0
  469. package/scripts/bongos/bug-attachment-recover.js +198 -0
  470. package/scripts/bongos/bug-triage.js +292 -0
  471. package/scripts/bongos/build-bongos.js +94 -0
  472. package/scripts/bongos/bump-version.js +221 -0
  473. package/scripts/bongos/capture.js +481 -0
  474. package/scripts/bongos/category-advisory-guard.js +206 -0
  475. package/scripts/bongos/ci-grade.js +82 -0
  476. package/scripts/bongos/claim-recall.js +112 -0
  477. package/scripts/bongos/claim.js +789 -0
  478. package/scripts/bongos/claude-materialize.js +1200 -0
  479. package/scripts/bongos/claude-md-template.js +142 -0
  480. package/scripts/bongos/cleanup-orphans.js +74 -0
  481. package/scripts/bongos/cli-lib.js +1226 -0
  482. package/scripts/bongos/client-baseurl-guard.js +116 -0
  483. package/scripts/bongos/codemod-rename-scripts-gds.js +380 -0
  484. package/scripts/bongos/conductor-dispatch.js +535 -0
  485. package/scripts/bongos/context-pack.js +326 -0
  486. package/scripts/bongos/control-manifest.js +199 -0
  487. package/scripts/bongos/copy-apply.js +758 -0
  488. package/scripts/bongos/copy-inventory.js +571 -0
  489. package/scripts/bongos/core-origin-follow.js +185 -0
  490. package/scripts/bongos/core-pin-sync.js +260 -0
  491. package/scripts/bongos/cost-report.js +63 -0
  492. package/scripts/bongos/cost.js +47 -0
  493. package/scripts/bongos/credential-presence.js +296 -0
  494. package/scripts/bongos/cutover-codemod.js +240 -0
  495. package/scripts/bongos/db-backup-nightly.sh +232 -0
  496. package/scripts/bongos/db-backup-offsite.sh +267 -0
  497. package/scripts/bongos/demote.js +45 -0
  498. package/scripts/bongos/deploy-divergence.js +454 -0
  499. package/scripts/bongos/deploy-main-audit-gate.sh +97 -0
  500. package/scripts/bongos/design-sync.js +12 -0
  501. package/scripts/bongos/dev-box-guard.js +166 -0
  502. package/scripts/bongos/dev-lib.js +722 -0
  503. package/scripts/bongos/dev.js +645 -0
  504. package/scripts/bongos/device-flow-help.js +72 -0
  505. package/scripts/bongos/diagnose-achievements.js +118 -0
  506. package/scripts/bongos/diagram-facts.js +355 -0
  507. package/scripts/bongos/discord-channels.js +77 -0
  508. package/scripts/bongos/do-api.js +109 -0
  509. package/scripts/bongos/doc-cli-guard.js +274 -0
  510. package/scripts/bongos/doc-comment-coverage.js +139 -0
  511. package/scripts/bongos/doc-control-claims.js +170 -0
  512. package/scripts/bongos/docs-entropy.js +453 -0
  513. package/scripts/bongos/doctor.js +493 -0
  514. package/scripts/bongos/enroll-control-plane.js +101 -0
  515. package/scripts/bongos/exec-path-guard.js +564 -0
  516. package/scripts/bongos/feedback-send.js +249 -0
  517. package/scripts/bongos/fetch-art-key.js +106 -0
  518. package/scripts/bongos/fetch-sound-prefs.js +126 -0
  519. package/scripts/bongos/figma-design-sync.js +11 -0
  520. package/scripts/bongos/find-untested.js +371 -0
  521. package/scripts/bongos/fitness-checks-error-envelope.js +134 -0
  522. package/scripts/bongos/fitness-checks-identity.js +332 -0
  523. package/scripts/bongos/fitness-checks-packaging.js +132 -0
  524. package/scripts/bongos/fitness-checks-route-pins.js +76 -0
  525. package/scripts/bongos/fitness-checks-vocabulary.js +392 -0
  526. package/scripts/bongos/fitness-checks-write-validation.js +157 -0
  527. package/scripts/bongos/fitness-lib.js +127 -0
  528. package/scripts/bongos/fitness-migration-contraction.js +50 -0
  529. package/scripts/bongos/fitness-ratchets.js +594 -0
  530. package/scripts/bongos/fitness.js +1498 -0
  531. package/scripts/bongos/forwarder.js +80 -0
  532. package/scripts/bongos/gate-review.js +330 -0
  533. package/scripts/bongos/gating.js +348 -0
  534. package/scripts/{gds → bongos}/gds-db-backup.service +6 -6
  535. package/scripts/{gds → bongos}/gds-db-backup.timer +4 -4
  536. package/scripts/{gds → bongos}/gds-db-offsite.service +4 -4
  537. package/scripts/{gds → bongos}/gds-db-offsite.timer +4 -4
  538. package/scripts/bongos/gds-literal-scan.js +196 -0
  539. package/scripts/bongos/gen-api-client.js +576 -0
  540. package/scripts/bongos/gen-api-docs.js +1111 -0
  541. package/scripts/bongos/gen-atlas.js +366 -0
  542. package/scripts/bongos/gen-diagrams.js +608 -0
  543. package/scripts/bongos/gen-file-map.js +337 -0
  544. package/scripts/bongos/gen-freshness.js +32 -0
  545. package/scripts/bongos/gen-interaction-posture.js +122 -0
  546. package/scripts/bongos/gen-repo-map.js +540 -0
  547. package/scripts/bongos/gen-role-responsibilities.js +134 -0
  548. package/scripts/bongos/gen-session-index.js +243 -0
  549. package/scripts/bongos/gen-sounds.js +176 -0
  550. package/scripts/bongos/git-merge-regen.js +254 -0
  551. package/scripts/bongos/go-live.js +1071 -0
  552. package/scripts/bongos/goal.js +272 -0
  553. package/scripts/bongos/government-walk.js +1477 -0
  554. package/scripts/bongos/grade-correlation-audit.js +310 -0
  555. package/scripts/bongos/grade-replay.js +237 -0
  556. package/scripts/bongos/grade-smoke.js +205 -0
  557. package/scripts/bongos/home-isolation-guard.js +126 -0
  558. package/scripts/bongos/hooks/pre-push.js +211 -0
  559. package/scripts/bongos/howto.js +145 -0
  560. package/scripts/bongos/http-api-client.js +81 -0
  561. package/scripts/bongos/identity-strip.js +75 -0
  562. package/scripts/bongos/init.js +1159 -0
  563. package/scripts/bongos/install-git-hooks.js +200 -0
  564. package/scripts/bongos/instance-apex.js +38 -0
  565. package/scripts/bongos/intent-retry.js +52 -0
  566. package/scripts/bongos/key-card.js +222 -0
  567. package/scripts/bongos/key-status.js +126 -0
  568. package/scripts/bongos/land-watch.js +201 -0
  569. package/scripts/bongos/leak-scan-allowlist.js +293 -0
  570. package/scripts/bongos/learning-capture.js +145 -0
  571. package/scripts/bongos/lib.sh +74 -0
  572. package/scripts/bongos/linkify-refs.js +655 -0
  573. package/scripts/bongos/lint-infra-exec.js +70 -0
  574. package/scripts/bongos/lint-migrations.js +102 -0
  575. package/scripts/bongos/lint-workflow-exec.js +63 -0
  576. package/scripts/bongos/local-preview-lib.js +128 -0
  577. package/scripts/bongos/local-preview.js +82 -0
  578. package/scripts/bongos/login.js +360 -0
  579. package/scripts/bongos/main-audit.js +625 -0
  580. package/scripts/bongos/me.js +97 -0
  581. package/scripts/bongos/memory-map.js +176 -0
  582. package/scripts/bongos/merge-lock.js +71 -0
  583. package/scripts/bongos/migration-namespace.js +313 -0
  584. package/scripts/bongos/mirror-lineage-check.js +343 -0
  585. package/scripts/bongos/mirror-redact.js +350 -0
  586. package/scripts/bongos/module-artifact.js +289 -0
  587. package/scripts/bongos/module-assess-docs.js +238 -0
  588. package/scripts/bongos/module-assess-installs.js +228 -0
  589. package/scripts/bongos/module-assess-score.js +111 -0
  590. package/scripts/bongos/module-assess-security.js +252 -0
  591. package/scripts/bongos/module-assess-tests.js +278 -0
  592. package/scripts/bongos/module-assess-version.js +92 -0
  593. package/scripts/bongos/module-error-report.js +148 -0
  594. package/scripts/{gds → bongos}/module-test-runner/README.md +3 -3
  595. package/scripts/{gds → bongos}/module-test-runner/module-tests.yml +2 -2
  596. package/scripts/bongos/module-test-runner.js +414 -0
  597. package/scripts/bongos/module.js +1376 -0
  598. package/scripts/bongos/move-escalation.js +141 -0
  599. package/scripts/{gds → bongos}/newcomer-floor.config.json +1 -1
  600. package/scripts/bongos/newcomer-floor.js +421 -0
  601. package/scripts/{gds → bongos}/newcomer-floor.templates.json +13 -13
  602. package/scripts/bongos/newcomer-floor.test.js +235 -0
  603. package/scripts/bongos/next-number.js +163 -0
  604. package/scripts/bongos/oauth-secret.js +202 -0
  605. package/scripts/bongos/onboard.js +267 -0
  606. package/scripts/bongos/onboarding-analyze.js +226 -0
  607. package/scripts/bongos/onboarding-config.js +179 -0
  608. package/scripts/bongos/onboarding-ship.js +92 -0
  609. package/scripts/bongos/pack-env-prefix.js +73 -0
  610. package/scripts/bongos/package-core.js +1200 -0
  611. package/scripts/bongos/page-inventory.js +348 -0
  612. package/scripts/bongos/page-reader.js +722 -0
  613. package/scripts/bongos/paste-token.js +212 -0
  614. package/scripts/bongos/plain-cards.js +351 -0
  615. package/scripts/bongos/portability-smoke-art.sh +85 -0
  616. package/scripts/bongos/portability-smoke-memory.sh +176 -0
  617. package/scripts/bongos/preflight.js +214 -0
  618. package/scripts/bongos/probe-cache.js +246 -0
  619. package/scripts/bongos/prove-strict-versioning.js +284 -0
  620. package/scripts/bongos/provision-auto-upgrade.js +162 -0
  621. package/scripts/bongos/provision-byo-host.js +68 -0
  622. package/scripts/bongos/provision-capacity.js +79 -0
  623. package/scripts/bongos/provision-caps.js +63 -0
  624. package/scripts/bongos/provision-config.js +233 -0
  625. package/scripts/bongos/provision-core-upgrade.js +1166 -0
  626. package/scripts/bongos/provision-disconnect.js +88 -0
  627. package/scripts/bongos/provision-github-setup.js +168 -0
  628. package/scripts/bongos/provision-net.js +357 -0
  629. package/scripts/bongos/provision-pin-key.js +176 -0
  630. package/scripts/bongos/provision-pin-replay.js +126 -0
  631. package/scripts/bongos/provision-process.js +170 -0
  632. package/scripts/bongos/provision-render.js +201 -0
  633. package/scripts/bongos/provision-repo-auth.js +164 -0
  634. package/scripts/bongos/provision-repo-private.js +98 -0
  635. package/scripts/bongos/provision-repo.js +1337 -0
  636. package/scripts/bongos/provision-teardown.js +106 -0
  637. package/scripts/bongos/provision-units.js +469 -0
  638. package/scripts/bongos/provision.js +1479 -0
  639. package/scripts/bongos/publish-credential-check.js +66 -0
  640. package/scripts/bongos/publish-integration-gate.js +142 -0
  641. package/scripts/bongos/publish-manifest.js +440 -0
  642. package/scripts/bongos/publish-watch.js +268 -0
  643. package/scripts/bongos/pulse.js +338 -0
  644. package/scripts/bongos/push-main.js +56 -0
  645. package/scripts/bongos/push-path-brief.js +100 -0
  646. package/scripts/bongos/read-session-export.js +359 -0
  647. package/scripts/bongos/reauth.js +155 -0
  648. package/scripts/bongos/recall.js +183 -0
  649. package/scripts/bongos/redteam-patrol.js +437 -0
  650. package/scripts/bongos/regen-instance-docs.js +47 -0
  651. package/scripts/bongos/release-core.js +80 -0
  652. package/scripts/bongos/release-notes.js +271 -0
  653. package/scripts/bongos/release.js +139 -0
  654. package/scripts/bongos/rename-history-check.js +369 -0
  655. package/scripts/bongos/rename-ledger-prose.js +482 -0
  656. package/scripts/bongos/render-api.js +197 -0
  657. package/scripts/bongos/render-check.js +206 -0
  658. package/scripts/bongos/render-ideas.js +226 -0
  659. package/scripts/bongos/render-payload.js +85 -0
  660. package/scripts/bongos/repo-metrics.js +363 -0
  661. package/scripts/bongos/review-sheet.js +108 -0
  662. package/scripts/bongos/role-pack-guard.js +142 -0
  663. package/scripts/bongos/route-shadow-guard.js +175 -0
  664. package/scripts/bongos/routine-schedule.js +318 -0
  665. package/scripts/bongos/run-routine.js +257 -0
  666. package/scripts/bongos/run-unit-tests.js +654 -0
  667. package/scripts/bongos/runner-drift.js +151 -0
  668. package/scripts/bongos/sandbox-stage.js +459 -0
  669. package/scripts/bongos/scope-map-guard.js +300 -0
  670. package/scripts/bongos/scope-roster-guard.js +118 -0
  671. package/scripts/bongos/seam-wiring-guard.js +275 -0
  672. package/scripts/bongos/search-ingest-db.js +288 -0
  673. package/scripts/bongos/search-ingest-md.js +269 -0
  674. package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +152 -0
  675. package/scripts/bongos/seed-bv1-profiles-tasks.js +135 -0
  676. package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +390 -0
  677. package/scripts/bongos/seed-staging.sh +117 -0
  678. package/scripts/bongos/seed-verify-criteria.js +124 -0
  679. package/scripts/bongos/sequence.js +597 -0
  680. package/scripts/bongos/session-cost.js +430 -0
  681. package/scripts/bongos/session-digest-build.js +293 -0
  682. package/scripts/bongos/session-digest.js +200 -0
  683. package/scripts/bongos/session-eval.js +631 -0
  684. package/scripts/bongos/session-transcript-build.js +155 -0
  685. package/scripts/bongos/session-transcript-upload.js +29 -0
  686. package/scripts/bongos/session.js +404 -0
  687. package/scripts/bongos/setup.js +646 -0
  688. package/scripts/bongos/ship-check.js +89 -0
  689. package/scripts/bongos/ship-deploy-target.js +393 -0
  690. package/scripts/bongos/ship-escalation.js +167 -0
  691. package/scripts/bongos/ship-finish.js +420 -0
  692. package/scripts/bongos/ship-flow.js +1217 -0
  693. package/scripts/bongos/ship-git.js +100 -0
  694. package/scripts/bongos/ship-grade-steps.js +547 -0
  695. package/scripts/bongos/ship-grade.js +426 -0
  696. package/scripts/bongos/ship-honesty.js +314 -0
  697. package/scripts/bongos/ship-io.js +139 -0
  698. package/scripts/bongos/ship-land.js +1130 -0
  699. package/scripts/bongos/ship-memory-sync.js +249 -0
  700. package/scripts/bongos/ship-merge-gate.js +225 -0
  701. package/scripts/bongos/ship-merge.js +466 -0
  702. package/scripts/bongos/ship-mode-ask.js +138 -0
  703. package/scripts/bongos/ship-mode-manual.js +54 -0
  704. package/scripts/bongos/ship-preflight-steps.js +399 -0
  705. package/scripts/bongos/ship-regen.js +291 -0
  706. package/scripts/bongos/ship-resume.js +201 -0
  707. package/scripts/bongos/ship-session-upload.js +313 -0
  708. package/scripts/bongos/ship-state.js +110 -0
  709. package/scripts/bongos/ship-surprise.js +84 -0
  710. package/scripts/bongos/ship-visual.js +75 -0
  711. package/scripts/bongos/ship.js +382 -0
  712. package/scripts/bongos/shipping-mode.js +71 -0
  713. package/scripts/bongos/skill-lint.js +250 -0
  714. package/scripts/bongos/skill-preflight.js +361 -0
  715. package/scripts/bongos/smoke-batch-claim.sh +238 -0
  716. package/scripts/bongos/smoke-batch-release.sh +316 -0
  717. package/scripts/bongos/smoke-claim-consistency.sh +222 -0
  718. package/scripts/bongos/smoke-dependencies.sh +143 -0
  719. package/scripts/bongos/smoke-gds.js +256 -0
  720. package/scripts/bongos/smoke-write.sh +275 -0
  721. package/scripts/bongos/source-text-test-scan.js +106 -0
  722. package/scripts/bongos/spark.js +294 -0
  723. package/scripts/bongos/stale-worktrees.js +212 -0
  724. package/scripts/bongos/start-goals.js +102 -0
  725. package/scripts/bongos/start.js +1090 -0
  726. package/scripts/bongos/status.js +545 -0
  727. package/scripts/bongos/strand-watch.js +315 -0
  728. package/scripts/bongos/stranded-rows.js +200 -0
  729. package/scripts/bongos/stray-unit-sweep.sh +71 -0
  730. package/scripts/bongos/surface.js +101 -0
  731. package/scripts/bongos/task.js +273 -0
  732. package/scripts/bongos/test-path-guard.js +99 -0
  733. package/scripts/bongos/triage.js +742 -0
  734. package/scripts/bongos/turn-end-sound.js +74 -0
  735. package/scripts/bongos/tweak-halt.js +70 -0
  736. package/scripts/bongos/tweak-renders.js +200 -0
  737. package/scripts/bongos/uat.js +120 -0
  738. package/scripts/bongos/ui-kit-transform.js +43 -0
  739. package/scripts/bongos/update-channel.js +512 -0
  740. package/scripts/bongos/update-sweep.js +829 -0
  741. package/scripts/bongos/upgrade-artist-gate.js +46 -0
  742. package/scripts/bongos/upgrade-commit-identity.js +32 -0
  743. package/scripts/bongos/upgrade-migrate.js +224 -0
  744. package/scripts/bongos/upgrade-operator.js +73 -0
  745. package/scripts/bongos/upgrade-outcome.js +174 -0
  746. package/scripts/bongos/upgrade.js +1499 -0
  747. package/scripts/bongos/validate-design.js +12 -0
  748. package/scripts/bongos/version-close.js +621 -0
  749. package/scripts/bongos/version-literal-guard.js +140 -0
  750. package/scripts/bongos/version-select.js +79 -0
  751. package/scripts/bongos/visual-review-nudge.js +39 -0
  752. package/scripts/bongos/wedge-remedy.js +174 -0
  753. package/scripts/bongos/worktree-claim-guard.js +130 -0
  754. package/scripts/bongos/worktree.js +449 -0
  755. package/scripts/discord/post.js +1 -1
  756. package/scripts/gds/README.md +9 -0
  757. package/scripts/gds/abandon.js +6 -136
  758. package/scripts/gds/accessibility-replay.js +5 -194
  759. package/scripts/gds/address-park-sweep.sh +7 -90
  760. package/scripts/gds/adopt-detect.js +5 -121
  761. package/scripts/gds/adopt-import.js +5 -109
  762. package/scripts/gds/adopt-preflight.js +5 -185
  763. package/scripts/gds/adr-namespace.js +5 -271
  764. package/scripts/gds/agent-invoke.js +5 -687
  765. package/scripts/gds/agents-sync.js +5 -500
  766. package/scripts/gds/api-alias-caller-scan.js +5 -255
  767. package/scripts/gds/api-artifacts.js +6 -0
  768. package/scripts/gds/api.js +6 -85
  769. package/scripts/gds/api.ps1 +8 -26
  770. package/scripts/gds/architect-audit.js +6 -293
  771. package/scripts/gds/artifact-audit.js +5 -324
  772. package/scripts/gds/artifact-format.js +6 -203
  773. package/scripts/gds/ask.js +5 -229
  774. package/scripts/gds/audit-authorship.sh +7 -328
  775. package/scripts/gds/audit-deps.js +6 -188
  776. package/scripts/gds/audit-gate.js +5 -119
  777. package/scripts/gds/audit-rank-roles.js +6 -171
  778. package/scripts/gds/audit-replay.sh +7 -204
  779. package/scripts/gds/autobongos-digest.js +5 -121
  780. package/scripts/gds/autobongos-grade-cap.js +5 -186
  781. package/scripts/gds/autobongos-loop.js +5 -208
  782. package/scripts/gds/autobongos-run.js +5 -1359
  783. package/scripts/gds/autobongos-service.cmd +8 -49
  784. package/scripts/gds/autobongos-service.ps1 +8 -270
  785. package/scripts/gds/autobongos-tweak-lane.js +5 -261
  786. package/scripts/gds/autobongos-verify.js +5 -616
  787. package/scripts/gds/autonomy-gate.js +5 -133
  788. package/scripts/gds/autonomy-gauge-statusline.js +5 -122
  789. package/scripts/gds/autonomy-gauge.js +5 -82
  790. package/scripts/gds/backfill-cost.js +6 -175
  791. package/scripts/gds/backfill-disciplines.js +5 -142
  792. package/scripts/gds/backfill-session-earnings.js +5 -121
  793. package/scripts/gds/backfill-session-types.js +5 -85
  794. package/scripts/gds/backfill-sessions.js +5 -409
  795. package/scripts/gds/backfill-subagent-rewards.js +5 -483
  796. package/scripts/gds/backfill-task-rewards.js +5 -411
  797. package/scripts/gds/backlog-review.js +6 -398
  798. package/scripts/gds/backup-dropin-sweep.sh +7 -94
  799. package/scripts/gds/backup.js +6 -115
  800. package/scripts/gds/baseline-staleness.js +5 -215
  801. package/scripts/gds/bfg-principal-token.js +6 -64
  802. package/scripts/gds/bug-attachment-audit.js +5 -147
  803. package/scripts/gds/bug-attachment-recover.js +5 -196
  804. package/scripts/gds/bug-triage.js +6 -291
  805. package/scripts/gds/build-bongos.js +5 -92
  806. package/scripts/gds/bump-version.js +5 -219
  807. package/scripts/gds/capture.js +6 -480
  808. package/scripts/gds/category-advisory-guard.js +5 -205
  809. package/scripts/gds/ci-grade.js +6 -81
  810. package/scripts/gds/claim-recall.js +6 -111
  811. package/scripts/gds/claim.js +6 -788
  812. package/scripts/gds/claude-materialize.js +5 -1198
  813. package/scripts/gds/claude-md-template.js +5 -140
  814. package/scripts/gds/cleanup-orphans.js +6 -73
  815. package/scripts/gds/cli-lib.js +6 -1204
  816. package/scripts/gds/client-baseurl-guard.js +5 -114
  817. package/scripts/gds/conductor-dispatch.js +6 -534
  818. package/scripts/gds/context-pack.js +6 -325
  819. package/scripts/gds/control-manifest.js +5 -197
  820. package/scripts/gds/copy-apply.js +5 -756
  821. package/scripts/gds/copy-inventory.js +5 -569
  822. package/scripts/gds/core-origin-follow.js +5 -184
  823. package/scripts/gds/core-pin-sync.js +5 -258
  824. package/scripts/gds/cost-report.js +6 -62
  825. package/scripts/gds/cost.js +6 -46
  826. package/scripts/gds/credential-presence.js +5 -294
  827. package/scripts/gds/cutover-codemod.js +5 -239
  828. package/scripts/gds/db-backup-nightly.sh +7 -231
  829. package/scripts/gds/db-backup-offsite.sh +7 -266
  830. package/scripts/gds/demote.js +6 -44
  831. package/scripts/gds/deploy-divergence.js +6 -445
  832. package/scripts/gds/deploy-main-audit-gate.sh +7 -96
  833. package/scripts/gds/design-sync.js +5 -10
  834. package/scripts/gds/dev-box-guard.js +5 -164
  835. package/scripts/gds/dev-lib.js +5 -721
  836. package/scripts/gds/dev.js +5 -643
  837. package/scripts/gds/device-flow-help.js +5 -70
  838. package/scripts/gds/diagnose-achievements.js +5 -116
  839. package/scripts/gds/diagram-facts.js +6 -355
  840. package/scripts/gds/discord-channels.js +5 -75
  841. package/scripts/gds/do-api.js +6 -109
  842. package/scripts/gds/doc-cli-guard.js +5 -266
  843. package/scripts/gds/doc-comment-coverage.js +5 -137
  844. package/scripts/gds/doc-control-claims.js +5 -166
  845. package/scripts/gds/docs-entropy.js +5 -443
  846. package/scripts/gds/doctor.js +6 -492
  847. package/scripts/gds/enroll-control-plane.js +5 -99
  848. package/scripts/gds/exec-path-guard.js +5 -562
  849. package/scripts/gds/feedback-send.js +5 -247
  850. package/scripts/gds/fetch-art-key.js +5 -104
  851. package/scripts/gds/fetch-sound-prefs.js +5 -124
  852. package/scripts/gds/figma-design-sync.js +5 -9
  853. package/scripts/gds/find-untested.js +5 -369
  854. package/scripts/gds/fitness-checks-error-envelope.js +5 -133
  855. package/scripts/gds/fitness-checks-identity.js +5 -342
  856. package/scripts/gds/fitness-checks-packaging.js +5 -131
  857. package/scripts/gds/fitness-checks-route-pins.js +5 -75
  858. package/scripts/gds/fitness-checks-vocabulary.js +5 -391
  859. package/scripts/gds/fitness-checks-write-validation.js +5 -156
  860. package/scripts/gds/fitness-lib.js +5 -126
  861. package/scripts/gds/fitness-migration-contraction.js +5 -49
  862. package/scripts/gds/fitness-ratchets.js +5 -563
  863. package/scripts/gds/fitness.js +5 -1493
  864. package/scripts/gds/gate-review.js +5 -328
  865. package/scripts/gds/gating.js +5 -346
  866. package/scripts/gds/gds-literal-scan.js +5 -194
  867. package/scripts/gds/gen-api-client.js +5 -555
  868. package/scripts/gds/gen-api-docs.js +5 -1100
  869. package/scripts/gds/gen-atlas.js +5 -364
  870. package/scripts/gds/gen-diagrams.js +6 -607
  871. package/scripts/gds/gen-file-map.js +5 -335
  872. package/scripts/gds/gen-freshness.js +5 -31
  873. package/scripts/gds/gen-interaction-posture.js +5 -120
  874. package/scripts/gds/gen-repo-map.js +5 -538
  875. package/scripts/gds/gen-role-responsibilities.js +5 -133
  876. package/scripts/gds/gen-session-index.js +5 -241
  877. package/scripts/gds/gen-sounds.js +5 -174
  878. package/scripts/gds/git-merge-regen.js +6 -291
  879. package/scripts/gds/go-live.js +5 -1069
  880. package/scripts/gds/goal.js +6 -271
  881. package/scripts/gds/government-walk.js +5 -1475
  882. package/scripts/gds/grade-correlation-audit.js +5 -308
  883. package/scripts/gds/grade-replay.js +5 -235
  884. package/scripts/gds/grade-smoke.js +6 -204
  885. package/scripts/gds/home-isolation-guard.js +5 -125
  886. package/scripts/gds/hooks/pre-push.js +5 -209
  887. package/scripts/gds/howto.js +5 -143
  888. package/scripts/gds/http-api-client.js +6 -81
  889. package/scripts/gds/identity-strip.js +5 -74
  890. package/scripts/gds/init.js +5 -1157
  891. package/scripts/gds/install-git-hooks.js +5 -198
  892. package/scripts/gds/instance-apex.js +5 -37
  893. package/scripts/gds/intent-retry.js +5 -51
  894. package/scripts/gds/key-card.js +6 -221
  895. package/scripts/gds/key-status.js +5 -124
  896. package/scripts/gds/land-watch.js +5 -199
  897. package/scripts/gds/leak-scan-allowlist.js +5 -291
  898. package/scripts/gds/learning-capture.js +6 -144
  899. package/scripts/gds/lib.sh +7 -73
  900. package/scripts/gds/linkify-refs.js +6 -654
  901. package/scripts/gds/lint-infra-exec.js +5 -68
  902. package/scripts/gds/lint-migrations.js +5 -100
  903. package/scripts/gds/lint-workflow-exec.js +5 -61
  904. package/scripts/gds/local-preview-lib.js +6 -128
  905. package/scripts/gds/local-preview.js +6 -81
  906. package/scripts/gds/login.js +5 -358
  907. package/scripts/gds/main-audit.js +5 -623
  908. package/scripts/gds/me.js +6 -96
  909. package/scripts/gds/memory-map.js +5 -174
  910. package/scripts/gds/merge-lock.js +6 -70
  911. package/scripts/gds/migration-namespace.js +5 -311
  912. package/scripts/gds/mirror-lineage-check.js +5 -341
  913. package/scripts/gds/mirror-redact.js +5 -348
  914. package/scripts/gds/module-artifact.js +6 -289
  915. package/scripts/gds/module-assess-docs.js +6 -237
  916. package/scripts/gds/module-assess-installs.js +6 -227
  917. package/scripts/gds/module-assess-score.js +6 -110
  918. package/scripts/gds/module-assess-security.js +6 -251
  919. package/scripts/gds/module-assess-tests.js +6 -277
  920. package/scripts/gds/module-assess-version.js +6 -91
  921. package/scripts/gds/module-error-report.js +5 -146
  922. package/scripts/gds/module-test-runner.js +6 -413
  923. package/scripts/gds/module.js +5 -1374
  924. package/scripts/gds/move-escalation.js +5 -140
  925. package/scripts/gds/newcomer-floor.js +6 -420
  926. package/scripts/gds/newcomer-floor.test.js +6 -234
  927. package/scripts/gds/next-number.js +6 -162
  928. package/scripts/gds/oauth-secret.js +5 -200
  929. package/scripts/gds/onboard.js +5 -265
  930. package/scripts/gds/onboarding-analyze.js +6 -225
  931. package/scripts/gds/onboarding-config.js +6 -179
  932. package/scripts/gds/onboarding-ship.js +6 -91
  933. package/scripts/gds/pack-env-prefix.js +5 -72
  934. package/scripts/gds/package-core.js +5 -1102
  935. package/scripts/gds/page-inventory.js +5 -346
  936. package/scripts/gds/page-reader.js +5 -720
  937. package/scripts/gds/paste-token.js +6 -211
  938. package/scripts/gds/plain-cards.js +5 -350
  939. package/scripts/gds/portability-smoke-art.sh +7 -84
  940. package/scripts/gds/portability-smoke-memory.sh +7 -175
  941. package/scripts/gds/preflight.js +5 -212
  942. package/scripts/gds/probe-cache.js +5 -244
  943. package/scripts/gds/prove-strict-versioning.js +6 -283
  944. package/scripts/gds/provision-auto-upgrade.js +5 -161
  945. package/scripts/gds/provision-byo-host.js +5 -67
  946. package/scripts/gds/provision-capacity.js +5 -78
  947. package/scripts/gds/provision-caps.js +5 -62
  948. package/scripts/gds/provision-config.js +5 -232
  949. package/scripts/gds/provision-core-upgrade.js +5 -1165
  950. package/scripts/gds/provision-disconnect.js +5 -87
  951. package/scripts/gds/provision-github-setup.js +5 -167
  952. package/scripts/gds/provision-net.js +5 -356
  953. package/scripts/gds/provision-pin-key.js +5 -175
  954. package/scripts/gds/provision-pin-replay.js +5 -125
  955. package/scripts/gds/provision-process.js +5 -169
  956. package/scripts/gds/provision-render.js +5 -200
  957. package/scripts/gds/provision-repo-auth.js +5 -163
  958. package/scripts/gds/provision-repo-private.js +5 -97
  959. package/scripts/gds/provision-repo.js +5 -1336
  960. package/scripts/gds/provision-teardown.js +5 -105
  961. package/scripts/gds/provision-units.js +5 -468
  962. package/scripts/gds/provision.js +5 -1477
  963. package/scripts/gds/publish-credential-check.js +6 -65
  964. package/scripts/gds/publish-integration-gate.js +5 -140
  965. package/scripts/gds/publish-manifest.js +5 -437
  966. package/scripts/gds/publish-watch.js +5 -266
  967. package/scripts/gds/pulse.js +6 -335
  968. package/scripts/gds/push-main.js +5 -54
  969. package/scripts/gds/push-path-brief.js +5 -98
  970. package/scripts/gds/read-session-export.js +5 -357
  971. package/scripts/gds/reauth.js +6 -154
  972. package/scripts/gds/recall.js +6 -182
  973. package/scripts/gds/redteam-patrol.js +5 -435
  974. package/scripts/gds/regen-instance-docs.js +5 -45
  975. package/scripts/gds/release-core.js +5 -78
  976. package/scripts/gds/release-notes.js +5 -270
  977. package/scripts/gds/release.js +6 -138
  978. package/scripts/gds/rename-history-check.js +5 -367
  979. package/scripts/gds/rename-ledger-prose.js +5 -480
  980. package/scripts/gds/render-api.js +5 -196
  981. package/scripts/gds/render-check.js +5 -204
  982. package/scripts/gds/render-ideas.js +6 -225
  983. package/scripts/gds/render-payload.js +5 -84
  984. package/scripts/gds/repo-metrics.js +6 -362
  985. package/scripts/gds/review-sheet.js +5 -106
  986. package/scripts/gds/role-pack-guard.js +5 -141
  987. package/scripts/gds/route-shadow-guard.js +5 -173
  988. package/scripts/gds/routine-schedule.js +5 -281
  989. package/scripts/gds/run-routine.js +5 -255
  990. package/scripts/gds/run-unit-tests.js +6 -659
  991. package/scripts/gds/runner-drift.js +5 -149
  992. package/scripts/gds/sandbox-stage.js +6 -458
  993. package/scripts/gds/scope-map-guard.js +5 -299
  994. package/scripts/gds/scope-roster-guard.js +5 -117
  995. package/scripts/gds/seam-wiring-guard.js +5 -274
  996. package/scripts/gds/search-ingest-db.js +6 -287
  997. package/scripts/gds/search-ingest-md.js +6 -268
  998. package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +6 -152
  999. package/scripts/gds/seed-bv1-profiles-tasks.js +6 -135
  1000. package/scripts/gds/seed-bv2-ideator-surface-tasks.js +6 -390
  1001. package/scripts/gds/seed-staging.sh +7 -116
  1002. package/scripts/gds/seed-verify-criteria.js +6 -124
  1003. package/scripts/gds/sequence.js +6 -596
  1004. package/scripts/gds/session-cost.js +6 -429
  1005. package/scripts/gds/session-digest-build.js +6 -293
  1006. package/scripts/gds/session-digest.js +6 -199
  1007. package/scripts/gds/session-eval.js +6 -630
  1008. package/scripts/gds/session-transcript-build.js +6 -155
  1009. package/scripts/gds/session-transcript-upload.js +6 -29
  1010. package/scripts/gds/session.js +6 -403
  1011. package/scripts/gds/setup.js +6 -645
  1012. package/scripts/gds/ship-check.js +5 -85
  1013. package/scripts/gds/ship-deploy-target.js +5 -392
  1014. package/scripts/gds/ship-escalation.js +5 -166
  1015. package/scripts/gds/ship-finish.js +5 -419
  1016. package/scripts/gds/ship-flow.js +5 -1216
  1017. package/scripts/gds/ship-git.js +5 -99
  1018. package/scripts/gds/ship-grade-steps.js +5 -546
  1019. package/scripts/gds/ship-grade.js +5 -425
  1020. package/scripts/gds/ship-honesty.js +5 -312
  1021. package/scripts/gds/ship-io.js +5 -138
  1022. package/scripts/gds/ship-land.js +5 -1129
  1023. package/scripts/gds/ship-memory-sync.js +5 -248
  1024. package/scripts/gds/ship-merge-gate.js +5 -224
  1025. package/scripts/gds/ship-merge.js +5 -465
  1026. package/scripts/gds/ship-mode-ask.js +5 -137
  1027. package/scripts/gds/ship-mode-manual.js +5 -53
  1028. package/scripts/gds/ship-preflight-steps.js +5 -398
  1029. package/scripts/gds/ship-regen.js +5 -313
  1030. package/scripts/gds/ship-resume.js +5 -200
  1031. package/scripts/gds/ship-session-upload.js +5 -312
  1032. package/scripts/gds/ship-state.js +5 -109
  1033. package/scripts/gds/ship-surprise.js +5 -83
  1034. package/scripts/gds/ship-visual.js +5 -74
  1035. package/scripts/gds/ship.js +5 -380
  1036. package/scripts/gds/shipping-mode.js +5 -69
  1037. package/scripts/gds/skill-lint.js +5 -248
  1038. package/scripts/gds/skill-preflight.js +5 -359
  1039. package/scripts/gds/smoke-batch-claim.sh +7 -237
  1040. package/scripts/gds/smoke-batch-release.sh +7 -315
  1041. package/scripts/gds/smoke-claim-consistency.sh +7 -221
  1042. package/scripts/gds/smoke-dependencies.sh +7 -142
  1043. package/scripts/gds/smoke-gds.js +6 -255
  1044. package/scripts/gds/smoke-write.sh +7 -274
  1045. package/scripts/gds/source-text-test-scan.js +7 -0
  1046. package/scripts/gds/spark.js +6 -293
  1047. package/scripts/gds/stale-worktrees.js +5 -210
  1048. package/scripts/gds/start-goals.js +5 -101
  1049. package/scripts/gds/start.js +6 -1089
  1050. package/scripts/gds/status.js +6 -544
  1051. package/scripts/gds/strand-watch.js +5 -313
  1052. package/scripts/gds/stranded-rows.js +5 -198
  1053. package/scripts/gds/stray-unit-sweep.sh +7 -70
  1054. package/scripts/gds/surface.js +5 -100
  1055. package/scripts/gds/task.js +6 -272
  1056. package/scripts/gds/test-path-guard.js +5 -97
  1057. package/scripts/gds/triage.js +6 -741
  1058. package/scripts/gds/turn-end-sound.js +5 -72
  1059. package/scripts/gds/tweak-halt.js +5 -68
  1060. package/scripts/gds/tweak-renders.js +5 -198
  1061. package/scripts/gds/uat.js +6 -119
  1062. package/scripts/gds/ui-kit-transform.js +5 -41
  1063. package/scripts/gds/update-channel.js +5 -510
  1064. package/scripts/gds/update-sweep.js +5 -827
  1065. package/scripts/gds/upgrade-artist-gate.js +5 -45
  1066. package/scripts/gds/upgrade-commit-identity.js +5 -31
  1067. package/scripts/gds/upgrade-migrate.js +5 -223
  1068. package/scripts/gds/upgrade-operator.js +6 -73
  1069. package/scripts/gds/upgrade-outcome.js +5 -173
  1070. package/scripts/gds/upgrade.js +5 -1497
  1071. package/scripts/gds/validate-design.js +5 -10
  1072. package/scripts/gds/version-close.js +6 -620
  1073. package/scripts/gds/version-literal-guard.js +5 -138
  1074. package/scripts/gds/version-select.js +5 -77
  1075. package/scripts/gds/visual-review-nudge.js +5 -38
  1076. package/scripts/gds/wedge-remedy.js +5 -173
  1077. package/scripts/gds/worktree-claim-guard.js +5 -129
  1078. package/scripts/gds/worktree.js +6 -448
  1079. package/scripts/hall-preview/refresh-fixtures.js +1 -1
  1080. package/scripts/hall-preview/server.js +2 -2
  1081. package/scripts/migrate.sh +3 -3
  1082. package/scripts/public-mirror-export.js +3 -3
  1083. package/scripts/security/dep-audit.js +50 -124
  1084. package/scripts/setup-builder.js +7 -7
  1085. package/src/bongos/api-errors.js +1 -0
  1086. package/src/bongos/api-prefix.js +1 -1
  1087. package/src/bongos/auth-github.js +19 -3
  1088. package/src/bongos/auth-idp.js +7 -0
  1089. package/src/bongos/claim-attribution.js +2 -2
  1090. package/src/bongos/core-moves.js +1 -1
  1091. package/src/bongos/core-update.js +3 -3
  1092. package/src/bongos/craft-mode.js +2 -2
  1093. package/src/bongos/db-kernel.js +15 -3
  1094. package/src/bongos/db.js +30 -4
  1095. package/src/bongos/github-repos.js +1 -1
  1096. package/src/bongos/llm-cache.js +1 -1
  1097. package/src/bongos/llm-pricing.js +1 -1
  1098. package/src/bongos/metrics.js +1 -1
  1099. package/src/bongos/middleware/rate-limit.js +2 -2
  1100. package/src/bongos/module-listing.js +93 -1
  1101. package/src/bongos/module-scope-map.js +90 -85
  1102. package/src/bongos/module-store.js +1 -1
  1103. package/src/bongos/module-submissions.js +1 -1
  1104. package/src/bongos/optimizer.js +1 -1
  1105. package/src/bongos/package-registry.js +1 -1
  1106. package/src/bongos/path-match.js +1 -1
  1107. package/src/bongos/permission-path-check.js +3 -3
  1108. package/src/bongos/platform-visibility-gate.js +3 -5
  1109. package/src/bongos/prelaunch-gate.js +7 -6
  1110. package/src/bongos/route-rank-check.js +2 -2
  1111. package/src/bongos/routes/auth.js +15 -2
  1112. package/src/bongos/routes/backup.js +1 -1
  1113. package/src/bongos/routes/builders.js +29 -1
  1114. package/src/bongos/routes/me.js +49 -18
  1115. package/src/bongos/routes/modules.js +29 -9
  1116. package/src/bongos/routes/public.js +3 -72
  1117. package/src/bongos/schema-lag.js +1 -1
  1118. package/src/bongos/sensitive-surfaces.js +1 -1
  1119. package/src/bongos/serve-internal.js +65 -16
  1120. package/src/bongos/software-update.js +2 -2
  1121. package/src/bongos/upgrade-hold.js +3 -3
  1122. package/src/hall-look.js +6 -5
  1123. package/src/module-api.js +3 -3
  1124. package/src/module-loader/catalog.js +1 -1
  1125. package/src/module-loader/error-tally.js +3 -3
  1126. package/src/module-loader/manifest-schema.js +3 -3
  1127. package/src/platform-server.js +10 -0
  1128. package/src/role-responsibilities.js +1 -1
  1129. package/src/stale-timer.js +2 -2
  1130. package/tests/accessibility_replay.mjs +1 -1
  1131. package/tests/activity_rollup_order_db.mjs +1 -1
  1132. package/tests/activity_snapshots_db.mjs +1 -1
  1133. package/tests/adopt_detect.mjs +1 -1
  1134. package/tests/adopt_import.mjs +1 -1
  1135. package/tests/adopt_preflight.mjs +1 -1
  1136. package/tests/adr_0089_scope.mjs +10 -7
  1137. package/tests/adr_0162_citation.mjs +1 -1
  1138. package/tests/adr_0162_gate_citation.mjs +1 -1
  1139. package/tests/agent_invoke.mjs +1 -1
  1140. package/tests/agent_invoke_live.mjs +3 -3
  1141. package/tests/agents_cron_trigger.mjs +2 -2
  1142. package/tests/agents_roster.mjs +1 -1
  1143. package/tests/agents_sync.mjs +4 -4
  1144. package/tests/allow_rule_guard.mjs +20 -20
  1145. package/tests/api_alias_caller_ratchet.mjs +9 -10
  1146. package/tests/api_alias_exceptions.mjs +7 -6
  1147. package/tests/api_artifacts.mjs +214 -0
  1148. package/tests/api_cli_flags.mjs +3 -3
  1149. package/tests/api_client.mjs +56 -54
  1150. package/tests/api_docs.mjs +30 -9
  1151. package/tests/api_error_envelope_buildcheck.mjs +1 -1
  1152. package/tests/api_msys_path_repair.mjs +2 -2
  1153. package/tests/architect.mjs +1 -1
  1154. package/tests/art_stage.mjs +2 -2
  1155. package/tests/artifact_audit.mjs +2 -2
  1156. package/tests/atlas.mjs +1 -1
  1157. package/tests/audit_deps.mjs +1 -1
  1158. package/tests/audit_gate.mjs +1 -1
  1159. package/tests/auth_flow_slice1.mjs +3 -3
  1160. package/tests/auth_inactive_builder.mjs +43 -5
  1161. package/tests/auth_session_expiry_db.mjs +16 -4
  1162. package/tests/auth_session_ttl.mjs +23 -0
  1163. package/tests/authorship_audit.mjs +2 -2
  1164. package/tests/autobongos_cadence.mjs +1 -1
  1165. package/tests/autobongos_fence.mjs +1 -1
  1166. package/tests/autobongos_grade_cap.mjs +2 -2
  1167. package/tests/autobongos_heartbeat_head.mjs +1 -1
  1168. package/tests/autobongos_host_access.mjs +3 -3
  1169. package/tests/autobongos_loop.mjs +17 -17
  1170. package/tests/autobongos_service_ps1.mjs +3 -3
  1171. package/tests/autobongos_tweak_lane.mjs +2 -2
  1172. package/tests/autobongos_verify.mjs +2 -2
  1173. package/tests/autonomous_fit_protected_paths.mjs +3 -3
  1174. package/tests/autonomy_config_idle.mjs +1 -1
  1175. package/tests/autonomy_daily_checks.mjs +201 -0
  1176. package/tests/autonomy_digest.mjs +1 -1
  1177. package/tests/autonomy_gate.mjs +1 -1
  1178. package/tests/autonomy_gauge.mjs +2 -2
  1179. package/tests/autonomy_runner_identity.mjs +1 -1
  1180. package/tests/backfill_sessions.mjs +8 -8
  1181. package/tests/backfill_subagent_rewards.mjs +1 -1
  1182. package/tests/backfill_task_rewards.mjs +2 -2
  1183. package/tests/backlog_review.mjs +3 -3
  1184. package/tests/baseline_staleness.mjs +2 -2
  1185. package/tests/bfg.mjs +11 -5
  1186. package/tests/bfg_write.mjs +20 -11
  1187. package/tests/blockers_hall.mjs +14 -4
  1188. package/tests/blockers_page_ui.mjs +56 -12
  1189. package/tests/bongos_dispatch.mjs +5 -5
  1190. package/tests/bongos_login.mjs +2 -2
  1191. package/tests/bug_attachment_audit.mjs +1 -1
  1192. package/tests/bug_attachment_recover.mjs +2 -2
  1193. package/tests/bug_triage.mjs +3 -3
  1194. package/tests/build_info.mjs +1 -1
  1195. package/tests/builder_tester_tag.mjs +184 -0
  1196. package/tests/bump_version.mjs +3 -3
  1197. package/tests/canonical_profile_url.mjs +1 -1
  1198. package/tests/capture_error_format.mjs +1 -1
  1199. package/tests/capture_goal_routing.mjs +2 -2
  1200. package/tests/category_advisory_guard.mjs +3 -3
  1201. package/tests/claim_error_surface.mjs +2 -2
  1202. package/tests/claim_from_task_and_home.mjs +1 -1
  1203. package/tests/claim_gate_open_blocker.mjs +7 -4
  1204. package/tests/claim_gate_rebase.mjs +12 -8
  1205. package/tests/claim_recall.mjs +4 -4
  1206. package/tests/claim_resolve_worktree_lock.mjs +1 -1
  1207. package/tests/claude_materialize.mjs +68 -68
  1208. package/tests/clawback_confirmed_backlog.mjs +8 -5
  1209. package/tests/cli_allowlist_permissions.mjs +11 -11
  1210. package/tests/cli_dispatcher.mjs +2 -2
  1211. package/tests/cli_err_code.mjs +6 -6
  1212. package/tests/cli_exit_no_abort.mjs +7 -7
  1213. package/tests/cli_lib_formatters.mjs +2 -2
  1214. package/tests/cli_sessions.mjs +5 -5
  1215. package/tests/cli_surface.mjs +15 -15
  1216. package/tests/cli_token_reissue.mjs +2 -2
  1217. package/tests/client_baseurl_guard.mjs +1 -1
  1218. package/tests/client_bundle_route.mjs +35 -4
  1219. package/tests/cloud_bongos_pack.mjs +1 -1
  1220. package/tests/community_leaderboard_db.mjs +1 -1
  1221. package/tests/conductor.mjs +18 -18
  1222. package/tests/conflict_resolve.mjs +14 -16
  1223. package/tests/consumer_layout_boot.mjs +12 -12
  1224. package/tests/context_pack.mjs +6 -6
  1225. package/tests/control_manifest.mjs +4 -4
  1226. package/tests/copy_desk_page_reads.mjs +1 -1
  1227. package/tests/copy_desk_page_release.mjs +192 -0
  1228. package/tests/copy_inventory.mjs +2 -2
  1229. package/tests/core_auto_upgrade.mjs +1 -1
  1230. package/tests/core_move_notice.mjs +2 -2
  1231. package/tests/core_origin_follow.mjs +7 -7
  1232. package/tests/core_pin_sync.mjs +3 -3
  1233. package/tests/core_upgrade_door.mjs +2 -2
  1234. package/tests/core_upgrade_owner_door.mjs +34 -1
  1235. package/tests/core_upgrade_runner.mjs +19 -19
  1236. package/tests/credential_presence.mjs +2 -2
  1237. package/tests/credit_grant.mjs +3 -3
  1238. package/tests/credit_log_single_writer.mjs +5 -5
  1239. package/tests/criterion_ref_status.mjs +2 -2
  1240. package/tests/cross_discipline_priority_direction.mjs +3 -3
  1241. package/tests/cutover_codemod.mjs +2 -4
  1242. package/tests/db_backup_nightly.mjs +1 -1
  1243. package/tests/db_backup_offsite.mjs +1 -1
  1244. package/tests/db_ownership_handover.mjs +2 -2
  1245. package/tests/dead_deps.mjs +3 -3
  1246. package/tests/dependency_advisory.mjs +1 -1
  1247. package/tests/deploy_audit_gate.mjs +4 -4
  1248. package/tests/deploy_divergence_line.mjs +36 -16
  1249. package/tests/deploy_page_projects.mjs +35 -4
  1250. package/tests/dev_lib.mjs +2 -2
  1251. package/tests/dev_windows.mjs +2 -2
  1252. package/tests/diagram_facts_offset.mjs +1 -1
  1253. package/tests/diagram_repo_slug.mjs +1 -1
  1254. package/tests/diff_derived_signals.mjs +2 -2
  1255. package/tests/dns_preflight.mjs +2 -2
  1256. package/tests/do_api.mjs +3 -3
  1257. package/tests/doc_cli_guard.mjs +28 -28
  1258. package/tests/doc_comment_coverage.mjs +1 -1
  1259. package/tests/doc_control_claims.mjs +11 -11
  1260. package/tests/docs_entropy.mjs +2 -2
  1261. package/tests/docs_openapi_route.mjs +8 -6
  1262. package/tests/doctor_hooks.mjs +1 -1
  1263. package/tests/edit_hints.mjs +3 -2
  1264. package/tests/effective_visibility_predicate.mjs +1 -19
  1265. package/tests/env_knobs_neutral_prefix.mjs +13 -13
  1266. package/tests/exec_path_guard.mjs +4 -4
  1267. package/tests/executed_closure.mjs +18 -12
  1268. package/tests/file_map.mjs +1 -1
  1269. package/tests/find_untested.mjs +13 -13
  1270. package/tests/first_admin_bootstrap.mjs +1 -1
  1271. package/tests/fitness.mjs +16 -16
  1272. package/tests/fitness_gds_ratchet.mjs +2 -2
  1273. package/tests/fitness_installed_core.mjs +3 -3
  1274. package/tests/fitness_no_raw_nul.mjs +1 -1
  1275. package/tests/fitness_ratchets.mjs +3 -3
  1276. package/tests/fitness_scope_roster.mjs +2 -2
  1277. package/tests/fitness_two_root.mjs +8 -8
  1278. package/tests/fixtures/accessibility-replay.json +5 -5
  1279. package/tests/fixtures/grade-replay/recorded-panel-grades.json +1 -1
  1280. package/tests/fixtures/ideator-prefold/README.md +1 -1
  1281. package/tests/fixtures/page-ledger.mjs +22 -0
  1282. package/tests/fixtures/session-506-digest.json +5 -5
  1283. package/tests/gate_approvals.mjs +50 -0
  1284. package/tests/gate_review.mjs +8 -8
  1285. package/tests/gating_review_retired.mjs +2 -2
  1286. package/tests/gen_freshness.mjs +3 -3
  1287. package/tests/git_guard.mjs +3 -3
  1288. package/tests/git_merge_regen.mjs +41 -65
  1289. package/tests/github_one_trip.mjs +4 -4
  1290. package/tests/github_pick_up.mjs +2 -2
  1291. package/tests/github_push_merge_driver.mjs +1 -1
  1292. package/tests/go_live.mjs +3 -2
  1293. package/tests/goal_category.mjs +1 -1
  1294. package/tests/goal_cli.mjs +2 -2
  1295. package/tests/goal_create_spec_entry.mjs +1 -1
  1296. package/tests/goal_invite_consent.mjs +3 -1
  1297. package/tests/goal_move.mjs +1 -1
  1298. package/tests/goal_working_area.mjs +1 -1
  1299. package/tests/government_agent_asks.mjs +7 -7
  1300. package/tests/government_board_room_copy.mjs +6 -1
  1301. package/tests/government_board_view.mjs +39 -0
  1302. package/tests/government_board_vote_ui.mjs +39 -1
  1303. package/tests/government_config.mjs +2 -2
  1304. package/tests/government_live_proof_shape.mjs +1 -1
  1305. package/tests/government_protected_surfaces.mjs +54 -53
  1306. package/tests/government_require_permission.mjs +9 -1
  1307. package/tests/government_vanilla_boot.mjs +1 -1
  1308. package/tests/government_vocabulary.mjs +2 -2
  1309. package/tests/government_walk.mjs +2 -2
  1310. package/tests/grade_body_limit.mjs +6 -4
  1311. package/tests/grade_correlation_audit.mjs +3 -3
  1312. package/tests/grade_diff_hash.mjs +1 -1
  1313. package/tests/grade_engine_replay.mjs +2 -2
  1314. package/tests/grade_server_authoritative.mjs +1 -1
  1315. package/tests/grade_unavailable_display.mjs +1 -1
  1316. package/tests/grader.mjs +8 -24
  1317. package/tests/grader_generated_provenance.mjs +14 -14
  1318. package/tests/grader_no_artifact.mjs +1 -1
  1319. package/tests/grader_prompt_fencing.mjs +1 -1
  1320. package/tests/grader_quality_window_overflow.mjs +1 -1
  1321. package/tests/grader_reader_lens.mjs +3 -3
  1322. package/tests/grader_regrade_delta.mjs +1 -1
  1323. package/tests/grader_unbacked_score.mjs +2 -2
  1324. package/tests/hall_acclaim_vote_control.mjs +113 -0
  1325. package/tests/hall_asset_cache.mjs +127 -0
  1326. package/tests/hall_audit.mjs +63 -0
  1327. package/tests/hall_board_world.mjs +20 -0
  1328. package/tests/hall_city_card_words.mjs +61 -0
  1329. package/tests/hall_client_request_shape.mjs +5 -1
  1330. package/tests/hall_home_ships_bounded.mjs +160 -0
  1331. package/tests/hall_landing_boot.mjs +15 -2
  1332. package/tests/hall_nav.mjs +33 -0
  1333. package/tests/hall_onboarding_bongos_setup.mjs +1 -1
  1334. package/tests/hall_oversight_world.mjs +44 -4
  1335. package/tests/hall_palette.mjs +12 -9
  1336. package/tests/hall_preview_security.mjs +1 -1
  1337. package/tests/hall_profile_world.mjs +17 -0
  1338. package/tests/hall_reading_world.mjs +16 -1
  1339. package/tests/hall_roster_world.mjs +2 -1
  1340. package/tests/hall_studio_world.mjs +4 -1
  1341. package/tests/hall_work_history_id.mjs +39 -0
  1342. package/tests/held_tweak_reporting.mjs +4 -4
  1343. package/tests/helpers.mjs +3 -3
  1344. package/tests/home_bounded_reads.mjs +1 -1
  1345. package/tests/home_isolation_guard.mjs +1 -1
  1346. package/tests/hook_core_resolve.mjs +7 -7
  1347. package/tests/hook_user_agents.mjs +1 -1
  1348. package/tests/hooks_drain.mjs +2 -2
  1349. package/tests/host_topology_skips.mjs +1 -1
  1350. package/tests/howto_guide.mjs +1 -1
  1351. package/tests/howto_moments.mjs +3 -3
  1352. package/tests/hub_account_page.mjs +1 -1
  1353. package/tests/idea_capture_grades.mjs +2 -2
  1354. package/tests/idea_develop_spark.mjs +1 -1
  1355. package/tests/idea_filed_via.mjs +2 -2
  1356. package/tests/idea_ideate_full.mjs +1 -1
  1357. package/tests/idea_spark_mark.mjs +1 -1
  1358. package/tests/idea_spark_queue.mjs +1 -1
  1359. package/tests/idea_triage.mjs +1 -1
  1360. package/tests/idea_triage_grade.mjs +3 -3
  1361. package/tests/idea_vote_permission.mjs +113 -0
  1362. package/tests/idea_votes_fold_db.mjs +123 -0
  1363. package/tests/infra_exec_paths.mjs +12 -12
  1364. package/tests/init.mjs +2 -2
  1365. package/tests/instance_db_migrated_on_code_move.mjs +5 -5
  1366. package/tests/instance_feedback.mjs +9 -9
  1367. package/tests/instance_mismatch_guard.mjs +2 -2
  1368. package/tests/integration_parked_ratchet.mjs +24 -2
  1369. package/tests/intent_retry.mjs +1 -1
  1370. package/tests/interaction_posture.mjs +3 -3
  1371. package/tests/invite_expiry_db.mjs +1 -1
  1372. package/tests/joinability_invite_only.mjs +1 -1
  1373. package/tests/karma_vote_lists.mjs +270 -0
  1374. package/tests/key-card.mjs +2 -2
  1375. package/tests/key-status.mjs +2 -2
  1376. package/tests/knip_ratchet_ambient.mjs +2 -2
  1377. package/tests/known_failing_ratchet.mjs +1 -1
  1378. package/tests/land_watch.mjs +2 -2
  1379. package/tests/landing_legal_pages.mjs +1 -1
  1380. package/tests/landing_page.mjs +2 -2
  1381. package/tests/leaderboard_roles.mjs +4 -1
  1382. package/tests/leak_scan_allowlist.mjs +8 -8
  1383. package/tests/leak_scan_fail_closed.mjs +1 -1
  1384. package/tests/lib_sh_resolution.mjs +9 -9
  1385. package/tests/lifecycle-card.mjs +7 -7
  1386. package/tests/linkify_check.mjs +2 -2
  1387. package/tests/linkify_refs.mjs +1 -1
  1388. package/tests/llm-cache-route.mjs +1 -1
  1389. package/tests/local_preview.mjs +2 -2
  1390. package/tests/main_audit.mjs +3 -3
  1391. package/tests/main_audit_attestation.mjs +1 -1
  1392. package/tests/main_audit_db_roster.mjs +2 -2
  1393. package/tests/main_worktree_busy_reason.mjs +3 -3
  1394. package/tests/markdown_line_endings.mjs +2 -2
  1395. package/tests/me_streak_leaderboard_queries.mjs +193 -0
  1396. package/tests/membership_kind_lockstep.mjs +1 -1
  1397. package/tests/memory_isolation.mjs +16 -8
  1398. package/tests/memory_map.mjs +2 -2
  1399. package/tests/memory_pull.mjs +33 -25
  1400. package/tests/merge_driver_register.mjs +3 -3
  1401. package/tests/migration_allocation.mjs +2 -2
  1402. package/tests/migration_namespace.mjs +1 -1
  1403. package/tests/migrations_forward_safe.mjs +1 -1
  1404. package/tests/mingle.mjs +1 -1
  1405. package/tests/mirror_lineage_fulltree.mjs +3 -3
  1406. package/tests/mirror_lineage_proof.mjs +2 -2
  1407. package/tests/mirror_redact.mjs +4 -4
  1408. package/tests/missing_dep_classify.mjs +3 -3
  1409. package/tests/module-scope-map.mjs +22 -22
  1410. package/tests/module_api_lazy.mjs +1 -1
  1411. package/tests/module_assess_docs.mjs +2 -2
  1412. package/tests/module_assess_installs.mjs +3 -3
  1413. package/tests/module_assess_price_parity.mjs +5 -5
  1414. package/tests/module_assess_score.mjs +5 -5
  1415. package/tests/module_assess_security.mjs +4 -4
  1416. package/tests/module_assess_tests.mjs +3 -3
  1417. package/tests/module_assessments_migration.mjs +1 -1
  1418. package/tests/module_catalog.mjs +2 -2
  1419. package/tests/module_cli.mjs +3 -3
  1420. package/tests/module_entitlements.mjs +1 -1
  1421. package/tests/module_error_counts.mjs +1 -1
  1422. package/tests/module_install.mjs +4 -4
  1423. package/tests/module_loader.mjs +3 -1
  1424. package/tests/module_owned_tests.mjs +1 -1
  1425. package/tests/module_release_channels.mjs +1 -1
  1426. package/tests/module_store_howto.mjs +3 -3
  1427. package/tests/module_store_listing.mjs +139 -2
  1428. package/tests/module_store_publish.mjs +4 -4
  1429. package/tests/module_store_publish_route.mjs +1 -1
  1430. package/tests/module_store_reassess.mjs +1 -1
  1431. package/tests/module_store_registry_migration.mjs +1 -1
  1432. package/tests/module_test_runner.mjs +3 -3
  1433. package/tests/module_update.mjs +4 -4
  1434. package/tests/module_upgrade_updates.mjs +1 -1
  1435. package/tests/move_escalation.mjs +2 -2
  1436. package/tests/nav_permission_atoms.mjs +3 -2
  1437. package/tests/needs_rebase.mjs +7 -3
  1438. package/tests/newcomer_floor.mjs +1 -1
  1439. package/tests/next_number.mjs +1 -1
  1440. package/tests/no_artifact_escalation.mjs +3 -3
  1441. package/tests/npm_release_where.mjs +1 -1
  1442. package/tests/oauth_secret.mjs +2 -2
  1443. package/tests/onboard.mjs +6 -6
  1444. package/tests/onboarding_gate.mjs +2 -2
  1445. package/tests/opt_in_skill_modules.mjs +3 -3
  1446. package/tests/own_scope_guard.mjs +1 -1
  1447. package/tests/own_session_revoke.mjs +4 -1
  1448. package/tests/package_core.mjs +10 -11
  1449. package/tests/page_inventory.mjs +5 -5
  1450. package/tests/page_reader.mjs +7 -7
  1451. package/tests/page_tweak_hold.mjs +6 -6
  1452. package/tests/parallel-load.mjs +1 -1
  1453. package/tests/paste_token_api_base.mjs +1 -1
  1454. package/tests/paste_token_session_store.mjs +2 -2
  1455. package/tests/pending_invite_purge_db.mjs +1 -1
  1456. package/tests/permission_path.mjs +1 -1
  1457. package/tests/pin_replay.mjs +1 -1
  1458. package/tests/pin_write_key.mjs +7 -7
  1459. package/tests/plain_cards.mjs +15 -15
  1460. package/tests/pr_assign.mjs +1 -1
  1461. package/tests/pre_push_hook.mjs +3 -3
  1462. package/tests/preflight_checks.mjs +2 -2
  1463. package/tests/prelaunch_gate.mjs +1 -1
  1464. package/tests/privacy_matrix.mjs +1 -1
  1465. package/tests/probe_cache.mjs +6 -6
  1466. package/tests/profile_connections_ui.mjs +4 -3
  1467. package/tests/profile_fields.mjs +11 -1
  1468. package/tests/profile_privacy_owner_view.mjs +1 -1
  1469. package/tests/profile_role_headline.mjs +10 -9
  1470. package/tests/project_admin_console_model.mjs +1 -1
  1471. package/tests/projects_hub.mjs +1 -1
  1472. package/tests/projects_hub_cloud_hop.mjs +1 -1
  1473. package/tests/promote_goal_id.mjs +6 -6
  1474. package/tests/promotion_sweep.mjs +1 -1
  1475. package/tests/provision.mjs +24 -24
  1476. package/tests/provision_account_identity.mjs +2 -2
  1477. package/tests/provision_byo_host.mjs +1 -1
  1478. package/tests/provision_caddy_wiring.mjs +2 -2
  1479. package/tests/provision_disconnect.mjs +2 -2
  1480. package/tests/provision_dns_first.mjs +1 -1
  1481. package/tests/provision_render.mjs +9 -9
  1482. package/tests/provision_repo_private.mjs +3 -3
  1483. package/tests/provision_resource_caps.mjs +5 -5
  1484. package/tests/provision_restart.mjs +3 -3
  1485. package/tests/provision_settings_apply.mjs +7 -7
  1486. package/tests/provision_teardown_address.mjs +2 -2
  1487. package/tests/provisioning_capacity.mjs +5 -5
  1488. package/tests/provisioning_credential_preflight.mjs +1 -1
  1489. package/tests/provisioning_disconnect.mjs +1 -1
  1490. package/tests/provisioning_error_note_scope.mjs +4 -4
  1491. package/tests/provisioning_paid_shape_gate.mjs +2 -2
  1492. package/tests/provisioning_planet_physics.mjs +16 -0
  1493. package/tests/provisioning_runner_drift_notice.mjs +2 -2
  1494. package/tests/provisioning_settings_env.mjs +1 -1
  1495. package/tests/pruned_lockfile_integrity.mjs +1 -1
  1496. package/tests/public_mirror_export.mjs +1 -1
  1497. package/tests/publish_integration_gate.mjs +2 -2
  1498. package/tests/publish_manifest.mjs +6 -6
  1499. package/tests/publish_watch.mjs +1 -1
  1500. package/tests/push_path_brief.mjs +2 -2
  1501. package/tests/raise.mjs +248 -0
  1502. package/tests/rank_roles_audit.mjs +1 -1
  1503. package/tests/rank_tier_single_source.mjs +2 -2
  1504. package/tests/rate_limit_public.mjs +1 -1
  1505. package/tests/read_default_meter.mjs +2 -2
  1506. package/tests/read_session_export.mjs +1 -1
  1507. package/tests/rebase_gate_set_aside.mjs +1 -1
  1508. package/tests/recall_cli.mjs +1 -1
  1509. package/tests/recall_corpus_health.mjs +3 -2
  1510. package/tests/recall_hints.mjs +1 -1
  1511. package/tests/recruiter_sliver_boundary.mjs +1 -1
  1512. package/tests/redteam_patrol.mjs +2 -2
  1513. package/tests/regrade_actual_minutes.mjs +2 -2
  1514. package/tests/regrade_eligibility.mjs +2 -2
  1515. package/tests/release_core.mjs +2 -2
  1516. package/tests/release_notes.mjs +4 -4
  1517. package/tests/rename_history_restraint.mjs +3 -3
  1518. package/tests/rename_ledger_prose.mjs +6 -6
  1519. package/tests/render_api.mjs +1 -1
  1520. package/tests/render_check.mjs +4 -4
  1521. package/tests/render_deploy.mjs +1 -1
  1522. package/tests/repo_info_binding.mjs +1 -1
  1523. package/tests/repo_map.mjs +5 -5
  1524. package/tests/reward_mode_cost_plus_only.mjs +7 -3
  1525. package/tests/reward_mode_surfacing.mjs +1 -1
  1526. package/tests/role_responsibilities.mjs +1 -1
  1527. package/tests/route_permission_check.mjs +1 -1
  1528. package/tests/route_shadow_guard.mjs +1 -1
  1529. package/tests/route_validation.mjs +1 -1
  1530. package/tests/routine_capture_kind.mjs +24 -13
  1531. package/tests/routine_schedule.mjs +51 -9
  1532. package/tests/run_routine.mjs +5 -5
  1533. package/tests/run_routine_two_root.mjs +5 -5
  1534. package/tests/runner_drift.mjs +17 -17
  1535. package/tests/sandbox_stage.mjs +5 -5
  1536. package/tests/scope_map_guard.mjs +7 -7
  1537. package/tests/scouting_owner_access_and_reach.mjs +1 -1
  1538. package/tests/scripts_gds_forwarders.mjs +224 -0
  1539. package/tests/scrubber_corpus.mjs +2 -2
  1540. package/tests/seam_wiring_guard.mjs +1 -1
  1541. package/tests/search_ingest.mjs +2 -2
  1542. package/tests/search_ingest_db.mjs +1 -1
  1543. package/tests/search_ingest_nul.mjs +6 -6
  1544. package/tests/seed_verify_criteria.mjs +3 -3
  1545. package/tests/sequence.mjs +3 -3
  1546. package/tests/served_paths_shipped.mjs +3 -3
  1547. package/tests/session_506_regression.mjs +1 -1
  1548. package/tests/session_accessibility.mjs +1 -1
  1549. package/tests/session_caps.mjs +1 -1
  1550. package/tests/session_cost.mjs +1 -1
  1551. package/tests/session_digest.mjs +2 -2
  1552. package/tests/session_eval.mjs +6 -6
  1553. package/tests/session_index.mjs +1 -1
  1554. package/tests/session_records.mjs +4 -4
  1555. package/tests/session_rename_fallback.mjs +2 -2
  1556. package/tests/session_reward_on_land.mjs +7 -149
  1557. package/tests/session_reward_on_land_db.mjs +191 -0
  1558. package/tests/session_reward_reconcile.mjs +6 -88
  1559. package/tests/session_reward_reconcile_db.mjs +132 -0
  1560. package/tests/session_transcript.mjs +1 -1
  1561. package/tests/sessions_kit_pager.mjs +2 -1
  1562. package/tests/setup_device_flow_fallback.mjs +2 -2
  1563. package/tests/setup_smoke.mjs +12 -5
  1564. package/tests/setup_status_facts.mjs +54 -12
  1565. package/tests/ship_autolinkify.mjs +2 -2
  1566. package/tests/ship_automerge_injection.mjs +1 -1
  1567. package/tests/ship_base_flag.mjs +1 -1
  1568. package/tests/ship_broadcast_routing.mjs +1 -1
  1569. package/tests/ship_broadcast_server.mjs +2 -2
  1570. package/tests/ship_builder_model.mjs +1 -1
  1571. package/tests/ship_cannot_lie.mjs +9 -9
  1572. package/tests/ship_card.mjs +2 -2
  1573. package/tests/ship_ci_deploy.mjs +7 -7
  1574. package/tests/ship_error_shape.mjs +1 -1
  1575. package/tests/ship_land_ci_not_started.mjs +3 -3
  1576. package/tests/ship_land_conflict.mjs +3 -3
  1577. package/tests/ship_land_proof.mjs +3 -3
  1578. package/tests/ship_land_red_pr.mjs +5 -5
  1579. package/tests/ship_merge_gate.mjs +14 -14
  1580. package/tests/ship_mode.mjs +1 -1
  1581. package/tests/ship_mode_first_ship.mjs +4 -4
  1582. package/tests/ship_mode_hands_off.mjs +8 -8
  1583. package/tests/ship_post_land_verify.mjs +1 -1
  1584. package/tests/ship_preflight.mjs +19 -19
  1585. package/tests/ship_premerge.mjs +1 -1
  1586. package/tests/ship_publish_error.mjs +2 -2
  1587. package/tests/ship_push_diagnosis.mjs +1 -1
  1588. package/tests/ship_regen_copy_inventory.mjs +3 -3
  1589. package/tests/ship_resume.mjs +4 -4
  1590. package/tests/ship_smoke_gate.mjs +1 -1
  1591. package/tests/ship_upload_skip.mjs +1 -1
  1592. package/tests/ship_upstream_deletion.mjs +1 -1
  1593. package/tests/ship_vendored_instance.mjs +8 -8
  1594. package/tests/ship_visual_regrade.mjs +3 -3
  1595. package/tests/ship_zero_commit.mjs +1 -1
  1596. package/tests/skill_docs_unavailable_regrade.mjs +3 -3
  1597. package/tests/skill_friction_kind.mjs +1 -1
  1598. package/tests/skill_grade_recover.mjs +1 -1
  1599. package/tests/skill_grader_health.mjs +1 -1
  1600. package/tests/skill_lint.mjs +1 -1
  1601. package/tests/skill_menu_ruling.mjs +1 -1
  1602. package/tests/skill_preflight.mjs +7 -7
  1603. package/tests/skip_is_not_pass.mjs +22 -1
  1604. package/tests/smoke_dependencies_witness.mjs +2 -2
  1605. package/tests/smoke_preflight.mjs +1 -1
  1606. package/tests/smoke_target.mjs +2 -2
  1607. package/tests/smoke_write_contract.mjs +2 -2
  1608. package/tests/sound_player.mjs +8 -8
  1609. package/tests/source_text_test_ratchet.mjs +97 -0
  1610. package/tests/speciality_corpus_scope.mjs +1 -1
  1611. package/tests/speciality_session_skills.mjs +1 -1
  1612. package/tests/sso_checkin_legacy_field_gone.mjs +4 -2
  1613. package/tests/stale_timer.mjs +3 -3
  1614. package/tests/stale_worktrees.mjs +1 -1
  1615. package/tests/start_env_guard.mjs +1 -1
  1616. package/tests/start_goal_first.mjs +3 -3
  1617. package/tests/start_inbox_count.mjs +1 -1
  1618. package/tests/start_rebase_warning.mjs +1 -1
  1619. package/tests/status_default_version.mjs +3 -3
  1620. package/tests/status_mirror_sync.mjs +1 -1
  1621. package/tests/status_page_no_dead_uptime.mjs +80 -0
  1622. package/tests/stop_refcheck.mjs +1 -1
  1623. package/tests/strand_watch.mjs +1 -1
  1624. package/tests/stranded_rows.mjs +1 -1
  1625. package/tests/stuck_detector.mjs +14 -14
  1626. package/tests/sweep_app_account.mjs +3 -3
  1627. package/tests/task_cli.mjs +2 -2
  1628. package/tests/task_detail_ui.mjs +11 -1
  1629. package/tests/task_discipline_required.mjs +2 -2
  1630. package/tests/task_list_paging.mjs +1 -1
  1631. package/tests/task_visual_slots.mjs +2 -2
  1632. package/tests/terms_acceptance.mjs +1 -1
  1633. package/tests/terms_grandfather_db.mjs +1 -1
  1634. package/tests/test_path_guard.mjs +1 -1
  1635. package/tests/triage_development.mjs +1 -1
  1636. package/tests/tweak_batch_apply.mjs +2 -2
  1637. package/tests/tweak_land_heal.mjs +3 -3
  1638. package/tests/tweak_unattended.mjs +3 -3
  1639. package/tests/ui_design_skills.mjs +2 -2
  1640. package/tests/unit_report_status.mjs +2 -2
  1641. package/tests/unit_runner_serial.mjs +2 -2
  1642. package/tests/unit_runner_teardown_abort.mjs +1 -1
  1643. package/tests/update_channel.mjs +2 -2
  1644. package/tests/update_channel_db.mjs +4 -4
  1645. package/tests/update_subscription_engine.mjs +26 -26
  1646. package/tests/update_sweep_home.mjs +14 -14
  1647. package/tests/upgrade.mjs +11 -11
  1648. package/tests/upgrade_artist_gate.mjs +4 -4
  1649. package/tests/upgrade_commit_identity.mjs +2 -2
  1650. package/tests/upgrade_migrate.mjs +7 -7
  1651. package/tests/upgrade_operator.mjs +2 -2
  1652. package/tests/upgrade_outcome.mjs +2 -2
  1653. package/tests/upgrade_persist_pin.mjs +5 -5
  1654. package/tests/upkeep_home.mjs +1 -1
  1655. package/tests/version_close.mjs +2 -2
  1656. package/tests/version_close_cli.mjs +2 -2
  1657. package/tests/version_close_route.mjs +1 -1
  1658. package/tests/version_literals.mjs +23 -23
  1659. package/tests/visual_review.mjs +5 -5
  1660. package/tests/wedge_remedy.mjs +5 -5
  1661. package/tests/welcome_boot.mjs +116 -0
  1662. package/tests/welcome_boot_browser.mjs +271 -0
  1663. package/tests/wizard_born_first_board.mjs +3 -3
  1664. package/tests/wizard_demo.mjs +1 -1
  1665. package/tests/wizard_one_page.mjs +4 -3
  1666. package/tests/wizard_physics.mjs +3 -1
  1667. package/tests/wizard_physics_more.mjs +42 -3
  1668. package/tests/work_title_wrap.mjs +1 -1
  1669. package/tests/workflow_exec_paths.mjs +6 -6
  1670. package/tests/worktree_claim_guard.mjs +1 -1
  1671. package/tests/worktree_helper.mjs +2 -2
  1672. package/tests/write_validation_gaps.mjs +3 -3
  1673. package/scripts/gds/api.sh +0 -6
  1674. package/scripts/gds/artifact-staleness.js +0 -267
  1675. package/scripts/gds/audit-exports.js +0 -128
  1676. package/scripts/gds/classify-discipline.js +0 -153
  1677. package/scripts/gds/codemod-rename-src-gds.js +0 -145
  1678. package/scripts/gds/coreB-carve-proof.sh +0 -725
  1679. package/scripts/gds/goal-names.js +0 -102
  1680. package/scripts/gds/rename-goals.js +0 -109
  1681. package/scripts/gds/resolve-skill-model.js +0 -57
  1682. package/scripts/gds/security-baseline-check.sh +0 -180
  1683. package/scripts/gds/seed-adopt-tasks.js +0 -75
  1684. package/scripts/gds/seed-api-contract-goal-tasks.js +0 -141
  1685. package/scripts/gds/seed-board-room-tasks.js +0 -196
  1686. package/scripts/gds/seed-bongos-app-tasks.js +0 -294
  1687. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +0 -81
  1688. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +0 -100
  1689. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +0 -307
  1690. package/scripts/gds/seed-bongos-module-system-tasks.js +0 -346
  1691. package/scripts/gds/seed-bongos-tasks.js +0 -214
  1692. package/scripts/gds/seed-bongos-v1-seo-tasks.js +0 -104
  1693. package/scripts/gds/seed-bv1-community-tasks.js +0 -131
  1694. package/scripts/gds/seed-bv1-privacy-invites-tasks.js +0 -133
  1695. package/scripts/gds/seed-bv1-profile-page-tasks.js +0 -161
  1696. package/scripts/gds/seed-bv1-r01-delta-tasks.js +0 -154
  1697. package/scripts/gds/seed-bv2-tweak-mode-tasks.js +0 -277
  1698. package/scripts/gds/seed-gds-v4-tasks.js +0 -624
  1699. package/scripts/gds/seed-governance-tasks.js +0 -340
  1700. package/scripts/gds/seed-medusa-tasks.js +0 -440
  1701. package/scripts/gds/seed-module-upstreaming.js +0 -219
  1702. package/scripts/gds/seed-productization-tasks.js +0 -235
  1703. package/scripts/gds/seed-project-admin-console-tasks.js +0 -88
  1704. package/scripts/gds/seed-provisioning-tasks.js +0 -83
  1705. package/scripts/gds/seed-strict-versioning-tasks.js +0 -275
  1706. package/scripts/gds/seed-v2-world-tasks.js +0 -283
  1707. package/scripts/gds/spike-task-map.js +0 -899
  1708. package/scripts/migrate_cost_ledger.sh +0 -178
  1709. package/scripts/status-probe.mjs +0 -213
  1710. package/src/bongos/uptime-poller.js +0 -93
  1711. package/tests/artifact_staleness.mjs +0 -207
  1712. package/tests/goal_names.mjs +0 -120
  1713. package/tests/government_fold_bench.mjs +0 -50
  1714. package/tests/spike_task_map.mjs +0 -422
  1715. package/tests/status-probe.mjs +0 -89
  1716. /package/{scripts/gds → modules/raise}/CLAUDE.md +0 -0
  1717. /package/scripts/{gds → bongos}/cloudbongos-token-isolation.conf +0 -0
  1718. /package/scripts/{gds → bongos}/discipline-modes.json +0 -0
  1719. /package/scripts/{gds → bongos}/retired-core-skills.json +0 -0
@@ -1,1166 +1,6 @@
1
+ // scripts/gds/provision-core-upgrade.js — @bongos-forwarder (task 1004848). Generated by
2
+ // scripts/bongos/codemod-rename-scripts-gds.js; do not edit.
3
+ // The real script is scripts/bongos/provision-core-upgrade.js. This forwarder keeps callers that still name
4
+ // the old path working, and warns once so they get repointed. Task 1003706 removes it.
1
5
  'use strict';
2
-
3
- // scripts/gds/provision-core-upgrade.js — the owner's deploy door, CONTROL-PLANE half
4
- // (task 1003159, ADR 0293).
5
- //
6
- // The web tier queues a 'core-upgrade' intent naming a target version and gains no new
7
- // capability doing so (modules/provisioning/core-upgrade.js). THIS is the half that acts:
8
- // the runner drains that intent and drives the proven `bongos upgrade` path, with its
9
- // health gate, its served-version check and its auto-rollback (task 2149) intact.
10
- //
11
- // It is a DOOR ONTO THE PROVEN PATH, NOT A SECOND UPGRADE MECHANISM. Every step that
12
- // could get an upgrade wrong — install, migrate, pin, restart, verify, revert — already
13
- // lives in upgrade.js and is exercised by every hand-run bump. Re-implementing any of it
14
- // here would mean two paths that must stay in step, and the one used less often would be
15
- // the one that rots. So this file does exactly three things upgrade.js cannot do for
16
- // itself: decide whether the request is ALLOWED, decide whether the target is REAL, and
17
- // report what the box actually serves afterwards.
18
- //
19
- // WHY THE REGISTRY CHECK LIVES HERE AND NOT ON THE ROUTE (ADR 0293 D3). Answering "is
20
- // this version published" means `npm view`, which update-channel.js runs via spawnSync —
21
- // on the single-process web server that blocks every other request for the seconds npm
22
- // takes. Here it is a CLI process with nothing else to serve, and blocking is free. The
23
- // check is not optional tidiness: the release lane mints a git tag BEFORE the npm publish
24
- // completes (8–13 minutes, measured 2026-09-16 — learnings 1000263/1000266), so a door
25
- // that trusted the request would routinely queue a version that does not exist yet and
26
- // fail deep inside npm with `notarget`.
27
- //
28
- // Its own file because scripts/gds/provision.js sits at the 1500-line oversized-file
29
- // ratchet, the same reason provision-net.js and provision-units.js were carved out.
30
-
31
- const crypto = require('crypto');
32
- const fs = require('fs');
33
- const os = require('os');
34
- const path = require('path');
35
- const { spawnSync } = require('child_process');
36
- const { CONFIG, MANIFEST_VERIFY_INTERVAL_MS, MANIFEST_VERIFY_TRIES, REPO_ROOT } = require('./provision-config.js');
37
- const { appUser, dbName, instanceUser, parseTargetRef, resolveOwnerGithubToken, selfInstanceRoot, standaloneRoot } = require('./provision-repo.js');
38
- const { ensurePinWriteKey, hasOwnAccount, pinKeyPath, pinSshCommand } = require('./provision-pin-key.js');
39
- const { replayPinCommit } = require('./provision-pin-replay.js'); // GitHub ahead → pin on top (task 1004733)
40
- const { isValidSlug } = require('../../modules/provisioning/provisioning.js');
41
- const { RELEASE_NOTES_FILE, RELEASE_NOTES_MAX_BYTES, parseChangeRecords, notesBetween } = require('./release-notes.js');
42
- const outcome = require('./upgrade-outcome.js'); // how far a failed move got, as a class (task 1004446)
43
-
44
- // The shapes whose box this runner can actually reach. Mirrors UPGRADE_SHAPES in the
45
- // web-tier half, and deliberately EXCLUDES 'dedicated': a dedicated droplet is stood up
46
- // by cloud-init and the runner has no post-hoc exec path to it, so queueing an upgrade
47
- // for one would be a request that is accepted and never lands. The route refuses the
48
- // same shape; this is the second gate, and it is the one that holds if a row's shape
49
- // changes between the request and the drain.
50
- const UPGRADE_SHAPES = Object.freeze(new Set(['co-tenant', 'cloud-host', 'control-plane']));
51
-
52
- // The strict three-number form a core version takes. Re-stated here rather than imported
53
- // from the web tier's core-upgrade.js: a module may not be required from scripts/ (ADR
54
- // 0083) and this side needs it to guard a SHELL interpolation, which is a stricter duty
55
- // than validating a request body.
56
- const CORE_VERSION_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
57
-
58
- // The box's own answer to "what core am I running?" — loopback, on the instance's port.
59
- //
60
- // THE APEX CANNOT BE ASKED (ADR 0293 D6). It sits behind pre-launch basic_auth and its
61
- // HTML rides a CDN, so a public read can report a stale or gated answer with complete
62
- // confidence. 127.0.0.1 is the only address that is answering FROM the process whose
63
- // version is in question. This is the same reasoning healthzCmd already encodes, and the
64
- // DONE-WHEN task 1003156 established in so many words.
65
- function versionCmd(inst) {
66
- return `curl -sS --max-time 5 http://127.0.0.1:${inst.port}/version`;
67
- }
68
-
69
- // Pull coreVersion out of whatever /version answers with.
70
- //
71
- // TOLERANT BY DESIGN, and the tolerance is load-bearing rather than lazy. This reads a
72
- // process that may be running a core OLDER than the one that wrote this parser — that is
73
- // the entire point of an upgrade — so the shape of its response is not something this
74
- // side gets to assume. A body it cannot read returns null, which the caller reports as
75
- // "could not confirm", never as a mismatch: claiming the upgrade failed because the
76
- // reply was unfamiliar would roll back a perfectly good deploy.
77
- function parseServedVersion(stdout) {
78
- if (!stdout || typeof stdout !== 'string') return null;
79
- try {
80
- const j = JSON.parse(stdout);
81
- for (const k of ['coreVersion', 'core_version', 'version']) {
82
- if (typeof j[k] === 'string' && j[k].trim()) return j[k].trim();
83
- }
84
- } catch { /* not JSON — fall through to the text probe */ }
85
- const m = stdout.match(/\b\d+\.\d+\.\d+\b/);
86
- return m ? m[0] : null;
87
- }
88
-
89
- /**
90
- * The `schemaPending` count from a /version body — migrations the box's code ships that its
91
- * own database has not recorded (task 1004153). PURE.
92
- *
93
- * null means UNKNOWN (no answer, not JSON, or a core older than the field), never 0: a
94
- * co-tenant that cannot say must not read as one whose database is current. Bounded the
95
- * same way scripts/gds/deploy-divergence.js bounds it, since the body is a network answer.
96
- */
97
- function parseSchemaPending(stdout) {
98
- if (!stdout || typeof stdout !== 'string') return null;
99
- let n;
100
- try { n = JSON.parse(stdout).schemaPending; } catch { return null; }
101
- return Number.isInteger(n) && n >= 0 && n <= 100000 ? n : null;
102
- }
103
-
104
- /**
105
- * Is this target a version the instance may actually be moved to? PURE.
106
- *
107
- * Two separate questions, and conflating them is how a door starts lying:
108
- * • does it EXIST — is it published to the registry at all;
109
- * • is it ALLOWED — does this instance's channel policy admit it (ADR 0136).
110
- *
111
- * A version that exists but the channel forbids is a refusal the owner can act on
112
- * ("your channel is stable and that is a prerelease"); one that does not exist yet is a
113
- * refusal they can only wait out. Saying which is which is the difference between a
114
- * useful message and "upgrade failed".
115
- *
116
- * @param {string} to the requested version
117
- * @param {string[]} available versions the registry reports
118
- * @param {string} installed the version running now
119
- * @param {string} channel this instance's update channel
120
- */
121
- function targetFault(to, available, installed, channel, channelAllows, compare) {
122
- if (!Array.isArray(available) || available.length === 0) {
123
- return `could not read the published core versions from the registry — nothing was changed; the release may still be publishing (a tag is minted before the publish completes)`;
124
- }
125
- if (!available.includes(to)) {
126
- return `core ${to} is not published yet — nothing was changed. A release tag appears several minutes before the package itself does; try again once it lands.`;
127
- }
128
- // AN UNREADABLE `installed` IS A FAULT, NOT A FREE PASS (task 1004123).
129
- //
130
- // This guard used to be written `if (installed && …)`, so a null installed version
131
- // skipped the channel check entirely rather than failing it. That is backwards: not
132
- // knowing where an instance is today is the one state in which "is this jump
133
- // permitted" cannot be answered, and the channel exists precisely to refuse jumps
134
- // nobody has looked at. It also hid the defect that motivated this: the control
135
- // plane read its installed version from the wrong directory for weeks and got null
136
- // every time, and every press sailed past this line.
137
- if (!installed) {
138
- return `could not read the core version installed at this instance — nothing was changed. An upgrade that cannot say where it is starting from cannot be bounded by the '${channel}' channel.`;
139
- }
140
- // A TARGET THE BOX HAS ALREADY REACHED IS NOT A CHANNEL QUESTION (task 1004534).
141
- // channelAllows answers "may an unattended jump go here" and says no to anything not
142
- // strictly newer, so on 2026-10-01 a press for 1.20.73, landed a minute earlier by the
143
- // sweep, was reported as "outside this project's 'minor' update channel … across a major
144
- // version or onto a prerelease" — false on every count, and it put a "your call" card on
145
- // /deploy for a project that was simply up to date. Already there: no fault, so the
146
- // caller's already-serving no-op answers it. Already past it: say that, in words that
147
- // classify as a downgrade, never as the update rule.
148
- if (installed === to) return null;
149
- if (compare && compare(to, installed) < 0) {
150
- return `core ${to} is older than the core this project already runs (it already runs core ${installed}) — nothing was changed. A move never goes back to an older core on its own.`;
151
- }
152
- if (channelAllows && !channelAllows(installed, to, channel)) {
153
- return `core ${to} is outside this project's '${channel}' update channel — nothing was changed. ${channelNextStep(channel)}`;
154
- }
155
- return null;
156
- }
157
-
158
- // The step that gets a channel-refused move through, named by the control a person can
159
- // actually reach (task 1004405). The old line said "change the channel first" while no
160
- // channel could be changed; the update rule on /deploy (task 1004445) is that control now,
161
- // and its labels are the words used here. `minor` is the widest rule, so a move it refuses
162
- // (a major, a prerelease) has no rule to widen to and is named as the by-hand step it is.
163
- function channelNextStep(channel) {
164
- if (channel === 'pinned') {
165
- return 'Its update rule on /deploy is "Stay put"; change it to "Fixes only" or "Fixes and new releases", then move again.';
166
- }
167
- if (channel === 'minor') {
168
- return 'No update rule moves a project across a major version or onto a prerelease; that move is made by hand with upgrade.js (docs/recipes/upgrading-the-core.md).';
169
- }
170
- return 'To take a new release line, set this project\'s update rule on /deploy to "Fixes and new releases" (or press "Allow new releases and move"), then move again.';
171
- }
172
-
173
- // The update channel that bounds a move for THIS instance (task 1004445): the row's own
174
- // `update_channel`, normalised by update-channel.js so anything unknown or absent (a row
175
- // read before migration provisioning_029) falls back to DEFAULT_CHANNEL. PURE. One helper
176
- // for the move and the snapshot, so the button's offer and the runner's refusal cannot
177
- // disagree about which rule applies.
178
- function instanceChannel(inst, channelMod) {
179
- return channelMod.normalizeChannel(inst && inst.update_channel != null ? inst.update_channel : channelMod.DEFAULT_CHANNEL);
180
- }
181
-
182
- // The versions this project may be moved to: the published ones its FOLLOW admits (task 1004298,
183
- // ADR 0361). The platform hall (control-plane) takes every candidate; every other project only what
184
- // has been released, and NOTHING when the registry cannot say which version that is — a project that
185
- // follows releases is never moved on a guess. A channel module without the follow (an old core
186
- // resolved at drain time) offers the whole list, which is what every version meant before candidates.
187
- //
188
- // The released label is one fact about the registry, the same for every project in a pass, and
189
- // reading it is a blocking `npm view`. So it is read once per channel module per RELEASE_TAGS_TTL_MS
190
- // and shared: a pass over N projects costs one extra subprocess, not N. A failed read is not kept.
191
- const RELEASE_TAGS_TTL_MS = 60 * 1000;
192
- const releaseTagsMemo = new WeakMap();
193
- function releaseTagsFor(channelMod, instanceDir, now = Date.now()) {
194
- const hit = releaseTagsMemo.get(channelMod);
195
- if (hit && now - hit.at < RELEASE_TAGS_TTL_MS) return hit.tags;
196
- const tags = channelMod.readReleaseTags({ cwd: instanceDir });
197
- if (tags && tags.ok) releaseTagsMemo.set(channelMod, { at: now, tags });
198
- return tags;
199
- }
200
-
201
- function offeredVersions(channelMod, inst, instanceDir) {
202
- const listed = channelMod.listAvailableVersions({ cwd: instanceDir });
203
- if (!listed || !listed.ok || typeof channelMod.followForShape !== 'function') return listed;
204
- if (channelMod.followForShape(inst && inst.hosting_shape) === 'candidates') return listed;
205
- const tags = releaseTagsFor(channelMod, instanceDir);
206
- if (!tags.ok) return { ok: false, error: `could not read which version is released (${tags.error})`, versions: [] };
207
- return { ok: true, versions: channelMod.versionsForFollow({ follow: 'released', available: listed.versions, released: tags.released }) };
208
- }
209
-
210
- // A classified refusal (task 1004446): the drain loop stores `failure` beside last_error,
211
- // so the rest of the self-heal chain acts on a class, not on a sentence. PURE.
212
- function failed(reason, error, extra = {}) {
213
- return { ok: false, error, failure: outcome.classifyFailure(reason), ...extra };
214
- }
215
-
216
- // The builder id a queued move is attributed to, from the actor the web tier recorded.
217
- // PURE. Two doors reach the move (ADR 0339): an Archon (`api:archon:<id>`) and, since
218
- // task 1004174, the project's own owner (`api:owner:<id>`). Both carry the id, because
219
- // it becomes `--requested-by` on the core_upgrades ledger (ADR 0293 D5). Anything else
220
- // yields '' — the id is interpolated into a shell command, so only digits ever pass.
221
- function requestedByOf(intent) {
222
- const m = intent && typeof intent.requested_by === 'string' && /^api:(?:archon|owner):(\d+)$/.exec(intent.requested_by);
223
- return m ? m[1] : '';
224
- }
225
-
226
- /**
227
- * Perform a queued core-pin move. Returns { ok } — NEVER throws for an expected refusal.
228
- *
229
- * The drain loop's catch flips the instance to 'error', which is the wrong outcome for
230
- * every refusal here: a request that was never valid, or a version that is not published
231
- * yet, says nothing at all about the health of a running instance. So each of those
232
- * returns { ok:false, error } and the loop retries or retires the INTENT, leaving the
233
- * instance exactly as it found it (ADR 0190 §2, the shape restartInstance established).
234
- *
235
- * @param {object} inst the provisioning_instances row
236
- * @param {object} deps the runner's dependency bag
237
- * @param {object} intent the claimed provisioning_intents row (carries target_version)
238
- */
239
- async function coreUpgradeInstance(inst, deps, intent) {
240
- const { db, provisioning, exec, log, apply, privileged } = deps;
241
- // A standalone's box IS the control plane's box, the same routing restartInstance and
242
- // settingsApplyInstance use; a co-tenant shares this checkout.
243
- const boxExec = inst.hosting_shape === 'cloud-host' ? (deps.controlExec || exec) : exec;
244
- const to = intent && intent.target_version;
245
- log(`core-upgrade ${inst.slug} → ${to || '(no target)'} (shape=${inst.hosting_shape}, status=${inst.status})`);
246
-
247
- // ---- 1. is this request allowed at all ------------------------------------------
248
- // UPGRADE_SHAPES IS THE WHOLE SHAPE CHECK. The self-row guard is deliberately not
249
- // consulted: `intentAllowedForShape('core-upgrade', …)` is true for every shape
250
- // there is, because 'core-upgrade' is permanently on CONTROL_PLANE_ACTIONS — so
251
- // calling it here would read as a second gate while being unable to refuse
252
- // anything. The guard's real job is the OTHER actions on the self row, enforced at
253
- // enqueueIntent where every intent passes.
254
- if (!UPGRADE_SHAPES.has(inst.hosting_shape)) {
255
- return failed('shape_not_automated', `core-upgrade is not automated for a '${inst.hosting_shape}' instance — whoever runs that machine has to upgrade it there`);
256
- }
257
- if (inst.status !== 'active') {
258
- // Not an error: a teardown or a stand-up that raced the request must not burn the
259
- // intent's retry budget, and there is no settled pin to move either way.
260
- log(` instance is '${inst.status}' — no running core whose pin can move`);
261
- return { ok: true, noop: true };
262
- }
263
- if (!to) {
264
- return failed('no_target', 'core-upgrade intent carries no target_version — refusing to guess which version was meant');
265
- }
266
- // THE SLUG IS INTERPOLATED INTO A SHELL COMMAND BELOW, so it is re-checked HERE
267
- // rather than trusted. `isValidSlug` is enforced on the create route, but the
268
- // control-plane self row is inserted by an operator script (enroll-control-plane.js)
269
- // and any later write path is one more place that would have to remember. The value
270
- // reaching a shell is this function's problem, and a format check at the point of use
271
- // is the only one that cannot be bypassed by a path nobody has written yet. The other
272
- // two interpolated values are already constrained — the version by the column's own
273
- // CHECK and by VERSION_RE, the actor by the digits-only extraction below.
274
- if (!isValidSlug(inst.slug)) {
275
- return failed('bad_slug', `instance slug '${inst.slug}' is not a valid slug — refusing to build a command from it`);
276
- }
277
-
278
- // ---- 2. is the target real, and permitted -----------------------------------------
279
- const channelMod = deps.updateChannel || require('./update-channel.js');
280
- const selfRoot = deps.selfInstanceRoot || selfInstanceRoot;
281
- const instanceDir = inst.hosting_shape === 'cloud-host' ? standaloneRoot(inst) : selfRoot();
282
- const readInstalled = deps.readInstalledCoreVersion || require('./upgrade.js').readInstalledCoreVersion;
283
- const installed = readInstalled(instanceDir);
284
- // THIS PROJECT'S OWN UPDATE RULE (task 1004445, migration provisioning_029). Before it
285
- // every instance was bounded by DEFAULT_CHANNEL (patch-only), so a step-up release
286
- // could reach no project through the door and the refusal's "change the channel first"
287
- // pointed at nothing. A row from before the column (undefined) still normalises to that
288
- // default, so an old runner schema reads exactly as it always did.
289
- const channel = instanceChannel(inst, channelMod);
290
- const listed = offeredVersions(channelMod, inst, instanceDir);
291
- const available = (listed && listed.versions) || [];
292
- const fault = targetFault(to, available, installed, channel, channelMod.channelAllows, channelMod.compareSemver);
293
- if (fault) return failed(outcome.runnerReason(fault), fault);
294
- if (installed && installed === to) {
295
- // `bongos upgrade` would no-op on this too, but saying so here keeps a re-drained
296
- // intent from restarting a healthy service to land exactly where it already is.
297
- log(` already serving core ${to} — nothing to move`);
298
- return { ok: true, noop: true };
299
- }
300
- // ---- 2b. is the database current for the code it runs NOW (task 1004448) -------------
301
- // A database behind its own code is already failing every page that touches the missing
302
- // tables (the 2026-07-04 shape), and moving the code on top of it tangles a catch-up
303
- // migration into a pin move. So it is refused as a known snag, and wedge-remedy.js
304
- // migrates that database and tries the move once more. An answer it cannot read proceeds.
305
- if (apply) {
306
- const probe = boxExec(versionCmd(inst), { allowFail: true });
307
- const pending = parseSchemaPending(probe && !probe.softFailed ? (probe.stdout || '') : null);
308
- if (pending > 0) return failed('schema_pending', `the project's database is ${pending} migration(s) behind the code it is running now — it has to catch up before the core moves`);
309
- }
310
-
311
- // ---- 3. drive the proven path -----------------------------------------------------
312
- // Exactly the invocation docs/recipes/core-release-pipeline.md gate 3 documents, plus
313
- // the two attribution flags (ADR 0293 D5). --commit-pin is NOT optional here: without
314
- // it the pin lives only in the working tree, and the next pull-deploy resets it away —
315
- // the silent thirteen-release revert upgrade.js's own header records.
316
- const versionUrl = `http://127.0.0.1:${inst.port}/version`;
317
- const requestedBy = requestedByOf(intent);
318
- // Built by the SAME function the preview uses, so "what you were shown" and "what runs"
319
- // cannot drift apart into two hand-maintained flag lists (task 1004121).
320
- // The preview probes; the move must probe identically or the two commands diverge on
321
- // the one field task 1004121 exists to keep identical. Skipped when !apply, where the
322
- // command is printed and never run — a plan should not spend a subprocess per tick.
323
- const { runAs, migrateAs } = resolveRunAs(inst, deps, { probe: apply });
324
- // A move the hub queued by itself (provision-auto-upgrade.js) says so in the project's
325
- // own ledger, so its hall can tell its owner "upgraded automatically" (task 1004731).
326
- const automatic = !!intent && intent.requested_by === 'runner:auto-upgrade';
327
- const { cmd, runDir } = upgradeInvocation(inst, to, { privileged, requestedBy, automatic, selfRoot, runAs, migrateAs });
328
-
329
- if (!apply) {
330
- // A --dry-run runner tick used to only PRINT this command. It now runs the CLI's own
331
- // dry run, so `provision.js --dry-run` reports what the upgrade would actually refuse
332
- // rather than a command string the reader has to evaluate in their head.
333
- log(` ✓ would run (in ${runDir}): ${cmd}`);
334
- const verdict = (deps.preflightUpgrade || preflightUpgrade)(inst, to, deps);
335
- for (const line of verdict.lines || []) log(` ✓ pre-flight: ${line}`);
336
- if (!verdict.ok) log(` ✖ ${verdict.error}`);
337
- log(` ✓ would then read ${versionUrl} on the box and require it to say ${to}`);
338
- return { ok: true, served: null, preflight: verdict };
339
- }
340
- try {
341
- log(` [upgrade] (in ${runDir}) ${cmd}`);
342
- boxExec(cmd, { cwd: runDir });
343
- } catch (e) {
344
- // HOW FAR IT GOT, from upgrade.js's own outcome line (task 1004446) — never assumed.
345
- // It used to say "failed and was rolled back" for every exit, including refusals that
346
- // fire before the pin moves (nothing changed) and rollbacks that themselves failed
347
- // (the project may be down). ok:false, never a throw: the drain loop's catch marks the
348
- // INSTANCE broken, which is only ever right for the rollback_failed case, and that one
349
- // is reported (and retired, never retried unattended) rather than guessed at here.
350
- const text = `${(e && e.stderr) || ''}\n${(e && e.message) || e}`;
351
- const o = outcome.parseOutcomeLine(text);
352
- const said = (/✖ ([^\n]+)/.exec(text) || [])[1] || String((e && e.message) || e).split('\n')[0];
353
- const reason = o ? o.reason : 'unknown';
354
- return failed(reason, outcome.describeUpgradeFailure(to, o, said), { stage: o ? o.stage : null, terminal: reason === 'rollback_failed' });
355
- }
356
-
357
- // ---- 4. read back what the BOX serves (ADR 0293 D6) --------------------------------
358
- // With the same patience the manifest probe uses: the service has just restarted and a
359
- // single immediate read races it binding its port. A false "did not take" here is
360
- // never cosmetic — it is what the owner is shown after the one act they were told they
361
- // could finally perform.
362
- const sleep = deps.sleep || ((ms) => new Promise((r) => setTimeout(r, ms)));
363
- let served = null;
364
- for (let i = 0; i < MANIFEST_VERIFY_TRIES; i++) {
365
- const res = boxExec(versionCmd(inst), { allowFail: true });
366
- served = parseServedVersion(res && !res.softFailed ? (res.stdout || '') : null);
367
- if (served) break;
368
- if (i < MANIFEST_VERIFY_TRIES - 1) await sleep(MANIFEST_VERIFY_INTERVAL_MS);
369
- }
370
- if (served && served !== to) {
371
- // upgrade.js's own --version-url gate should have caught and reverted this, so
372
- // reaching here means the two disagree. Report what was SEEN rather than a verdict.
373
- return failed('served_mismatch', `the box is serving core ${served}, not the requested ${to} — the move did not take`);
374
- }
375
-
376
- // ---- 5. the pin reaches the project's own repo, pushed from HERE (task 1004065) ----
377
- // Only now: a pin worth saving is one the box is serving. upgrade.js was told
378
- // --pin-no-push for this shape, so it committed and stopped; see pushUpgradePin.
379
- const repo = hubPushesPin(inst) ? await pushUpgradePin(inst, deps, { instanceDir }) : null;
380
- const unsaved = repo && !repo.pushed ? `; GitHub was not updated (${repo.code})` : '';
381
- await provisioning.recordEvent(db, {
382
- instanceId: inst.id, ownerBuilderId: inst.owner_builder_id, event: 'core-upgraded',
383
- detail: (served ? `core pin moved to ${served}` : `core pin moved to ${to}; the box did not answer /version, so this is unconfirmed`) + unsaved,
384
- actor: intent.requested_by || 'runner',
385
- }).catch(() => {});
386
- if (provisioning.clearErrorNote) await provisioning.clearErrorNote(db, inst.id, 'core-upgrade').catch(() => {});
387
- log(served ? ` ✓ ${inst.slug} serves core ${served}` : ` ⚠ ${inst.slug} upgraded to ${to}, but did not answer /version — unconfirmed`);
388
- // `doneNote`: the drain loop resolves the intent DONE and stores this beside it, which
389
- // is how the deploy page learns the upgrade landed but GitHub did not get it.
390
- return { ok: true, served, confirmed: served === to, repo, doneNote: repo && !repo.pushed ? repo.note : null };
391
- }
392
-
393
- // ── the pin reaches the project's GitHub repo, pushed from the HUB (task 1004065) ──
394
- //
395
- // THE BUG THIS EXISTS FOR. upgrade.js commits the new pin on the box and then pushes it.
396
- // On a hosted project it runs connected to the PROJECT's database — it has to, for
397
- // migrations — while the owner's GitHub token lives in the HUB's. Its token lookup found
398
- // no provisioning table there (ADR 0281), fell back to `git push origin`, and origin is a
399
- // read-only deploy key (ADR 0176). GitHub refused, the refusal reached only the journal
400
- // and named the wrong cause, and the intent resolved `done`. The box ran the new core,
401
- // GitHub still pinned the old one, and the box's local commit stopped its fast-forward
402
- // pulls from taking the owner's new work: hermeslines-marketing served 1.19.994 against
403
- // a repo pinning 1.19.881, and pages pushed to that repo 404'd on the live site.
404
- //
405
- // WHY THE RUNNER PUSHES rather than handing upgrade.js the token. This process already
406
- // holds the hub's database, where the token is, and it runs as the account that owns the
407
- // checkout (the project's own account only READS it — grantInstanceRepoReadCmd). Passing
408
- // the token into the upgrade would put a credential that can write the repo inside the
409
- // project's own process. So the move passes --pin-no-push, upgrade.js commits, and the
410
- // push happens here, in the shape refreshStandaloneCorePin already uses for this repo.
411
- //
412
- // A FAILED PUSH IS NOT A FAILED UPGRADE. The site runs the new core, and rolling a good
413
- // deploy back would be worse than the split. The move still resolves `done`, carrying a
414
- // note the deploy page reads: `repo_not_updated:<code>: <sentence>`, parsed by
415
- // parseRepoNote in modules/provisioning/core-upgrade.js (re-stated there because a
416
- // module may not require a script; tests/core_upgrade_runner.mjs round-trips the two).
417
- //
418
- // NOTHING IS FORCED, AND THE LIVE BOX IS NEVER REBASED. When GitHub has commits the box
419
- // does not, moving the box onto them would change what it runs with no restart and no
420
- // health check. Since task 1004733 the pin commit ALONE is replayed onto GitHub's history in
421
- // a scratch worktree and pushed as an ordinary fast-forward (provision-pin-replay.js), so
422
- // GitHub names the new core and the box stays exactly what the move proved. A conflict in
423
- // the pin files is reported ("conflict"), never resolved here. The box still does not pick
424
- // up the owner's other commits — that would be a deploy, not a pin push (ADR 0350 amendment).
425
- //
426
- // WHAT MAKES IT DURABLE (task 1004291, ADR 0350). The owner's token is kept for an hour
427
- // after they sign in with repository access (GITHUB_TOKEN_TTL_MS in src/bongos/db.js — one
428
- // wizard sitting), so on its own it cannot carry an upgrade days later. The hub therefore
429
- // holds a per-project WRITE deploy key (provision-pin-key.js) and tries it FIRST: write key
430
- // → owner token (when fresh) → the box's own remote, which can only read a private repo.
431
- // A fresh token also mints the key when the project has none, so reconnecting GitHub once
432
- // is enough for every later upgrade. The note says which of these is missing, in words.
433
-
434
- const REPO_NOTE_PREFIX = 'repo_not_updated';
435
- const REPO_NOTES = Object.freeze({
436
- no_repo: 'This project has no GitHub repository on record, so the new version was saved on the server only.',
437
- no_branch: 'The server\'s copy of the project is not on a branch, so there was nothing to save to GitHub.',
438
- no_access: 'The hub had no permission to write to the project\'s GitHub repository: it holds no write key for it yet, the owner\'s GitHub access is only kept for an hour after they connect GitHub, and the server\'s own key can only read the repository. Reconnecting GitHub with repository access sets up lasting access.',
439
- needs_account: 'The hub could not set up lasting write access to the project\'s GitHub repository: this project needs its own account on the server first. Once it has one, reconnecting GitHub with repository access sets up lasting access.',
440
- refused: 'GitHub turned down the owner\'s GitHub access — it may have expired, or lack permission to write to the repository.',
441
- behind: 'GitHub has changes the server does not have, so the new version could not be added on top of them. An operator needs to bring the two back in line; the site itself is running normally.',
442
- conflict: 'GitHub has its own changes to the same version files (package.json or package-lock.json), so the new version was not added on top of them and nothing there was overwritten. An operator needs to choose between the two; the site itself is running normally.',
443
- failed: 'The hub could not save the new version to GitHub.',
444
- });
445
- // A branch name that is safe to interpolate. Narrower than git's own ref grammar on
446
- // purpose: a name outside it is refused, never quoted.
447
- const BRANCH_RE = /^[A-Za-z0-9][A-Za-z0-9._/-]{0,99}$/;
448
-
449
- /** The note a done-but-unsaved move carries, bounded for the DOM it reaches. PURE. */
450
- function repoNote(code, extra = '') {
451
- const known = Object.prototype.hasOwnProperty.call(REPO_NOTES, code) ? code : 'failed';
452
- return `${REPO_NOTE_PREFIX}:${known}: ${REPO_NOTES[known]}${extra ? ` ${extra}` : ''}`.slice(0, 600);
453
- }
454
-
455
- // Which shapes get their pin pushed from here: a hosted project, whose repo is the
456
- // owner's own. The platform's own row pushes to a repo its key CAN write, and a
457
- // co-tenant shares the platform's checkout, so neither changes.
458
- function hubPushesPin(inst) { return !!inst && inst.hosting_shape === 'cloud-host'; }
459
-
460
- // Why a push did not happen, from what git said. `behind` is checked first: a rejected
461
- // update means the credential WORKED and the history is what stopped it.
462
- function pushFault(r) {
463
- const said = `${(r && r.stdout) || ''}\n${(r && r.stderr) || ''}`;
464
- if (/\[rejected\]|non-fast-forward|fetch first|Updates were rejected/i.test(said)) return 'behind';
465
- if (/\b403\b|Authentication failed|Invalid username or password|Write access to repository not granted|Permission to \S+ denied|marked as read only|Permission denied \(publickey\)|could not read Username/i.test(said)) return 'refused';
466
- return 'failed';
467
- }
468
-
469
- // GitHub's own line beats git's closing `fatal:`, which names no reason (upgrade.js
470
- // gitSaid has the same preference).
471
- function gitLine(r) {
472
- const lines = String((r && r.stderr) || '').split('\n').map((l) => l.trim()).filter(Boolean);
473
- const server = lines.filter((l) => /^(ERROR:|remote:|!)/i.test(l));
474
- const said = server.length ? server[server.length - 1] : lines[lines.length - 1];
475
- return said ? `(git: ${said.slice(0, 200)})` : '';
476
- }
477
-
478
- /**
479
- * Push a confirmed upgrade's committed pin to the project's repo. NEVER THROWS: every
480
- * miss returns `{ pushed:false, code, note }`, because the drain loop turns a throw into
481
- * a broken instance and this instance is running fine.
482
- *
483
- * The token rides a chmod-600 credential file that is removed whatever the push did —
484
- * never argv (ps, the journal), never a log line. The helper list is reset first
485
- * (helpers are cumulative, so a global one would answer with some other account) and
486
- * hooks are off, so nothing in the project's checkout runs as this account.
487
- */
488
- async function pushUpgradePin(inst, deps, { instanceDir }) {
489
- const log = deps.log || (() => {});
490
- // The CONTROL PLANE's executor and writer: the checkout, the hub db and the token are
491
- // all here, never on a remote co-hosting box (refreshStandaloneCorePin's routing).
492
- const exec = deps.controlExec || deps.exec;
493
- const writeFile = deps.controlWriteFile || deps.writeFile || ((p, body, o) => fs.writeFileSync(p, body, o));
494
- const failedRun = (r) => !r || r.softFailed === true || r.ok === false;
495
- const miss = (code, extra = '') => {
496
- log(` ⚠ ${inst.slug}: GitHub was not updated — ${REPO_NOTES[code] || REPO_NOTES.failed}${extra ? ` ${extra}` : ''}`);
497
- return { pushed: false, code, note: repoNote(code, extra) };
498
- };
499
- const repo = parseTargetRef(inst.target_ref);
500
- if (!repo) return miss('no_repo');
501
- // Exported and callable on its own, and the slug reaches shell strings below (the write
502
- // key's path), so it is checked here rather than trusting coreUpgradeInstance's own guard.
503
- if (!isValidSlug(inst.slug)) return miss('failed', '(the project name is not a valid slug)');
504
- const head = exec(`git -C ${instanceDir} symbolic-ref --short HEAD`, { allowFail: true });
505
- const branch = failedRun(head) ? '' : String(head.stdout || '').trim();
506
- if (!BRANCH_RE.test(branch)) return miss('no_branch');
507
- const at = `${repo.owner}/${repo.name}@${branch}`;
508
- const hardened = `git -C ${instanceDir} -c core.hooksPath=/dev/null`;
509
- const env = { GIT_TERMINAL_PROMPT: '0' }; // a refused credential fails; it never waits at a prompt
510
- // GitHub is ahead: replay the pin commit alone on top, over the credential that was just
511
- // refused as behind, and push again — never forced (task 1004733, provision-pin-replay.js).
512
- const replayed = (via, git, remote) => {
513
- const rr = replayPinCommit({ exec, instanceDir, branch, git, remote, env, slug: inst.slug, tmpDir: deps.tmpDir, pushFault, gitLine, log });
514
- if (!rr.ok) return miss(rr.code, rr.extra);
515
- if (rr.already) log(` ✓ ${at} already names this version — nothing to add`);
516
- return { pushed: true, via, branch, ...(rr.replayed ? { replayed: true } : { already: true }) };
517
- };
518
-
519
- const token = await resolveOwnerGithubToken(inst, deps, { tag: '[core-upgrade]' });
520
-
521
- // 1. The hub's own WRITE key (ADR 0350). A fresh token mints it when the project has
522
- // none yet — the reconnect the deploy page asks for — and the mint is best effort: a
523
- // miss falls through to the token, then to the box's remote, exactly as before.
524
- const fsImpl = deps.fsImpl || fs;
525
- const keyPath = pinKeyPath(inst, deps);
526
- if (token && !fsImpl.existsSync(keyPath)) await ensurePinWriteKey(inst, deps, { token });
527
- if (fsImpl.existsSync(keyPath)) {
528
- const r = exec(`${hardened} -c ${pinSshCommand(keyPath)} push git@github.com:${repo.owner}/${repo.name}.git HEAD:${branch}`,
529
- { allowFail: true, env });
530
- if (!failedRun(r)) {
531
- log(` ✓ pushed the pin to ${at} from the hub, over its write deploy key`);
532
- return { pushed: true, via: 'write-key', branch };
533
- }
534
- const fault = pushFault(r);
535
- // The key WORKED and the history stopped it: no other credential changes that, so the
536
- // pin is replayed on top of GitHub's history over this same key (task 1004733).
537
- if (fault === 'behind') return replayed('write-key', `${hardened} -c ${pinSshCommand(keyPath)}`, `git@github.com:${repo.owner}/${repo.name}.git`);
538
- log(` • ${inst.slug}: the write key did not push (${fault}) — trying the next credential`);
539
- }
540
-
541
- if (token) {
542
- const credFile = path.join(os.tmpdir(), `bongos-gitcred-upgrade-${inst.slug}-${process.pid}-${crypto.randomBytes(6).toString('hex')}`);
543
- let r = null;
544
- try {
545
- writeFile(credFile, `https://x-access-token:${token}@github.com\n`, { mode: 0o600 });
546
- const viaToken = `${hardened} -c credential.helper= -c credential.helper='store --file=${credFile}'`;
547
- const tokenRemote = `https://x-access-token@github.com/${repo.owner}/${repo.name}.git`;
548
- r = exec(`${viaToken} push ${tokenRemote} HEAD:${branch}`, { allowFail: true, env });
549
- // Behind: replayed while the credential file still exists (the finally removes it).
550
- if (failedRun(r) && pushFault(r) === 'behind') return replayed('owner-token', viaToken, tokenRemote);
551
- } catch (e) {
552
- return miss('failed', `(could not stage the owner's credential: ${String((e && e.message) || e).slice(0, 160)})`);
553
- } finally {
554
- exec(`rm -f ${credFile}`, { allowFail: true });
555
- }
556
- if (!failedRun(r)) {
557
- log(` ✓ pushed the pin to ${at} from the hub, over the owner's GitHub token`);
558
- return { pushed: true, via: 'owner-token', branch };
559
- }
560
- return miss(pushFault(r), gitLine(r));
561
- }
562
-
563
- // No token stored — which is the ordinary case (see THE LIMIT above). The box's own
564
- // remote is still tried: a checkout wired with a key that can write is not wrong to use.
565
- const r = exec(`${hardened} push origin HEAD:${branch}`, { allowFail: true, env });
566
- if (!failedRun(r)) {
567
- log(` ✓ pushed the pin to ${at} from the hub, over the checkout's own remote`);
568
- return { pushed: true, via: 'origin', branch };
569
- }
570
- const fault = pushFault(r);
571
- if (fault === 'behind') return replayed('origin', hardened, 'origin');
572
- // A refusal here is not the owner's access being turned down — there was none to turn
573
- // down. It is the read-only key, which is the no-access case.
574
- // ...unless the project has no account of its own, in which case no key CAN be minted
575
- // for it (ADR 0350) and reconnecting GitHub alone will not help: say that instead.
576
- if (fault === 'refused') return miss(hasOwnAccount(inst, exec) ? 'no_access' : 'needs_account', gitLine(r));
577
- return miss(fault, gitLine(r));
578
- }
579
-
580
- // The pre-flight lines a dry run emits, and the refusal when it has one. upgrade.js writes
581
- // its pre-flight to stdout as ` ✓ pre-flight: …` and returns a `✖`-prefixed multi-line
582
- // error on a refusal, so BOTH streams matter: a pass is only legible from stdout, and a
583
- // refusal only from the failure text. PURE given its input.
584
- function parsePreflight(out) {
585
- const text = String(out || '');
586
- const lines = text.split('\n').map((l) => l.trim());
587
- const checks = lines.filter((l) => /^[✓✖]\s*pre-flight:/.test(l)).map((l) => l.replace(/^[✓✖]\s*/, ''));
588
- // A refusal is whatever upgrade.js said after the ✖ — reported verbatim rather than
589
- // re-worded, because its wording already names the fix ("Set PGDATABASE, or …").
590
- const failAt = text.indexOf('✖');
591
- const error = failAt >= 0 ? text.slice(failAt + 1).trim() : null;
592
- return { checks, error };
593
- }
594
-
595
- /**
596
- * Which unix accounts does this instance's upgrade need? Asks the box (task 1004128).
597
- *
598
- * TWO ANSWERS, NOT ONE (task 1004512). Task 1004128 asked a single question — "which
599
- * account does this instance run as?" — and ran the WHOLE move as it. That is right for
600
- * the database and wrong for the files, and the two have different owners on every
601
- * project provisioned since task 1003369:
602
- *
603
- * • `runAs` — the account that owns the CHECKOUT, which is the app user on every
604
- * hosting shape (provision-repo.js scaffolds /srv/<base>/<slug> as the runner, and
605
- * grantInstanceRepoReadCmd gives the project's own account group READ, nothing more).
606
- * Everything the move writes — the pin, node_modules, .claude/, the pin commit — and
607
- * the `git status` it starts with, belong to this account. Running them as the
608
- * project's account is what made every such move die on `fatal: detected dubious
609
- * ownership in repository` and report a dirty tree that did not exist.
610
- * • `migrateAs` — the project's OWN account, which is also its Postgres login role
611
- * (provision-repo.js instanceDbRole); its database is owned by that role with CONNECT
612
- * revoked from PUBLIC, so this is the only identity that can migrate it. That is where
613
- * the isolation of task 1003369 actually lives, and it is kept.
614
- *
615
- * The fleet is heterogeneous: instances provisioned before task 1003369 run as the
616
- * shared app user, instances provisioned after run as their own `bongos-<slug>`. Neither
617
- * is guessable from the row, and getting it wrong is not a soft failure — `sudo` refuses
618
- * an unknown user and the upgrade dies before pre-flight, which is exactly how the
619
- * tenant leg has been broken.
620
- *
621
- * Falling back is NOT a privilege escalation: an instance with no account of its own is
622
- * already running as the app user (its unit says so), so this migrates as precisely the
623
- * account that owns the database it is about to touch. It IS reported, because a missing
624
- * per-instance account is a provisioning gap someone should close, and a silent fallback
625
- * would hide it forever. On that shape the two answers coincide and the move is byte-for-
626
- * byte what it was before this task.
627
- */
628
- function resolveRunAs(inst, deps, { probe: allowProbe = true } = {}) {
629
- const owner = appUser(); // owns the checkout on every shape — see above
630
- if (inst.hosting_shape === 'control-plane') return { runAs: owner, migrateAs: owner, fellBack: false };
631
- // Re-checked HERE rather than left to instanceUser()'s own throw, for the reason
632
- // upgradeInvocation states about itself: a call site whose safety depends on a
633
- // helper's internals is one refactor away from a shell-interpolation path.
634
- if (!isValidSlug(inst && inst.slug)) {
635
- throw new Error(`resolveRunAs: refusing to probe an account for invalid slug ${JSON.stringify(inst && inst.slug)}`);
636
- }
637
- const wanted = instanceUser(inst);
638
- if (!allowProbe) return { runAs: owner, migrateAs: wanted, fellBack: false };
639
- // THE SAME EXECUTOR THE UPGRADE ITSELF WILL USE. Every sibling here picks
640
- // `standalone ? (controlExec || exec) : exec`, because under PROVISION_REMOTE_HOST
641
- // (ADR 0130) `exec` is the REMOTE ssh executor while `controlExec` stays local. A
642
- // probe on `exec` would then ask the co-hosting box whether an account exists while
643
- // the command it is deciding for runs on the control plane — a wrong answer that
644
- // looks like a right one.
645
- const boxExec = inst.hosting_shape === 'cloud-host' ? (deps.controlExec || deps.exec) : deps.exec;
646
- const r = boxExec(`id -u ${wanted}`, { allowFail: true });
647
- const failed = !r || r.softFailed === true || r.ok === false;
648
- if (!failed) return { runAs: owner, migrateAs: wanted, fellBack: false };
649
- // ONLY A DEFINITIVE "no such user" JUSTIFIES THE FALLBACK. A probe that could not
650
- // answer — an exec timeout, an NSS hiccup — must not silently narrow the per-instance
651
- // isolation of task 1003369 for this operation. So an inconclusive probe keeps the
652
- // intended account: if it really is missing the upgrade fails loudly, and since this
653
- // task a failure now carries the reason instead of "the dry run did not complete".
654
- const said = `${(r && r.stdout) || ''}\n${(r && r.stderr) || ''}`;
655
- if (!/no such user|unknown user/i.test(said)) {
656
- return { runAs: owner, migrateAs: wanted, fellBack: false, probeInconclusive: true };
657
- }
658
- return { runAs: owner, migrateAs: owner, fellBack: true, wanted };
659
- }
660
-
661
- // ONE BUILDER FOR BOTH LEGS (task 1004121).
662
- //
663
- // The preview and the move must be the same command or the preview is worthless — and
664
- // two hand-copied builders are exactly how they stop being the same. The mode decides
665
- // only the TAIL: a dry run stops after pre-flight, so the flags that describe what to do
666
- // AFTER the pin moves (restart, health, version, pin-commit, attribution) would be
667
- // inert on it. Everything that decides whether the upgrade is ALLOWED — the account, the
668
- // database, the target, the instance — is shared, which is the half a preview is about.
669
- //
670
- // The slug rides into a shell command through instanceUser()/dbName(), so it is checked
671
- // HERE rather than left to instanceUser()'s own throw: that throw is correct today, but
672
- // a call site whose safety depends on a helper's internals is one refactor away from a
673
- // shell-injection path (and the apply leg's own guard sits at the route, not here).
674
- function upgradeInvocation(inst, to, { privileged = false, dryRun = false, requestedBy = '', automatic = false, selfRoot = selfInstanceRoot, runAs = null, migrateAs = null } = {}) {
675
- if (!isValidSlug(inst && inst.slug)) {
676
- throw new Error(`upgradeInvocation: refusing to build a shell command from an invalid slug ${JSON.stringify(inst && inst.slug)}`);
677
- }
678
- // WHERE THE CLI LIVES AND WHERE THE TARGET LIVES ARE DIFFERENT PLACES, TWICE OVER.
679
- //
680
- // `upgrade.js` ships in the CORE, and a provisioned instance root holds no scripts/
681
- // directory at all — so the CLI runs from REPO_ROOT and NAMES its target (task
682
- // 1004053, which fixed every standalone tenant).
683
- //
684
- // The second half is that REPO_ROOT is not the instance either (task 1004123). It
685
- // names the copy of the core that is EXECUTING, which coincides with the instance
686
- // only while the core is a checkout run in place. Once the control plane's runner
687
- // moved into its vendored core the two diverged silently — REPO_ROOT still resolved,
688
- // just to node_modules/@bongos/core — and the door aimed at the package instead of
689
- // the project. So ask, rather than assume; in the legacy shape the answer is
690
- // REPO_ROOT and the command below is byte-identical to what it always was.
691
- const instanceDir = inst.hosting_shape === 'cloud-host' ? standaloneRoot(inst) : selfRoot();
692
- // WHICH ACCOUNT, AND WHY IT IS RESOLVED RATHER THAN DERIVED (task 1004128).
693
- //
694
- // Task 1004119 wrote this as `control-plane ? APP_USER : instanceUser(inst)` and was
695
- // half right. The control-plane leg is correct and verified live. The tenant leg
696
- // assumed the per-instance account model of task 1003369 is provisioned everywhere —
697
- // and on the live box NO `bongos-*` account exists, no such Postgres role exists, and
698
- // every instance unit still names the shared app user. So the fix for "Postgres has no role
699
- // root" swapped one absent account for another, and every tenant upgrade died with
700
- // `sudo: unknown user bongos-test4`.
701
- //
702
- // The account model is a real security control, not an accident — a distinct uid per
703
- // instance is what stops a co-tenant reading a sibling's /proc/<pid>/environ. So the
704
- // answer is NOT to route everyone back to the shared account. It is to run as the
705
- // account the instance ACTUALLY runs as, which a caller establishes by probing
706
- // (resolveRunAs below) instead of either side assuming. Passing it in keeps this
707
- // builder pure; the default preserves the old derivation for callers that have not
708
- // probed.
709
- //
710
- // AND WHICH ACCOUNT DOES WHAT (task 1004512). `account` runs the move; `dbAccount` runs
711
- // its three database steps. They differ on exactly the projects that have an account of
712
- // their own, because the checkout is the app user's and the database is theirs —
713
- // resolveRunAs above argues the split. `--migrate-as` is emitted ONLY when they differ,
714
- // so a control plane and a pre-1003369 project produce the command they always did.
715
- const account = runAs || appUser();
716
- const dbAccount = migrateAs || (inst.hosting_shape === 'control-plane' ? appUser() : instanceUser(inst));
717
- const sudoP = privileged ? `sudo -u ${account} env PGDATABASE=${dbName(inst)} ` : '';
718
- const cli = path.posix.join('scripts', 'gds', 'upgrade.js');
719
- const shared = [`${sudoP}node ${cli}`, '--registry', `--to ${to}`,
720
- instanceDir === REPO_ROOT ? '' : `--instance ${instanceDir}`, // REPO_ROOT is where the CLI runs (runDir below)
721
- // SHARED, not in the tail: the dry run's own database pre-check connects as this
722
- // account too, so a preview that omitted it would test a different identity than the
723
- // move — the exact drift one builder for both legs exists to prevent.
724
- dbAccount === account ? '' : `--migrate-as ${dbAccount}`];
725
- const tail = dryRun
726
- ? ['--dry-run']
727
- : [`--service ${inst.slug}`,
728
- `--health-url http://127.0.0.1:${inst.port}/healthz`,
729
- `--version-url http://127.0.0.1:${inst.port}/version`,
730
- '--commit-pin',
731
- // A hosted project's pin is pushed by the RUNNER, which can reach the owner's
732
- // token; the upgrade process cannot (task 1004065, pushUpgradePin).
733
- hubPushesPin(inst) ? '--pin-no-push' : '',
734
- requestedBy ? `--requested-by ${requestedBy}` : '',
735
- requestedBy ? '--upgrade-source owner-control' : '',
736
- // The ledger's existing mark for an unattended move (the self-host sweep writes
737
- // `auto-subscription (<rule>)`); one shell-safe word here (task 1004731).
738
- automatic && !requestedBy ? '--note auto-subscription' : ''];
739
- return { cmd: [...shared, ...tail].filter(Boolean).join(' '), runDir: REPO_ROOT, instanceDir, runAs: account, migrateAs: dbAccount };
740
- }
741
-
742
- // Ask the upgrade CLI what it WOULD do, changing nothing. `allowFail` because a refusal
743
- // is the interesting answer, not an exception: pre-flight refusing is what this is for.
744
- function preflightUpgrade(inst, to, deps) {
745
- const { exec, privileged } = deps;
746
- const boxExec = inst.hosting_shape === 'cloud-host' ? (deps.controlExec || exec) : exec;
747
- // A distinct local name: `deps.selfInstanceRoot || selfInstanceRoot` with a const of
748
- // the same name would TDZ-shadow the import and crash every uninjected call.
749
- const selfRoot = deps.selfInstanceRoot || selfInstanceRoot;
750
- const { runAs, migrateAs, fellBack, wanted } = resolveRunAs(inst, deps);
751
- const { cmd, runDir } = upgradeInvocation(inst, to, { privileged, dryRun: true, selfRoot, runAs, migrateAs });
752
- const r = boxExec(cmd, { cwd: runDir, allowFail: true });
753
- const out = `${(r && r.stdout) || ''}\n${(r && r.stderr) || ''}`;
754
- const { checks, error } = parsePreflight(out);
755
- // ok is the RUN's verdict, not the parser's: a command that exited non-zero without a
756
- // recognisable ✖ is still a refusal, and reporting it as a pass is the failure mode
757
- // this whole task exists to remove.
758
- const ok = !!(r && !r.softFailed && r.ok !== false) && !error;
759
- // WHEN THERE IS NO ✖, SAY WHAT THE COMMAND SAID (task 1004128). The generic sentence
760
- // is the LAST resort, not the first: the first live pre-flight reported "the dry run
761
- // did not complete" while `sudo: unknown user bongos-test4` sat in the journal, and
762
- // the second did the same over `✖ already on 1.19.927`. Both were in hand. The trim
763
- // is because this reaches a DOM.
764
- const raw = out.trim().split('\n').filter(Boolean).slice(-4).join('\n').slice(0, 600);
765
- const why = error || (raw || null);
766
- const note = fellBack
767
- ? `migrated as ${migrateAs} — this instance has no ${wanted} account yet (it predates the per-instance account model)`
768
- : null;
769
- return {
770
- // Both accounts, because since task 1004512 there are two and "which user did this run
771
- // as" has no single answer: `ran_as` writes the files, `migrated_as` touches the database.
772
- target: to, ok, lines: checks, ran_as: runAs, migrated_as: migrateAs, account_note: note,
773
- error: ok ? null : (why || 'the dry run did not complete, and said nothing this could report'),
774
- };
775
- }
776
-
777
- // ── WHAT THE MOVE WOULD CARRY (task 1004173) ────────────────────────────────
778
- //
779
- // The owner, 2026-09-22: "I don't actually see what would change when I hit the button."
780
- // The pre-flight above answers a different question — whether the machinery will let the
781
- // move happen — and answering it was being presented as a preview. ADR 0293 D4 promised
782
- // both halves in so many words: "the control shows what a bump would move — live version
783
- // → target, AND WHAT SITS BETWEEN THEM." Only the first half was built, so the owner was
784
- // asked to restart a live site to take ninety-one releases of work the page named none of.
785
- //
786
- // WHERE THE ANSWER ALREADY LIVES. Every ship writes a merge commit whose summary is
787
- // already prose for exactly this reader — the owner, not a developer — because ship.js
788
- // requires one and posts it to Discord. So this reads the merge summaries between the two
789
- // releases rather than inventing a changelog nobody would maintain.
790
- //
791
- // IT READS THE NOTES THE CORE PACKAGE CARRIES, and a core checkout only as a fallback
792
- // (task 1004218). "What changed in the core between 1.19.881 and 1.19.972" is a question
793
- // about the CORE repository, and no tenant box will ever hold its history — every project
794
- // is a checkout of its OWN repo with the core vendored in from npm. So the packer writes
795
- // the summaries down once, from the full history CI packs with (release-notes.json, built
796
- // by scripts/gds/release-notes.js), and any machine that can download a core version can
797
- // read what it carries. The checkout path below is kept for a machine that has one.
798
- const CHANGE_CAP = 20;
799
- // One registry download of a core tarball. The preview's owner is waiting on the dry run
800
- // beside it anyway, but a hung registry must not hold the runner forever.
801
- const NOTES_FETCH_TIMEOUT_MS = 60000;
802
-
803
- function runFault(r) {
804
- if (!r) return 'no answer';
805
- if (r.error) return String(r.error.message || r.error).slice(0, 160);
806
- const tail = String(r.stderr || '').trim().split('\n').filter(Boolean).slice(-1)[0] || '';
807
- return (tail || `exit ${r.status}`).slice(0, 160);
808
- }
809
-
810
- /**
811
- * The release notes the core THIS runner executes from carries, if any. Free to read, and
812
- * enough on its own whenever the target is at or below this core's own version — a tenant
813
- * catching up to where the platform already is.
814
- */
815
- function readInstalledNotes(deps = {}) {
816
- const fsImpl = deps.fs || fs;
817
- let raw;
818
- try { raw = fsImpl.readFileSync(path.join(REPO_ROOT, RELEASE_NOTES_FILE), 'utf8'); }
819
- catch { return { missing: 'this core carries no release notes' }; }
820
- try { return { notes: JSON.parse(raw) }; }
821
- catch { return { error: "this core's release notes are not valid JSON" }; }
822
- }
823
-
824
- /**
825
- * The release notes inside ONE published core package — the TARGET's own (task 1004218).
826
- *
827
- * WHY THE TARGET'S. The installed core's notes stop at its own version, which is zero
828
- * coverage for the move looked at most — the platform's own, onto a release newer than
829
- * itself. The target's package is the one guaranteed to reach the target, because that is
830
- * where the target was packed. `npm pack` downloads it (the core is public, so no
831
- * credential — the same registry listAvailableVersions reads) and `tar -xzOf` reads the one
832
- * file out of it rather than unpacking the rest.
833
- *
834
- * Returns `{ notes }`, `{ missing }` when the package carries none (every release published
835
- * before the notes were packaged), or `{ error }`. The download never outlives the call.
836
- */
837
- function readPackagedNotes(version, deps = {}) {
838
- if (!CORE_VERSION_RE.test(String(version || ''))) return { error: 'could not work out which package to read' };
839
- const run = deps.spawn || spawnSync;
840
- const fsImpl = deps.fs || fs;
841
- let dir = null;
842
- try {
843
- dir = fsImpl.mkdtempSync(path.join(deps.tmpDir || os.tmpdir(), 'bongos-release-notes-'));
844
- const packed = run('npm', ['pack', `@bongos/core@${version}`, '--pack-destination', dir, '--silent'],
845
- { cwd: dir, env: deps.env || process.env, encoding: 'utf8', timeout: NOTES_FETCH_TIMEOUT_MS });
846
- if (!packed || packed.error || packed.status !== 0) {
847
- return { error: `could not download the core ${version} package to read its release notes (${runFault(packed)})` };
848
- }
849
- // Whatever npm named it: a scoped package's tarball is <scope>-<name>-<version>.tgz today.
850
- const tgz = fsImpl.readdirSync(dir).find((f) => f.endsWith('.tgz'));
851
- if (!tgz) return { error: `npm reported the core ${version} package downloaded, but left no tarball` };
852
- const x = run('tar', ['-xzOf', path.join(dir, tgz), `package/${RELEASE_NOTES_FILE}`],
853
- { encoding: 'utf8', maxBuffer: 4 * RELEASE_NOTES_MAX_BYTES, timeout: NOTES_FETCH_TIMEOUT_MS });
854
- if (!x || x.error || x.status !== 0) {
855
- if (/not found in archive/i.test(String((x && x.stderr) || ''))) {
856
- return { missing: `the core ${version} package carries no release notes` };
857
- }
858
- return { error: `could not read the release notes out of the core ${version} package (${runFault(x)})` };
859
- }
860
- try { return { notes: JSON.parse(x.stdout) }; }
861
- catch { return { error: `the release notes in the core ${version} package are not valid JSON` }; }
862
- } catch (e) {
863
- return { error: `could not fetch the core ${version} package (${String((e && e.message) || e).slice(0, 160)})` };
864
- } finally {
865
- if (dir) { try { fsImpl.rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ } }
866
- }
867
- }
868
-
869
- /**
870
- * The range, answered from release notes alone: `{ entries }`, or `{ why }` they cannot.
871
- * The installed core first, when its notes already reach the target; the target's own
872
- * package otherwise. No git, no SHAs, no checkout.
873
- */
874
- function changesFromNotes(fromVersion, toVersion, deps) {
875
- const installed = (deps.readInstalledNotes || readInstalledNotes)(deps);
876
- if (installed.notes) {
877
- const r = notesBetween(installed.notes, fromVersion, toVersion);
878
- if (r.entries) return r;
879
- }
880
- const target = (deps.readPackagedNotes || readPackagedNotes)(toVersion, deps);
881
- if (!target.notes) return { why: target.missing || target.error || `the core ${toVersion} package's release notes could not be read` };
882
- const r = notesBetween(target.notes, fromVersion, toVersion);
883
- return r.entries ? r : { why: `the release notes in the core ${toVersion} package ${r.uncovered}` };
884
- }
885
-
886
- /**
887
- * Classify a git command that did not succeed. PURE.
888
- *
889
- * "COULD NOT LOOK" AND "LOOKED AND DID NOT FIND" ARE DIFFERENT ANSWERS (task 1004212).
890
- * The first cut collapsed both into "could not find those releases in the core history on
891
- * this machine", and that sentence sent the investigation at the history for an hour when
892
- * the history was never the problem — the directory was. A message that names the wrong
893
- * cause is worse than a vague one, because it is followed.
894
- */
895
- function gitFault(r, dir) {
896
- const said = `${(r && r.stdout) || ''}\n${(r && r.stderr) || ''}`;
897
- if (/dubious ownership|safe\.directory/i.test(said)) {
898
- return `the core checkout at ${dir} belongs to another account, so this could not read it`;
899
- }
900
- if (/not a git repository/i.test(said)) return `${dir} is not a git checkout`;
901
- const tail = said.trim().split('\n').filter(Boolean).slice(-1)[0] || '';
902
- return `could not read ${dir}${tail ? ` — ${tail.slice(0, 160)}` : ''}`;
903
- }
904
-
905
- /**
906
- * Where the CORE's own git history lives on this machine, if anywhere (task 1004212).
907
- *
908
- * WHAT THE FIRST CUT GOT WRONG, and it was not a small thing. It read `selfInstanceRoot()`
909
- * on the assumption that the control plane's instance root is a checkout of the core. On
910
- * the live box it is not: `/version` there reports a commit that does not exist in the core
911
- * repository at all, because the instance root is a checkout of the INSTANCE's own repo
912
- * with the core vendored in at node_modules (the task 1004123 shape). So every lookup
913
- * searched the wrong repository's history.
914
- *
915
- * THAT IS A CORRECTNESS BUG, NOT ONLY A MISSING FEATURE. On a box whose instance repo
916
- * happened to carry `Merge <branch>: <summary>` commits — which any repo built this way
917
- * does — the page would have shown ANOTHER project's changelog as the core's, with no
918
- * error at all. Which is why a candidate is not trusted for being a git repo: it has to
919
- * prove it carries core RELEASE history, and `looksLikeCore` is that proof.
920
- *
921
- * NO PATH IS HARDCODED. `audit-authorship.sh` forbids naming the founder's directories,
922
- * and a guessed path is how this got here. The candidates are: an explicit operator
923
- * setting, the directory the CLI is executing from, and the instance root — each checked,
924
- * none assumed.
925
- */
926
- function coreCheckoutCandidates(deps) {
927
- const selfRoot = deps.selfInstanceRoot || selfInstanceRoot;
928
- const env = deps.env || process.env;
929
- const out = [];
930
- const add = (dir, why) => { if (dir && !out.some((c) => c.dir === dir)) out.push({ dir, why }); };
931
- add(String(env.PROVISION_CORE_CHECKOUT || '').trim() || null, 'PROVISION_CORE_CHECKOUT');
932
- add(REPO_ROOT, 'the directory this core is running from');
933
- add(selfRoot(), "this project's own root");
934
- return out;
935
- }
936
-
937
- /**
938
- * Read the core's release history, or say precisely why it cannot be. Returns
939
- * `{ dir }` on success, or `{ error }` — never a directory it has not verified.
940
- */
941
- function findCoreCheckout(deps, git) {
942
- const tried = [];
943
- for (const { dir, why } of coreCheckoutCandidates(deps)) {
944
- const probe = git(dir, 'rev-parse --is-shallow-repository');
945
- if (!probe.ok) { tried.push(`${why}: ${gitFault(probe, dir)}`); continue; }
946
- if (probe.stdout.trim() === 'true') {
947
- // A depth-limited clone resolves HEAD perfectly well — which is why /version reports
948
- // `resolvedVia: git` on a box that cannot answer this — and carries no old releases.
949
- tried.push(`${why}: ${dir} is a shallow clone, so it carries no release history`);
950
- continue;
951
- }
952
- // THE PROOF THAT THIS IS THE CORE. Any repository answers `rev-parse`; only the core's
953
- // carries release commits, and accepting a repo without asking is how the wrong
954
- // project's changelog would have been shown as this one's.
955
- const marker = git(dir, "log --format=%H --max-count=1 -E --grep='^release: core [0-9]+\\.[0-9]+\\.[0-9]+ '");
956
- if (!marker.ok) { tried.push(`${why}: ${gitFault(marker, dir)}`); continue; }
957
- if (!marker.stdout.trim()) { tried.push(`${why}: ${dir} is a git checkout, but not of the core`); continue; }
958
- return { dir };
959
- }
960
- return { error: `no core checkout is reachable on this machine (${tried.join('; ')}). Set PROVISION_CORE_CHECKOUT to one.` };
961
- }
962
-
963
- /**
964
- * The range, answered from a core CHECKOUT's git history: `{ entries }` or `{ error }`.
965
- * The fallback for a machine that has one, since the package's notes only exist for
966
- * releases published after they were introduced (task 1004218).
967
- */
968
- function changesFromCheckout(fromVersion, toVersion, deps) {
969
- // The CONTROL PLANE's executor, never the previewed instance's: under
970
- // PROVISION_REMOTE_HOST `exec` is the remote box, while the core history — and the whole
971
- // question of what changed in the CORE — belongs to the machine that builds it.
972
- const exec = deps.controlExec || deps.exec;
973
- // AS THE ACCOUNT THAT OWNS THE CHECKOUT, for the same reason the dry run beside this one
974
- // does (task 1004128). `appUser()` is defined as "the unprivileged account that owns this
975
- // checkout" and throws rather than return root, so a runner executing as root reads the
976
- // files through the account that may actually read them instead of tripping git's
977
- // ownership check. Unprivileged runners are unchanged — there is nothing to escalate to.
978
- let runAs = null;
979
- if (deps.privileged) {
980
- try { runAs = (deps.appUser || appUser)(); } catch { runAs = null; }
981
- }
982
- const git = (dir, args) => {
983
- const r = exec(`${runAs ? `sudo -u ${runAs} ` : ''}git -C ${dir} ${args}`, { allowFail: true });
984
- return {
985
- ok: !!(r && r.softFailed !== true && r.ok !== false),
986
- stdout: String((r && r.stdout) || ''),
987
- stderr: String((r && r.stderr) || ''),
988
- };
989
- };
990
- const found = findCoreCheckout(deps, git);
991
- if (found.error) return { error: found.error };
992
- const dir = found.dir;
993
- const shaOf = (v) => {
994
- const r = git(dir, `log --format=%H --max-count=1 -F --grep='release: core ${v} '`);
995
- if (!r.ok) return { fault: gitFault(r, dir) };
996
- const sha = r.stdout.trim().split('\n')[0] || '';
997
- return /^[0-9a-f]{7,40}$/.test(sha) ? { sha } : {};
998
- };
999
- const from = shaOf(fromVersion);
1000
- const to = shaOf(toVersion);
1001
- if (from.fault || to.fault) return { error: from.fault || to.fault };
1002
- // LOOKED, AND DID NOT FIND — a different sentence from "could not look", and it names
1003
- // WHICH version is missing so the reader can tell a not-yet-published target from a
1004
- // checkout that has not been fetched.
1005
- const missing = [!from.sha && fromVersion, !to.sha && toVersion].filter(Boolean);
1006
- if (missing.length) {
1007
- return { error: `core ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} not in the core history on this machine yet` };
1008
- }
1009
- const r = git(dir, `log --merges --format=%s%x1f%b%x1e ${from.sha}..${to.sha}`);
1010
- if (!r.ok) return { error: gitFault(r, dir) };
1011
- return { entries: parseChangeRecords(r.stdout) };
1012
- }
1013
-
1014
- /**
1015
- * What landed between two core releases, as the summaries their ships wrote.
1016
- *
1017
- * Returns `{ from, to, entries, more, source }`, or `{ from, to, error }` — NEVER an empty
1018
- * `entries` for a range it could not resolve. An empty list reads as "nothing changed",
1019
- * which on a page whose job is to say what a restart buys is the one wrong impression it
1020
- * must not give, and it is exactly what a missing checkout produces.
1021
- *
1022
- * THE PACKAGE'S NOTES FIRST, THE CHECKOUT SECOND (task 1004218). The notes answer on every
1023
- * box; the checkout only where one exists, which is never a tenant. When neither can, the
1024
- * error carries BOTH reasons — the notes' and the checkout's own precise sentence (task
1025
- * 1004212) — so the reader is told everything that was tried and why each fell short.
1026
- *
1027
- * Every version reaching a shell is re-checked against the strict three-number form
1028
- * FIRST. They arrive from an intent row whose column has the same CHECK, but a value that
1029
- * is interpolated into a command is checked where it is interpolated — the rule
1030
- * upgradeInvocation states about the slug.
1031
- */
1032
- function changesBetween(fromVersion, toVersion, deps) {
1033
- const bad = [fromVersion, toVersion].find((v) => !CORE_VERSION_RE.test(String(v || '')));
1034
- if (bad !== undefined) return { from: fromVersion || null, to: toVersion || null, error: 'could not work out which releases this covers' };
1035
- const listed = (all, source) => ({
1036
- from: fromVersion, to: toVersion, entries: all.slice(0, CHANGE_CAP), more: Math.max(0, all.length - CHANGE_CAP), source,
1037
- });
1038
- const notes = changesFromNotes(fromVersion, toVersion, deps);
1039
- if (notes.entries) return listed(notes.entries, 'release-notes');
1040
- const checkout = changesFromCheckout(fromVersion, toVersion, deps);
1041
- if (checkout.entries) return listed(checkout.entries, 'checkout');
1042
- return { from: fromVersion, to: toVersion, error: `${notes.why}; ${checkout.error}` };
1043
- }
1044
-
1045
- // Run a dry run for one instance and cache its verdict — the ON-DEMAND leg, drained from
1046
- // a `core-upgrade-preflight` intent the owner's arming queues (task 1004121). The tick
1047
- // does not do this: a verdict that is only ever produced on a background schedule is
1048
- // missing at exactly the moment it is wanted (a fresh release, a new instance), and
1049
- // re-running it every tick for a box that has been behind for hours spends a subprocess
1050
- // to re-learn the same answer. Asked for, then cached, is both cheaper and timelier.
1051
- async function preflightCoreUpgrade(inst, deps, intent) {
1052
- const { db, log } = deps;
1053
- const to = intent && intent.target_version;
1054
- if (!UPGRADE_SHAPES.has(inst.hosting_shape) || inst.status !== 'active') {
1055
- return { ok: false, error: `cannot preview a ${inst.hosting_shape} instance` };
1056
- }
1057
- if (!to) return { ok: false, error: 'no target version to preview' };
1058
- const verdict = (deps.preflightUpgrade || preflightUpgrade)(inst, to, deps);
1059
- // AND WHAT THE MOVE WOULD CARRY, taken in the same breath (task 1004173). It rides the
1060
- // verdict rather than a column of its own for the reason the verdict's own `target`
1061
- // exists: both answers are about ONE move, and storing them together is what makes
1062
- // "is this still the move on offer" a single question with a single answer. It also
1063
- // costs the owner no second wait — the dry run is already the thing they are waiting on.
1064
- //
1065
- // `from` is the version the box is on RIGHT NOW, read back from the snapshot the tick
1066
- // writes, and it is stored because the answer is only true of that starting point. The
1067
- // web tier withholds the list when the box has moved since, the same way it withholds a
1068
- // verdict taken against a superseded target.
1069
- let servedNow = null;
1070
- try {
1071
- const { rows } = await db.query('SELECT served_version FROM provisioning_core_version_snapshot WHERE instance_id = $1', [inst.id]);
1072
- servedNow = (rows[0] && rows[0].served_version) || null;
1073
- } catch { /* no snapshot yet — changesBetween refuses on the missing version, and says so */ }
1074
- verdict.changes = (deps.changesBetween || changesBetween)(servedNow, to, deps);
1075
- await db.query(
1076
- `INSERT INTO provisioning_core_version_snapshot (instance_id, preflight, preflight_at, observed_at)
1077
- VALUES ($1, $2::jsonb, now(), now())
1078
- ON CONFLICT (instance_id) DO UPDATE
1079
- SET preflight = EXCLUDED.preflight, preflight_at = now()`,
1080
- [inst.id, JSON.stringify(verdict)]);
1081
- log(` ${verdict.ok ? '✓' : '✖'} ${inst.slug}: pre-flight for ${to} — ${verdict.ok ? 'clear' : verdict.error}`);
1082
- // ok:true means THE PREVIEW RAN. A refusal is a successful preview of a refusal — the
1083
- // intent must not go to 'error', or the owner's next arming is blocked by a stale open
1084
- // intent describing a check that worked perfectly.
1085
- return { ok: true, preflight: verdict };
1086
- }
1087
-
1088
- /**
1089
- * Observe one instance and cache what the deploy control needs, without acting.
1090
- *
1091
- * Runs on every drain tick for each upgradable instance. Both facts it records are ones
1092
- * the web tier cannot reach for itself — the served version lives on loopback, the
1093
- * available versions need a blocking `npm view` (migration provisioning_019 says why at length)
1094
- * — so this is the runner reporting on behalf of a process that may only ask.
1095
- *
1096
- * BEST-EFFORT, ALWAYS. A registry hiccup or a box that will not answer must never fail a
1097
- * tick that has real work in it: the snapshot simply keeps its previous value and its
1098
- * previous, now-visibly-older, observed_at. That staleness is the honest signal, and it
1099
- * is why observed_at is stored rather than assumed.
1100
- */
1101
- async function snapshotCoreVersions(inst, deps) {
1102
- const { db, exec, log } = deps;
1103
- if (!UPGRADE_SHAPES.has(inst.hosting_shape) || inst.status !== 'active') return { ok: true, skipped: true };
1104
- const boxExec = inst.hosting_shape === 'cloud-host' ? (deps.controlExec || exec) : exec;
1105
- const channelMod = deps.updateChannel || require('./update-channel.js');
1106
- const selfRoot = deps.selfInstanceRoot || selfInstanceRoot;
1107
- const instanceDir = inst.hosting_shape === 'cloud-host' ? standaloneRoot(inst) : selfRoot();
1108
- try {
1109
- const probe = boxExec(versionCmd(inst), { allowFail: true });
1110
- const body = probe && !probe.softFailed ? (probe.stdout || '') : null;
1111
- const served = parseServedVersion(body);
1112
- const schemaPending = parseSchemaPending(body);
1113
- const listed = offeredVersions(channelMod, inst, instanceDir);
1114
- const available = (listed && listed.versions) || [];
1115
- // What the channel would take FROM the version the box is actually on. Resolving it
1116
- // here rather than in the browser is what keeps the button's promise and the
1117
- // runner's behaviour the same sentence.
1118
- // resolveChannelTarget returns the bare version string, or null when the channel
1119
- // admits nothing newer — "already current" and "nothing to take" are the same
1120
- // answer here, and both correctly leave `recommended` NULL.
1121
- const recommended = served
1122
- ? channelMod.resolveChannelTarget({ installed: served, channel: instanceChannel(inst, channelMod), available })
1123
- : null;
1124
- // THE TICK DOES NOT DRY-RUN. The verdict is produced on demand (preflightCoreUpgrade),
1125
- // because a check re-run every tick for a box that has been behind for hours spends a
1126
- // subprocess to re-learn the same answer, and is still missing in the one window that
1127
- // matters — the minutes after a release, which is when someone presses the button.
1128
- // The version probe below is cheap and genuinely per-tick; a dry run is not.
1129
- const preflight = null;
1130
- await db.query(
1131
- `INSERT INTO provisioning_core_version_snapshot
1132
- (instance_id, served_version, available, recommended, observed_at, preflight, preflight_at, schema_pending)
1133
- VALUES ($1, $2, $3::jsonb, $4, now(), $5::jsonb, $6, $7)
1134
- ON CONFLICT (instance_id) DO UPDATE
1135
- SET served_version = EXCLUDED.served_version, available = EXCLUDED.available,
1136
- recommended = EXCLUDED.recommended, observed_at = now(),
1137
- schema_pending = EXCLUDED.schema_pending,
1138
- -- A tick with nothing to preview must not ERASE the last verdict; it simply
1139
- -- has nothing newer to say. Only a real dry run overwrites one.
1140
- preflight = COALESCE(EXCLUDED.preflight, provisioning_core_version_snapshot.preflight),
1141
- preflight_at = COALESCE(EXCLUDED.preflight_at, provisioning_core_version_snapshot.preflight_at)`,
1142
- [inst.id, served, JSON.stringify(available), recommended || null,
1143
- preflight ? JSON.stringify(preflight) : null, preflight ? new Date() : null, schemaPending]);
1144
- return { ok: true, served, available: available.length, preflight, schemaPending };
1145
- } catch (e) {
1146
- log(` ~ core-version snapshot for ${inst.slug} skipped (${(e && e.message) || e})`);
1147
- return { ok: true, skipped: true };
1148
- }
1149
- }
1150
-
1151
- /** Snapshot every instance whose box the runner can reach. Never throws. */
1152
- async function snapshotAllCoreVersions(deps) {
1153
- const { db, log } = deps;
1154
- const shapes = [...UPGRADE_SHAPES];
1155
- const { rows } = await db.query(
1156
- `SELECT * FROM provisioning_instances WHERE status = 'active' AND hosting_shape = ANY($1)`, [shapes]);
1157
- let seen = 0;
1158
- for (const inst of rows) {
1159
- const r = await snapshotCoreVersions(inst, deps);
1160
- if (r && !r.skipped) seen++;
1161
- }
1162
- if (seen) log(`core-version snapshot: refreshed ${seen} instance(s)`);
1163
- return { seen };
1164
- }
1165
-
1166
- module.exports = { pushUpgradePin, UPGRADE_SHAPES, instanceChannel, CHANGE_CAP, REPO_NOTES, repoNote, requestedByOf, parseChangeRecords, readInstalledNotes, readPackagedNotes, changesBetween, coreCheckoutCandidates, findCoreCheckout, gitFault, resolveRunAs, versionCmd, parseServedVersion, parseSchemaPending, targetFault, parsePreflight, upgradeInvocation, preflightUpgrade, preflightCoreUpgrade, coreUpgradeInstance, snapshotCoreVersions, snapshotAllCoreVersions };
6
+ require('../bongos/forwarder.js').forward(module, 'provision-core-upgrade.js');