@bongos/core 1.21.175 → 1.21.176

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 (1739) hide show
  1. package/.bongos-core.json +3551 -1516
  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 +14 -14
  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/docs/adr/0029-status-page-outage-resilience.md +6 -6
  58. package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
  59. package/docs/adr/0294-cli-sessions-do-not-expire.md +1 -1
  60. package/docs/adr/0383-sessions-end-after-ten-idle-days.md +35 -0
  61. package/docs/adr/0384-the-raise-page-is-a-hub-module-builders-edit-in-place.md +31 -0
  62. package/docs/adr/README.md +2 -0
  63. package/docs/api/openapi.json +606 -44
  64. package/docs/api-reference.md +25 -12
  65. package/docs/architecture.md +8 -7
  66. package/docs/canonical-permissions.md +3 -3
  67. package/docs/copy-inventory.md +1370 -1411
  68. package/docs/copy-registry.json +2136 -2536
  69. package/docs/design/demonolith-plan.md +6 -6
  70. package/docs/design/modular-architecture/00-research-report.md +1 -1
  71. package/docs/design/project-startup-direction.md +2 -2
  72. package/docs/design/projects-hub-direction-v2.md +1 -1
  73. package/docs/design/reviews/hall-v2/README.md +2 -2
  74. package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
  75. package/docs/file-map.md +89 -88
  76. package/docs/handoff-template.md +4 -4
  77. package/docs/module-api-changelog.md +5 -3
  78. package/docs/modules-contract.md +8 -7
  79. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +1 -1
  80. package/docs/onboarding/diagrams/02-rank-ladder.mmd +1 -1
  81. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +1 -1
  82. package/docs/onboarding/diagrams/04-architecture.mmd +1 -1
  83. package/docs/onboarding/diagrams/05-versioning.mmd +1 -1
  84. package/docs/onboarding/diagrams/README.md +2 -2
  85. package/docs/onboarding/diagrams/assertions.json +2 -2
  86. package/docs/onboarding/slash-commands.md +2 -2
  87. package/docs/packs/artist.md +4 -4
  88. package/docs/packs/engineer.md +11 -10
  89. package/docs/packs/ideator.md +7 -7
  90. package/docs/page-inventory.json +20 -1
  91. package/docs/page-readings.json +4387 -4603
  92. package/docs/recipes/README.md +1 -1
  93. package/docs/recipes/audit-replay.md +4 -4
  94. package/docs/recipes/autobongos-windows-host.md +6 -6
  95. package/docs/recipes/bongos-cli-release.md +2 -2
  96. package/docs/recipes/claude-design-loop.md +7 -7
  97. package/docs/recipes/core-release-pipeline.md +19 -19
  98. package/docs/recipes/failed-ship-recovery-proof.md +2 -2
  99. package/docs/recipes/figma-design-loop.md +6 -6
  100. package/docs/recipes/gds-db-backup.md +9 -9
  101. package/docs/recipes/instance-deploy.md +3 -3
  102. package/docs/recipes/instance-first-run.md +1 -1
  103. package/docs/recipes/multi-builder-merge.md +2 -2
  104. package/docs/recipes/ops-gotchas.md +10 -9
  105. package/docs/recipes/packaging-the-core.md +6 -6
  106. package/docs/recipes/parallel-goal-waves.md +4 -4
  107. package/docs/recipes/private-npm-distribution.md +9 -9
  108. package/docs/recipes/redteam-patrol.md +5 -5
  109. package/docs/recipes/render-pilot.md +2 -2
  110. package/docs/recipes/reranking-a-goals-board.md +2 -2
  111. package/docs/recipes/search-index-ingestion.md +5 -5
  112. package/docs/recipes/self-host.md +1 -1
  113. package/docs/recipes/ship-and-regrade.md +4 -4
  114. package/docs/recipes/staging-environment.md +1 -1
  115. package/docs/recipes/standalone-live-docs.md +1 -1
  116. package/docs/recipes/ui-look-before-you-ship.md +2 -2
  117. package/docs/recipes/upgrading-the-core.md +11 -11
  118. package/docs/recipes/windows-builders.md +18 -18
  119. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +6 -6
  120. package/docs/research/task-network-map-readability.md +3 -3
  121. package/migrations/core_278_builder_tester_tag.sql +18 -0
  122. package/migrations/core_279_bongos_shipper_new_scripts_path.sql +13 -0
  123. package/modules/agents/lib/answer-hold.js +1 -1
  124. package/modules/agents/lib/gate.js +1 -1
  125. package/modules/agents/lib/validate.js +1 -1
  126. package/modules/autonomy/gauge.js +1 -1
  127. package/modules/autonomy/governor-docket.js +2 -2
  128. package/modules/autonomy/pollers/routine-timers.js +3 -3
  129. package/modules/autonomy/routes/autonomy.js +3 -3
  130. package/modules/builder-settings/interaction-prefs.js +1 -1
  131. package/modules/builder-settings/render-prefs.js +1 -1
  132. package/modules/builder-settings/routes/settings.js +1 -1
  133. package/modules/builder-settings/skill-prefs.js +2 -2
  134. package/modules/builder-settings/wandering-prefs.js +2 -2
  135. package/modules/copy-desk/module.json +2 -2
  136. package/modules/copy-desk/page-data.js +5 -5
  137. package/modules/copy-desk/page-decisions.js +13 -1
  138. package/modules/copy-desk/proposals.js +4 -4
  139. package/modules/copy-desk/registry.js +2 -2
  140. package/modules/copy-desk/routes/copy-desk-release.js +119 -0
  141. package/modules/copy-desk/routes/copy-desk.js +3 -12
  142. package/modules/copy-desk/skills/tweak/SKILL.md +12 -12
  143. package/modules/copy-desk/tests/copy_flags.mjs +1 -1
  144. package/modules/copy-desk/tests/copy_no_cms.mjs +7 -3
  145. package/modules/copy-desk/tests/copy_proposals.mjs +2 -2
  146. package/modules/copy-desk/tests/copy_queue.mjs +1 -1
  147. package/modules/design-styles/skills/README.md +4 -4
  148. package/modules/design-styles/skills/imagegen-frontend-mobile/SKILL.md +1 -1
  149. package/modules/design-styles/skills/imagegen-frontend-web/SKILL.md +1 -1
  150. package/modules/discord/bug-attachments.js +1 -1
  151. package/modules/discord/ship-broadcast.js +1 -1
  152. package/modules/economy/achievements.js +49 -7
  153. package/modules/economy/cost-classify.js +6 -6
  154. package/modules/economy/cost-report.js +1 -1
  155. package/modules/economy/cost.js +1 -1
  156. package/modules/economy/credits.js +2 -1
  157. package/modules/economy/idea-size.js +2 -2
  158. package/modules/economy/reward.js +2 -0
  159. package/modules/economy/routes/cost.js +1 -1
  160. package/modules/economy/streak.js +43 -4
  161. package/modules/government/asks.js +1 -1
  162. package/modules/government/board.js +19 -2
  163. package/modules/government/catalog.js +3 -0
  164. package/modules/government/migrations/government_033_idea_vote.sql +46 -0
  165. package/modules/government/protected-surfaces.json +48 -47
  166. package/modules/government/recommendations.js +6 -2
  167. package/modules/government/routes/government.js +1 -1
  168. package/modules/grading/generated-provenance.js +13 -5
  169. package/modules/grading/grade-engine.js +1 -1
  170. package/modules/grading/grader-rubric.json +1 -1
  171. package/modules/grading/grader-score.js +1 -1
  172. package/modules/grading/grader-workers/index.js +1 -1
  173. package/modules/grading/grader.js +1 -1
  174. package/modules/grading/routes/grade.js +1 -1
  175. package/modules/hall-ui/public/atlas.html +5 -7
  176. package/modules/hall-ui/public/atlas.js +1 -1
  177. package/modules/hall-ui/public/atlas.states.json +1 -1
  178. package/modules/hall-ui/public/blockers.css +9 -0
  179. package/modules/hall-ui/public/blockers.html +4 -4
  180. package/modules/hall-ui/public/blockers.js +29 -30
  181. package/modules/hall-ui/public/board-room.css +5 -17
  182. package/modules/hall-ui/public/board-room.html +5 -6
  183. package/modules/hall-ui/public/board-room.js +41 -23
  184. package/modules/hall-ui/public/board-room.states.json +1 -1
  185. package/modules/hall-ui/public/brand-apply.js +1 -1
  186. package/modules/hall-ui/public/brand-holes.js +1 -1
  187. package/modules/hall-ui/public/builders.js +40 -86
  188. package/modules/hall-ui/public/city-decide.js +18 -4
  189. package/modules/hall-ui/public/city.html +1 -1
  190. package/modules/hall-ui/public/collab.html +1 -1
  191. package/modules/hall-ui/public/commands.html +6 -9
  192. package/modules/hall-ui/public/copy-desk.html +1 -1
  193. package/modules/hall-ui/public/copy-desk.js +2 -2
  194. package/modules/hall-ui/public/craft-mode.js +4 -0
  195. package/modules/hall-ui/public/deploy.html +6 -2
  196. package/modules/hall-ui/public/deploy.js +21 -13
  197. package/modules/hall-ui/public/diagrams.css +1 -1
  198. package/modules/hall-ui/public/diagrams.html +5 -8
  199. package/modules/hall-ui/public/diagrams.states.json +1 -1
  200. package/modules/hall-ui/public/drachmae.html +3 -7
  201. package/modules/hall-ui/public/fleet.html +3 -2
  202. package/modules/hall-ui/public/fleet.js +0 -4
  203. package/modules/hall-ui/public/gate.html +7 -7
  204. package/modules/hall-ui/public/gate.js +58 -77
  205. package/modules/hall-ui/public/goal-map.html +1 -1
  206. package/modules/hall-ui/public/goals-page.js +5 -5
  207. package/modules/hall-ui/public/goals-render.js +10 -11
  208. package/modules/hall-ui/public/goals.css +10 -0
  209. package/modules/hall-ui/public/goals.html +14 -7
  210. package/modules/hall-ui/public/government.html +3 -5
  211. package/modules/hall-ui/public/government.js +1 -5
  212. package/modules/hall-ui/public/hall-render.js +117 -57
  213. package/modules/hall-ui/public/hall-widgets.js +11 -11
  214. package/modules/hall-ui/public/idea.html +1 -1
  215. package/modules/hall-ui/public/ideas.html +3 -1
  216. package/modules/hall-ui/public/ideas.js +1 -0
  217. package/modules/hall-ui/public/index.html +12 -6
  218. package/modules/hall-ui/public/index.states.json +1 -1
  219. package/modules/hall-ui/public/mine-lens.js +1 -1
  220. package/modules/hall-ui/public/modules.html +7 -10
  221. package/modules/hall-ui/public/modules.js +0 -2
  222. package/modules/hall-ui/public/my-agents.html +1 -1
  223. package/modules/hall-ui/public/palette.js +5 -5
  224. package/modules/hall-ui/public/primer.html +4 -9
  225. package/modules/hall-ui/public/profile-connections.js +10 -2
  226. package/modules/hall-ui/public/profile-roles.js +3 -10
  227. package/modules/hall-ui/public/profile.html +12 -10
  228. package/modules/hall-ui/public/profile.js +13 -17
  229. package/modules/hall-ui/public/project-settings.html +3 -4
  230. package/modules/hall-ui/public/project-settings.js +0 -3
  231. package/modules/hall-ui/public/ranks.html +5 -11
  232. package/modules/hall-ui/public/ranks.js +6 -8
  233. package/modules/hall-ui/public/roadmap.css +0 -2
  234. package/modules/hall-ui/public/roadmap.html +1 -1
  235. package/modules/hall-ui/public/roadmap.js +16 -51
  236. package/modules/hall-ui/public/roster.html +1 -1
  237. package/modules/hall-ui/public/sessions.html +6 -8
  238. package/modules/hall-ui/public/sessions.js +7 -7
  239. package/modules/hall-ui/public/settings.html +1 -1
  240. package/modules/hall-ui/public/shell-trail.js +1 -1
  241. package/modules/hall-ui/public/shell.js +17 -17
  242. package/modules/hall-ui/public/street-deck.css +2 -1
  243. package/modules/hall-ui/public/street-deck.js +10 -2
  244. package/modules/hall-ui/public/street-desk.js +16 -5
  245. package/modules/hall-ui/public/street.html +1 -1
  246. package/modules/hall-ui/public/studio-lib.js +4 -0
  247. package/modules/hall-ui/public/studio.css +2 -0
  248. package/modules/hall-ui/public/studio.html +1 -1
  249. package/modules/hall-ui/public/studio.js +27 -1
  250. package/modules/hall-ui/public/style.css +43 -26
  251. package/modules/hall-ui/public/task-detail.js +10 -7
  252. package/modules/hall-ui/public/task.css +2 -0
  253. package/modules/hall-ui/public/task.html +3 -1
  254. package/modules/hall-ui/public/task.js +23 -7
  255. package/modules/hall-ui/public/thinking.html +1 -1
  256. package/modules/hall-ui/public/tweak-editor.html +1 -1
  257. package/modules/hall-ui/public/vote-control.js +208 -0
  258. package/modules/hall-ui/public/watch.html +3 -5
  259. package/modules/hall-ui/public/watch.js +5 -4
  260. package/modules/hall-ui/public/welcome-boot.css +130 -0
  261. package/modules/hall-ui/public/welcome-boot.js +334 -0
  262. package/modules/hall-ui/public/welcome-day.webp +0 -0
  263. package/modules/hall-ui/public/welcome-night.webp +0 -0
  264. package/modules/hall-ui/public/work-summary.js +1 -1
  265. package/modules/hall-ui/public/work.css +1 -0
  266. package/modules/hall-ui/public/work.html +3 -1
  267. package/modules/hall-ui/public/work.js +2 -1
  268. package/modules/hall-ui/records/accomplishments.md +16 -0
  269. package/modules/hall-ui/records/hall-ask-card.md +9 -0
  270. package/modules/hall-ui/records/karma-vote-control.md +13 -0
  271. package/modules/hall-ui/records/oversight-family.md +1 -1
  272. package/modules/hall-ui/records/profile-connections.md +2 -0
  273. package/modules/hall-ui/records/profile-roles.md +1 -1
  274. package/modules/hall-ui/records/reading-rooms.md +1 -1
  275. package/modules/hall-ui/records/welcome-tower.md +50 -0
  276. package/modules/ideas/migrations/ideas_011_idea_votes.sql +31 -0
  277. package/modules/ideas/projection.js +1 -1
  278. package/modules/ideas/routes/blockers.js +3 -3
  279. package/modules/ideas/routes/inbox.js +29 -1
  280. package/modules/ideas/routes/ratify-goal.js +1 -1
  281. package/modules/ideas/routing.js +1 -1
  282. package/modules/ideas/templates.js +1 -1
  283. package/modules/ideas/trail-descent.js +1 -1
  284. package/modules/ideas/trail-size.js +1 -1
  285. package/modules/ideas/votes.js +93 -0
  286. package/modules/lifecycle/abandon-leftovers.js +1 -1
  287. package/modules/lifecycle/cascade.js +1 -1
  288. package/modules/lifecycle/conflict-resolve.js +13 -21
  289. package/modules/lifecycle/criterion-ref.js +1 -1
  290. package/modules/lifecycle/db-analytics.js +57 -4
  291. package/modules/lifecycle/db-deps-criteria.js +1 -1
  292. package/modules/lifecycle/db-ship.js +2 -2
  293. package/modules/lifecycle/db-tasks.js +2 -2
  294. package/modules/lifecycle/db-versions.js +1 -1
  295. package/modules/lifecycle/db.js +2 -0
  296. package/modules/lifecycle/dead-deps.js +3 -3
  297. package/modules/lifecycle/dependency-advisory.js +3 -3
  298. package/modules/lifecycle/goal-category.js +1 -1
  299. package/modules/lifecycle/goal-forest.js +1 -1
  300. package/modules/lifecycle/goal-task-relevance-advisory.js +1 -1
  301. package/modules/lifecycle/kickoff-checklist.js +1 -1
  302. package/modules/lifecycle/kickoff-seed.js +1 -1
  303. package/modules/lifecycle/lifecycle.js +2 -0
  304. package/modules/lifecycle/merge-reach.js +29 -15
  305. package/modules/lifecycle/missing-dep-classify.js +3 -3
  306. package/modules/lifecycle/module.json +2 -1
  307. package/modules/lifecycle/page-tweak-approve.js +85 -1
  308. package/modules/lifecycle/page-tweak-hold.js +1 -1
  309. package/modules/lifecycle/publish-reconciler.js +1 -2
  310. package/modules/lifecycle/rot.js +1 -1
  311. package/modules/lifecycle/routes/artist-gate.js +1 -1
  312. package/modules/lifecycle/routes/gate-approvals.js +22 -1
  313. package/modules/lifecycle/routes/goals.js +1 -1
  314. package/modules/lifecycle/routes/task-route-helpers.js +1 -1
  315. package/modules/lifecycle/routes/task-votes.js +54 -0
  316. package/modules/lifecycle/routes/task-write-routes.js +1 -1
  317. package/modules/lifecycle/routes/tasks.js +2 -2
  318. package/modules/lifecycle/routes/versions.js +2 -2
  319. package/modules/lifecycle/ship-card.js +4 -4
  320. package/modules/lifecycle/ship-preflight.js +1 -1
  321. package/modules/lifecycle/task-classifier.js +1 -1
  322. package/modules/lifecycle/task-status.js +1 -1
  323. package/modules/lifecycle/task-visual-db.js +1 -1
  324. package/modules/memory/learnings.js +1 -1
  325. package/modules/memory/pollers/search-index.js +2 -2
  326. package/modules/memory/routes/learnings.js +1 -1
  327. package/modules/memory/routes/memory.js +1 -1
  328. package/modules/memory/search.js +2 -2
  329. package/modules/npm-release/release.js +1 -1
  330. package/modules/onboarding/howto-moments.js +1 -1
  331. package/modules/onboarding/newcomer-restock.js +3 -3
  332. package/modules/onboarding/onboarding.js +1 -1
  333. package/modules/pixel-art/skills/otb-tile-generate/SKILL.md +1 -1
  334. package/modules/platform-identity/origin-containment.js +1 -1
  335. package/modules/platform-identity/publish-gate.js +1 -1
  336. package/modules/platform-identity/tests/platform-identity.mjs +1 -1
  337. package/modules/provisioning/capacity.js +1 -1
  338. package/modules/provisioning/core-upgrade.js +15 -9
  339. package/modules/provisioning/credential-preflight.js +3 -3
  340. package/modules/provisioning/disconnect.js +1 -1
  341. package/modules/provisioning/dns-resolves.js +1 -1
  342. package/modules/provisioning/module.json +1 -1
  343. package/modules/provisioning/onboard-plan.js +1 -1
  344. package/modules/provisioning/paid-shape-gate.js +2 -2
  345. package/modules/provisioning/planet-physics.js +11 -2
  346. package/modules/provisioning/pollers/liveness-sweep.js +1 -1
  347. package/modules/provisioning/pollers/runner-drift-notify.js +5 -5
  348. package/modules/provisioning/provisioning.js +2 -2
  349. package/modules/provisioning/render-lookup.js +1 -1
  350. package/modules/provisioning/render-standup.js +3 -3
  351. package/modules/provisioning/repo-private.js +1 -1
  352. package/modules/provisioning/routes/callback-page.js +1 -1
  353. package/modules/provisioning/routes/core-upgrade.js +23 -3
  354. package/modules/provisioning/routes/provisioning.js +2 -2
  355. package/modules/provisioning/routes/render-standup.js +1 -1
  356. package/modules/provisioning/routes/repo-private.js +1 -1
  357. package/modules/provisioning/soft-limits.js +1 -1
  358. package/modules/provisioning/starter-bundles.js +4 -2
  359. package/modules/provisioning/tests/provisioning.mjs +1 -1
  360. package/modules/public-landing/public/account.html +4 -6
  361. package/modules/public-landing/public/assets/cosmos.css +13 -6
  362. package/modules/public-landing/public/connections.html +4 -6
  363. package/modules/public-landing/public/contact.html +4 -6
  364. package/modules/public-landing/public/guild.html +4 -6
  365. package/modules/public-landing/public/index.html +11 -9
  366. package/modules/public-landing/public/invitations.html +4 -6
  367. package/modules/public-landing/public/privacy.html +4 -6
  368. package/modules/public-landing/public/projects.html +168 -46
  369. package/modules/public-landing/public/terms.html +4 -6
  370. package/modules/raise/content/copy.json +40 -0
  371. package/modules/raise/content/nda.html +39 -0
  372. package/modules/raise/content/settings.json +49 -0
  373. package/modules/raise/db.js +95 -0
  374. package/modules/raise/migrations/raise_001_tables.sql +71 -0
  375. package/modules/raise/module.json +28 -0
  376. package/modules/raise/page.js +194 -0
  377. package/modules/raise/public/edit.js +152 -0
  378. package/modules/raise/public/favicon.svg +1 -0
  379. package/modules/raise/public/logo-ink.svg +1 -0
  380. package/modules/raise/public/logo-night.svg +1 -0
  381. package/modules/raise/public/mode.js +8 -0
  382. package/modules/raise/public/raise.css +234 -0
  383. package/modules/raise/public/raise.js +91 -0
  384. package/modules/raise/raise.js +174 -0
  385. package/modules/raise/routes/raise.js +152 -0
  386. package/modules/raise/views/gate.html +39 -0
  387. package/modules/raise/views/nda.html +21 -0
  388. package/modules/raise/views/page.html +133 -0
  389. package/modules/raise/web.js +72 -0
  390. package/modules/render-deploy/deploys.js +1 -1
  391. package/modules/render-deploy/render.js +2 -2
  392. package/modules/security/secret-scrub.js +3 -3
  393. package/modules/security/security.js +1 -1
  394. package/modules/security/tests/artifact_scan.mjs +1 -1
  395. package/modules/security/tests/mirror.mjs +1 -1
  396. package/modules/security/tests/scan_store.mjs +1 -1
  397. package/modules/sessions/db.js +2 -2
  398. package/modules/sessions/pulse.js +2 -2
  399. package/modules/sessions/routes/sessions.js +1 -1
  400. package/modules/specialities/specialities.js +1 -1
  401. package/modules/status-ui/public/README.md +3 -4
  402. package/modules/status-ui/public/index.html +5 -31
  403. package/modules/status-ui/public/status.js +6 -174
  404. package/modules/status-ui/public/style.css +4 -133
  405. package/modules/ui-design/docs/design-contract.md +3 -3
  406. package/modules/ui-design/kit/README.md +1 -1
  407. package/modules/ui-design/kit/serve.js +13 -4
  408. package/modules/ui-design/scripts/design-sync.js +1 -1
  409. package/modules/ui-design/scripts/figma-design-sync.js +1 -1
  410. package/modules/ui-design/scripts/validate-design.js +1 -1
  411. package/package-lock.json +27 -11
  412. package/package.json +2 -3
  413. package/release-notes.json +172 -0
  414. package/scripts/bongos/CLAUDE.md +15 -0
  415. package/scripts/bongos/abandon.js +137 -0
  416. package/scripts/bongos/accessibility-replay.js +195 -0
  417. package/scripts/bongos/address-park-sweep.sh +91 -0
  418. package/scripts/bongos/adopt-detect.js +123 -0
  419. package/scripts/bongos/adopt-import.js +111 -0
  420. package/scripts/bongos/adopt-preflight.js +187 -0
  421. package/scripts/bongos/adr-namespace.js +273 -0
  422. package/scripts/bongos/agent-invoke.js +689 -0
  423. package/scripts/bongos/agents-sync.js +502 -0
  424. package/scripts/bongos/api-alias-caller-scan.js +256 -0
  425. package/scripts/bongos/api-artifacts.js +91 -0
  426. package/scripts/bongos/api.js +86 -0
  427. package/scripts/bongos/api.ps1 +26 -0
  428. package/scripts/bongos/architect-audit.js +294 -0
  429. package/scripts/bongos/artifact-audit.js +326 -0
  430. package/scripts/bongos/artifact-format.js +203 -0
  431. package/scripts/bongos/artifact-staleness.js +267 -0
  432. package/scripts/bongos/ask.js +231 -0
  433. package/scripts/bongos/audit-authorship.sh +329 -0
  434. package/scripts/bongos/audit-deps.js +189 -0
  435. package/scripts/bongos/audit-gate.js +121 -0
  436. package/scripts/bongos/audit-rank-roles.js +172 -0
  437. package/scripts/bongos/audit-replay.sh +205 -0
  438. package/scripts/bongos/autobongos-digest.js +123 -0
  439. package/scripts/bongos/autobongos-grade-cap.js +187 -0
  440. package/scripts/bongos/autobongos-loop.js +210 -0
  441. package/scripts/bongos/autobongos-run.js +1361 -0
  442. package/scripts/bongos/autobongos-service.cmd +50 -0
  443. package/scripts/bongos/autobongos-service.ps1 +270 -0
  444. package/scripts/bongos/autobongos-tweak-lane.js +262 -0
  445. package/scripts/bongos/autobongos-verify.js +618 -0
  446. package/scripts/bongos/autonomy-gate.js +135 -0
  447. package/scripts/bongos/autonomy-gauge-statusline.js +124 -0
  448. package/scripts/bongos/autonomy-gauge.js +84 -0
  449. package/scripts/bongos/backfill-cost.js +176 -0
  450. package/scripts/bongos/backfill-disciplines.js +144 -0
  451. package/scripts/bongos/backfill-session-earnings.js +123 -0
  452. package/scripts/bongos/backfill-session-types.js +87 -0
  453. package/scripts/bongos/backfill-sessions.js +411 -0
  454. package/scripts/bongos/backfill-subagent-rewards.js +485 -0
  455. package/scripts/bongos/backfill-task-rewards.js +413 -0
  456. package/scripts/bongos/backlog-review.js +399 -0
  457. package/scripts/bongos/backup-dropin-sweep.sh +95 -0
  458. package/scripts/bongos/backup.js +116 -0
  459. package/scripts/bongos/baseline-staleness.js +217 -0
  460. package/scripts/bongos/bfg-principal-token.js +65 -0
  461. package/scripts/bongos/bug-attachment-audit.js +149 -0
  462. package/scripts/bongos/bug-attachment-recover.js +198 -0
  463. package/scripts/bongos/bug-triage.js +292 -0
  464. package/scripts/bongos/build-bongos.js +94 -0
  465. package/scripts/bongos/bump-version.js +221 -0
  466. package/scripts/bongos/capture.js +481 -0
  467. package/scripts/bongos/category-advisory-guard.js +206 -0
  468. package/scripts/bongos/ci-grade.js +82 -0
  469. package/scripts/bongos/claim-recall.js +112 -0
  470. package/scripts/bongos/claim.js +789 -0
  471. package/scripts/bongos/classify-discipline.js +153 -0
  472. package/scripts/bongos/claude-materialize.js +1200 -0
  473. package/scripts/bongos/claude-md-template.js +142 -0
  474. package/scripts/bongos/cleanup-orphans.js +74 -0
  475. package/scripts/bongos/cli-lib.js +1226 -0
  476. package/scripts/bongos/client-baseurl-guard.js +116 -0
  477. package/scripts/bongos/codemod-rename-scripts-gds.js +381 -0
  478. package/scripts/bongos/codemod-rename-src-gds.js +145 -0
  479. package/scripts/bongos/conductor-dispatch.js +535 -0
  480. package/scripts/bongos/context-pack.js +326 -0
  481. package/scripts/bongos/control-manifest.js +199 -0
  482. package/scripts/bongos/copy-apply.js +758 -0
  483. package/scripts/bongos/copy-inventory.js +571 -0
  484. package/scripts/bongos/core-origin-follow.js +185 -0
  485. package/scripts/bongos/core-pin-sync.js +260 -0
  486. package/scripts/bongos/coreB-carve-proof.sh +725 -0
  487. package/scripts/bongos/cost-report.js +63 -0
  488. package/scripts/bongos/cost.js +47 -0
  489. package/scripts/bongos/credential-presence.js +296 -0
  490. package/scripts/bongos/cutover-codemod.js +240 -0
  491. package/scripts/bongos/db-backup-nightly.sh +232 -0
  492. package/scripts/bongos/db-backup-offsite.sh +267 -0
  493. package/scripts/bongos/demote.js +45 -0
  494. package/scripts/bongos/deploy-divergence.js +454 -0
  495. package/scripts/bongos/deploy-main-audit-gate.sh +97 -0
  496. package/scripts/bongos/design-sync.js +12 -0
  497. package/scripts/bongos/dev-box-guard.js +166 -0
  498. package/scripts/bongos/dev-lib.js +722 -0
  499. package/scripts/bongos/dev.js +645 -0
  500. package/scripts/bongos/device-flow-help.js +72 -0
  501. package/scripts/bongos/diagnose-achievements.js +118 -0
  502. package/scripts/bongos/diagram-facts.js +355 -0
  503. package/scripts/bongos/discord-channels.js +77 -0
  504. package/scripts/bongos/do-api.js +109 -0
  505. package/scripts/bongos/doc-cli-guard.js +274 -0
  506. package/scripts/bongos/doc-comment-coverage.js +139 -0
  507. package/scripts/bongos/doc-control-claims.js +170 -0
  508. package/scripts/bongos/docs-entropy.js +453 -0
  509. package/scripts/bongos/doctor.js +493 -0
  510. package/scripts/bongos/enroll-control-plane.js +101 -0
  511. package/scripts/bongos/exec-path-guard.js +564 -0
  512. package/scripts/bongos/feedback-send.js +249 -0
  513. package/scripts/bongos/fetch-art-key.js +106 -0
  514. package/scripts/bongos/fetch-sound-prefs.js +126 -0
  515. package/scripts/bongos/figma-design-sync.js +11 -0
  516. package/scripts/bongos/find-untested.js +371 -0
  517. package/scripts/bongos/fitness-checks-error-envelope.js +134 -0
  518. package/scripts/bongos/fitness-checks-identity.js +343 -0
  519. package/scripts/bongos/fitness-checks-packaging.js +132 -0
  520. package/scripts/bongos/fitness-checks-route-pins.js +76 -0
  521. package/scripts/bongos/fitness-checks-vocabulary.js +392 -0
  522. package/scripts/bongos/fitness-checks-write-validation.js +157 -0
  523. package/scripts/bongos/fitness-lib.js +127 -0
  524. package/scripts/bongos/fitness-migration-contraction.js +50 -0
  525. package/scripts/bongos/fitness-ratchets.js +594 -0
  526. package/scripts/bongos/fitness.js +1498 -0
  527. package/scripts/bongos/forwarder.js +80 -0
  528. package/scripts/bongos/gate-review.js +330 -0
  529. package/scripts/bongos/gating.js +348 -0
  530. package/scripts/{gds → bongos}/gds-db-backup.service +6 -6
  531. package/scripts/{gds → bongos}/gds-db-backup.timer +4 -4
  532. package/scripts/{gds → bongos}/gds-db-offsite.service +4 -4
  533. package/scripts/{gds → bongos}/gds-db-offsite.timer +4 -4
  534. package/scripts/bongos/gds-literal-scan.js +196 -0
  535. package/scripts/bongos/gen-api-client.js +576 -0
  536. package/scripts/bongos/gen-api-docs.js +1111 -0
  537. package/scripts/bongos/gen-atlas.js +366 -0
  538. package/scripts/bongos/gen-diagrams.js +608 -0
  539. package/scripts/bongos/gen-file-map.js +337 -0
  540. package/scripts/bongos/gen-freshness.js +32 -0
  541. package/scripts/bongos/gen-interaction-posture.js +122 -0
  542. package/scripts/bongos/gen-repo-map.js +540 -0
  543. package/scripts/bongos/gen-role-responsibilities.js +134 -0
  544. package/scripts/bongos/gen-session-index.js +243 -0
  545. package/scripts/bongos/gen-sounds.js +176 -0
  546. package/scripts/bongos/git-merge-regen.js +254 -0
  547. package/scripts/bongos/go-live.js +1071 -0
  548. package/scripts/bongos/goal-names.js +102 -0
  549. package/scripts/bongos/goal.js +272 -0
  550. package/scripts/bongos/government-walk.js +1477 -0
  551. package/scripts/bongos/grade-correlation-audit.js +310 -0
  552. package/scripts/bongos/grade-replay.js +237 -0
  553. package/scripts/bongos/grade-smoke.js +205 -0
  554. package/scripts/bongos/home-isolation-guard.js +126 -0
  555. package/scripts/bongos/hooks/pre-push.js +211 -0
  556. package/scripts/bongos/howto.js +145 -0
  557. package/scripts/bongos/http-api-client.js +81 -0
  558. package/scripts/bongos/identity-strip.js +75 -0
  559. package/scripts/bongos/init.js +1159 -0
  560. package/scripts/bongos/install-git-hooks.js +200 -0
  561. package/scripts/bongos/instance-apex.js +38 -0
  562. package/scripts/bongos/intent-retry.js +52 -0
  563. package/scripts/bongos/key-card.js +222 -0
  564. package/scripts/bongos/key-status.js +126 -0
  565. package/scripts/bongos/land-watch.js +201 -0
  566. package/scripts/bongos/leak-scan-allowlist.js +293 -0
  567. package/scripts/bongos/learning-capture.js +145 -0
  568. package/scripts/bongos/lib.sh +74 -0
  569. package/scripts/bongos/linkify-refs.js +655 -0
  570. package/scripts/bongos/lint-infra-exec.js +70 -0
  571. package/scripts/bongos/lint-migrations.js +102 -0
  572. package/scripts/bongos/lint-workflow-exec.js +63 -0
  573. package/scripts/bongos/local-preview-lib.js +128 -0
  574. package/scripts/bongos/local-preview.js +82 -0
  575. package/scripts/bongos/login.js +360 -0
  576. package/scripts/bongos/main-audit.js +625 -0
  577. package/scripts/bongos/me.js +97 -0
  578. package/scripts/bongos/memory-map.js +176 -0
  579. package/scripts/bongos/merge-lock.js +71 -0
  580. package/scripts/bongos/migration-namespace.js +313 -0
  581. package/scripts/bongos/mirror-lineage-check.js +343 -0
  582. package/scripts/bongos/mirror-redact.js +350 -0
  583. package/scripts/bongos/module-artifact.js +289 -0
  584. package/scripts/bongos/module-assess-docs.js +238 -0
  585. package/scripts/bongos/module-assess-installs.js +228 -0
  586. package/scripts/bongos/module-assess-score.js +111 -0
  587. package/scripts/bongos/module-assess-security.js +252 -0
  588. package/scripts/bongos/module-assess-tests.js +278 -0
  589. package/scripts/bongos/module-assess-version.js +92 -0
  590. package/scripts/bongos/module-error-report.js +148 -0
  591. package/scripts/{gds → bongos}/module-test-runner/README.md +3 -3
  592. package/scripts/{gds → bongos}/module-test-runner/module-tests.yml +2 -2
  593. package/scripts/bongos/module-test-runner.js +414 -0
  594. package/scripts/bongos/module.js +1376 -0
  595. package/scripts/bongos/move-escalation.js +141 -0
  596. package/scripts/{gds → bongos}/newcomer-floor.config.json +1 -1
  597. package/scripts/bongos/newcomer-floor.js +421 -0
  598. package/scripts/{gds → bongos}/newcomer-floor.templates.json +13 -13
  599. package/scripts/bongos/newcomer-floor.test.js +235 -0
  600. package/scripts/bongos/next-number.js +163 -0
  601. package/scripts/bongos/oauth-secret.js +202 -0
  602. package/scripts/bongos/onboard.js +267 -0
  603. package/scripts/bongos/onboarding-analyze.js +226 -0
  604. package/scripts/bongos/onboarding-config.js +179 -0
  605. package/scripts/bongos/onboarding-ship.js +92 -0
  606. package/scripts/bongos/pack-env-prefix.js +73 -0
  607. package/scripts/bongos/package-core.js +1200 -0
  608. package/scripts/bongos/page-inventory.js +348 -0
  609. package/scripts/bongos/page-reader.js +722 -0
  610. package/scripts/bongos/paste-token.js +212 -0
  611. package/scripts/bongos/plain-cards.js +351 -0
  612. package/scripts/bongos/portability-smoke-art.sh +85 -0
  613. package/scripts/bongos/portability-smoke-memory.sh +176 -0
  614. package/scripts/bongos/preflight.js +214 -0
  615. package/scripts/bongos/probe-cache.js +246 -0
  616. package/scripts/bongos/prove-strict-versioning.js +284 -0
  617. package/scripts/bongos/provision-auto-upgrade.js +162 -0
  618. package/scripts/bongos/provision-byo-host.js +68 -0
  619. package/scripts/bongos/provision-capacity.js +79 -0
  620. package/scripts/bongos/provision-caps.js +63 -0
  621. package/scripts/bongos/provision-config.js +233 -0
  622. package/scripts/bongos/provision-core-upgrade.js +1166 -0
  623. package/scripts/bongos/provision-disconnect.js +88 -0
  624. package/scripts/bongos/provision-github-setup.js +168 -0
  625. package/scripts/bongos/provision-net.js +357 -0
  626. package/scripts/bongos/provision-pin-key.js +176 -0
  627. package/scripts/bongos/provision-pin-replay.js +126 -0
  628. package/scripts/bongos/provision-process.js +170 -0
  629. package/scripts/bongos/provision-render.js +201 -0
  630. package/scripts/bongos/provision-repo-auth.js +164 -0
  631. package/scripts/bongos/provision-repo-private.js +98 -0
  632. package/scripts/bongos/provision-repo.js +1337 -0
  633. package/scripts/bongos/provision-teardown.js +106 -0
  634. package/scripts/bongos/provision-units.js +469 -0
  635. package/scripts/bongos/provision.js +1479 -0
  636. package/scripts/bongos/publish-credential-check.js +66 -0
  637. package/scripts/bongos/publish-integration-gate.js +142 -0
  638. package/scripts/bongos/publish-manifest.js +440 -0
  639. package/scripts/bongos/publish-watch.js +268 -0
  640. package/scripts/bongos/pulse.js +336 -0
  641. package/scripts/bongos/push-main.js +56 -0
  642. package/scripts/bongos/push-path-brief.js +100 -0
  643. package/scripts/bongos/read-session-export.js +359 -0
  644. package/scripts/bongos/reauth.js +155 -0
  645. package/scripts/bongos/recall.js +183 -0
  646. package/scripts/bongos/redteam-patrol.js +437 -0
  647. package/scripts/bongos/regen-instance-docs.js +47 -0
  648. package/scripts/bongos/release-core.js +80 -0
  649. package/scripts/bongos/release-notes.js +271 -0
  650. package/scripts/bongos/release.js +139 -0
  651. package/scripts/bongos/rename-goals.js +109 -0
  652. package/scripts/bongos/rename-history-check.js +369 -0
  653. package/scripts/bongos/rename-ledger-prose.js +482 -0
  654. package/scripts/bongos/render-api.js +197 -0
  655. package/scripts/bongos/render-check.js +206 -0
  656. package/scripts/bongos/render-ideas.js +226 -0
  657. package/scripts/bongos/render-payload.js +85 -0
  658. package/scripts/bongos/repo-metrics.js +363 -0
  659. package/scripts/bongos/review-sheet.js +108 -0
  660. package/scripts/bongos/role-pack-guard.js +142 -0
  661. package/scripts/bongos/route-shadow-guard.js +175 -0
  662. package/scripts/bongos/routine-schedule.js +283 -0
  663. package/scripts/bongos/run-routine.js +257 -0
  664. package/scripts/bongos/run-unit-tests.js +654 -0
  665. package/scripts/bongos/runner-drift.js +151 -0
  666. package/scripts/bongos/sandbox-stage.js +459 -0
  667. package/scripts/bongos/scope-map-guard.js +300 -0
  668. package/scripts/bongos/scope-roster-guard.js +118 -0
  669. package/scripts/bongos/seam-wiring-guard.js +275 -0
  670. package/scripts/bongos/search-ingest-db.js +288 -0
  671. package/scripts/bongos/search-ingest-md.js +269 -0
  672. package/scripts/bongos/seed-adopt-tasks.js +75 -0
  673. package/scripts/bongos/seed-api-contract-goal-tasks.js +141 -0
  674. package/scripts/bongos/seed-board-room-tasks.js +196 -0
  675. package/scripts/bongos/seed-bongos-app-tasks.js +294 -0
  676. package/scripts/bongos/seed-bongos-coreB-tranche1-tasks.js +81 -0
  677. package/scripts/bongos/seed-bongos-coreB-tranche2-tasks.js +100 -0
  678. package/scripts/bongos/seed-bongos-goal-hierarchy-tasks.js +307 -0
  679. package/scripts/bongos/seed-bongos-module-system-tasks.js +346 -0
  680. package/scripts/bongos/seed-bongos-tasks.js +214 -0
  681. package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +152 -0
  682. package/scripts/bongos/seed-bongos-v1-seo-tasks.js +104 -0
  683. package/scripts/bongos/seed-bv1-community-tasks.js +131 -0
  684. package/scripts/bongos/seed-bv1-privacy-invites-tasks.js +133 -0
  685. package/scripts/bongos/seed-bv1-profile-page-tasks.js +161 -0
  686. package/scripts/bongos/seed-bv1-profiles-tasks.js +135 -0
  687. package/scripts/bongos/seed-bv1-r01-delta-tasks.js +154 -0
  688. package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +390 -0
  689. package/scripts/bongos/seed-bv2-tweak-mode-tasks.js +277 -0
  690. package/scripts/bongos/seed-gds-v4-tasks.js +624 -0
  691. package/scripts/bongos/seed-governance-tasks.js +340 -0
  692. package/scripts/bongos/seed-medusa-tasks.js +440 -0
  693. package/scripts/bongos/seed-module-upstreaming.js +219 -0
  694. package/scripts/bongos/seed-productization-tasks.js +235 -0
  695. package/scripts/bongos/seed-project-admin-console-tasks.js +88 -0
  696. package/scripts/bongos/seed-provisioning-tasks.js +83 -0
  697. package/scripts/bongos/seed-staging.sh +117 -0
  698. package/scripts/bongos/seed-strict-versioning-tasks.js +275 -0
  699. package/scripts/bongos/seed-v2-world-tasks.js +283 -0
  700. package/scripts/bongos/seed-verify-criteria.js +124 -0
  701. package/scripts/bongos/sequence.js +597 -0
  702. package/scripts/bongos/session-cost.js +430 -0
  703. package/scripts/bongos/session-digest-build.js +293 -0
  704. package/scripts/bongos/session-digest.js +200 -0
  705. package/scripts/bongos/session-eval.js +631 -0
  706. package/scripts/bongos/session-transcript-build.js +155 -0
  707. package/scripts/bongos/session-transcript-upload.js +29 -0
  708. package/scripts/bongos/session.js +404 -0
  709. package/scripts/bongos/setup.js +646 -0
  710. package/scripts/bongos/ship-check.js +89 -0
  711. package/scripts/bongos/ship-deploy-target.js +393 -0
  712. package/scripts/bongos/ship-escalation.js +167 -0
  713. package/scripts/bongos/ship-finish.js +420 -0
  714. package/scripts/bongos/ship-flow.js +1217 -0
  715. package/scripts/bongos/ship-git.js +100 -0
  716. package/scripts/bongos/ship-grade-steps.js +547 -0
  717. package/scripts/bongos/ship-grade.js +426 -0
  718. package/scripts/bongos/ship-honesty.js +314 -0
  719. package/scripts/bongos/ship-io.js +139 -0
  720. package/scripts/bongos/ship-land.js +1130 -0
  721. package/scripts/bongos/ship-memory-sync.js +249 -0
  722. package/scripts/bongos/ship-merge-gate.js +225 -0
  723. package/scripts/bongos/ship-merge.js +466 -0
  724. package/scripts/bongos/ship-mode-ask.js +138 -0
  725. package/scripts/bongos/ship-mode-manual.js +54 -0
  726. package/scripts/bongos/ship-preflight-steps.js +399 -0
  727. package/scripts/bongos/ship-regen.js +292 -0
  728. package/scripts/bongos/ship-resume.js +201 -0
  729. package/scripts/bongos/ship-session-upload.js +313 -0
  730. package/scripts/bongos/ship-state.js +110 -0
  731. package/scripts/bongos/ship-surprise.js +84 -0
  732. package/scripts/bongos/ship-visual.js +75 -0
  733. package/scripts/bongos/ship.js +382 -0
  734. package/scripts/bongos/shipping-mode.js +71 -0
  735. package/scripts/bongos/skill-lint.js +250 -0
  736. package/scripts/bongos/skill-preflight.js +361 -0
  737. package/scripts/bongos/smoke-batch-claim.sh +238 -0
  738. package/scripts/bongos/smoke-batch-release.sh +316 -0
  739. package/scripts/bongos/smoke-claim-consistency.sh +222 -0
  740. package/scripts/bongos/smoke-dependencies.sh +143 -0
  741. package/scripts/bongos/smoke-gds.js +256 -0
  742. package/scripts/bongos/smoke-write.sh +275 -0
  743. package/scripts/bongos/source-text-test-scan.js +106 -0
  744. package/scripts/bongos/spark.js +294 -0
  745. package/scripts/bongos/stale-worktrees.js +212 -0
  746. package/scripts/bongos/start-goals.js +102 -0
  747. package/scripts/bongos/start.js +1090 -0
  748. package/scripts/bongos/status.js +545 -0
  749. package/scripts/bongos/strand-watch.js +315 -0
  750. package/scripts/bongos/stranded-rows.js +200 -0
  751. package/scripts/bongos/stray-unit-sweep.sh +71 -0
  752. package/scripts/bongos/surface.js +101 -0
  753. package/scripts/bongos/task.js +273 -0
  754. package/scripts/bongos/test-path-guard.js +99 -0
  755. package/scripts/bongos/triage.js +742 -0
  756. package/scripts/bongos/turn-end-sound.js +74 -0
  757. package/scripts/bongos/tweak-halt.js +70 -0
  758. package/scripts/bongos/tweak-renders.js +200 -0
  759. package/scripts/bongos/uat.js +120 -0
  760. package/scripts/bongos/ui-kit-transform.js +43 -0
  761. package/scripts/bongos/update-channel.js +512 -0
  762. package/scripts/bongos/update-sweep.js +829 -0
  763. package/scripts/bongos/upgrade-artist-gate.js +46 -0
  764. package/scripts/bongos/upgrade-commit-identity.js +32 -0
  765. package/scripts/bongos/upgrade-migrate.js +224 -0
  766. package/scripts/bongos/upgrade-operator.js +73 -0
  767. package/scripts/bongos/upgrade-outcome.js +174 -0
  768. package/scripts/bongos/upgrade.js +1499 -0
  769. package/scripts/bongos/validate-design.js +12 -0
  770. package/scripts/bongos/version-close.js +621 -0
  771. package/scripts/bongos/version-literal-guard.js +140 -0
  772. package/scripts/bongos/version-select.js +79 -0
  773. package/scripts/bongos/visual-review-nudge.js +39 -0
  774. package/scripts/bongos/wedge-remedy.js +174 -0
  775. package/scripts/bongos/worktree-claim-guard.js +130 -0
  776. package/scripts/bongos/worktree.js +449 -0
  777. package/scripts/discord/post.js +1 -1
  778. package/scripts/gds/README.md +9 -0
  779. package/scripts/gds/abandon.js +6 -136
  780. package/scripts/gds/accessibility-replay.js +5 -194
  781. package/scripts/gds/address-park-sweep.sh +7 -90
  782. package/scripts/gds/adopt-detect.js +5 -121
  783. package/scripts/gds/adopt-import.js +5 -109
  784. package/scripts/gds/adopt-preflight.js +5 -185
  785. package/scripts/gds/adr-namespace.js +5 -271
  786. package/scripts/gds/agent-invoke.js +5 -687
  787. package/scripts/gds/agents-sync.js +5 -500
  788. package/scripts/gds/api-alias-caller-scan.js +5 -255
  789. package/scripts/gds/api-artifacts.js +6 -0
  790. package/scripts/gds/api.js +6 -85
  791. package/scripts/gds/api.ps1 +8 -26
  792. package/scripts/gds/architect-audit.js +6 -293
  793. package/scripts/gds/artifact-audit.js +5 -324
  794. package/scripts/gds/artifact-format.js +6 -203
  795. package/scripts/gds/artifact-staleness.js +5 -265
  796. package/scripts/gds/ask.js +5 -229
  797. package/scripts/gds/audit-authorship.sh +7 -328
  798. package/scripts/gds/audit-deps.js +6 -188
  799. package/scripts/gds/audit-gate.js +5 -119
  800. package/scripts/gds/audit-rank-roles.js +6 -171
  801. package/scripts/gds/audit-replay.sh +7 -204
  802. package/scripts/gds/autobongos-digest.js +5 -121
  803. package/scripts/gds/autobongos-grade-cap.js +5 -186
  804. package/scripts/gds/autobongos-loop.js +5 -208
  805. package/scripts/gds/autobongos-run.js +5 -1359
  806. package/scripts/gds/autobongos-service.cmd +8 -49
  807. package/scripts/gds/autobongos-service.ps1 +8 -270
  808. package/scripts/gds/autobongos-tweak-lane.js +5 -261
  809. package/scripts/gds/autobongos-verify.js +5 -616
  810. package/scripts/gds/autonomy-gate.js +5 -133
  811. package/scripts/gds/autonomy-gauge-statusline.js +5 -122
  812. package/scripts/gds/autonomy-gauge.js +5 -82
  813. package/scripts/gds/backfill-cost.js +6 -175
  814. package/scripts/gds/backfill-disciplines.js +5 -142
  815. package/scripts/gds/backfill-session-earnings.js +5 -121
  816. package/scripts/gds/backfill-session-types.js +5 -85
  817. package/scripts/gds/backfill-sessions.js +5 -409
  818. package/scripts/gds/backfill-subagent-rewards.js +5 -483
  819. package/scripts/gds/backfill-task-rewards.js +5 -411
  820. package/scripts/gds/backlog-review.js +6 -398
  821. package/scripts/gds/backup-dropin-sweep.sh +7 -94
  822. package/scripts/gds/backup.js +6 -115
  823. package/scripts/gds/baseline-staleness.js +5 -215
  824. package/scripts/gds/bfg-principal-token.js +6 -64
  825. package/scripts/gds/bug-attachment-audit.js +5 -147
  826. package/scripts/gds/bug-attachment-recover.js +5 -196
  827. package/scripts/gds/bug-triage.js +6 -291
  828. package/scripts/gds/build-bongos.js +5 -92
  829. package/scripts/gds/bump-version.js +5 -219
  830. package/scripts/gds/capture.js +6 -480
  831. package/scripts/gds/category-advisory-guard.js +5 -205
  832. package/scripts/gds/ci-grade.js +6 -81
  833. package/scripts/gds/claim-recall.js +6 -111
  834. package/scripts/gds/claim.js +6 -788
  835. package/scripts/gds/classify-discipline.js +6 -152
  836. package/scripts/gds/claude-materialize.js +5 -1198
  837. package/scripts/gds/claude-md-template.js +5 -140
  838. package/scripts/gds/cleanup-orphans.js +6 -73
  839. package/scripts/gds/cli-lib.js +6 -1204
  840. package/scripts/gds/client-baseurl-guard.js +5 -114
  841. package/scripts/gds/codemod-rename-src-gds.js +6 -144
  842. package/scripts/gds/conductor-dispatch.js +6 -534
  843. package/scripts/gds/context-pack.js +6 -325
  844. package/scripts/gds/control-manifest.js +5 -197
  845. package/scripts/gds/copy-apply.js +5 -756
  846. package/scripts/gds/copy-inventory.js +5 -569
  847. package/scripts/gds/core-origin-follow.js +5 -184
  848. package/scripts/gds/core-pin-sync.js +5 -258
  849. package/scripts/gds/coreB-carve-proof.sh +7 -724
  850. package/scripts/gds/cost-report.js +6 -62
  851. package/scripts/gds/cost.js +6 -46
  852. package/scripts/gds/credential-presence.js +5 -294
  853. package/scripts/gds/cutover-codemod.js +5 -239
  854. package/scripts/gds/db-backup-nightly.sh +7 -231
  855. package/scripts/gds/db-backup-offsite.sh +7 -266
  856. package/scripts/gds/demote.js +6 -44
  857. package/scripts/gds/deploy-divergence.js +6 -445
  858. package/scripts/gds/deploy-main-audit-gate.sh +7 -96
  859. package/scripts/gds/design-sync.js +5 -10
  860. package/scripts/gds/dev-box-guard.js +5 -164
  861. package/scripts/gds/dev-lib.js +5 -721
  862. package/scripts/gds/dev.js +5 -643
  863. package/scripts/gds/device-flow-help.js +5 -70
  864. package/scripts/gds/diagnose-achievements.js +5 -116
  865. package/scripts/gds/diagram-facts.js +6 -355
  866. package/scripts/gds/discord-channels.js +5 -75
  867. package/scripts/gds/do-api.js +6 -109
  868. package/scripts/gds/doc-cli-guard.js +5 -266
  869. package/scripts/gds/doc-comment-coverage.js +5 -137
  870. package/scripts/gds/doc-control-claims.js +5 -166
  871. package/scripts/gds/docs-entropy.js +5 -443
  872. package/scripts/gds/doctor.js +6 -492
  873. package/scripts/gds/enroll-control-plane.js +5 -99
  874. package/scripts/gds/exec-path-guard.js +5 -562
  875. package/scripts/gds/feedback-send.js +5 -247
  876. package/scripts/gds/fetch-art-key.js +5 -104
  877. package/scripts/gds/fetch-sound-prefs.js +5 -124
  878. package/scripts/gds/figma-design-sync.js +5 -9
  879. package/scripts/gds/find-untested.js +5 -369
  880. package/scripts/gds/fitness-checks-error-envelope.js +5 -133
  881. package/scripts/gds/fitness-checks-identity.js +5 -342
  882. package/scripts/gds/fitness-checks-packaging.js +5 -131
  883. package/scripts/gds/fitness-checks-route-pins.js +5 -75
  884. package/scripts/gds/fitness-checks-vocabulary.js +5 -391
  885. package/scripts/gds/fitness-checks-write-validation.js +5 -156
  886. package/scripts/gds/fitness-lib.js +5 -126
  887. package/scripts/gds/fitness-migration-contraction.js +5 -49
  888. package/scripts/gds/fitness-ratchets.js +5 -563
  889. package/scripts/gds/fitness.js +5 -1493
  890. package/scripts/gds/gate-review.js +5 -328
  891. package/scripts/gds/gating.js +5 -346
  892. package/scripts/gds/gds-literal-scan.js +5 -194
  893. package/scripts/gds/gen-api-client.js +5 -555
  894. package/scripts/gds/gen-api-docs.js +5 -1100
  895. package/scripts/gds/gen-atlas.js +5 -364
  896. package/scripts/gds/gen-diagrams.js +6 -607
  897. package/scripts/gds/gen-file-map.js +5 -335
  898. package/scripts/gds/gen-freshness.js +5 -31
  899. package/scripts/gds/gen-interaction-posture.js +5 -120
  900. package/scripts/gds/gen-repo-map.js +5 -538
  901. package/scripts/gds/gen-role-responsibilities.js +5 -133
  902. package/scripts/gds/gen-session-index.js +5 -241
  903. package/scripts/gds/gen-sounds.js +5 -174
  904. package/scripts/gds/git-merge-regen.js +6 -291
  905. package/scripts/gds/go-live.js +5 -1069
  906. package/scripts/gds/goal-names.js +5 -100
  907. package/scripts/gds/goal.js +6 -271
  908. package/scripts/gds/government-walk.js +5 -1475
  909. package/scripts/gds/grade-correlation-audit.js +5 -308
  910. package/scripts/gds/grade-replay.js +5 -235
  911. package/scripts/gds/grade-smoke.js +6 -204
  912. package/scripts/gds/home-isolation-guard.js +5 -125
  913. package/scripts/gds/hooks/pre-push.js +5 -209
  914. package/scripts/gds/howto.js +5 -143
  915. package/scripts/gds/http-api-client.js +6 -81
  916. package/scripts/gds/identity-strip.js +5 -74
  917. package/scripts/gds/init.js +5 -1157
  918. package/scripts/gds/install-git-hooks.js +5 -198
  919. package/scripts/gds/instance-apex.js +5 -37
  920. package/scripts/gds/intent-retry.js +5 -51
  921. package/scripts/gds/key-card.js +6 -221
  922. package/scripts/gds/key-status.js +5 -124
  923. package/scripts/gds/land-watch.js +5 -199
  924. package/scripts/gds/leak-scan-allowlist.js +5 -291
  925. package/scripts/gds/learning-capture.js +6 -144
  926. package/scripts/gds/lib.sh +7 -73
  927. package/scripts/gds/linkify-refs.js +6 -654
  928. package/scripts/gds/lint-infra-exec.js +5 -68
  929. package/scripts/gds/lint-migrations.js +5 -100
  930. package/scripts/gds/lint-workflow-exec.js +5 -61
  931. package/scripts/gds/local-preview-lib.js +6 -128
  932. package/scripts/gds/local-preview.js +6 -81
  933. package/scripts/gds/login.js +5 -358
  934. package/scripts/gds/main-audit.js +5 -623
  935. package/scripts/gds/me.js +6 -96
  936. package/scripts/gds/memory-map.js +5 -174
  937. package/scripts/gds/merge-lock.js +6 -70
  938. package/scripts/gds/migration-namespace.js +5 -311
  939. package/scripts/gds/mirror-lineage-check.js +5 -341
  940. package/scripts/gds/mirror-redact.js +5 -348
  941. package/scripts/gds/module-artifact.js +6 -289
  942. package/scripts/gds/module-assess-docs.js +6 -237
  943. package/scripts/gds/module-assess-installs.js +6 -227
  944. package/scripts/gds/module-assess-score.js +6 -110
  945. package/scripts/gds/module-assess-security.js +6 -251
  946. package/scripts/gds/module-assess-tests.js +6 -277
  947. package/scripts/gds/module-assess-version.js +6 -91
  948. package/scripts/gds/module-error-report.js +5 -146
  949. package/scripts/gds/module-test-runner.js +6 -413
  950. package/scripts/gds/module.js +5 -1374
  951. package/scripts/gds/move-escalation.js +5 -140
  952. package/scripts/gds/newcomer-floor.js +6 -420
  953. package/scripts/gds/newcomer-floor.test.js +6 -234
  954. package/scripts/gds/next-number.js +6 -162
  955. package/scripts/gds/oauth-secret.js +5 -200
  956. package/scripts/gds/onboard.js +5 -265
  957. package/scripts/gds/onboarding-analyze.js +6 -225
  958. package/scripts/gds/onboarding-config.js +6 -179
  959. package/scripts/gds/onboarding-ship.js +6 -91
  960. package/scripts/gds/pack-env-prefix.js +5 -72
  961. package/scripts/gds/package-core.js +5 -1102
  962. package/scripts/gds/page-inventory.js +5 -346
  963. package/scripts/gds/page-reader.js +5 -720
  964. package/scripts/gds/paste-token.js +6 -211
  965. package/scripts/gds/plain-cards.js +5 -350
  966. package/scripts/gds/portability-smoke-art.sh +7 -84
  967. package/scripts/gds/portability-smoke-memory.sh +7 -175
  968. package/scripts/gds/preflight.js +5 -212
  969. package/scripts/gds/probe-cache.js +5 -244
  970. package/scripts/gds/prove-strict-versioning.js +6 -283
  971. package/scripts/gds/provision-auto-upgrade.js +5 -161
  972. package/scripts/gds/provision-byo-host.js +5 -67
  973. package/scripts/gds/provision-capacity.js +5 -78
  974. package/scripts/gds/provision-caps.js +5 -62
  975. package/scripts/gds/provision-config.js +5 -232
  976. package/scripts/gds/provision-core-upgrade.js +5 -1165
  977. package/scripts/gds/provision-disconnect.js +5 -87
  978. package/scripts/gds/provision-github-setup.js +5 -167
  979. package/scripts/gds/provision-net.js +5 -356
  980. package/scripts/gds/provision-pin-key.js +5 -175
  981. package/scripts/gds/provision-pin-replay.js +5 -125
  982. package/scripts/gds/provision-process.js +5 -169
  983. package/scripts/gds/provision-render.js +5 -200
  984. package/scripts/gds/provision-repo-auth.js +5 -163
  985. package/scripts/gds/provision-repo-private.js +5 -97
  986. package/scripts/gds/provision-repo.js +5 -1336
  987. package/scripts/gds/provision-teardown.js +5 -105
  988. package/scripts/gds/provision-units.js +5 -468
  989. package/scripts/gds/provision.js +5 -1477
  990. package/scripts/gds/publish-credential-check.js +6 -65
  991. package/scripts/gds/publish-integration-gate.js +5 -140
  992. package/scripts/gds/publish-manifest.js +5 -437
  993. package/scripts/gds/publish-watch.js +5 -266
  994. package/scripts/gds/pulse.js +6 -335
  995. package/scripts/gds/push-main.js +5 -54
  996. package/scripts/gds/push-path-brief.js +5 -98
  997. package/scripts/gds/read-session-export.js +5 -357
  998. package/scripts/gds/reauth.js +6 -154
  999. package/scripts/gds/recall.js +6 -182
  1000. package/scripts/gds/redteam-patrol.js +5 -435
  1001. package/scripts/gds/regen-instance-docs.js +5 -45
  1002. package/scripts/gds/release-core.js +5 -78
  1003. package/scripts/gds/release-notes.js +5 -270
  1004. package/scripts/gds/release.js +6 -138
  1005. package/scripts/gds/rename-goals.js +5 -107
  1006. package/scripts/gds/rename-history-check.js +5 -367
  1007. package/scripts/gds/rename-ledger-prose.js +5 -480
  1008. package/scripts/gds/render-api.js +5 -196
  1009. package/scripts/gds/render-check.js +5 -204
  1010. package/scripts/gds/render-ideas.js +6 -225
  1011. package/scripts/gds/render-payload.js +5 -84
  1012. package/scripts/gds/repo-metrics.js +6 -362
  1013. package/scripts/gds/review-sheet.js +5 -106
  1014. package/scripts/gds/role-pack-guard.js +5 -141
  1015. package/scripts/gds/route-shadow-guard.js +5 -173
  1016. package/scripts/gds/routine-schedule.js +5 -281
  1017. package/scripts/gds/run-routine.js +5 -255
  1018. package/scripts/gds/run-unit-tests.js +6 -659
  1019. package/scripts/gds/runner-drift.js +5 -149
  1020. package/scripts/gds/sandbox-stage.js +6 -458
  1021. package/scripts/gds/scope-map-guard.js +5 -299
  1022. package/scripts/gds/scope-roster-guard.js +5 -117
  1023. package/scripts/gds/seam-wiring-guard.js +5 -274
  1024. package/scripts/gds/search-ingest-db.js +6 -287
  1025. package/scripts/gds/search-ingest-md.js +6 -268
  1026. package/scripts/gds/seed-adopt-tasks.js +6 -74
  1027. package/scripts/gds/seed-api-contract-goal-tasks.js +6 -140
  1028. package/scripts/gds/seed-board-room-tasks.js +6 -196
  1029. package/scripts/gds/seed-bongos-app-tasks.js +6 -293
  1030. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +6 -80
  1031. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +6 -99
  1032. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +6 -306
  1033. package/scripts/gds/seed-bongos-module-system-tasks.js +6 -345
  1034. package/scripts/gds/seed-bongos-tasks.js +6 -213
  1035. package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +6 -152
  1036. package/scripts/gds/seed-bongos-v1-seo-tasks.js +6 -104
  1037. package/scripts/gds/seed-bv1-community-tasks.js +6 -131
  1038. package/scripts/gds/seed-bv1-privacy-invites-tasks.js +6 -133
  1039. package/scripts/gds/seed-bv1-profile-page-tasks.js +6 -161
  1040. package/scripts/gds/seed-bv1-profiles-tasks.js +6 -135
  1041. package/scripts/gds/seed-bv1-r01-delta-tasks.js +6 -154
  1042. package/scripts/gds/seed-bv2-ideator-surface-tasks.js +6 -390
  1043. package/scripts/gds/seed-bv2-tweak-mode-tasks.js +6 -277
  1044. package/scripts/gds/seed-gds-v4-tasks.js +6 -623
  1045. package/scripts/gds/seed-governance-tasks.js +6 -339
  1046. package/scripts/gds/seed-medusa-tasks.js +6 -439
  1047. package/scripts/gds/seed-module-upstreaming.js +5 -217
  1048. package/scripts/gds/seed-productization-tasks.js +6 -234
  1049. package/scripts/gds/seed-project-admin-console-tasks.js +6 -88
  1050. package/scripts/gds/seed-provisioning-tasks.js +6 -82
  1051. package/scripts/gds/seed-staging.sh +7 -116
  1052. package/scripts/gds/seed-strict-versioning-tasks.js +6 -274
  1053. package/scripts/gds/seed-v2-world-tasks.js +6 -282
  1054. package/scripts/gds/seed-verify-criteria.js +6 -124
  1055. package/scripts/gds/sequence.js +6 -596
  1056. package/scripts/gds/session-cost.js +6 -429
  1057. package/scripts/gds/session-digest-build.js +6 -293
  1058. package/scripts/gds/session-digest.js +6 -199
  1059. package/scripts/gds/session-eval.js +6 -630
  1060. package/scripts/gds/session-transcript-build.js +6 -155
  1061. package/scripts/gds/session-transcript-upload.js +6 -29
  1062. package/scripts/gds/session.js +6 -403
  1063. package/scripts/gds/setup.js +6 -645
  1064. package/scripts/gds/ship-check.js +5 -85
  1065. package/scripts/gds/ship-deploy-target.js +5 -392
  1066. package/scripts/gds/ship-escalation.js +5 -166
  1067. package/scripts/gds/ship-finish.js +5 -419
  1068. package/scripts/gds/ship-flow.js +5 -1216
  1069. package/scripts/gds/ship-git.js +5 -99
  1070. package/scripts/gds/ship-grade-steps.js +5 -546
  1071. package/scripts/gds/ship-grade.js +5 -425
  1072. package/scripts/gds/ship-honesty.js +5 -312
  1073. package/scripts/gds/ship-io.js +5 -138
  1074. package/scripts/gds/ship-land.js +5 -1129
  1075. package/scripts/gds/ship-memory-sync.js +5 -248
  1076. package/scripts/gds/ship-merge-gate.js +5 -224
  1077. package/scripts/gds/ship-merge.js +5 -465
  1078. package/scripts/gds/ship-mode-ask.js +5 -137
  1079. package/scripts/gds/ship-mode-manual.js +5 -53
  1080. package/scripts/gds/ship-preflight-steps.js +5 -398
  1081. package/scripts/gds/ship-regen.js +5 -313
  1082. package/scripts/gds/ship-resume.js +5 -200
  1083. package/scripts/gds/ship-session-upload.js +5 -312
  1084. package/scripts/gds/ship-state.js +5 -109
  1085. package/scripts/gds/ship-surprise.js +5 -83
  1086. package/scripts/gds/ship-visual.js +5 -74
  1087. package/scripts/gds/ship.js +5 -380
  1088. package/scripts/gds/shipping-mode.js +5 -69
  1089. package/scripts/gds/skill-lint.js +5 -248
  1090. package/scripts/gds/skill-preflight.js +5 -359
  1091. package/scripts/gds/smoke-batch-claim.sh +7 -237
  1092. package/scripts/gds/smoke-batch-release.sh +7 -315
  1093. package/scripts/gds/smoke-claim-consistency.sh +7 -221
  1094. package/scripts/gds/smoke-dependencies.sh +7 -142
  1095. package/scripts/gds/smoke-gds.js +6 -255
  1096. package/scripts/gds/smoke-write.sh +7 -274
  1097. package/scripts/gds/source-text-test-scan.js +7 -0
  1098. package/scripts/gds/spark.js +6 -293
  1099. package/scripts/gds/stale-worktrees.js +5 -210
  1100. package/scripts/gds/start-goals.js +5 -101
  1101. package/scripts/gds/start.js +6 -1089
  1102. package/scripts/gds/status.js +6 -544
  1103. package/scripts/gds/strand-watch.js +5 -313
  1104. package/scripts/gds/stranded-rows.js +5 -198
  1105. package/scripts/gds/stray-unit-sweep.sh +7 -70
  1106. package/scripts/gds/surface.js +5 -100
  1107. package/scripts/gds/task.js +6 -272
  1108. package/scripts/gds/test-path-guard.js +5 -97
  1109. package/scripts/gds/triage.js +6 -741
  1110. package/scripts/gds/turn-end-sound.js +5 -72
  1111. package/scripts/gds/tweak-halt.js +5 -68
  1112. package/scripts/gds/tweak-renders.js +5 -198
  1113. package/scripts/gds/uat.js +6 -119
  1114. package/scripts/gds/ui-kit-transform.js +5 -41
  1115. package/scripts/gds/update-channel.js +5 -510
  1116. package/scripts/gds/update-sweep.js +5 -827
  1117. package/scripts/gds/upgrade-artist-gate.js +5 -45
  1118. package/scripts/gds/upgrade-commit-identity.js +5 -31
  1119. package/scripts/gds/upgrade-migrate.js +5 -223
  1120. package/scripts/gds/upgrade-operator.js +6 -73
  1121. package/scripts/gds/upgrade-outcome.js +5 -173
  1122. package/scripts/gds/upgrade.js +5 -1497
  1123. package/scripts/gds/validate-design.js +5 -10
  1124. package/scripts/gds/version-close.js +6 -620
  1125. package/scripts/gds/version-literal-guard.js +5 -138
  1126. package/scripts/gds/version-select.js +5 -77
  1127. package/scripts/gds/visual-review-nudge.js +5 -38
  1128. package/scripts/gds/wedge-remedy.js +5 -173
  1129. package/scripts/gds/worktree-claim-guard.js +5 -129
  1130. package/scripts/gds/worktree.js +6 -448
  1131. package/scripts/hall-preview/refresh-fixtures.js +1 -1
  1132. package/scripts/hall-preview/server.js +2 -2
  1133. package/scripts/migrate.sh +3 -3
  1134. package/scripts/public-mirror-export.js +3 -3
  1135. package/scripts/setup-builder.js +7 -7
  1136. package/src/bongos/api-errors.js +1 -0
  1137. package/src/bongos/api-prefix.js +1 -1
  1138. package/src/bongos/auth-github.js +19 -3
  1139. package/src/bongos/auth-idp.js +7 -0
  1140. package/src/bongos/claim-attribution.js +2 -2
  1141. package/src/bongos/core-moves.js +1 -1
  1142. package/src/bongos/core-update.js +3 -3
  1143. package/src/bongos/craft-mode.js +2 -2
  1144. package/src/bongos/db-kernel.js +15 -3
  1145. package/src/bongos/db.js +30 -4
  1146. package/src/bongos/github-repos.js +1 -1
  1147. package/src/bongos/llm-cache.js +1 -1
  1148. package/src/bongos/llm-pricing.js +1 -1
  1149. package/src/bongos/metrics.js +1 -1
  1150. package/src/bongos/middleware/rate-limit.js +2 -2
  1151. package/src/bongos/module-listing.js +93 -1
  1152. package/src/bongos/module-scope-map.js +90 -85
  1153. package/src/bongos/module-store.js +1 -1
  1154. package/src/bongos/module-submissions.js +1 -1
  1155. package/src/bongos/optimizer.js +1 -1
  1156. package/src/bongos/package-registry.js +1 -1
  1157. package/src/bongos/path-match.js +1 -1
  1158. package/src/bongos/permission-path-check.js +3 -3
  1159. package/src/bongos/platform-visibility-gate.js +3 -5
  1160. package/src/bongos/prelaunch-gate.js +7 -6
  1161. package/src/bongos/route-rank-check.js +2 -2
  1162. package/src/bongos/routes/auth.js +15 -2
  1163. package/src/bongos/routes/backup.js +1 -1
  1164. package/src/bongos/routes/builders.js +29 -1
  1165. package/src/bongos/routes/me.js +49 -18
  1166. package/src/bongos/routes/modules.js +29 -9
  1167. package/src/bongos/routes/public.js +3 -72
  1168. package/src/bongos/schema-lag.js +1 -1
  1169. package/src/bongos/sensitive-surfaces.js +1 -1
  1170. package/src/bongos/serve-internal.js +65 -16
  1171. package/src/bongos/software-update.js +2 -2
  1172. package/src/bongos/upgrade-hold.js +3 -3
  1173. package/src/hall-look.js +6 -5
  1174. package/src/module-api.js +3 -3
  1175. package/src/module-loader/catalog.js +1 -1
  1176. package/src/module-loader/error-tally.js +3 -3
  1177. package/src/module-loader/manifest-schema.js +3 -3
  1178. package/src/platform-server.js +10 -0
  1179. package/src/role-responsibilities.js +1 -1
  1180. package/src/stale-timer.js +2 -2
  1181. package/tests/accessibility_replay.mjs +1 -1
  1182. package/tests/activity_rollup_order_db.mjs +1 -1
  1183. package/tests/activity_snapshots_db.mjs +1 -1
  1184. package/tests/adopt_detect.mjs +1 -1
  1185. package/tests/adopt_import.mjs +1 -1
  1186. package/tests/adopt_preflight.mjs +1 -1
  1187. package/tests/adr_0089_scope.mjs +10 -7
  1188. package/tests/adr_0162_citation.mjs +1 -1
  1189. package/tests/adr_0162_gate_citation.mjs +1 -1
  1190. package/tests/agent_invoke.mjs +1 -1
  1191. package/tests/agent_invoke_live.mjs +3 -3
  1192. package/tests/agents_cron_trigger.mjs +2 -2
  1193. package/tests/agents_roster.mjs +1 -1
  1194. package/tests/agents_sync.mjs +4 -4
  1195. package/tests/allow_rule_guard.mjs +20 -20
  1196. package/tests/api_alias_caller_ratchet.mjs +9 -10
  1197. package/tests/api_alias_exceptions.mjs +7 -6
  1198. package/tests/api_artifacts.mjs +214 -0
  1199. package/tests/api_cli_flags.mjs +3 -3
  1200. package/tests/api_client.mjs +56 -54
  1201. package/tests/api_docs.mjs +30 -9
  1202. package/tests/api_error_envelope_buildcheck.mjs +1 -1
  1203. package/tests/api_msys_path_repair.mjs +2 -2
  1204. package/tests/architect.mjs +1 -1
  1205. package/tests/art_stage.mjs +2 -2
  1206. package/tests/artifact_audit.mjs +2 -2
  1207. package/tests/artifact_staleness.mjs +9 -9
  1208. package/tests/atlas.mjs +1 -1
  1209. package/tests/audit_deps.mjs +1 -1
  1210. package/tests/audit_gate.mjs +1 -1
  1211. package/tests/auth_flow_slice1.mjs +3 -3
  1212. package/tests/auth_inactive_builder.mjs +43 -5
  1213. package/tests/auth_session_expiry_db.mjs +16 -4
  1214. package/tests/auth_session_ttl.mjs +23 -0
  1215. package/tests/authorship_audit.mjs +2 -2
  1216. package/tests/autobongos_cadence.mjs +1 -1
  1217. package/tests/autobongos_fence.mjs +1 -1
  1218. package/tests/autobongos_grade_cap.mjs +2 -2
  1219. package/tests/autobongos_heartbeat_head.mjs +1 -1
  1220. package/tests/autobongos_host_access.mjs +3 -3
  1221. package/tests/autobongos_loop.mjs +17 -17
  1222. package/tests/autobongos_service_ps1.mjs +3 -3
  1223. package/tests/autobongos_tweak_lane.mjs +2 -2
  1224. package/tests/autobongos_verify.mjs +2 -2
  1225. package/tests/autonomous_fit_protected_paths.mjs +3 -3
  1226. package/tests/autonomy_config_idle.mjs +1 -1
  1227. package/tests/autonomy_digest.mjs +1 -1
  1228. package/tests/autonomy_gate.mjs +1 -1
  1229. package/tests/autonomy_gauge.mjs +2 -2
  1230. package/tests/autonomy_runner_identity.mjs +1 -1
  1231. package/tests/backfill_sessions.mjs +8 -8
  1232. package/tests/backfill_subagent_rewards.mjs +1 -1
  1233. package/tests/backfill_task_rewards.mjs +2 -2
  1234. package/tests/backlog_review.mjs +3 -3
  1235. package/tests/baseline_staleness.mjs +2 -2
  1236. package/tests/bfg.mjs +11 -5
  1237. package/tests/bfg_write.mjs +20 -11
  1238. package/tests/blockers_hall.mjs +14 -4
  1239. package/tests/blockers_page_ui.mjs +56 -12
  1240. package/tests/bongos_dispatch.mjs +5 -5
  1241. package/tests/bongos_login.mjs +2 -2
  1242. package/tests/bug_attachment_audit.mjs +1 -1
  1243. package/tests/bug_attachment_recover.mjs +2 -2
  1244. package/tests/bug_triage.mjs +3 -3
  1245. package/tests/build_info.mjs +1 -1
  1246. package/tests/builder_tester_tag.mjs +184 -0
  1247. package/tests/bump_version.mjs +3 -3
  1248. package/tests/canonical_profile_url.mjs +1 -1
  1249. package/tests/capture_error_format.mjs +1 -1
  1250. package/tests/capture_goal_routing.mjs +2 -2
  1251. package/tests/category_advisory_guard.mjs +3 -3
  1252. package/tests/claim_error_surface.mjs +2 -2
  1253. package/tests/claim_from_task_and_home.mjs +1 -1
  1254. package/tests/claim_gate_open_blocker.mjs +7 -4
  1255. package/tests/claim_gate_rebase.mjs +12 -8
  1256. package/tests/claim_recall.mjs +4 -4
  1257. package/tests/claim_resolve_worktree_lock.mjs +1 -1
  1258. package/tests/claude_materialize.mjs +58 -58
  1259. package/tests/clawback_confirmed_backlog.mjs +8 -5
  1260. package/tests/cli_allowlist_permissions.mjs +11 -11
  1261. package/tests/cli_dispatcher.mjs +2 -2
  1262. package/tests/cli_err_code.mjs +6 -6
  1263. package/tests/cli_exit_no_abort.mjs +7 -7
  1264. package/tests/cli_lib_formatters.mjs +2 -2
  1265. package/tests/cli_sessions.mjs +5 -5
  1266. package/tests/cli_surface.mjs +15 -15
  1267. package/tests/cli_token_reissue.mjs +2 -2
  1268. package/tests/client_baseurl_guard.mjs +1 -1
  1269. package/tests/client_bundle_route.mjs +35 -4
  1270. package/tests/cloud_bongos_pack.mjs +1 -1
  1271. package/tests/community_leaderboard_db.mjs +1 -1
  1272. package/tests/conductor.mjs +18 -18
  1273. package/tests/conflict_resolve.mjs +14 -16
  1274. package/tests/consumer_layout_boot.mjs +12 -12
  1275. package/tests/context_pack.mjs +6 -6
  1276. package/tests/control_manifest.mjs +4 -4
  1277. package/tests/copy_desk_page_reads.mjs +1 -1
  1278. package/tests/copy_desk_page_release.mjs +192 -0
  1279. package/tests/copy_inventory.mjs +2 -2
  1280. package/tests/core_auto_upgrade.mjs +1 -1
  1281. package/tests/core_move_notice.mjs +2 -2
  1282. package/tests/core_origin_follow.mjs +7 -7
  1283. package/tests/core_pin_sync.mjs +3 -3
  1284. package/tests/core_upgrade_door.mjs +2 -2
  1285. package/tests/core_upgrade_owner_door.mjs +34 -1
  1286. package/tests/core_upgrade_runner.mjs +19 -19
  1287. package/tests/credential_presence.mjs +2 -2
  1288. package/tests/credit_grant.mjs +3 -3
  1289. package/tests/credit_log_single_writer.mjs +5 -5
  1290. package/tests/criterion_ref_status.mjs +2 -2
  1291. package/tests/cross_discipline_priority_direction.mjs +3 -3
  1292. package/tests/cutover_codemod.mjs +2 -4
  1293. package/tests/db_backup_nightly.mjs +1 -1
  1294. package/tests/db_backup_offsite.mjs +1 -1
  1295. package/tests/db_ownership_handover.mjs +2 -2
  1296. package/tests/dead_deps.mjs +3 -3
  1297. package/tests/dependency_advisory.mjs +1 -1
  1298. package/tests/deploy_audit_gate.mjs +4 -4
  1299. package/tests/deploy_divergence_line.mjs +36 -16
  1300. package/tests/deploy_page_projects.mjs +35 -4
  1301. package/tests/dev_lib.mjs +2 -2
  1302. package/tests/dev_windows.mjs +2 -2
  1303. package/tests/diagram_facts_offset.mjs +1 -1
  1304. package/tests/diagram_repo_slug.mjs +1 -1
  1305. package/tests/diff_derived_signals.mjs +2 -2
  1306. package/tests/dns_preflight.mjs +2 -2
  1307. package/tests/do_api.mjs +3 -3
  1308. package/tests/doc_cli_guard.mjs +28 -28
  1309. package/tests/doc_comment_coverage.mjs +1 -1
  1310. package/tests/doc_control_claims.mjs +11 -11
  1311. package/tests/docs_entropy.mjs +2 -2
  1312. package/tests/docs_openapi_route.mjs +8 -6
  1313. package/tests/doctor_hooks.mjs +1 -1
  1314. package/tests/edit_hints.mjs +3 -2
  1315. package/tests/effective_visibility_predicate.mjs +3 -3
  1316. package/tests/env_knobs_neutral_prefix.mjs +13 -13
  1317. package/tests/exec_path_guard.mjs +4 -4
  1318. package/tests/executed_closure.mjs +18 -12
  1319. package/tests/file_map.mjs +1 -1
  1320. package/tests/find_untested.mjs +13 -13
  1321. package/tests/first_admin_bootstrap.mjs +1 -1
  1322. package/tests/fitness.mjs +16 -16
  1323. package/tests/fitness_gds_ratchet.mjs +2 -2
  1324. package/tests/fitness_installed_core.mjs +3 -3
  1325. package/tests/fitness_no_raw_nul.mjs +1 -1
  1326. package/tests/fitness_ratchets.mjs +3 -3
  1327. package/tests/fitness_scope_roster.mjs +2 -2
  1328. package/tests/fitness_two_root.mjs +8 -8
  1329. package/tests/fixtures/accessibility-replay.json +5 -5
  1330. package/tests/fixtures/grade-replay/recorded-panel-grades.json +1 -1
  1331. package/tests/fixtures/ideator-prefold/README.md +1 -1
  1332. package/tests/fixtures/page-ledger.mjs +22 -0
  1333. package/tests/fixtures/session-506-digest.json +5 -5
  1334. package/tests/gate_approvals.mjs +50 -0
  1335. package/tests/gate_review.mjs +8 -8
  1336. package/tests/gating_review_retired.mjs +2 -2
  1337. package/tests/gen_freshness.mjs +3 -3
  1338. package/tests/git_guard.mjs +3 -3
  1339. package/tests/git_merge_regen.mjs +41 -65
  1340. package/tests/github_one_trip.mjs +4 -4
  1341. package/tests/github_pick_up.mjs +2 -2
  1342. package/tests/github_push_merge_driver.mjs +1 -1
  1343. package/tests/go_live.mjs +3 -2
  1344. package/tests/goal_category.mjs +1 -1
  1345. package/tests/goal_cli.mjs +2 -2
  1346. package/tests/goal_create_spec_entry.mjs +1 -1
  1347. package/tests/goal_invite_consent.mjs +3 -1
  1348. package/tests/goal_move.mjs +1 -1
  1349. package/tests/goal_names.mjs +2 -2
  1350. package/tests/goal_working_area.mjs +1 -1
  1351. package/tests/government_agent_asks.mjs +7 -7
  1352. package/tests/government_board_room_copy.mjs +6 -1
  1353. package/tests/government_board_view.mjs +39 -0
  1354. package/tests/government_board_vote_ui.mjs +39 -1
  1355. package/tests/government_config.mjs +2 -2
  1356. package/tests/government_live_proof_shape.mjs +1 -1
  1357. package/tests/government_protected_surfaces.mjs +54 -53
  1358. package/tests/government_require_permission.mjs +9 -1
  1359. package/tests/government_vanilla_boot.mjs +1 -1
  1360. package/tests/government_vocabulary.mjs +2 -2
  1361. package/tests/government_walk.mjs +2 -2
  1362. package/tests/grade_body_limit.mjs +6 -4
  1363. package/tests/grade_correlation_audit.mjs +3 -3
  1364. package/tests/grade_diff_hash.mjs +1 -1
  1365. package/tests/grade_engine_replay.mjs +2 -2
  1366. package/tests/grade_server_authoritative.mjs +1 -1
  1367. package/tests/grade_unavailable_display.mjs +1 -1
  1368. package/tests/grader.mjs +8 -24
  1369. package/tests/grader_generated_provenance.mjs +14 -14
  1370. package/tests/grader_no_artifact.mjs +1 -1
  1371. package/tests/grader_prompt_fencing.mjs +1 -1
  1372. package/tests/grader_quality_window_overflow.mjs +1 -1
  1373. package/tests/grader_reader_lens.mjs +3 -3
  1374. package/tests/grader_regrade_delta.mjs +1 -1
  1375. package/tests/grader_unbacked_score.mjs +2 -2
  1376. package/tests/hall_acclaim_vote_control.mjs +113 -0
  1377. package/tests/hall_asset_cache.mjs +127 -0
  1378. package/tests/hall_audit.mjs +63 -0
  1379. package/tests/hall_board_world.mjs +20 -0
  1380. package/tests/hall_city_card_words.mjs +61 -0
  1381. package/tests/hall_client_request_shape.mjs +5 -1
  1382. package/tests/hall_home_ships_bounded.mjs +160 -0
  1383. package/tests/hall_landing_boot.mjs +15 -2
  1384. package/tests/hall_nav.mjs +33 -0
  1385. package/tests/hall_onboarding_bongos_setup.mjs +1 -1
  1386. package/tests/hall_oversight_world.mjs +44 -4
  1387. package/tests/hall_palette.mjs +12 -9
  1388. package/tests/hall_preview_security.mjs +1 -1
  1389. package/tests/hall_profile_world.mjs +17 -0
  1390. package/tests/hall_reading_world.mjs +16 -1
  1391. package/tests/hall_roster_world.mjs +2 -1
  1392. package/tests/hall_studio_world.mjs +4 -1
  1393. package/tests/hall_work_history_id.mjs +39 -0
  1394. package/tests/held_tweak_reporting.mjs +4 -4
  1395. package/tests/helpers.mjs +3 -3
  1396. package/tests/home_bounded_reads.mjs +1 -1
  1397. package/tests/home_isolation_guard.mjs +1 -1
  1398. package/tests/hook_core_resolve.mjs +7 -7
  1399. package/tests/hook_user_agents.mjs +1 -1
  1400. package/tests/hooks_drain.mjs +2 -2
  1401. package/tests/host_topology_skips.mjs +1 -1
  1402. package/tests/howto_guide.mjs +1 -1
  1403. package/tests/howto_moments.mjs +3 -3
  1404. package/tests/hub_account_page.mjs +1 -1
  1405. package/tests/idea_capture_grades.mjs +2 -2
  1406. package/tests/idea_develop_spark.mjs +1 -1
  1407. package/tests/idea_filed_via.mjs +2 -2
  1408. package/tests/idea_ideate_full.mjs +1 -1
  1409. package/tests/idea_spark_mark.mjs +1 -1
  1410. package/tests/idea_spark_queue.mjs +1 -1
  1411. package/tests/idea_triage.mjs +1 -1
  1412. package/tests/idea_triage_grade.mjs +3 -3
  1413. package/tests/idea_vote_permission.mjs +113 -0
  1414. package/tests/idea_votes_fold_db.mjs +123 -0
  1415. package/tests/infra_exec_paths.mjs +12 -12
  1416. package/tests/init.mjs +2 -2
  1417. package/tests/instance_db_migrated_on_code_move.mjs +5 -5
  1418. package/tests/instance_feedback.mjs +9 -9
  1419. package/tests/instance_mismatch_guard.mjs +2 -2
  1420. package/tests/integration_parked_ratchet.mjs +24 -2
  1421. package/tests/intent_retry.mjs +1 -1
  1422. package/tests/interaction_posture.mjs +3 -3
  1423. package/tests/invite_expiry_db.mjs +1 -1
  1424. package/tests/joinability_invite_only.mjs +1 -1
  1425. package/tests/karma_vote_lists.mjs +270 -0
  1426. package/tests/key-card.mjs +2 -2
  1427. package/tests/key-status.mjs +2 -2
  1428. package/tests/knip_ratchet_ambient.mjs +2 -2
  1429. package/tests/known_failing_ratchet.mjs +1 -1
  1430. package/tests/land_watch.mjs +2 -2
  1431. package/tests/landing_legal_pages.mjs +1 -1
  1432. package/tests/landing_page.mjs +2 -2
  1433. package/tests/leaderboard_roles.mjs +4 -1
  1434. package/tests/leak_scan_allowlist.mjs +8 -8
  1435. package/tests/leak_scan_fail_closed.mjs +1 -1
  1436. package/tests/lib_sh_resolution.mjs +9 -9
  1437. package/tests/lifecycle-card.mjs +7 -7
  1438. package/tests/linkify_check.mjs +2 -2
  1439. package/tests/linkify_refs.mjs +1 -1
  1440. package/tests/llm-cache-route.mjs +1 -1
  1441. package/tests/local_preview.mjs +2 -2
  1442. package/tests/main_audit.mjs +3 -3
  1443. package/tests/main_audit_attestation.mjs +1 -1
  1444. package/tests/main_audit_db_roster.mjs +2 -2
  1445. package/tests/main_worktree_busy_reason.mjs +3 -3
  1446. package/tests/markdown_line_endings.mjs +2 -2
  1447. package/tests/me_streak_leaderboard_queries.mjs +193 -0
  1448. package/tests/membership_kind_lockstep.mjs +1 -1
  1449. package/tests/memory_isolation.mjs +16 -8
  1450. package/tests/memory_map.mjs +2 -2
  1451. package/tests/memory_pull.mjs +33 -25
  1452. package/tests/merge_driver_register.mjs +3 -3
  1453. package/tests/migration_allocation.mjs +2 -2
  1454. package/tests/migration_namespace.mjs +1 -1
  1455. package/tests/migrations_forward_safe.mjs +1 -1
  1456. package/tests/mingle.mjs +1 -1
  1457. package/tests/mirror_lineage_fulltree.mjs +3 -3
  1458. package/tests/mirror_lineage_proof.mjs +2 -2
  1459. package/tests/mirror_redact.mjs +4 -4
  1460. package/tests/missing_dep_classify.mjs +3 -3
  1461. package/tests/module-scope-map.mjs +22 -22
  1462. package/tests/module_api_lazy.mjs +1 -1
  1463. package/tests/module_assess_docs.mjs +2 -2
  1464. package/tests/module_assess_installs.mjs +3 -3
  1465. package/tests/module_assess_price_parity.mjs +5 -5
  1466. package/tests/module_assess_score.mjs +5 -5
  1467. package/tests/module_assess_security.mjs +4 -4
  1468. package/tests/module_assess_tests.mjs +3 -3
  1469. package/tests/module_assessments_migration.mjs +1 -1
  1470. package/tests/module_catalog.mjs +2 -2
  1471. package/tests/module_cli.mjs +3 -3
  1472. package/tests/module_entitlements.mjs +1 -1
  1473. package/tests/module_error_counts.mjs +1 -1
  1474. package/tests/module_install.mjs +4 -4
  1475. package/tests/module_loader.mjs +3 -1
  1476. package/tests/module_owned_tests.mjs +1 -1
  1477. package/tests/module_release_channels.mjs +1 -1
  1478. package/tests/module_store_howto.mjs +3 -3
  1479. package/tests/module_store_listing.mjs +139 -2
  1480. package/tests/module_store_publish.mjs +4 -4
  1481. package/tests/module_store_publish_route.mjs +1 -1
  1482. package/tests/module_store_reassess.mjs +1 -1
  1483. package/tests/module_store_registry_migration.mjs +1 -1
  1484. package/tests/module_test_runner.mjs +3 -3
  1485. package/tests/module_update.mjs +4 -4
  1486. package/tests/module_upgrade_updates.mjs +1 -1
  1487. package/tests/move_escalation.mjs +2 -2
  1488. package/tests/nav_permission_atoms.mjs +3 -2
  1489. package/tests/needs_rebase.mjs +7 -3
  1490. package/tests/newcomer_floor.mjs +1 -1
  1491. package/tests/newcomer_generator.mjs +48 -0
  1492. package/tests/next_number.mjs +1 -1
  1493. package/tests/no_artifact_escalation.mjs +3 -3
  1494. package/tests/npm_release_where.mjs +1 -1
  1495. package/tests/oauth_secret.mjs +2 -2
  1496. package/tests/onboard.mjs +6 -6
  1497. package/tests/onboarding_gate.mjs +2 -2
  1498. package/tests/opt_in_skill_modules.mjs +3 -3
  1499. package/tests/own_scope_guard.mjs +1 -1
  1500. package/tests/own_session_revoke.mjs +4 -1
  1501. package/tests/package_core.mjs +10 -11
  1502. package/tests/page_inventory.mjs +5 -5
  1503. package/tests/page_reader.mjs +7 -7
  1504. package/tests/page_tweak_hold.mjs +6 -6
  1505. package/tests/parallel-load.mjs +1 -1
  1506. package/tests/paste_token_api_base.mjs +1 -1
  1507. package/tests/paste_token_session_store.mjs +2 -2
  1508. package/tests/pending_invite_purge_db.mjs +1 -1
  1509. package/tests/permission_path.mjs +1 -1
  1510. package/tests/pin_replay.mjs +1 -1
  1511. package/tests/pin_write_key.mjs +7 -7
  1512. package/tests/plain_cards.mjs +15 -15
  1513. package/tests/pr_assign.mjs +1 -1
  1514. package/tests/pre_push_hook.mjs +3 -3
  1515. package/tests/preflight_checks.mjs +2 -2
  1516. package/tests/prelaunch_gate.mjs +1 -1
  1517. package/tests/privacy_matrix.mjs +1 -1
  1518. package/tests/probe_cache.mjs +6 -6
  1519. package/tests/profile_connections_ui.mjs +4 -3
  1520. package/tests/profile_fields.mjs +11 -1
  1521. package/tests/profile_privacy_owner_view.mjs +1 -1
  1522. package/tests/profile_role_headline.mjs +10 -9
  1523. package/tests/project_admin_console_model.mjs +1 -1
  1524. package/tests/projects_hub.mjs +1 -1
  1525. package/tests/projects_hub_cloud_hop.mjs +1 -1
  1526. package/tests/promote_goal_id.mjs +6 -6
  1527. package/tests/promotion_sweep.mjs +1 -1
  1528. package/tests/provision.mjs +24 -24
  1529. package/tests/provision_account_identity.mjs +2 -2
  1530. package/tests/provision_byo_host.mjs +1 -1
  1531. package/tests/provision_caddy_wiring.mjs +2 -2
  1532. package/tests/provision_disconnect.mjs +2 -2
  1533. package/tests/provision_dns_first.mjs +1 -1
  1534. package/tests/provision_render.mjs +9 -9
  1535. package/tests/provision_repo_private.mjs +3 -3
  1536. package/tests/provision_resource_caps.mjs +5 -5
  1537. package/tests/provision_restart.mjs +3 -3
  1538. package/tests/provision_settings_apply.mjs +7 -7
  1539. package/tests/provision_teardown_address.mjs +2 -2
  1540. package/tests/provisioning_capacity.mjs +5 -5
  1541. package/tests/provisioning_credential_preflight.mjs +1 -1
  1542. package/tests/provisioning_disconnect.mjs +1 -1
  1543. package/tests/provisioning_error_note_scope.mjs +4 -4
  1544. package/tests/provisioning_paid_shape_gate.mjs +2 -2
  1545. package/tests/provisioning_planet_physics.mjs +16 -0
  1546. package/tests/provisioning_runner_drift_notice.mjs +2 -2
  1547. package/tests/provisioning_settings_env.mjs +1 -1
  1548. package/tests/pruned_lockfile_integrity.mjs +1 -1
  1549. package/tests/public_mirror_export.mjs +1 -1
  1550. package/tests/publish_integration_gate.mjs +2 -2
  1551. package/tests/publish_manifest.mjs +6 -6
  1552. package/tests/publish_watch.mjs +1 -1
  1553. package/tests/push_path_brief.mjs +2 -2
  1554. package/tests/raise.mjs +248 -0
  1555. package/tests/rank_roles_audit.mjs +1 -1
  1556. package/tests/rank_tier_single_source.mjs +2 -2
  1557. package/tests/rate_limit_public.mjs +1 -1
  1558. package/tests/read_default_meter.mjs +2 -2
  1559. package/tests/read_session_export.mjs +1 -1
  1560. package/tests/rebase_gate_set_aside.mjs +1 -1
  1561. package/tests/recall_cli.mjs +1 -1
  1562. package/tests/recall_corpus_health.mjs +3 -2
  1563. package/tests/recall_hints.mjs +1 -1
  1564. package/tests/recruiter_sliver_boundary.mjs +1 -1
  1565. package/tests/redteam_patrol.mjs +2 -2
  1566. package/tests/regrade_actual_minutes.mjs +2 -2
  1567. package/tests/regrade_eligibility.mjs +2 -2
  1568. package/tests/release_core.mjs +2 -2
  1569. package/tests/release_notes.mjs +4 -4
  1570. package/tests/rename_history_restraint.mjs +3 -3
  1571. package/tests/rename_ledger_prose.mjs +6 -6
  1572. package/tests/render_api.mjs +1 -1
  1573. package/tests/render_check.mjs +4 -4
  1574. package/tests/render_deploy.mjs +1 -1
  1575. package/tests/repo_info_binding.mjs +1 -1
  1576. package/tests/repo_map.mjs +5 -5
  1577. package/tests/reward_mode_cost_plus_only.mjs +7 -3
  1578. package/tests/reward_mode_surfacing.mjs +1 -1
  1579. package/tests/role_responsibilities.mjs +1 -1
  1580. package/tests/route_permission_check.mjs +1 -1
  1581. package/tests/route_shadow_guard.mjs +1 -1
  1582. package/tests/route_validation.mjs +1 -1
  1583. package/tests/routine_capture_kind.mjs +6 -6
  1584. package/tests/routine_schedule.mjs +9 -9
  1585. package/tests/run_routine.mjs +5 -5
  1586. package/tests/run_routine_two_root.mjs +5 -5
  1587. package/tests/runner_drift.mjs +17 -17
  1588. package/tests/sandbox_stage.mjs +5 -5
  1589. package/tests/scope_map_guard.mjs +7 -7
  1590. package/tests/scouting_owner_access_and_reach.mjs +1 -1
  1591. package/tests/scripts_gds_forwarders.mjs +224 -0
  1592. package/tests/scrubber_corpus.mjs +2 -2
  1593. package/tests/seam_wiring_guard.mjs +1 -1
  1594. package/tests/search_ingest.mjs +2 -2
  1595. package/tests/search_ingest_db.mjs +1 -1
  1596. package/tests/search_ingest_nul.mjs +6 -6
  1597. package/tests/seed_verify_criteria.mjs +3 -3
  1598. package/tests/sequence.mjs +3 -3
  1599. package/tests/served_paths_shipped.mjs +3 -3
  1600. package/tests/session_506_regression.mjs +1 -1
  1601. package/tests/session_accessibility.mjs +1 -1
  1602. package/tests/session_caps.mjs +1 -1
  1603. package/tests/session_cost.mjs +1 -1
  1604. package/tests/session_digest.mjs +2 -2
  1605. package/tests/session_eval.mjs +6 -6
  1606. package/tests/session_index.mjs +1 -1
  1607. package/tests/session_records.mjs +4 -4
  1608. package/tests/session_rename_fallback.mjs +2 -2
  1609. package/tests/session_reward_on_land.mjs +7 -149
  1610. package/tests/session_reward_on_land_db.mjs +191 -0
  1611. package/tests/session_reward_reconcile.mjs +6 -88
  1612. package/tests/session_reward_reconcile_db.mjs +132 -0
  1613. package/tests/session_transcript.mjs +1 -1
  1614. package/tests/sessions_kit_pager.mjs +2 -1
  1615. package/tests/setup_device_flow_fallback.mjs +2 -2
  1616. package/tests/setup_smoke.mjs +12 -5
  1617. package/tests/setup_status_facts.mjs +54 -12
  1618. package/tests/ship_autolinkify.mjs +2 -2
  1619. package/tests/ship_automerge_injection.mjs +1 -1
  1620. package/tests/ship_base_flag.mjs +1 -1
  1621. package/tests/ship_broadcast_routing.mjs +1 -1
  1622. package/tests/ship_broadcast_server.mjs +2 -2
  1623. package/tests/ship_builder_model.mjs +1 -1
  1624. package/tests/ship_cannot_lie.mjs +9 -9
  1625. package/tests/ship_card.mjs +2 -2
  1626. package/tests/ship_ci_deploy.mjs +7 -7
  1627. package/tests/ship_error_shape.mjs +1 -1
  1628. package/tests/ship_land_ci_not_started.mjs +3 -3
  1629. package/tests/ship_land_conflict.mjs +3 -3
  1630. package/tests/ship_land_proof.mjs +3 -3
  1631. package/tests/ship_land_red_pr.mjs +5 -5
  1632. package/tests/ship_merge_gate.mjs +14 -14
  1633. package/tests/ship_mode.mjs +1 -1
  1634. package/tests/ship_mode_first_ship.mjs +4 -4
  1635. package/tests/ship_mode_hands_off.mjs +8 -8
  1636. package/tests/ship_post_land_verify.mjs +1 -1
  1637. package/tests/ship_preflight.mjs +19 -19
  1638. package/tests/ship_premerge.mjs +1 -1
  1639. package/tests/ship_publish_error.mjs +2 -2
  1640. package/tests/ship_push_diagnosis.mjs +1 -1
  1641. package/tests/ship_regen_copy_inventory.mjs +3 -3
  1642. package/tests/ship_resume.mjs +4 -4
  1643. package/tests/ship_smoke_gate.mjs +1 -1
  1644. package/tests/ship_upload_skip.mjs +1 -1
  1645. package/tests/ship_upstream_deletion.mjs +1 -1
  1646. package/tests/ship_vendored_instance.mjs +8 -8
  1647. package/tests/ship_visual_regrade.mjs +3 -3
  1648. package/tests/ship_zero_commit.mjs +1 -1
  1649. package/tests/skill_docs_unavailable_regrade.mjs +3 -3
  1650. package/tests/skill_friction_kind.mjs +1 -1
  1651. package/tests/skill_grade_recover.mjs +1 -1
  1652. package/tests/skill_grader_health.mjs +1 -1
  1653. package/tests/skill_lint.mjs +1 -1
  1654. package/tests/skill_menu_ruling.mjs +1 -1
  1655. package/tests/skill_preflight.mjs +7 -7
  1656. package/tests/skip_is_not_pass.mjs +22 -1
  1657. package/tests/smoke_dependencies_witness.mjs +2 -2
  1658. package/tests/smoke_preflight.mjs +1 -1
  1659. package/tests/smoke_target.mjs +2 -2
  1660. package/tests/smoke_write_contract.mjs +2 -2
  1661. package/tests/sound_player.mjs +8 -8
  1662. package/tests/source_text_test_ratchet.mjs +97 -0
  1663. package/tests/speciality_corpus_scope.mjs +1 -1
  1664. package/tests/speciality_session_skills.mjs +1 -1
  1665. package/tests/sso_checkin_legacy_field_gone.mjs +4 -2
  1666. package/tests/stale_timer.mjs +3 -3
  1667. package/tests/stale_worktrees.mjs +1 -1
  1668. package/tests/start_env_guard.mjs +1 -1
  1669. package/tests/start_goal_first.mjs +3 -3
  1670. package/tests/start_inbox_count.mjs +1 -1
  1671. package/tests/start_rebase_warning.mjs +1 -1
  1672. package/tests/status_default_version.mjs +3 -3
  1673. package/tests/status_mirror_sync.mjs +1 -1
  1674. package/tests/status_page_no_dead_uptime.mjs +80 -0
  1675. package/tests/stop_refcheck.mjs +1 -1
  1676. package/tests/strand_watch.mjs +1 -1
  1677. package/tests/stranded_rows.mjs +1 -1
  1678. package/tests/stuck_detector.mjs +14 -14
  1679. package/tests/sweep_app_account.mjs +3 -3
  1680. package/tests/task_cli.mjs +2 -2
  1681. package/tests/task_detail_ui.mjs +11 -1
  1682. package/tests/task_discipline_required.mjs +2 -2
  1683. package/tests/task_list_paging.mjs +1 -1
  1684. package/tests/task_visual_slots.mjs +2 -2
  1685. package/tests/terms_acceptance.mjs +1 -1
  1686. package/tests/terms_grandfather_db.mjs +1 -1
  1687. package/tests/test_path_guard.mjs +1 -1
  1688. package/tests/triage_development.mjs +1 -1
  1689. package/tests/tweak_batch_apply.mjs +2 -2
  1690. package/tests/tweak_land_heal.mjs +3 -3
  1691. package/tests/tweak_unattended.mjs +3 -3
  1692. package/tests/ui_design_skills.mjs +2 -2
  1693. package/tests/unit_report_status.mjs +2 -2
  1694. package/tests/unit_runner_serial.mjs +2 -2
  1695. package/tests/unit_runner_teardown_abort.mjs +1 -1
  1696. package/tests/update_channel.mjs +2 -2
  1697. package/tests/update_channel_db.mjs +4 -4
  1698. package/tests/update_subscription_engine.mjs +26 -26
  1699. package/tests/update_sweep_home.mjs +14 -14
  1700. package/tests/upgrade.mjs +11 -11
  1701. package/tests/upgrade_artist_gate.mjs +4 -4
  1702. package/tests/upgrade_commit_identity.mjs +2 -2
  1703. package/tests/upgrade_migrate.mjs +7 -7
  1704. package/tests/upgrade_operator.mjs +2 -2
  1705. package/tests/upgrade_outcome.mjs +2 -2
  1706. package/tests/upgrade_persist_pin.mjs +5 -5
  1707. package/tests/upkeep_home.mjs +1 -1
  1708. package/tests/version_close.mjs +2 -2
  1709. package/tests/version_close_cli.mjs +2 -2
  1710. package/tests/version_close_route.mjs +1 -1
  1711. package/tests/version_literals.mjs +23 -23
  1712. package/tests/visual_review.mjs +5 -5
  1713. package/tests/wedge_remedy.mjs +5 -5
  1714. package/tests/welcome_boot.mjs +116 -0
  1715. package/tests/welcome_boot_browser.mjs +271 -0
  1716. package/tests/wizard_born_first_board.mjs +3 -3
  1717. package/tests/wizard_demo.mjs +1 -1
  1718. package/tests/wizard_one_page.mjs +4 -3
  1719. package/tests/wizard_physics.mjs +3 -1
  1720. package/tests/wizard_physics_more.mjs +42 -3
  1721. package/tests/work_title_wrap.mjs +1 -1
  1722. package/tests/workflow_exec_paths.mjs +6 -6
  1723. package/tests/worktree_claim_guard.mjs +1 -1
  1724. package/tests/worktree_helper.mjs +2 -2
  1725. package/tests/write_validation_gaps.mjs +3 -3
  1726. package/scripts/gds/api.sh +0 -6
  1727. package/scripts/gds/audit-exports.js +0 -128
  1728. package/scripts/gds/resolve-skill-model.js +0 -57
  1729. package/scripts/gds/security-baseline-check.sh +0 -180
  1730. package/scripts/gds/spike-task-map.js +0 -899
  1731. package/scripts/status-probe.mjs +0 -213
  1732. package/src/bongos/uptime-poller.js +0 -93
  1733. package/tests/government_fold_bench.mjs +0 -50
  1734. package/tests/spike_task_map.mjs +0 -422
  1735. package/tests/status-probe.mjs +0 -89
  1736. /package/{scripts/gds → modules/raise}/CLAUDE.md +0 -0
  1737. /package/scripts/{gds → bongos}/cloudbongos-token-isolation.conf +0 -0
  1738. /package/scripts/{gds → bongos}/discipline-modes.json +0 -0
  1739. /package/scripts/{gds → bongos}/retired-core-skills.json +0 -0
@@ -1,1499 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ // scripts/gds/upgrade.js — @bongos-forwarder (task 1004848). Generated by
3
+ // scripts/bongos/codemod-rename-scripts-gds.js; do not edit.
4
+ // The real script is scripts/bongos/upgrade.js. This forwarder keeps callers that still name
5
+ // the old path working, and warns once so they get repointed. Task 1003706 removes it.
2
6
  'use strict';
3
- // scripts/gds/upgrade.js — the `bongos upgrade` update-consumption channel (ADR 0100 §2, task 1690).
4
- //
5
- // Turns the former stub (which only ran a module-vs-core compatibility PRE-CHECK) into the real
6
- // channel a two-repo consumer uses to pull the Cloud Bongos core from version N to N+1:
7
- //
8
- // pre-flight clean git tree + module-compat vs the TARGET core version + the artist gate (ADR 0241)
9
- // → bump pin vendor the new core .tgz, rewrite the package.json `file:` dependency
10
- // → npm install node_modules/@bongos/core becomes the new version
11
- // → migrate `npm run migrate` (no such script: the core's migrate.sh itself, upgrade-migrate.js) applies additive `core_*` migrations
12
- // → materialize refresh .claude/ skills+settings+hooks from the new core (claude-materialize / W3)
13
- // → restart restart the instance's service so the new core is live
14
- // → verify installed package version == target (+ optional /healthz + ledger row)
15
- //
16
- // SCOPE (ADR 0100 §2, reshaped by ADR 0103 §4): first built for emersonian-circles (task 1917), an
17
- // npm-dependency instance pinning "@bongos/core": "file:vendor/bongos-core-<ver>.tgz" with
18
- // `start`/`migrate` npm scripts and a materialized .claude/; the registry source (ADR 0134) and
19
- // auto-rollback (task 2149) came later, with the consumers that needed them.
20
- //
21
- // Runs from the consumer instance root (default) or `--instance <dir>`. This script ships IN the core
22
- // package, so once a consumer is on core vN+1 its own `bongos upgrade` is this code. The FIRST bump
23
- // (before vN+1 is installed) is driven by running THIS file out of the new version's staged tree
24
- // against `--instance <consumer>` — see docs/recipes for the bootstrap note.
25
-
26
- const fs = require('node:fs');
27
- const os = require('node:os');
28
- const path = require('node:path');
29
- const crypto = require('node:crypto');
30
- const { spawnSync } = require('node:child_process');
31
- const { arg, hasFlag } = require('./cli-lib');
32
- const { parseSemver, compareSemver, isStable, listAvailableVersions, npmSpawnOpts } = require('./update-channel');
33
- const { checkArtistGate } = require('./upgrade-artist-gate');
34
- // The database side of a move: which command migrates, as which account, and whether that
35
- // account can reach the database (tasks 1004274, 1002712, 1004512).
36
- const { preflightDbIdentity, asAccount, ACCOUNT_RE, teeSpawn, migrateResult, migrateError } = require('./upgrade-migrate');
37
-
38
- const CORE_PKG = '@bongos/core';
39
- const ARTIFACT = 'bongos-core';
40
- // WHERE THE VENDORED TARBALL SITS, as a package.json `file:` specifier — and the reason
41
- // this is not a path.join(). The same string is spent two ways: it is joined onto an
42
- // absolute dir for an fs check (path.join normalises a forward slash on every platform,
43
- // so that direction is free), and it is WRITTEN INTO package.json as `file:<vendorRel>`.
44
- // npm specifiers are POSIX. A path.join() here emits `file:vendor\\bongos-core-x.y.z.tgz`
45
- // on a Windows builder's machine, and that pin is then COMMITTED to the instance repo —
46
- // where the provisioner runs `npm ci` on Linux and reads a literal backslash in the
47
- // filename. One copy, POSIX by construction, so a scaffold cannot be platform-stamped
48
- // by the box that happened to run the scaffolder (task 1003839).
49
- function vendorRelFor(version) { return path.posix.join('vendor', `${ARTIFACT}-${version}.tgz`); }
50
-
51
- // ---- pure helpers (no I/O side effects beyond the injected fs) --------------
52
-
53
- // The pin a consumer carries is the vendored-tarball version in its `file:` dependency — there is no
54
- // separate pin file for this consumer shape. Extract the version from either the dep string or the
55
- // installed package.
56
- function versionFromTgzPath(p) {
57
- const m = String(p || '').match(new RegExp(`${ARTIFACT}-(\\d+\\.\\d+\\.\\d+[^/]*)\\.tgz$`));
58
- return m ? m[1] : null;
59
- }
60
-
61
- // The version from a REGISTRY dep spec — a bare semver, optionally range-prefixed
62
- // (`1.17.0`, `^1.17.0`, `~1.17.0`). Returns null for a `file:` tarball spec (that's
63
- // versionFromTgzPath's job) so the two never both match. ADR 0134 (task 2090).
64
- function versionFromDep(dep) {
65
- const s = String(dep || '').trim();
66
- if (!s || /^file:/.test(s)) return null;
67
- const m = s.match(/^[\^~>=<\s]*v?(\d+\.\d+\.\d+[A-Za-z0-9.+-]*)$/);
68
- return m ? m[1] : null;
69
- }
70
-
71
- function readJson(file, fsImpl = fs) {
72
- try { return JSON.parse(fsImpl.readFileSync(file, 'utf8')); } catch { return null; }
73
- }
74
-
75
- // The version currently installed under node_modules — the authoritative "from".
76
- function readInstalledCoreVersion(instanceDir, fsImpl = fs) {
77
- const pkg = readJson(path.join(instanceDir, 'node_modules', CORE_PKG, 'package.json'), fsImpl);
78
- return pkg && pkg.version ? pkg.version : null;
79
- }
80
-
81
- // The version the consumer's package.json currently pins — from either the `file:`
82
- // tarball path (vendored) or a bare registry semver (ADR 0134). A best-effort "from"
83
- // hint; readInstalledCoreVersion (node_modules) is the authoritative source.
84
- function readPinnedCoreVersion(instanceDir, fsImpl = fs) {
85
- const pkg = readJson(path.join(instanceDir, 'package.json'), fsImpl);
86
- const dep = pkg && ((pkg.dependencies || {})[CORE_PKG] || (pkg.devDependencies || {})[CORE_PKG]);
87
- return versionFromTgzPath(dep) || versionFromDep(dep);
88
- }
89
-
90
- // Rewrite the consumer package.json to pin `file:<vendorRel>`. Returns the previous dep string.
91
- function writePin(instanceDir, vendorRel, fsImpl = fs) {
92
- const pkgPath = path.join(instanceDir, 'package.json');
93
- const pkg = readJson(pkgPath, fsImpl);
94
- if (!pkg) throw new Error(`no readable package.json at ${pkgPath}`);
95
- pkg.dependencies = pkg.dependencies || {};
96
- const prev = pkg.dependencies[CORE_PKG];
97
- pkg.dependencies[CORE_PKG] = `file:${vendorRel}`;
98
- fsImpl.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
99
- return prev;
100
- }
101
-
102
- // Rewrite the consumer package.json to pin an EXACT registry version: the registry sibling
103
- // of writePin. `npm install` then resolves @bongos/core@version from the public registry —
104
- // no credential, since the package is public (task 1003872). Returns the previous dep string.
105
- function writeRegistryPin(instanceDir, version, fsImpl = fs) {
106
- const pkgPath = path.join(instanceDir, 'package.json');
107
- const pkg = readJson(pkgPath, fsImpl);
108
- if (!pkg) throw new Error(`no readable package.json at ${pkgPath}`);
109
- pkg.dependencies = pkg.dependencies || {};
110
- const prev = pkg.dependencies[CORE_PKG];
111
- pkg.dependencies[CORE_PKG] = version;
112
- fsImpl.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
113
- return prev;
114
- }
115
-
116
- // Restore the consumer package.json's @bongos/core pin to an EXACT previous dep string,
117
- // VERBATIM — whether that was a `file:` tarball path (vendored) or a bare registry semver.
118
- // The inverse of writePin/writeRegistryPin used by the auto-rollback path (task 2149), which
119
- // snapshots the returned prev-dep before the bump. Returns the dep string it overwrote.
120
- function restorePin(instanceDir, depString, fsImpl = fs) {
121
- const pkgPath = path.join(instanceDir, 'package.json');
122
- const pkg = readJson(pkgPath, fsImpl);
123
- if (!pkg) throw new Error(`no readable package.json at ${pkgPath}`);
124
- pkg.dependencies = pkg.dependencies || {};
125
- const prev = pkg.dependencies[CORE_PKG];
126
- pkg.dependencies[CORE_PKG] = depString;
127
- fsImpl.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
128
- return prev;
129
- }
130
-
131
- // ---- steps (each injectable for tests) --------------------------------------
132
-
133
- // `ignore` is waived (it comes from — and is argued for in — claude-materialize.js materializeWillRewrite, task 1004122); every OTHER dirty path still halts the bump. -uall (task 1004188): a bare status collapses a NEW untracked dir to one '?? dir/' entry the file-path waiver never matches.
134
- function gitTreeClean(instanceDir, run = spawnSync, ignore = []) {
135
- const r = run('git', ['status', '--porcelain', '-uall'], { cwd: instanceDir, encoding: 'utf8' });
136
- // git's OWN words, not a guess at them (task 1004512). `not a git repo?` was the only
137
- // explanation ever offered, and the failure that actually happens in the field is
138
- // `detected dubious ownership` — a repo git can see perfectly well and refuses to read
139
- // for the account asking. Swallowing the reason is what let that read as dirt.
140
- if (!r || r.error || r.status !== 0) {
141
- const said = String((r && (r.stderr || r.stdout)) || (r && r.error && r.error.message) || '').trim().split('\n').slice(0, 4).join('\n');
142
- return { ok: false, reason: said || 'git status failed (not a git repo?)' };
143
- }
144
- const skip = new Set(ignore), all = (r.stdout || '').split('\n').filter((l) => l.trim());
145
- const kept = all.filter((l) => !skip.has(l.slice(3).trim()));
146
- return { ok: !kept.length, dirty: kept.join('\n'), ignored: all.length - kept.length };
147
- }
148
-
149
- // ---- persisting the pin (task 1002712) --------------------------------------
150
- //
151
- // THE BUG THIS EXISTS FOR. `bongos upgrade` rewrites package.json +
152
- // package-lock.json in the instance WORKING TREE and stops there. On a
153
- // pull-deploy instance that is not durable, and the way it fails is silent:
154
- //
155
- // deploy.sh short-circuits while HEAD == origin/main, so a freshly-upgraded
156
- // (but uncommitted) tree survives — health-green, ledger-recorded, apparently
157
- // done. Then ANY later push to the instance repo moves origin/main, deploy.sh
158
- // runs `git reset --hard origin/main`, and the pin reverts to whatever is
159
- // COMMITTED. The lockfile hash changes with it, which trips deploy.sh's
160
- // `npm ci`, which reinstalls the OLD core. Nothing errors, at any point.
161
- //
162
- // cloudbongos.com sat on 1.19.56 for thirteen releases exactly this way: the
163
- // core_upgrades ledger holds two successful `auto-subscription (patch)` rows
164
- // (1.19.56→1.19.60, 1.19.60→1.19.62) whose result no longer existed.
165
- //
166
- // The pin is REPO state, so the repo of record is the right place for it —
167
- // deploy.sh treating origin/main as authoritative is correct, not the bug.
168
- // Hence: --commit-pin lands it, and its absence WARNS rather than staying quiet.
169
- const PIN_FILES = ['package.json', 'package-lock.json'];
170
-
171
- // The tracked files regenerateApiArtifacts' generators rewrite WHOLE, by generator (task
172
- // 1003926). Committing only the pin left these dirty, so the NEXT `bongos upgrade` refused
173
- // its clean-tree pre-flight. They are generated end to end, so once a generator has run
174
- // their content is its output whatever they held before: committing them can never carry
175
- // an owner's edit. tests/upgrade_persist_pin.mjs pins this list against both generators.
176
- const API_ARTIFACT_FILES = {
177
- 'gen-api-docs.js': ['docs/api/openapi.json', 'docs/api-reference.md', 'docs/routes-permissions.md'],
178
- 'gen-api-client.js': ['index.mjs', 'index.cjs', 'bongos-client.global.js', 'index.d.ts', 'package.json', 'README.md']
179
- .map((f) => `clients/bongos-client/${f}`),
180
- };
181
-
182
- function gitCurrentBranch(instanceDir, run = spawnSync) {
183
- const r = run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: instanceDir, encoding: 'utf8' });
184
- if (!r || r.error || r.status !== 0) return null;
185
- const b = (r.stdout || '').trim();
186
- return b && b !== 'HEAD' ? b : null;
187
- }
188
-
189
- // Which of `paths` git currently reports as changed — never a path it was not asked about,
190
- // and no git call for an empty list (a pathspec of nothing is the whole tree).
191
- function dirtyPaths(instanceDir, paths, run = spawnSync) {
192
- if (!paths.length) return [];
193
- const r = run('git', ['status', '--porcelain', '--', ...paths], { cwd: instanceDir, encoding: 'utf8' });
194
- if (!r || r.error || r.status !== 0) return null; // not a git repo — nothing to persist
195
- return (r.stdout || '').split('\n').map((l) => l.slice(3).trim()).filter((p) => paths.includes(p));
196
- }
197
-
198
- function dirtyPinFiles(instanceDir, run = spawnSync) { return dirtyPaths(instanceDir, PIN_FILES, run); }
199
-
200
- // ---- which credential the pin push rides (task 1003081, ADR 0176 follow-up) ----
201
- //
202
- // THE BUG THIS EXISTS FOR. A PRIVATE standalone instance's `origin` authenticates with
203
- // a per-repo deploy key that GitHub registers READ-ONLY (ADR 0176): it can pull, never
204
- // push. The push leg below went `git push origin HEAD:main` regardless, so on such an
205
- // instance GitHub refused the pin push, the bump was not durable, and the next
206
- // pull-deploy `git reset --hard origin/main` + `npm ci` reinstalled the OLD core
207
- // against an already-migrated DB — the exact silent rollback task 1002712 closed for
208
- // every other path, back through a warning line nobody read. The scaffold push and the
209
- // re-provision pin refresh already prefer the owner's stored `repo`-scoped OAuth token
210
- // over the SSH origin (provision.js resolveOwnerGithubToken + buildCorePinRefreshCommit);
211
- // the pin push now has the same preference — the token when one is stored, the git
212
- // remote otherwise — and a refused push is LOUD, naming the read-only key and the fix.
213
-
214
- // The GitHub owner/name behind `remote`, or null when the remote is not a GitHub
215
- // repository (there is nothing to push a GitHub token at) or cannot be read. Accepts
216
- // the plain github.com forms and every SSH alias instanceRepoRemotes wires
217
- // (`git@github-deploy:owner/repo.git`) — never another host, so a stored token is
218
- // never pointed at github.com/<owner>/<repo> for a repo that lives elsewhere.
219
- function remoteGithubRepo(instanceDir, remote = 'origin', run = spawnSync) {
220
- const r = run('git', ['remote', 'get-url', remote], { cwd: instanceDir, encoding: 'utf8' });
221
- if (!r || r.error || r.status !== 0) return null;
222
- const url = String(r.stdout || '').trim();
223
- let auth;
224
- try { auth = require('./provision-repo-auth'); } catch { return null; } // a package without the provisioner has no token path
225
- const repo = auth.parseTargetRef(url);
226
- if (!repo) return null;
227
- const host = (url.match(/^(?:[a-z+]+:\/\/)?(?:[^@/]+@)?([^/:]+)[/:]/i) || [])[1] || '';
228
- if (host.toLowerCase() !== 'github.com' && !auth.instanceRepoRemotes(repo).includes(url)) return null;
229
- return repo;
230
- }
231
-
232
- // The deploy key `remote` authenticates with when the checkout is wired the ADR 0176
233
- // way (`core.sshCommand … -i <key>` in the repo's own config); null when it is not.
234
- // What a refused origin push is diagnosed against — GitHub's SSH refusal is a terse
235
- // one-liner that names no key.
236
- function pinnedDeployKey(instanceDir, run = spawnSync) {
237
- const r = run('git', ['config', '--get', 'core.sshCommand'], { cwd: instanceDir, encoding: 'utf8' });
238
- if (!r || r.error || r.status !== 0) return null;
239
- const m = String(r.stdout || '').match(/(?:^|\s)-i\s+(\S+)/);
240
- return m ? m[1] : null;
241
- }
242
-
243
- // Resolve { token, repo } for the pin push, or null → push via the git remote.
244
- // repo — the remote's GitHub owner/name (remoteGithubRepo);
245
- // row — provision-repo-auth lookupInstanceRow, used ONLY when its target_ref IS that
246
- // repo, so another instance's credential is never spent on this checkout;
247
- // token — provision-repo-auth resolveOwnerGithubToken (deps.getGithubToken / deps.db
248
- // are its test seams), the same resolver the scaffold push uses.
249
- // Every miss is the origin path, not an error, and the token is never logged. The row
250
- // lookup and the token read BOTH live in the leaf rather than here because their default
251
- // requires are computed, and this file is inside the merge resolver's executed closure
252
- // with a pinned computed-require count of its own (task 1003081).
253
- async function resolvePinPushAuth({ instanceDir, remote = 'origin' }, deps = {}, run = spawnSync) {
254
- const log = deps.log || console.log;
255
- const repo = remoteGithubRepo(instanceDir, remote, run);
256
- if (!repo) return null;
257
- const auth = require('./provision-repo-auth');
258
- const inst = await auth.lookupInstanceRow(instanceDir, deps);
259
- if (!inst) { const key = pinnedDeployKey(instanceDir, run); if (key) log(auth.missingRowNote(key, remote)); return null; } // task 1004065
260
- const rowRepo = auth.parseTargetRef(inst.target_ref);
261
- const same = (a, b) => a && b && a.owner.toLowerCase() === b.owner.toLowerCase() && a.name.toLowerCase() === b.name.toLowerCase();
262
- if (!same(rowRepo, repo)) {
263
- log(` • pin push: the provisioning row for ${path.basename(instanceDir)} names ${inst.target_ref}, not ${remote}'s ${repo.owner}/${repo.name} — its owner's token is not for this checkout; pushing via ${remote}`);
264
- return null;
265
- }
266
- const token = await auth.resolveOwnerGithubToken(inst, { ...deps, log }, { tag: '[pin-push]' });
267
- if (!token) {
268
- log(` • pin push: no owner GitHub token stored for ${repo.owner}/${repo.name} — pushing via ${remote}`);
269
- return null;
270
- }
271
- return { token, repo };
272
- }
273
-
274
- // The pin push over the owner's token: a chmod-600 credential-store file in the temp
275
- // dir carries the secret, git reads it through `credential.helper=store`, and the file
276
- // is removed in `finally` whatever the push did — the token is never in argv (ps,
277
- // journald) and never in a log line. provision.js buildCorePinRefreshCommit's shape,
278
- // as argv instead of a shell string.
279
- function pushPinViaToken({ instanceDir, token, repo, target }, run = spawnSync) {
280
- const credFile = path.join(os.tmpdir(), `bongos-gitcred-pin-${process.pid}-${crypto.randomBytes(6).toString('hex')}`);
281
- try {
282
- fs.writeFileSync(credFile, `https://x-access-token:${token}@github.com\n`, { mode: 0o600 });
283
- return run('git', ['-c', `credential.helper=store --file=${credFile}`, 'push', `https://x-access-token@github.com/${repo.owner}/${repo.name}.git`, target], {
284
- cwd: instanceDir, encoding: 'utf8',
285
- env: { ...process.env, GIT_TERMINAL_PROMPT: '0' }, // a rejected credential must fail, not sit at a password prompt
286
- });
287
- } finally {
288
- fs.rmSync(credFile, { force: true });
289
- }
290
- }
291
-
292
- // What git said on stderr, for a refusal line — GitHub's own reason ("ERROR: The key you
293
- // are authenticating with has been marked as read only", "remote: Write access to
294
- // repository not granted") is the fact an operator wants beside the diagnosis, and it
295
- // is never the LAST line: git closes with its generic `fatal:`. Prefer the server's
296
- // line, fall back to the last one.
297
- function gitSaid(r) {
298
- const lines = String((r && r.stderr) || '').split('\n').map((l) => l.trim()).filter(Boolean);
299
- const server = lines.filter((l) => /^(ERROR:|remote:)/i.test(l));
300
- const said = server.length ? server[server.length - 1] : lines[lines.length - 1];
301
- return said ? ` (git: ${said})` : '';
302
- }
303
-
304
- // `push: false` is CO-TENANT MODE (task 1003521). The reasoning above assumes the repo
305
- // of record is OURS; on a provisioned instance it is the customer's own GitHub repo, so
306
- // pushing there is both wrong and uncredentialed. Such an instance also has no
307
- // pull-deploy timer, so nothing will `reset --hard` the pin away — the commit alone
308
- // makes it durable, and leaves the tree clean for the customer's own pulls.
309
- //
310
- // `pushAuth` ({ token, repo }, from resolvePinPushAuth) makes the push ride the owner's
311
- // GitHub token over HTTPS (task 1003081); null pushes via `remote`. The result carries
312
- // `via: 'owner-token'` on the token path and `refused` ('read-only-deploy-key' |
313
- // 'owner-token') with a plain-sentence `error` when GitHub turned the push away.
314
- // `artifactPaths` (task 1003926) are the generated files this upgrade rewrote; the ones
315
- // that changed are staged and committed with the pin.
316
- function persistPin({ instanceDir, fromVersion, toVersion, commitPin, push = true, remote = 'origin', dryRun = false, pushAuth = null, artifactPaths = [] },
317
- run = spawnSync, log = console.log, err = console.error) {
318
- const dirtyPins = dirtyPinFiles(instanceDir, run);
319
- if (dirtyPins === null) return { applicable: false, reason: 'not a git repo' };
320
- const dirtyArtifacts = dirtyPaths(instanceDir, artifactPaths, run) || [];
321
- const dirty = [...dirtyPins, ...dirtyArtifacts];
322
- if (!dirty.length) return { applicable: false, reason: 'pin files already match the repo' };
323
- const toStage = [...PIN_FILES, ...dirtyArtifacts];
324
-
325
- const branch = gitCurrentBranch(instanceDir, run);
326
- const target = `HEAD:${branch || 'main'}`;
327
- // Single-quote the interpolated values. Nothing here executes these strings — they
328
- // are printed for a human to paste — but an unquoted branch or remote carrying shell
329
- // metacharacters would misbehave once pasted, so emit them paste-safe.
330
- const q = (s) => `'${String(s).replace(/'/g, `'\\''`)}'`;
331
- const at = `git -C ${q(instanceDir)}`;
332
-
333
- if (!commitPin) {
334
- if (!push) {
335
- // No pull-deploy of ours reaches this instance, so an uncommitted pin is untidy
336
- // rather than doomed. Crying wolf here would teach an operator to ignore the
337
- // warning that DOES matter on the platform instance.
338
- err(` ! pin not committed — ${dirty.join(', ')} changed in the working tree only.`);
339
- err(' This target pulls from a repo that is not ours, so nothing here will revert it —');
340
- err(' but the tree stays dirty until it is committed. Re-run with --commit-pin to commit it.');
341
- return { applicable: true, committed: false, pushed: false, dirty, warned: true };
342
- }
343
- // LOUD — this is the whole point. A silent uncommitted pin is the bug.
344
- err(` ! PIN NOT COMMITTED — ${dirty.join(', ')} changed in the working tree only.`);
345
- err(' On a pull-deploy instance the next push to the repo of record makes deploy.sh');
346
- err(` 'git reset --hard ${remote}/${branch || 'main'}', which REVERTS this pin and lets npm ci`);
347
- err(` reinstall ${fromVersion || 'the previous core'}. Re-run with --commit-pin, or commit + push:`);
348
- err(` ${at} add ${toStage.map(q).join(' ')} && ${at} commit -m ${q(`pin @bongos/core ${toVersion}`)} && ${at} push ${q(remote)} ${q(target)}`);
349
- return { applicable: true, committed: false, pushed: false, dirty, warned: true };
350
- }
351
-
352
- if (dryRun) {
353
- log(push
354
- ? ` [dry-run] would commit + push ${dirty.join(', ')} to ${remote}/${branch || 'main'}`
355
- : ` [dry-run] would commit ${dirty.join(', ')} locally (no push — this remote is not ours)`);
356
- return { applicable: true, committed: false, pushed: false, dirty, dryRun: true };
357
- }
358
-
359
- const message = `pin @bongos/core ${toVersion}${fromVersion ? ` (was ${fromVersion})` : ''}`;
360
- const add = run('git', ['add', ...toStage], { cwd: instanceDir, encoding: 'utf8' });
361
- if (!add || add.error || add.status !== 0) {
362
- err(' ! could not stage the pin files — commit + push them by hand or the next deploy reverts this bump.');
363
- return { applicable: true, committed: false, pushed: false, dirty, error: 'git add failed' };
364
- }
365
- const idEnv = require('./upgrade-commit-identity').commitIdentityEnv(instanceDir, run), commit = run('git', ['commit', '-m', message], { cwd: instanceDir, encoding: 'utf8', ...(idEnv ? { env: idEnv } : {}) }); // a repo naming nobody still commits (task 1004514)
366
- if (!commit || commit.error || commit.status !== 0) {
367
- err(' ! could not commit the pin — commit + push it by hand or the next deploy reverts this bump.');
368
- return { applicable: true, committed: false, pushed: false, dirty, error: 'git commit failed' };
369
- }
370
- log(` ✓ committed the pin (${dirty.join(', ')})`);
371
-
372
- if (!push) {
373
- log(' ✓ not pushed, by request — this instance\'s repo of record is not ours, and no pull-deploy of ours can revert the commit');
374
- return { applicable: true, committed: true, pushed: false, dirty, pushSkipped: true };
375
- }
376
-
377
- // Committed but not pushed is still doomed: deploy.sh resets to the REMOTE. So every
378
- // refusal below is LOUD (task 1003081) — the pull-deploy consequence, the diagnosis,
379
- // and a by-hand push that can actually write.
380
- const revert = () => err(` The next pull-deploy 'git reset --hard ${remote}/${branch || 'main'}' + npm ci then reinstalls ${fromVersion || 'the previous core'}.`);
381
-
382
- if (pushAuth && pushAuth.token && pushAuth.repo) {
383
- const { repo } = pushAuth;
384
- let pushed = null;
385
- try {
386
- pushed = pushPinViaToken({ instanceDir, token: pushAuth.token, repo, target }, run);
387
- } catch (e) {
388
- // The credential file could not even be written (an unwritable temp dir): say so
389
- // and fall through to the remote — a public origin may still take it.
390
- err(` ! could not stage the owner's GitHub credential (${e && e.message}) — pushing via ${remote} instead`);
391
- }
392
- if (pushed && !pushed.error && pushed.status === 0) {
393
- log(` ✓ pushed the pin to ${repo.owner}/${repo.name}@${branch || 'main'} via the owner's GitHub token — a pull-deploy reset can no longer revert it`);
394
- return { applicable: true, committed: true, pushed: true, dirty, via: 'owner-token' };
395
- }
396
- if (pushed) {
397
- err(` ! PIN NOT PUSHED — GitHub refused the push over the owner's GitHub token, so this bump is NOT durable.`);
398
- err(` The stored token could not write ${repo.owner}/${repo.name}: it may have expired (they live an hour), or`);
399
- err(` lack the \`repo\` scope (\`public_repo\` cannot write a private repository — ADR 0155).${gitSaid(pushed)}`);
400
- revert();
401
- err(' Fix: have the instance owner reconnect GitHub with repository access, then re-run `bongos upgrade --commit-pin`;');
402
- err(' or push the commit yourself with a credential that can write:');
403
- err(` ${at} push ${q(`https://github.com/${repo.owner}/${repo.name}.git`)} ${q(target)}`);
404
- return {
405
- applicable: true, committed: true, pushed: false, dirty, refused: 'owner-token',
406
- error: `GitHub refused the pin push over the owner's GitHub token (expired, or missing the repo scope) — the pin is committed locally but not on ${repo.owner}/${repo.name}`,
407
- };
408
- }
409
- }
410
-
411
- const pushed = run('git', ['push', remote, target], { cwd: instanceDir, encoding: 'utf8' });
412
- if (!pushed || pushed.error || pushed.status !== 0) {
413
- const key = pinnedDeployKey(instanceDir, run);
414
- if (key) {
415
- // A wired private instance (ADR 0176): the key can pull, never push, and no owner
416
- // token was stored to push with instead — the bug this leg exists for.
417
- const repo = remoteGithubRepo(instanceDir, remote, run);
418
- err(` ! PIN NOT PUSHED — GitHub refused the push to ${remote}, so this bump is NOT durable.`);
419
- err(` ${remote} authenticates with the deploy key at ${key}, which is registered READ-ONLY on the`);
420
- err(` repository (ADR 0176): it can pull, never push. No owner GitHub token was available to push with instead (none is stored, or — on a hosted project's own box — the hub's record of it is not readable from here).${gitSaid(pushed)}`);
421
- revert();
422
- err(' Fix: have the instance owner reconnect GitHub with repository access (that stores a short-lived repo token),');
423
- err(` then re-run \`bongos upgrade --commit-pin\` where that token is readable — the control plane, with --instance ${q(instanceDir)};`);
424
- err(' or push the commit yourself with a credential that can write:');
425
- err(` ${at} push ${q(`https://github.com/${repo ? `${repo.owner}/${repo.name}` : '<owner>/<repo>'}.git`)} ${q(target)}`);
426
- return {
427
- applicable: true, committed: true, pushed: false, dirty, refused: 'read-only-deploy-key',
428
- error: `GitHub refused the pin push: ${remote} authenticates with the read-only deploy key at ${key}, and no owner GitHub token was available to push with — the pin is committed locally but not on the remote`,
429
- };
430
- }
431
- err(` ! commit landed locally but the push to ${remote} FAILED — this bump is still not durable.`);
432
- err(` Push it: git -C ${instanceDir} push ${remote} ${target}`);
433
- return { applicable: true, committed: true, pushed: false, dirty, error: 'git push failed' };
434
- }
435
- log(` ✓ pushed the pin to ${remote}/${branch || 'main'} — a pull-deploy reset can no longer revert it`);
436
- return { applicable: true, committed: true, pushed: true, dirty };
437
- }
438
-
439
- // Copy the source .tgz (+ its side-car manifest, if present) into the consumer's vendor/ dir under the
440
- // canonical name. Returns the vendor-relative tarball path to pin.
441
- function vendorTarball({ instanceDir, fromTgz, targetVersion }, fsImpl = fs) {
442
- const vendorDir = path.join(instanceDir, 'vendor');
443
- fsImpl.mkdirSync(vendorDir, { recursive: true });
444
- const destName = `${ARTIFACT}-${targetVersion}.tgz`;
445
- const destAbs = path.join(vendorDir, destName);
446
- fsImpl.copyFileSync(fromTgz, destAbs);
447
- const fromManifest = fromTgz.replace(/\.tgz$/, '.manifest.json');
448
- if (fsImpl.existsSync(fromManifest)) {
449
- fsImpl.copyFileSync(fromManifest, path.join(vendorDir, `${ARTIFACT}-${targetVersion}.manifest.json`));
450
- }
451
- return path.posix.join('vendor', destName);
452
- }
453
-
454
- // Lightweight module-compat pre-check reusing module.js against the TARGET core version. Best-effort:
455
- // a vanilla consumer has no modules/ (trivially OK); any failure downgrades to a warning, never blocks
456
- // the MVP bump. Returns { ok, blocking:[], warnings:[], deprecations:[], expired:[], note }.
457
- //
458
- // WARNINGS ARE NOT OPTIONAL OUTPUT (ADR 0166 / task 1001773). This function used to return only
459
- // `blocking`, so a DISABLED module whose coreVersion the target no longer satisfies vanished from the
460
- // bump entirely. That is precisely the catalog-rot case ADR 0107 §7 names: an accepted catalog module
461
- // ships `default: false` (§6), so EVERY rotted catalog entry is disabled by construction and every one
462
- // of them was invisible here. The bump still doesn't BLOCK on them — a disabled module breaks nothing
463
- // at boot — but it must SAY so, with the maintainer named, or the incompatibility is discovered by
464
- // whoever next tries to enable it.
465
- function preflightModules({ instanceDir, targetVersion }, deps = {}) {
466
- const empty = { blocking: [], warnings: [], deprecations: [], expired: [] };
467
- const modulesDir = path.join(instanceDir, 'modules');
468
- if (!fs.existsSync(modulesDir)) return { ok: true, ...empty, note: 'no modules/ — nothing to pre-check' };
469
- try {
470
- const mod = deps.moduleLib || require('./module');
471
- const data = mod.gatherUpgrade({ modulesDir, core: targetVersion });
472
- const verdict = mod.evaluateUpgrade(data);
473
- const rotted = (verdict.warnings || []).length;
474
- const note = !verdict.ok
475
- ? 'incompatible enabled module(s)'
476
- : rotted
477
- ? `all enabled modules satisfy the target, but ${rotted} disabled module(s) do NOT`
478
- : 'all enabled modules satisfy the target';
479
- return {
480
- ok: verdict.ok,
481
- blocking: verdict.blocking || [],
482
- warnings: verdict.warnings || [],
483
- deprecations: verdict.deprecations || [],
484
- expired: verdict.expired || [],
485
- note,
486
- };
487
- } catch (e) {
488
- return { ok: true, ...empty, note: `module pre-check skipped (${e.message})` };
489
- }
490
- }
491
-
492
- // Print the non-blocking half of the module pre-check: rotted-but-disabled modules and
493
- // self-declared deprecations, each with its maintenance hint so the reader knows who to chase.
494
- // Split out of runUpgrade so it is testable without driving a whole bump.
495
- function reportModulePreflight(mods, targetVersion, { log = console.log, err = console.error, hint } = {}) {
496
- const fmt = hint || ((row) => { try { return require('./module').formatMaintenanceHint(row); } catch { return ''; } });
497
- const lines = [];
498
- for (const w of mods.warnings || []) {
499
- lines.push(` ! module "${w.key}" is DISABLED here, so it does not block this bump — but its coreVersion ${w.coreVersion || '(none)'} is not satisfied by core ${targetVersion}: enabling it would silently fail to mount.`);
500
- lines.push(` ↳ ${fmt(w)}`);
501
- }
502
- for (const d of mods.deprecations || []) {
503
- const overdue = (mods.expired || []).includes(d);
504
- lines.push(` ! module "${d.key}" is ${d.maintenance.status}${overdue ? ` and PAST its removeAfter ${d.maintenance.removeAfter} (core ${targetVersion}) — it is due for removal` : ''}.`);
505
- lines.push(` ↳ ${fmt(d)}`);
506
- }
507
- for (const l of lines) err(l);
508
- return lines;
509
- }
510
-
511
- function npmInstall(instanceDir, run = spawnSync) {
512
- // `npm install` (NOT `npm ci`): the pin just changed, so the lockfile must be regenerated from the
513
- // new tarball; `npm ci` would refuse on the package.json↔lock divergence.
514
- // This used to take an extraEnv carrying a resolved npm credential, because the instance
515
- // `.npmrc`'s env expansion could shadow a valid user-level one (task 1002754). The core is
516
- // public and writes no `.npmrc`, so there is no credential to resolve (task 1003878).
517
- const opts = { cwd: instanceDir, stdio: 'inherit', ...npmSpawnOpts() }; // Windows: npm.cmd needs a shell (task 1004631)
518
- const r = run('npm', ['install', '--no-audit', '--no-fund'], opts);
519
- return !r || r.error ? { ok: false, reason: r && r.error ? r.error.message : 'spawn failed' } : { ok: r.status === 0, code: r.status };
520
- }
521
-
522
- async function runMigrate(instanceDir, run = spawnSync, account = null) {
523
- const { cmd, args, env } = require('./upgrade-migrate').migratePlan(instanceDir); // its own migrate script, else the core's migrate.sh (task 1004274)
524
- // `account`: the project's own unix+Postgres identity when the move itself is running as
525
- // the account that owns the CHECKOUT instead (--migrate-as; upgrade-migrate.js, task 1004512).
526
- const q = asAccount(account, cmd, args, env ? { INIT_CWD: instanceDir } : {});
527
- // TEED, not inherited: still streams live, and a failure names its migration + psql's ERROR line (upgrade-migrate.js, task 1004734)
528
- return migrateResult(await (run === spawnSync ? teeSpawn : run)(q.cmd, q.args, { cwd: instanceDir, ...(env ? { env } : {}) }));
529
- }
530
-
531
- // WHICH database will migrate target? (task 1002755)
532
- //
533
- // The pre-flight probe below is only meaningful if it tests the SAME database the migration
534
- // will later use. It used to be handed `process.env.PGDATABASE` — undefined on a normal box —
535
- // so psql fell through to a database named after the OS user, failed for an unrelated reason,
536
- // and soft-skipped with "psql failed for another reason". migrate then picked its own name and
537
- // hit a database that did not exist. Two soft failures composing into a hard one, discovered
538
- // only AFTER the pin had moved.
539
- //
540
- // So resolve it here, up front, by asking the core's OWN resolver in a child pointed at this
541
- // instance — the same precedence migrate.sh uses (PGDATABASE wins, else the instance's branding
542
- // pack) and the same function, so the probe and the migration cannot disagree. Spawned rather
543
- // than required because requiring pool.js constructs a pg Pool in this process.
544
- // Returns { db, ran }:
545
- // { db: 'name', ran: true } — resolved
546
- // { db: null, ran: true } — the resolver RAN and this instance names no database. Fatal:
547
- // migrate cannot proceed and we know it before the pin moves.
548
- // { db: null, ran: false } — the resolver could not run at all (no node_modules yet, a
549
- // stubbed spawn in tests). NOT fatal: that is a different problem
550
- // from "no database configured", and guessing which one it is would
551
- // block bumps for the wrong reason. migrate.sh makes the same
552
- // distinction and still fails loudly later, so the net holds.
553
- function resolveInstanceDb({ instanceDir }, run = spawnSync) {
554
- if (process.env.PGDATABASE) return { db: process.env.PGDATABASE, ran: true };
555
- const poolPath = path.join(instanceDir, 'node_modules', CORE_PKG, 'src', 'bongos', 'pool');
556
- // the module path rides as argv, never interpolated into JS source — a Windows-shaped path's
557
- // backslashes are escape sequences inside a string literal
558
- const r = run(process.execPath, ['-e', "process.stdout.write(require(process.argv[1]).instanceDbName() || '')", poolPath], {
559
- cwd: instanceDir,
560
- encoding: 'utf8',
561
- env: { ...process.env, BONGOS_INSTANCE_ROOT: instanceDir },
562
- });
563
- if (!r || r.error || r.status !== 0 || typeof r.stdout !== 'string') return { db: null, ran: false };
564
- return { db: String(r.stdout).trim() || null, ran: true };
565
- }
566
-
567
- // Regenerate the per-instance API artifacts (OpenAPI spec + api-reference + typed
568
- // client) from the NEW core's routes — the claude-materialize sibling (task 2051).
569
- // WHY: the routes + generators ship WITH core, and the generated spec/docs/client also
570
- // ship as CORE STARTERS (task 2078 — a fresh hall/docs must render before first regen),
571
- // but they are per-instance GENERATED, so a bump changes the served API while the
572
- // instance's committed spec/client lag until regenerated (the classification settled in
573
- // task 2141; init does the same at standup). We SPAWN the new core's generators (a fresh child
574
- // captures its output root from the env below) with <FALLBACK_PREFIX>_INSTANCE_ROOT set
575
- // so resolveDocsRoot() writes INTO the instance repo, not node_modules. docs first — the
576
- // client reads the spec it produces. Best-effort: a hiccup warns, never fails the bump
577
- // (fitness `gen-api-docs --check` + the api_client test backstop it on the next ship).
578
- // Runs AFTER npm install so the generators come from the NEW core.
579
- function regenerateApiArtifacts({ instanceDir, coreRoot }, run = spawnSync, fsImpl = fs) {
580
- const env = { ...process.env, BONGOS_INSTANCE_ROOT: instanceDir };
581
- const ran = [];
582
- for (const gen of Object.keys(API_ARTIFACT_FILES)) {
583
- const script = path.join(coreRoot, 'scripts', 'gds', gen);
584
- if (!fsImpl.existsSync(script)) return { ok: false, ran, reason: `${gen} not found in core (${coreRoot})` };
585
- const r = run(process.execPath, [script], { cwd: instanceDir, env, stdio: 'inherit' });
586
- if (!r || r.error || r.status !== 0) {
587
- return { ok: false, ran, reason: r && r.error ? r.error.message : `${gen} exited ${r && r.status}` };
588
- }
589
- ran.push(gen);
590
- }
591
- return { ok: true, ran };
592
- }
593
-
594
- // The instance's GITIGNORED WHOLE-FILE navigation docs (ADR 0110). On the monorepo these
595
- // regenerate at deploy (deploy-prod.sh) + box-fetch and are gitignored so no branch ever diffs
596
- // them. STANDALONE instances (ADR 0108) never got that step: their bespoke deploy regenerated
597
- // nothing and init/upgrade only did the API docs, so a fresh instance shipped with an empty docs/
598
- // and nothing kept the index live (task 1002314, the owner's "docs didn't transfer from primea").
599
- // This is the standalone sibling of deploy-prod.sh's regen: run the generator(s) against the
600
- // INSTANCE root, best-effort + LOUD — a broken generator must surface (::ERROR::) but must NEVER
601
- // fail the deploy/bump (a stale nav doc is tolerable; a failed deploy is not — ADR 0110 §2
602
- // "accepted staleness").
603
- //
604
- // SCOPE — deliberately just session-index (the one gitignored whole-file doc that is INSTANCE
605
- // content). Excluded on purpose:
606
- // • repo-map.md — CORE-scoped: gen-repo-map writes to resolveCoreRoot() (the platform code map),
607
- // not the instance. A pure standalone instance runs core from node_modules and has ~no code of
608
- // its own to map, so an instance-level repo-map is empty/meaningless; the core ships its own.
609
- // (An instance-scoped map for BROWNFIELD/adopted repos is a separate enhancement — task 1001655.)
610
- // • file-map.md + API docs — TRACKED/committed (seeded at init, refreshed at ship/upgrade);
611
- // regenerating them on the box would perpetually dirty the tree that deploy.sh `git reset
612
- // --hard`es. file-map is also HYBRID (hand-written prose + generated sections, ADR 0110) so it
613
- // cannot leave git; seeding it at standup is a follow-up (needs a scaffolded file-map.md).
614
- // • diagrams + atlas.json — NOT instance content: they are CORE-scoped generated assets that
615
- // live under resolveCoreRoot(). They are handled separately by healDocAssets() below, because
616
- // an upgrade is precisely what destroys them (task 1002441).
617
- const NAV_WHOLE_FILE_GENERATORS = ['gen-session-index.js'];
618
- function regenerateNavDocs({ instanceDir, coreRoot, generators = NAV_WHOLE_FILE_GENERATORS }, run = spawnSync, fsImpl = fs) {
619
- const env = { ...process.env, BONGOS_INSTANCE_ROOT: instanceDir };
620
- const ran = [];
621
- const failed = [];
622
- for (const gen of generators) {
623
- const script = path.join(coreRoot, 'scripts', 'gds', gen);
624
- if (!fsImpl.existsSync(script)) { failed.push({ gen, reason: `not found in core (${coreRoot})` }); continue; }
625
- const r = run(process.execPath, [script], { cwd: instanceDir, env, stdio: 'inherit' });
626
- if (!r || r.error || r.status !== 0) {
627
- // LOUD per ADR 0110 §2 — journald greps ::ERROR:: so a broken generator alarms.
628
- failed.push({ gen, reason: r && r.error ? r.error.message : `exited ${r && r.status}` });
629
- continue;
630
- }
631
- ran.push(gen);
632
- }
633
- return { ok: failed.length === 0, ran, failed };
634
- }
635
-
636
- // The CORE-scoped generated doc assets that back two builders'-hall surfaces:
637
- //
638
- // modules/hall-ui/public/atlas.json → the Repo Atlas (/builders/atlas)
639
- // docs/onboarding/diagrams/<n>.svg+.png → the system maps (/builders/diagrams)
640
- //
641
- // Both are GITIGNORED (.gitignore: `modules/hall-ui/public/atlas.json`,
642
- // `docs/onboarding/diagrams/*.svg|*.png` — ADR 0122 / task 1002027) and both are generated INTO
643
- // the vendored core root. So an upgrade DESTROYS them: npmInstall replaces node_modules wholesale
644
- // and the new tarball carries only the .mmd sources. Nothing else puts them back —
645
- // • packaging does not render (package-core.js has no render step, and the renders are
646
- // gitignored so a git checkout has none to copy), and
647
- // • a standalone instance's pull-deploy typically short-circuits on an unchanged git SHA, which
648
- // an upgrade does not move — so its regen hooks never fire.
649
- // Result before this healer: /builders/atlas 404'd and the diagrams page showed broken images
650
- // after every `bongos upgrade`, until some unrelated commit happened to land (task 1002441).
651
- //
652
- // Both generators resolve their own output dir from __dirname, so running the CORE's copy always
653
- // writes into coreRoot regardless of cwd. Idempotent by design — each asset is regenerated only
654
- // when actually absent, so this is also safe to call from a deploy loop.
655
- //
656
- // Best-effort + LOUD, per ADR 0110 §2 "accepted staleness": a stale diagram is tolerable, a failed
657
- // upgrade is not. render-diagrams.sh additionally needs a system Chromium (ADR 0122); where none is
658
- // installed it fails and we say so via ::ERROR:: rather than aborting the bump.
659
- const DOC_ASSET_GENERATORS = {
660
- atlas: { rel: path.join('scripts', 'gds', 'gen-atlas.js'), kind: 'node' },
661
- diagrams: { rel: path.join('scripts', 'render-diagrams.sh'), kind: 'bash' },
662
- };
663
-
664
- // Which of the two asset groups are missing under coreRoot. Exported for testing.
665
- function missingDocAssets(coreRoot, fsImpl = fs) {
666
- const missing = [];
667
- if (!fsImpl.existsSync(path.join(coreRoot, 'modules', 'hall-ui', 'public', 'atlas.json'))) {
668
- missing.push('atlas');
669
- }
670
- const diagramDir = path.join(coreRoot, 'docs', 'onboarding', 'diagrams');
671
- let sources = [];
672
- try {
673
- sources = fsImpl.readdirSync(diagramDir).filter((f) => f.endsWith('.mmd'));
674
- } catch { sources = []; } // no diagram dir in this core → nothing to render
675
- const unrendered = sources.some((src) => {
676
- const base = path.join(diagramDir, src.replace(/\.mmd$/, ''));
677
- return !fsImpl.existsSync(`${base}.svg`) || !fsImpl.existsSync(`${base}.png`);
678
- });
679
- if (unrendered) missing.push('diagrams');
680
- return missing;
681
- }
682
-
683
- function healDocAssets({ coreRoot }, run = spawnSync, fsImpl = fs) {
684
- const missing = missingDocAssets(coreRoot, fsImpl);
685
- if (missing.length === 0) return { ok: true, ran: [], failed: [], missing: [] };
686
- const ran = [];
687
- const failed = [];
688
- for (const group of missing) {
689
- const gen = DOC_ASSET_GENERATORS[group];
690
- const script = path.join(coreRoot, gen.rel);
691
- if (!fsImpl.existsSync(script)) { failed.push({ group, reason: `not found in core (${gen.rel})` }); continue; }
692
- const argv = gen.kind === 'bash' ? ['bash', [script]] : [process.execPath, [script]];
693
- const r = run(argv[0], argv[1], { cwd: coreRoot, stdio: 'inherit' });
694
- if (!r || r.error || r.status !== 0) {
695
- failed.push({ group, reason: r && r.error ? r.error.message : `exited ${r && r.status}` });
696
- continue;
697
- }
698
- ran.push(group);
699
- }
700
- return { ok: failed.length === 0, ran, failed, missing };
701
- }
702
-
703
- // Restart the instance service so the newly-installed core becomes the one being SERVED.
704
- // Escalation is the whole difficulty here (task 1002884). A provisioned instance runs under a
705
- // `User=` systemd unit, and the unattended sweep that restarts it has no TTY — so a bare
706
- // `systemctl restart` from the owning (non-root) user returns "Interactive authentication
707
- // required" and exits 1. We retry once through `sudo -n`, the same idiom dev.js and dev-lib.js
708
- // already use for privileged systemctl; `-n` fails fast rather than blocking on a password
709
- // prompt, so the retry costs nothing when it isn't permitted. An operator who prefers polkit
710
- // over sudo can install the rule in docs/recipes/instance-service-restart.md instead — either
711
- // path makes this return ok.
712
- // `--restart-cmd` is NOT escalated: an explicit command is the operator's own contract.
713
- // Trust boundary: `service` comes from `--service` or the subscription roster — operator-supplied
714
- // config, never request input — and the escalation reaches only as far as the host's own sudoers
715
- // or polkit scoping allows. Do not wire a caller that derives `service` from anything untrusted.
716
- function restartService({ service, restartCmd }, run = spawnSync, deps = {}) {
717
- if (restartCmd) {
718
- const parts = restartCmd.split(/\s+/);
719
- const r = run(parts[0], parts.slice(1), { stdio: 'inherit' });
720
- return { ok: !!r && !r.error && r.status === 0, code: r && r.status };
721
- }
722
- if (service) {
723
- const r = run('systemctl', ['restart', service], { stdio: 'inherit' });
724
- if (r && !r.error && r.status === 0) return { ok: true, code: 0 };
725
- const isRoot = deps.isRoot !== undefined
726
- ? !!deps.isRoot
727
- : (typeof process.getuid === 'function' && process.getuid() === 0);
728
- if (isRoot) return { ok: false, code: r && r.status };
729
- const s = run('sudo', ['-n', 'systemctl', 'restart', service], { stdio: 'inherit' });
730
- const ok = !!s && !s.error && s.status === 0;
731
- return { ok, code: ok ? 0 : (s && s.status), triedSudo: true, directCode: r && r.status };
732
- }
733
- return { ok: null, skipped: true };
734
- }
735
-
736
- // The two attribution columns migration core_241 adds (task 1003159, ADR 0293 D5).
737
- //
738
- // APPENDED ONLY WHEN THE CALLER SUPPLIES THEM, and that conditionality is the whole
739
- // design rather than laziness. An upgrade run the old way — a human at a shell — has
740
- // no builder to attribute, and this file also runs ON instances whose DB may not have
741
- // core_241 yet (the core upgrades itself; the migration lands during the very run that
742
- // would be writing this row). Naming a column that does not exist turns a best-effort
743
- // ledger append into a hard `column "source" does not exist`, so the bump would report
744
- // a failure over bookkeeping. Absent → the original four-column INSERT, byte for byte.
745
- //
746
- // The DB is still the backstop: core_upgrades_door_needs_actor_chk refuses a row that
747
- // claims source='owner-control' without an actor, so a caller that passes one and not
748
- // the other is rejected there rather than landing an unattributable privileged row.
749
- const LEDGER_ACTOR_COLS = Object.freeze(['requested_by_builder_id', 'source']);
750
-
751
- // Build the INSERT for the columns this call actually has. Returns the statement plus
752
- // the ordered values, so the two connection paths below cannot drift apart.
753
- function ledgerInsert({ fromVersion, toVersion, sourceCommit, note, requestedByBuilderId, source }) {
754
- const cols = ['from_version', 'to_version', 'source_commit', 'note'];
755
- const vals = [fromVersion || null, toVersion, sourceCommit || null, note || null];
756
- if (requestedByBuilderId != null || source) {
757
- cols.push(...LEDGER_ACTOR_COLS);
758
- vals.push(requestedByBuilderId != null ? String(requestedByBuilderId) : null, source || null);
759
- }
760
- const holders = cols.map((_, i) => `$${i + 1}`).join(',');
761
- return { sql: `INSERT INTO core_upgrades (${cols.join(', ')}) VALUES (${holders})`, cols, vals };
762
- }
763
-
764
- // Best-effort append to the core_upgrades ledger (migration core_189). Resolves the DB the same two
765
- // ways a consumer might connect:
766
- // • DATABASE_URL — a connection string (managed / hosted shape): via the pg driver.
767
- // • PGDATABASE — a bare db name over the unix socket + peer auth (the self-host shape): by
768
- // delegating to `psql -d "$PGDATABASE"`, EXACTLY as migrate.sh does. We shell out rather than
769
- // reuse pg here because pg defaults host to localhost/TCP, so `new Pool({database})` would miss
770
- // the socket + peer auth a provisioned instance relies on (systemd sets only PGDATABASE — task
771
- // 1976 found the URL-only path silently skipped on emersonian, the very shape it must serve).
772
- // Skips silently only when NEITHER is present (a local rehearsal with no DB pointed at) — the bump's
773
- // verification never depends on the ledger. An attempted-but-failed insert returns skipped:false so
774
- // the caller can surface it (the manual-INSERT footgun from 1976), never lose it.
775
- async function recordLedger({ fromVersion, toVersion, sourceCommit, note, requestedByBuilderId, source, account = null }, deps = {}) {
776
- const url = deps.databaseUrl !== undefined ? deps.databaseUrl : process.env.DATABASE_URL;
777
- const database = deps.pgDatabase !== undefined ? deps.pgDatabase : process.env.PGDATABASE;
778
- if (!url && !database) return { ok: false, skipped: true, reason: 'no DATABASE_URL or PGDATABASE' };
779
- const stmt = ledgerInsert({ fromVersion, toVersion, sourceCommit, note, requestedByBuilderId, source });
780
-
781
- // DATABASE_URL path: the pg driver with a bound-parameter query (no psql client needed).
782
- if (url) {
783
- let Pool;
784
- try { ({ Pool } = deps.pg || require('pg')); } catch { return { ok: false, skipped: true, reason: 'pg not resolvable' }; }
785
- const pool = new Pool({ connectionString: url });
786
- try {
787
- await pool.query(stmt.sql, stmt.vals);
788
- return { ok: true };
789
- } catch (e) {
790
- return { ok: false, skipped: false, reason: e.message };
791
- } finally {
792
- try { await pool.end(); } catch { /* ignore */ }
793
- }
794
- }
795
-
796
- // PGDATABASE path: `psql -d <db>` lets libpq resolve the socket + peer auth (same as migrate.sh).
797
- // Values pass as separate argv `--set`s (no shell → no shell injection) and reach the SQL as psql
798
- // :'var' literals, which psql quotes/escapes safely (no SQL injection). NULLIF maps an absent value
799
- // to NULL, matching the `x || null` of the pg path. The SQL is fed on STDIN, not `-c`: `-c` requires
800
- // pure server-parseable SQL and does NOT run :'var' interpolation, so a `-c` INSERT would send the
801
- // literal `:'from_version'` and syntax-error — psql only interpolates variables in script/stdin
802
- // mode. ON_ERROR_STOP=1 guarantees a non-zero exit on any SQL error.
803
- const run = deps.run || spawnSync;
804
- // Built from the SAME column list the pg path uses, so the two cannot drift.
805
- // to_version is the one NOT NULL column, hence the one without a NULLIF; the
806
- // builder id is text on the wire (a psql :'var' is always a quoted literal) and
807
- // casts at the DB, which also rejects anything non-numeric rather than coercing.
808
- const psqlValue = (col) => {
809
- if (col === 'to_version') return `:'${col}'`;
810
- if (col === 'requested_by_builder_id') return `NULLIF(:'${col}','')::bigint`;
811
- return `NULLIF(:'${col}','')`;
812
- };
813
- const sql = `${stmt.sql.slice(0, stmt.sql.indexOf(' VALUES '))}\n VALUES (${stmt.cols.map(psqlValue).join(', ')});\n`;
814
- const sets = [];
815
- for (let i = 0; i < stmt.cols.length; i++) sets.push('--set', `${stmt.cols[i]}=${stmt.vals[i] == null ? '' : stmt.vals[i]}`);
816
- // Through the project's own account when the move is not running as it (task 1004512):
817
- // this psql peer-auths exactly as migrate does, so it must be the same identity or the
818
- // ledger row silently stops being written on every own-account project.
819
- const q = asAccount(account, 'psql', ['-d', database, '-v', 'ON_ERROR_STOP=1', '-q', '--no-psqlrc', ...sets]);
820
- const r = run(q.cmd, q.args, { encoding: 'utf8', input: sql });
821
- if (!r || r.error) {
822
- const enoent = !!(r && r.error && r.error.code === 'ENOENT');
823
- return { ok: false, skipped: enoent, reason: enoent ? 'psql not found' : (r && r.error ? r.error.message : 'psql spawn failed') };
824
- }
825
- if (r.status !== 0) return { ok: false, skipped: false, reason: (r.stderr || '').trim() || `psql exit ${r.status}` };
826
- return { ok: true };
827
- }
828
-
829
- // Poll a health URL until it returns 2xx or the time budget (~30s) elapses. After `systemctl restart`
830
- // the service needs a moment to bind its port, so a single immediate GET races the restart and
831
- // spuriously reports `fetch failed` (task 1976 — it bound ~1s later on the emersonian 1.15→1.16 bump).
832
- // Connection-refused fails fast, so the early retries are cheap; the backoff caps at 2s.
833
- async function pollHealth(healthUrl, deps = {}) {
834
- const fetchImpl = deps.fetch || fetch;
835
- const sleep = deps.sleep || ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
836
- const now = deps.now || Date.now;
837
- const budgetMs = deps.healthBudgetMs != null ? deps.healthBudgetMs : 30_000;
838
- const deadline = now() + budgetMs;
839
- let attempt = 0;
840
- let last = { ok: false, error: 'not attempted' };
841
- for (;;) {
842
- attempt++;
843
- try {
844
- const res = await fetchImpl(healthUrl, { signal: AbortSignal.timeout(5_000) });
845
- if (res.ok) return { ok: true, status: res.status, attempts: attempt };
846
- last = { ok: false, status: res.status };
847
- } catch (e) {
848
- last = { ok: false, error: e.message };
849
- }
850
- if (now() >= deadline) return { ...last, attempts: attempt, timedOut: true };
851
- await sleep(Math.min(2_000, 500 * attempt));
852
- }
853
- }
854
-
855
- // ---- served-version verification (task 1002884) -----------------------------
856
- // The gap this closes: after a restart, `readInstalledCoreVersion` reads node_modules on DISK
857
- // and `pollHealth` proves only that *something* answers the port. Neither can tell "the new core
858
- // is up" from "the old core never went down" — so when a restart silently failed on
859
- // cloudbongos.com (2026-08-11), the health poll hit the STILL-RUNNING old process, got 200, and
860
- // the bump reported "✓ upgrade complete" while live kept serving the previous core.
861
- // `/version` reports the LIVE process's coreVersion (serve-internal.js, since 1.17.2), which is
862
- // the one signal that distinguishes the two.
863
-
864
- // Default the version endpoint to /version on the same origin as the health URL. Deriving rather
865
- // than demanding a second flag is deliberate: every existing call site passes only --health-url,
866
- // and a check that has to be opted into is off exactly where it is needed. Returns null when the
867
- // health URL isn't parseable as one.
868
- function deriveVersionUrl(healthUrl) {
869
- try {
870
- const u = new URL(healthUrl);
871
- u.pathname = '/version';
872
- u.search = '';
873
- u.hash = '';
874
- return u.toString();
875
- } catch { return null; }
876
- }
877
-
878
- // Poll the version endpoint until it yields a parseable coreVersion or the budget elapses. Runs
879
- // AFTER the health poll, so the service is already answering and the budget is short — this is
880
- // re-reading a live endpoint, not waiting for a boot. A body without a usable coreVersion is
881
- // "unreadable", NOT a mismatch: the caller must be able to tell "it says the wrong version"
882
- // (a real failure) from "it wouldn't tell me" (unconfirmed), because only the first is proof.
883
- async function pollServedVersion(versionUrl, deps = {}) {
884
- const fetchImpl = deps.fetch || fetch;
885
- const sleep = deps.sleep || ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
886
- const now = deps.now || Date.now;
887
- // Default to the health budget when a caller (or a test) has already narrowed it, else 15s.
888
- const budgetMs = deps.versionBudgetMs != null
889
- ? deps.versionBudgetMs
890
- : (deps.healthBudgetMs != null ? deps.healthBudgetMs : 15_000);
891
- // A hard attempt cap alongside the clock: `now` is injectable, and a frozen or non-advancing
892
- // clock would otherwise spin this loop forever instead of giving up.
893
- const maxAttempts = deps.versionMaxAttempts != null ? deps.versionMaxAttempts : 12;
894
- const deadline = now() + budgetMs;
895
- let attempt = 0;
896
- let last = { ok: false, error: 'not attempted' };
897
- for (;;) {
898
- attempt++;
899
- try {
900
- const res = await fetchImpl(versionUrl, { signal: AbortSignal.timeout(5_000) });
901
- if (!res || !res.ok) last = { ok: false, error: `status ${res && res.status}` };
902
- else if (typeof res.json !== 'function') last = { ok: false, error: 'response carried no JSON body' };
903
- else {
904
- const body = await res.json();
905
- const version = body && typeof body.coreVersion === 'string' ? body.coreVersion : null;
906
- if (version) return { ok: true, version, attempts: attempt };
907
- last = { ok: false, error: 'no coreVersion in the response body' };
908
- }
909
- } catch (e) {
910
- last = { ok: false, error: e.message };
911
- }
912
- if (now() >= deadline || attempt >= maxAttempts) return { ...last, attempts: attempt, timedOut: true };
913
- await sleep(Math.min(2_000, 500 * attempt));
914
- }
915
- }
916
-
917
- // ---- integrity-pin verification (task 1002216 / audit H8, finding F1) --------
918
- // The packager (package-core.js) computes tree_sha256 = canonicalTreeHash over the
919
- // redacted core files (+ the two synthesized files) and records it, the per-file
920
- // hashes, AND the exact tarball bytes' sha256 in a side-car manifest — stating a
921
- // consumer "verifies an install by recomputing it from the unpacked tree." Until now
922
- // nothing on the CONSUME side did: `bongos upgrade` compared only the version STRING,
923
- // so a corrupted / truncated / swapped tarball whose package.json still read the target
924
- // version installed silently — the R88-class failure this goal exists to prevent.
925
- // The three functions below close that gap: recompute the pin over the INSTALLED tree
926
- // and assert it equals the TRUSTED reference manifest.
927
-
928
- // Read + parse a manifest JSON; null on any failure (missing / unparseable).
929
- function readManifest(file, fsImpl = fs) {
930
- try { return JSON.parse(fsImpl.readFileSync(file, 'utf8')); } catch { return null; }
931
- }
932
-
933
- // Resolve the trusted reference pin for this bump:
934
- // • VENDORED — the committed side-car `vendor/<artifact>-<v>.manifest.json` (carries
935
- // tree_sha256 + files[] + the exact tarball.sha256). It lives OUTSIDE the tarball
936
- // (version-controlled in the consumer repo), so it detects a swapped/corrupted
937
- // tarball. This is the strong reference.
938
- // • REGISTRY / no side-car — the inner manifest `<core>/.bongos-core.json` that ships
939
- // INSIDE the package (tree_sha256 + files[], no tarball.*). Self-referential (a full
940
- // swap regenerates it too), so it is a self-consistency check backing npm's own
941
- // registry integrity rather than an independent one — flagged `strong:false`.
942
- function resolveReferenceManifest({ instanceDir, coreDir, targetVersion }, fsImpl = fs) {
943
- const sidecarPath = path.join(instanceDir, 'vendor', `${ARTIFACT}-${targetVersion}.manifest.json`);
944
- const sidecar = readManifest(sidecarPath, fsImpl);
945
- if (sidecar && sidecar.tree_sha256) {
946
- const tgz = path.join(instanceDir, 'vendor', `${ARTIFACT}-${targetVersion}.tgz`);
947
- return { manifest: sidecar, tgzPath: fsImpl.existsSync(tgz) ? tgz : null, source: 'vendored side-car manifest', strong: true };
948
- }
949
- const inner = readManifest(path.join(coreDir, '.bongos-core.json'), fsImpl);
950
- if (inner && inner.tree_sha256) return { manifest: inner, tgzPath: null, source: 'installed inner manifest', strong: false };
951
- return { manifest: null, tgzPath: null, source: null, strong: false };
952
- }
953
-
954
- // Recompute the integrity pin over the installed core tree and compare to `referenceManifest`.
955
- // Reuses the PACKAGER's exact hash functions (canonicalTreeHash / sha256hex) so the consume-side
956
- // recompute can never drift from the produce-side pin. Returns { ran, ok, checks, problems };
957
- // ran=false ⇒ the manifest carried no pin to check against.
958
- function verifyInstalledPin({ coreDir, referenceManifest, tgzPath }, deps = {}) {
959
- const fsImpl = deps.fs || fs;
960
- const pc = deps.packageCore || require('./package-core');
961
- const checks = [];
962
- const problems = [];
963
- if (!referenceManifest || !referenceManifest.tree_sha256) return { ran: false, ok: false, checks, problems };
964
-
965
- // (a) exact tarball bytes (vendored path only) — the strongest single check: the bytes
966
- // npm actually installs, hashed and compared to the externally-held pin.
967
- const tb = referenceManifest.tarball;
968
- if (tgzPath && tb && tb.sha256 && fsImpl.existsSync(tgzPath)) {
969
- const got = pc.sha256hex(fsImpl.readFileSync(tgzPath));
970
- const ok = got === tb.sha256;
971
- checks.push({ name: 'tarball.sha256', ok });
972
- if (!ok) problems.push(`vendored tarball bytes sha256 ${got.slice(0, 12)}… ≠ pinned ${String(tb.sha256).slice(0, 12)}…`);
973
- }
974
-
975
- // (b) installed tree — recompute each pinned file's sha256 from the unpacked tree, rebuild
976
- // the canonical tree hash (using the manifest's already-canonical modes), assert equality.
977
- // Catches partial extraction, post-install corruption, or a registry package that diverged.
978
- const files = Array.isArray(referenceManifest.files) ? referenceManifest.files : [];
979
- if (files.length) {
980
- const recomputed = [];
981
- let missing = 0, changed = 0;
982
- for (const f of files) {
983
- const abs = path.join(coreDir, ...String(f.path).split('/')); // POSIX manifest path → native
984
- let buf;
985
- try { buf = fsImpl.readFileSync(abs); } catch { missing++; problems.push(`missing installed file: ${f.path}`); continue; }
986
- const sha = pc.sha256hex(buf);
987
- if (sha !== f.sha256) { changed++; problems.push(`content mismatch: ${f.path}`); }
988
- recomputed.push({ path: f.path, mode: f.mode, sha256: sha });
989
- }
990
- const treeHash = pc.canonicalTreeHash(recomputed);
991
- const ok = missing === 0 && changed === 0 && treeHash === referenceManifest.tree_sha256;
992
- checks.push({ name: 'tree_sha256', ok, missing, changed, file_count: files.length });
993
- if (!ok && missing === 0 && changed === 0) {
994
- problems.push(`recomputed tree_sha256 ${treeHash.slice(0, 12)}… ≠ pinned ${String(referenceManifest.tree_sha256).slice(0, 12)}…`);
995
- }
996
- }
997
-
998
- const ran = checks.length > 0;
999
- return { ran, ok: ran && problems.length === 0, checks, problems };
1000
- }
1001
-
1002
- // Auto-rollback (task 2149): a bump failed AFTER the pin was moved — an install or migrate
1003
- // error, or a failed post-restart health check. Revert the code pin to the pre-upgrade
1004
- // snapshot, reinstall the previous core, restart, re-verify health, and record the reversal
1005
- // in the ledger. The DB is deliberately NOT rolled back: core migrations are additive +
1006
- // forward-safe (the core migration rule), so any already-applied migration is left in place —
1007
- // only the code PIN moves back. Best-effort + fail-soft: every sub-step logs but never throws,
1008
- // so a rollback attempt can't itself crash the upgrader on top of the original failure.
1009
- async function rollback({ instanceDir, snapshot, fromVersion, toVersion, opts }, reason, deps = {}) {
1010
- const log = deps.log || console.log;
1011
- const err = deps.err || console.error;
1012
- const run = deps.run || spawnSync;
1013
- const fsImpl = deps.fs || fs;
1014
- const restore = deps.restorePin || restorePin;
1015
-
1016
- err(` ↩ rolling back: ${reason} — reverting ${CORE_PKG} ${toVersion} → ${snapshot.prevVersion || snapshot.prevPin}`);
1017
- const result = { rolledBack: true, reason, restoredPin: snapshot.prevPin, restoredVersion: snapshot.prevVersion };
1018
-
1019
- // 1. revert the pin to the exact previous dep string.
1020
- try { restore(instanceDir, snapshot.prevPin, fsImpl); result.restoreOk = true; log(` ✓ restored pin → ${snapshot.prevPin}`); }
1021
- catch (e) { result.restoreOk = false; err(` ! could not restore pin (${e.message}) — package.json may need manual repair`); }
1022
-
1023
- // 2. reinstall the previous core.
1024
- const inst = npmInstall(instanceDir, run);
1025
- result.reinstallOk = !!inst.ok;
1026
- if (inst.ok) log(' ✓ reinstalled previous core');
1027
- else err(` ! reinstall of previous core failed (${inst.reason || 'exit ' + inst.code}) — the instance may need manual repair`);
1028
-
1029
- // 3. restart back onto the previous core.
1030
- // `deps` is passed here for the same reason the forward path passes it: this restart runs
1031
- // AFTER a failure, so its sudo-escalation is the one that matters most and must be testable.
1032
- const rs = restartService({ service: opts.service, restartCmd: opts.restartCmd }, run, deps);
1033
- if (rs.skipped) log(' • restart: no --service/--restart-cmd — restart the instance service manually to load the reverted core.');
1034
- else if (!rs.ok) err(` ! restart after rollback failed (exit ${rs.code}) — restart the service manually.`);
1035
- else log(` ✓ restarted ${opts.service || 'service'} on the previous core`);
1036
- result.restartOk = rs.ok;
1037
-
1038
- // 4. re-verify: installed == previous, optional health recovery.
1039
- const installedNow = readInstalledCoreVersion(instanceDir, fsImpl);
1040
- result.installedAfter = installedNow;
1041
- log(` ${installedNow === snapshot.prevVersion ? '✓' : '!'} installed core after rollback: ${installedNow || '(unknown)'}`);
1042
- if (opts.healthUrl) {
1043
- const h = await pollHealth(opts.healthUrl, deps);
1044
- result.healthOk = h.ok;
1045
- if (h.ok) log(` ✓ health recovered ${opts.healthUrl} → ${h.status}${h.attempts > 1 ? ` (after ${h.attempts} tries)` : ''}`);
1046
- else err(` ! health STILL failing after rollback (${h.error || 'status ' + h.status}) — manual intervention needed`);
1047
- }
1048
-
1049
- // 5. record the reversal in the ledger via the always-present `note` column (no schema
1050
- // dependency — so it records even when a FAILED migrate means a newer column wouldn't exist).
1051
- const note = `rolled_back: ${reason} (attempted ${fromVersion || '(none)'} → ${toVersion}, restored ${snapshot.prevVersion || 'previous'})`;
1052
- const ledger = await recordLedger({ fromVersion, toVersion, sourceCommit: opts.sourceCommit, note, requestedByBuilderId: opts.requestedBy, source: opts.upgradeSource, account: opts.migrateAs || null }, deps);
1053
- if (ledger.ok) log(' ✓ recorded rollback in core_upgrades ledger');
1054
- else if (ledger.skipped) log(` • rollback ledger skipped (${ledger.reason})`);
1055
- else err(` ! rollback ledger insert failed (${ledger.reason}) — record it manually`);
1056
- result.ledger = ledger.ok;
1057
-
1058
- err(` ↩ rollback complete — instance restored to core ${snapshot.prevVersion || snapshot.prevPin}.`);
1059
- return result;
1060
- }
1061
-
1062
- // ---- orchestration ----------------------------------------------------------
1063
-
1064
- async function runUpgrade(opts, deps = {}) {
1065
- const log = deps.log || console.log;
1066
- const err = deps.err || console.error;
1067
- const run = deps.run || spawnSync;
1068
- const fsImpl = deps.fs || fs;
1069
- const materialize = deps.materialize || require('./claude-materialize').materializeClaude;
1070
-
1071
- const instanceDir = path.resolve(opts.instance || process.cwd());
1072
- const targetVersion = opts.to;
1073
- const dryRun = !!opts.dryRun;
1074
- // Auto-rollback is ON by default (task 2149); `--no-rollback-on-failure` opts out (e.g. an
1075
- // interactive run that wants to inspect a broken state). Programmatic callers pass false.
1076
- const rollbackOnFailure = opts.rollbackOnFailure !== false;
1077
- // Pre-upgrade snapshot { prevPin, prevVersion } — captured the instant the pin is moved, so a
1078
- // failure AFTER that point (install / migrate / health) can revert. null until then = nothing to undo.
1079
- let snapshot = null;
1080
- if (!targetVersion) return { ok: false, error: 'missing --to <version> (the target core version)' };
1081
- // Checked once, here, rather than at each of the three places it is spent: an account
1082
- // name that reaches `sudo` is refused outright, never quoted into shape (task 1004512).
1083
- if (opts.migrateAs && !ACCOUNT_RE.test(opts.migrateAs)) return { ok: false, error: `--migrate-as ${JSON.stringify(opts.migrateAs)} is not a unix account name` };
1084
-
1085
- const pinnedVersion = readPinnedCoreVersion(instanceDir, fsImpl);
1086
- const fromVersion = readInstalledCoreVersion(instanceDir, fsImpl) || pinnedVersion;
1087
- const doRollback = (reason) => rollback({ instanceDir, snapshot, fromVersion, toVersion: targetVersion, opts }, reason, deps);
1088
- // A --to OLDER than this instance's core is refused before anything moves, --force included
1089
- // (task 1004009). Measured against the NEWER of installed and pinned — a half-applied bump
1090
- // leaves them apart. rollback() restores its own pin and never comes through here.
1091
- const baseline = compareSemver(pinnedVersion, fromVersion) > 0 ? pinnedVersion : fromVersion;
1092
- const isDowngrade = !!(parseSemver(baseline) && parseSemver(targetVersion) && compareSemver(targetVersion, baseline) < 0);
1093
- if (isDowngrade && !opts.allowDowngrade) {
1094
- const newest = listAvailableVersions({ cwd: instanceDir, run }).versions.filter(isStable).sort(compareSemver).pop();
1095
- return { ok: false, downgrade: true, fromVersion, toVersion: targetVersion, error: `refusing to DOWNGRADE: --to ${targetVersion} is older than this instance's core ${baseline}${pinnedVersion && pinnedVersion !== fromVersion ? ` (installed ${fromVersion}, pinned ${pinnedVersion})` : ''}; newest published: ${newest || 'unknown — the registry could not be read'}. Re-read the live version and target that; pass --allow-downgrade only if going backwards is the point (migrations are not reverted).` };
1096
- }
1097
- log(`bongos ${isDowngrade ? 'DOWNGRADE (--allow-downgrade; migrations are NOT reverted)' : 'upgrade'} — ${CORE_PKG}: ${fromVersion || '(none)'} → ${targetVersion}`);
1098
- log(` instance: ${instanceDir}${dryRun ? ' [DRY RUN — no changes]' : ''}`);
1099
- if (fromVersion === targetVersion && !opts.force) {
1100
- return { ok: false, error: `already on ${targetVersion} (pass --force to re-run the steps anyway)`, fromVersion };
1101
- }
1102
-
1103
- // 1. pre-flight: clean tree (so the pin change is reviewable + revertable) + module compatibility.
1104
- if (!opts.force) {
1105
- // Step 5's own output is not dirt (task 1004122) — but only when step 5 is going to run.
1106
- const preview = opts.skipMaterialize ? () => [] : (deps.willRewrite || require('./claude-materialize').materializeWillRewrite);
1107
- const tree = gitTreeClean(instanceDir, run, preview({ instanceDir, materialize }, err));
1108
- // TWO DIFFERENT FAILURES, TWO DIFFERENT SENTENCES (task 1004512). git ANSWERING with a
1109
- // list of dirty paths is a dirty tree, which the self-heal chain knows how to fix. git
1110
- // REFUSING to answer is not: committing anything would be committing a guess. They used
1111
- // to share one message, so a `dubious ownership` refusal was classified dirty_tree, the
1112
- // runner committed a tree that was never dirty, and the retry failed identically.
1113
- if (!tree.ok && tree.reason) return { ok: false, error: `git could not read the working tree in ${instanceDir} — the clean-tree pre-flight never ran, so this is NOT a report of uncommitted work.\n${tree.reason}` };
1114
- if (!tree.ok) return { ok: false, error: `working tree not clean — commit/stash first, or pass --force.\n${tree.dirty || ''}` };
1115
- if (tree.ignored) log(` • pre-flight: ignored ${tree.ignored} dirty path(s) this upgrade rewrites from the core (.claude/ materialization)${opts.commitPin ? ' — they are committed with the pin' : ' — pass --commit-pin to commit them'}.`);
1116
- }
1117
- const mods = preflightModules({ instanceDir, targetVersion }, deps);
1118
- log(` ✓ pre-flight: ${mods.note}`);
1119
- // Surface the non-blocking findings (rotted-but-disabled + deprecated modules) BEFORE the
1120
- // blocking check returns, so they are reported on a refused bump too — a refusal is exactly
1121
- // when someone is reading this output (ADR 0166).
1122
- (deps.reportModulePreflight || reportModulePreflight)(mods, targetVersion, { log, err });
1123
- if (!mods.ok) return { ok: false, error: `module pre-check failed: ${mods.blocking.map((b) => b.key).join(', ')} incompatible with core ${targetVersion}` };
1124
- // Fail on the DB identity BEFORE anything moves — a wrong OS user is an operator
1125
- // mistake, and finding it at migrate means unwinding a pin that never should have
1126
- // been written (task 1002712).
1127
- if (!opts.skipMigrate) {
1128
- const { db, ran } = (deps.resolveInstanceDb || resolveInstanceDb)({ instanceDir }, run);
1129
- if (ran && !db) {
1130
- return { ok: false, error: 'cannot determine which database to migrate.\n'
1131
- + ' Set PGDATABASE, or give this instance a db.database in config/branding.json.\n'
1132
- + ' Checked BEFORE the pin moves: migrate runs after the install, so a name that\n'
1133
- + ' cannot be resolved there costs a full rollback to discover (task 1002755).' };
1134
- }
1135
- const dbId = (deps.preflightDbIdentity || preflightDbIdentity)({ instanceDir, db, account: opts.migrateAs || null }, run);
1136
- if (!dbId.ok) return { ok: false, error: dbId.reason };
1137
- if (dbId.skipped) log(` • db identity pre-check${db ? ` (${db})` : ''}: ${dbId.skipped}`);
1138
- else log(` ✓ pre-flight: database${db ? ` "${db}"` : ''} reachable as ${opts.migrateAs || 'the current user'}`);
1139
- const { note: migrateNote } = require('./upgrade-migrate').migratePlan(instanceDir); if (migrateNote) log(` ✓ pre-flight: ${migrateNote}`);
1140
- }
1141
-
1142
- // 1a. artist gate (ADR 0241, task 1004205): an open review holds the pin, --force too; a downgrade never waits.
1143
- const gate = isDowngrade ? { halts: [], notes: [] } : await (deps.checkArtistGate || checkArtistGate)(opts, deps);
1144
- for (const n of gate.notes) err(` ! ${n.message}`);
1145
- if (gate.halts.length) return { ok: false, artistGate: true, error: gate.halts.map((h) => [h.message, h.detail].filter(Boolean).join('\n ')).join('\n') };
1146
- // 1b. mandatory post-restart health check (audit H9 / task 1002222, F5): a bump that restarts the
1147
- // service must prove it serves, so --health-url is required up front, before anything moves.
1148
- // (No managed restart ⇒ nothing is brought live here ⇒ the operator restarts + verifies.)
1149
- const willRestart = !!(opts.service || opts.restartCmd);
1150
- if (!dryRun && opts.healthCheck !== false && willRestart && !opts.healthUrl) {
1151
- return { ok: false, error: 'post-restart health check is mandatory for a bump that restarts the service, but no --health-url was given.\n Pass --health-url <url> to confirm the new core serves after restart, or --no-health-check to explicitly skip the confirmation.' };
1152
- }
1153
-
1154
- // 2. bump the pin. Two mutually exclusive core sources:
1155
- // REGISTRY (--registry): pin @bongos/core@<version> and let `npm install` pull it from
1156
- // the public registry. No credential — the package is public (task 1003872), which
1157
- // also retired the whole resolve-a-token-and-inject-it dance (task 1002754/1003878).
1158
- // VENDORED (default, --from <tgz>): copy the .tgz into vendor/ + rewrite the file: dep.
1159
- if (opts.registry) {
1160
- if (opts.from) return { ok: false, error: '--registry and --from are mutually exclusive (registry pull vs vendored tarball) — pick one core source' };
1161
- const prevPin = dryRun ? null : writeRegistryPin(instanceDir, targetVersion, fsImpl);
1162
- if (!dryRun) { snapshot = { prevPin, prevVersion: fromVersion }; }
1163
- log(` ${dryRun ? '[dry-run] would pin' : '✓ pinned'} ${CORE_PKG} → ${targetVersion} (registry)${prevPin ? ` (was ${prevPin})` : ''}`);
1164
- } else {
1165
- let vendorRel = opts.pinPath || (opts.from ? null : vendorRelFor(targetVersion));
1166
- if (opts.from) {
1167
- if (!fsImpl.existsSync(opts.from)) return { ok: false, error: `--from tarball not found: ${opts.from}` };
1168
- if (dryRun) { log(` [dry-run] would vendor ${opts.from} → vendor/${ARTIFACT}-${targetVersion}.tgz`); vendorRel = vendorRelFor(targetVersion); }
1169
- else vendorRel = vendorTarball({ instanceDir, fromTgz: path.resolve(opts.from), targetVersion }, fsImpl);
1170
- }
1171
- if (!fsImpl.existsSync(path.join(instanceDir, vendorRel)) && !dryRun) {
1172
- return { ok: false, error: `no core tarball at ${vendorRel} — pass --from <path-to-.tgz> to vendor it (or --registry to pull from the npm registry)` };
1173
- }
1174
- const prevPin = dryRun ? null : writePin(instanceDir, vendorRel, fsImpl);
1175
- if (!dryRun) snapshot = { prevPin, prevVersion: fromVersion };
1176
- log(` ${dryRun ? '[dry-run] would pin' : '✓ pinned'} ${CORE_PKG} → file:${vendorRel}${prevPin ? ` (was ${prevPin})` : ''}`);
1177
- }
1178
-
1179
- if (dryRun) { log(` [dry-run] would: npm install → ${opts.skipMigrate ? '(no migrate)' : require('./upgrade-migrate').migratePlan(instanceDir).label} → materialize .claude → regen API docs+client → restart → verify`); return { ok: true, dryRun: true, fromVersion, toVersion: targetVersion }; }
1180
-
1181
- // 3. npm install.
1182
- const inst = npmInstall(instanceDir, run);
1183
- if (!inst.ok) {
1184
- const error = `npm install failed (${inst.reason || 'exit ' + inst.code})`;
1185
- if (rollbackOnFailure && snapshot) {
1186
- const rb = await doRollback('npm install failed');
1187
- return { ok: false, error, fromVersion, toVersion: targetVersion, rolledBack: true, rollback: rb };
1188
- }
1189
- return { ok: false, error, fromVersion };
1190
- }
1191
- log(' ✓ npm install');
1192
-
1193
- // 3b. verify the integrity pin (audit H8 / task 1002216, finding F1). Recompute tree_sha256 over
1194
- // the freshly-installed core (+ the exact vendored tarball bytes) and assert it matches the
1195
- // TRUSTED reference manifest — the pin the packager produced but the consume side never
1196
- // re-checked. Runs BEFORE migrate so a corrupted core can never touch the DB. A MISMATCH is
1197
- // fatal → rollback (like an install/migrate failure). A MISSING reference (no side-car AND no
1198
- // inner manifest) can't be verified: a warning by default, fatal only with --require-pin.
1199
- if (!opts.skipPinVerify) {
1200
- const coreDir = path.join(instanceDir, 'node_modules', CORE_PKG);
1201
- const ref = (deps.resolveReferenceManifest || resolveReferenceManifest)({ instanceDir, coreDir, targetVersion }, fsImpl);
1202
- if (!ref.manifest) {
1203
- const msg = `integrity pin: no reference manifest (looked for vendor/${ARTIFACT}-${targetVersion}.manifest.json and ${CORE_PKG}/.bongos-core.json) — cannot verify this install`;
1204
- if (opts.requirePin) {
1205
- const error = `${msg} (--require-pin)`;
1206
- if (rollbackOnFailure && snapshot) { const rb = await doRollback('integrity pin unverifiable (--require-pin)'); return { ok: false, error, fromVersion, toVersion: targetVersion, rolledBack: true, rollback: rb }; }
1207
- return { ok: false, error, fromVersion };
1208
- }
1209
- err(` ! ${msg} — pass --require-pin to treat this as fatal.`);
1210
- } else {
1211
- const pin = (deps.verifyInstalledPin || verifyInstalledPin)({ coreDir, referenceManifest: ref.manifest, tgzPath: ref.tgzPath }, deps);
1212
- if (!pin.ok) {
1213
- const detail = pin.problems.slice(0, 6).join('; ') + (pin.problems.length > 6 ? `; +${pin.problems.length - 6} more` : '');
1214
- const error = `integrity pin MISMATCH (${ref.source}) — installed core does not match its pin: ${detail}`;
1215
- if (rollbackOnFailure && snapshot) {
1216
- const rb = await doRollback('integrity pin mismatch');
1217
- return { ok: false, error, fromVersion, toVersion: targetVersion, rolledBack: true, rollback: rb };
1218
- }
1219
- return { ok: false, error, fromVersion };
1220
- }
1221
- log(` ✓ integrity pin verified (${pin.checks.map((c) => c.name).join(' + ')}) against the ${ref.source}${ref.strong ? '' : ' — self-consistency check; npm registry integrity is the primary guard'}`);
1222
- }
1223
- } else log(' • integrity-pin verify skipped (--skip-pin-verify)');
1224
-
1225
- // 4. migrate (additive core_* migrations).
1226
- if (!opts.skipMigrate) {
1227
- const mig = await runMigrate(instanceDir, run, opts.migrateAs || null);
1228
- if (!mig.ok) {
1229
- const error = migrateError(mig); // names the failing migration + its ERROR line (task 1004734)
1230
- if (rollbackOnFailure && snapshot) {
1231
- const rb = await doRollback('migrate failed');
1232
- return { ok: false, error, fromVersion, toVersion: targetVersion, rolledBack: true, rollback: rb };
1233
- }
1234
- return { ok: false, error, fromVersion };
1235
- }
1236
- log(' ✓ migrate');
1237
- } else log(' • migrate skipped (--skip-migrate)');
1238
-
1239
- // 5. materialize .claude/ from the freshly-installed core.
1240
- //
1241
- // Its output rides the pin commit for the same reason the regenerated API artifacts below
1242
- // do (task 1003957 extending task 1003926): left dirty, the NEXT sweep's clean-tree guard
1243
- // reads `.claude/skills/*` as a human's uncommitted work and skips the instance forever —
1244
- // an enrolled co-tenant that upgrades exactly once. materializeClaude reports the paths it
1245
- // actually wrote or withdrew, so this is what THIS run touched, not a static list.
1246
- let materializedPaths = [];
1247
- if (!opts.skipMaterialize) {
1248
- const coreRoot = path.join(instanceDir, 'node_modules', CORE_PKG);
1249
- const sum = materialize({ coreRoot, instanceDir, log: (m) => log(m) });
1250
- materializedPaths = sum.writtenPaths || [];
1251
- log(` ✓ materialized .claude/ (${sum.skills} skill file(s)${sum.settings ? ', settings.json' : ''}${sum.hooks ? `, ${sum.hooks} hook(s)` : ''})`);
1252
- } else log(' • materialize skipped (--skip-materialize)');
1253
-
1254
- // 5b. regenerate the per-instance API artifacts (OpenAPI spec + typed client) from the
1255
- // new core's routes — the claude-materialize sibling (task 2051). Best-effort: a regen
1256
- // hiccup is a warning, not a failed bump (the next ship's fitness gate refreshes them).
1257
- let regenArtifacts = [];
1258
- if (!opts.skipRegenDocs) {
1259
- const coreRoot = path.join(instanceDir, 'node_modules', CORE_PKG);
1260
- const regen = (deps.regenerateApiArtifacts || regenerateApiArtifacts)({ instanceDir, coreRoot }, run);
1261
- regenArtifacts = (regen.ran || []).flatMap((gen) => API_ARTIFACT_FILES[gen] || []);
1262
- if (regen.ok) log(` ✓ regenerated API docs + typed client from core ${targetVersion}`);
1263
- else err(` ! API-artifact regen incomplete (${regen.reason}) — ran ${regen.ran.join(', ') || 'nothing'}; the next ship's fitness gate refreshes them.`);
1264
- // 5c. regenerate the whole-file navigation docs (repo-map + session-index) from the new
1265
- // core against the instance root (ADR 0110 / task 1002314). Best-effort + LOUD: a broken
1266
- // generator alarms via ::ERROR:: but never fails the bump.
1267
- const nav = (deps.regenerateNavDocs || regenerateNavDocs)({ instanceDir, coreRoot }, run);
1268
- if (nav.ok) log(` ✓ regenerated navigation docs (${nav.ran.join(', ')}) from core ${targetVersion}`);
1269
- else err(` ! ::ERROR:: navigation-doc regen incomplete — ran ${nav.ran.join(', ') || 'nothing'}; failed ${nav.failed.map((f) => `${f.gen} (${f.reason})`).join(', ')}. The next deploy retries.`);
1270
- // 5d. re-generate the CORE-scoped doc assets this very upgrade just wiped — the Repo Atlas
1271
- // data file + the onboarding diagram renders (task 1002441). See healDocAssets() for why
1272
- // nothing else puts them back. Best-effort + LOUD, same contract as 5c.
1273
- const heal = (deps.healDocAssets || healDocAssets)({ coreRoot }, run);
1274
- if (heal.missing.length === 0) log(' • doc assets intact (atlas + diagram renders present)');
1275
- else if (heal.ok) log(` ✓ regenerated doc assets wiped by the core swap (${heal.ran.join(', ')})`);
1276
- else err(` ! ::ERROR:: doc-asset regen incomplete — ran ${heal.ran.join(', ') || 'nothing'}; failed ${heal.failed.map((f) => `${f.group} (${f.reason})`).join(', ')}. /builders/atlas or /builders/diagrams may be broken until the next deploy retries (diagram renders need a system Chromium — ADR 0122).`);
1277
- } else log(' • doc regen skipped (--skip-regen-docs)');
1278
-
1279
- // 6. restart.
1280
- const rs = restartService({ service: opts.service, restartCmd: opts.restartCmd }, run, deps);
1281
- if (rs.skipped) log(` • restart: no --service/--restart-cmd — restart the instance service to load core ${targetVersion}.`);
1282
- else if (!rs.ok) {
1283
- // task 1002884: a failed restart is an upgrade FAILURE, not a warning. It used to fall
1284
- // through to the verification below — but the old process is still up, so the health poll
1285
- // passed against IT and the bump wrote a success row for a core that was never served.
1286
- // Failing here also keeps disk and process consistent: rollback puts the previous core back
1287
- // on disk, matching the one that is (still) running.
1288
- err(` ✖ restart failed (exit ${rs.code})${rs.triedSudo ? ` — \`systemctl restart\` exited ${rs.directCode} and \`sudo -n systemctl restart\` could not escalate` : ''}`);
1289
- err(' The previous core is still the one being served. Grant the restart a non-interactive path');
1290
- err(' (sudoers NOPASSWD or a polkit rule — docs/recipes/instance-service-restart.md), then re-run.');
1291
- const error = `restart failed (exit ${rs.code}) — the instance is still running the previous core`;
1292
- if (rollbackOnFailure && snapshot) {
1293
- const rb = await doRollback('restart failed');
1294
- return { ok: false, error, fromVersion, toVersion: targetVersion, restartOk: false, rolledBack: true, rollback: rb };
1295
- }
1296
- return { ok: false, error, fromVersion, toVersion: targetVersion, restartOk: false };
1297
- } else log(` ✓ restarted ${opts.service || 'service'}${rs.triedSudo ? ' (via sudo -n)' : ''}`);
1298
-
1299
- // 7. verify: installed version == target, optional /healthz, ledger row.
1300
- const installed = readInstalledCoreVersion(instanceDir, fsImpl);
1301
- const versionOk = installed === targetVersion;
1302
- log(` ${versionOk ? '✓' : '!'} installed core version: ${installed || '(unknown)'}${versionOk ? '' : ` (expected ${targetVersion})`}`);
1303
-
1304
- let healthOk = null;
1305
- if (opts.healthCheck === false) {
1306
- log(' • post-restart health check skipped (--no-health-check) — success is NOT confirmed against a live endpoint.');
1307
- } else if (opts.healthUrl) {
1308
- const h = await pollHealth(opts.healthUrl, deps);
1309
- healthOk = h.ok;
1310
- if (h.ok) log(` ✓ health ${opts.healthUrl} → ${h.status}${h.attempts > 1 ? ` (ready after ${h.attempts} tries)` : ''}`);
1311
- else err(` ! health ${opts.healthUrl} not ready after ${h.attempts} tr${h.attempts === 1 ? 'y' : 'ies'}: ${h.error || 'status ' + h.status}`);
1312
- } else {
1313
- // Reachable only when NO managed restart happened (pre-flight requires a URL when one will):
1314
- // the new core is installed on disk, but nothing was brought live here to health-check.
1315
- log(' • no managed restart + no --health-url — new core installed but not confirmed serving; restart the instance + health-check it to complete the bump.');
1316
- }
1317
-
1318
- // 7b. Confirm the SERVED process actually swapped (task 1002884). Everything above this point
1319
- // can be true of an instance still running the OLD core: the pin moved, node_modules holds
1320
- // the new version, and /healthz answers 200 — from the process that never went down. Only
1321
- // the live coreVersion settles it.
1322
- // A definite MISMATCH is a failure (same treatment as a failed health check). Being unable
1323
- // to READ the endpoint is not: an instance may not expose it, and refusing every such bump
1324
- // would be a worse regression than the false-pass. Passing --version-url explicitly asks
1325
- // for proof, so there an unreadable endpoint IS a failure.
1326
- let servedOk = null;
1327
- let servedVersion = null;
1328
- const versionUrl = opts.versionUrl || (opts.healthUrl ? deriveVersionUrl(opts.healthUrl) : null);
1329
- if (opts.healthCheck === false) {
1330
- // --no-health-check is the documented opt-out from confirming the bump serves; it covers this.
1331
- } else if (versionUrl && healthOk !== false) {
1332
- const sv = await pollServedVersion(versionUrl, deps);
1333
- servedVersion = sv.version || null;
1334
- if (sv.ok && servedVersion === targetVersion) {
1335
- servedOk = true;
1336
- log(` ✓ served core version: ${servedVersion} (${versionUrl})`);
1337
- } else if (sv.ok) {
1338
- servedOk = false;
1339
- err(` ! served core version is ${servedVersion} but the target is ${targetVersion} (${versionUrl})`);
1340
- err(' The restart did not swap the running process — the old core is still being served.');
1341
- } else if (opts.versionUrl) {
1342
- servedOk = false;
1343
- err(` ! could not read ${versionUrl} (${sv.error}) — --version-url was given, so this bump cannot be confirmed`);
1344
- } else {
1345
- err(` ! could not read ${versionUrl} (${sv.error}) — this bump is NOT confirmed against the running process.`);
1346
- err(' Pass --version-url <url> if this instance serves its version elsewhere.');
1347
- }
1348
- }
1349
-
1350
- // A failed post-restart health check means the new core is serving broken — auto-revert (task
1351
- // 2149) instead of recording an "upgraded" row + leaving the instance down. A served-version
1352
- // mismatch means the new core is not serving AT ALL (task 1002884) and reverts the same way.
1353
- // The rollback writes its OWN rolled_back ledger row, so skip the normal insert below.
1354
- if ((healthOk === false || servedOk === false) && rollbackOnFailure && snapshot) {
1355
- const why = healthOk === false
1356
- ? 'health check failed after restart'
1357
- : `served core version did not change (still ${servedVersion || 'unconfirmed'}, expected ${targetVersion})`;
1358
- const rb = await doRollback(why);
1359
- return { ok: false, error: `${why} — rolled back to ${snapshot.prevVersion || 'the previous core'}`, fromVersion, toVersion: targetVersion, versionOk, healthOk, servedOk, servedVersion, rolledBack: true, rollback: rb };
1360
- }
1361
-
1362
- const ledger = await recordLedger({ fromVersion, toVersion: targetVersion, sourceCommit: opts.sourceCommit, note: isDowngrade ? `downgrade (--allow-downgrade)${opts.note ? `: ${opts.note}` : ''}` : opts.note, requestedByBuilderId: opts.requestedBy, source: opts.upgradeSource, account: opts.migrateAs || null }, deps);
1363
- if (ledger.ok) log(' ✓ recorded in core_upgrades ledger');
1364
- else if (ledger.skipped) log(` • ledger skipped (${ledger.reason})`);
1365
- else err(` ! ledger insert failed (${ledger.reason}) — record it manually`);
1366
-
1367
- // Make the pin durable (task 1002712). Runs LAST — only a verified-healthy
1368
- // upgrade is worth persisting, and a rolled-back one returned long before here.
1369
- //
1370
- // Which credential the push rides is resolved HERE (async — it may read the token
1371
- // store) and handed to persistPin, which stays synchronous — and only when a push is
1372
- // actually coming: --commit-pin without --pin-no-push, not a dry run, and the pin
1373
- // files really are dirty. Nothing reads a credential it will not spend (task 1003081).
1374
- const remote = opts.gitRemote || 'origin';
1375
- // Everything this upgrade generated into the instance's tree: the API artifacts (task
1376
- // 1003926) and the materialized .claude/ (task 1003957). One list, so the push-credential
1377
- // probe and persistPin agree on what "the upgrade rewrote" means.
1378
- const generatedPaths = [...regenArtifacts, ...materializedPaths];
1379
- const pushComing = !!opts.commitPin && !opts.pinNoPush && !dryRun
1380
- && ((dirtyPinFiles(instanceDir, run) || []).length > 0 || (dirtyPaths(instanceDir, generatedPaths, run) || []).length > 0);
1381
- const pushAuth = pushComing ? await (deps.resolvePinPushAuth || resolvePinPushAuth)({ instanceDir, remote }, deps, run) : null;
1382
- const pin = persistPin({
1383
- instanceDir,
1384
- fromVersion,
1385
- toVersion: targetVersion,
1386
- commitPin: opts.commitPin,
1387
- push: !opts.pinNoPush,
1388
- remote,
1389
- dryRun: opts.dryRun,
1390
- pushAuth,
1391
- artifactPaths: generatedPaths,
1392
- }, run, log, err);
1393
-
1394
- const ok = versionOk && healthOk !== false && servedOk !== false;
1395
- log(ok ? `\n✓ ${isDowngrade ? 'downgrade' : 'upgrade'} complete — core ${fromVersion || '(none)'} → ${targetVersion}` : `\n! ${isDowngrade ? 'downgrade' : 'upgrade'} finished with warnings — review above.`);
1396
- return { ok, fromVersion, toVersion: targetVersion, versionOk, healthOk, servedOk, servedVersion, ledger: ledger.ok, pin };
1397
- }
1398
-
1399
- function parseArgs(argv) {
1400
- return {
1401
- to: arg('--to', argv),
1402
- from: arg('--from', argv),
1403
- instance: arg('--instance', argv),
1404
- service: arg('--service', argv),
1405
- restartCmd: arg('--restart-cmd', argv),
1406
- healthUrl: arg('--health-url', argv),
1407
- versionUrl: arg('--version-url', argv), // task 1002884: read the LIVE process's coreVersion back; defaults to /version on the health URL's origin
1408
- sourceCommit: arg('--source-commit', argv),
1409
- note: arg('--note', argv),
1410
- // Who asked, and through which door (task 1003159, ADR 0293 D5). Both reach the
1411
- // core_upgrades row so a privileged act that an HTTP request could start is never
1412
- // unattributable. Omitted on a hand-run bump, where there is no builder to name —
1413
- // and omitting them keeps the INSERT on its pre-core_241 four columns, which is
1414
- // what lets this script keep working against an instance DB that has not migrated.
1415
- requestedBy: arg('--requested-by', argv),
1416
- upgradeSource: arg('--upgrade-source', argv),
1417
- pinPath: arg('--pin-path', argv),
1418
- migrateAs: arg('--migrate-as', argv), // task 1004512: the project's own unix+Postgres identity, when the move itself runs as the account that owns the checkout
1419
- registry: hasFlag('--registry', argv), // ADR 0134: pull @bongos/core@<--to> from the npm registry instead of vendoring
1420
- commitPin: hasFlag('--commit-pin', argv), // task 1002712: commit + push package.json/-lock so a pull-deploy reset cannot revert the bump
1421
- pinNoPush: hasFlag('--pin-no-push', argv), // task 1003521 co-tenant mode: commit the pin but leave the customer's own remote alone
1422
- gitRemote: arg('--git-remote', argv),
1423
- dryRun: hasFlag('--dry-run', argv),
1424
- force: hasFlag('--force', argv),
1425
- allowDowngrade: hasFlag('--allow-downgrade', argv), // task 1004009: a --to older than the installed core is refused without it
1426
- skipMigrate: hasFlag('--skip-migrate', argv),
1427
- skipMaterialize: hasFlag('--skip-materialize', argv),
1428
- skipRegenDocs: hasFlag('--skip-regen-docs', argv),
1429
- skipPinVerify: hasFlag('--skip-pin-verify', argv), // task 1002216: opt out of the post-install integrity-pin check
1430
- requirePin: hasFlag('--require-pin', argv), // task 1002216: a MISSING reference manifest becomes fatal (not just a warning)
1431
- healthCheck: !hasFlag('--no-health-check', argv), // task 1002222: post-restart health check is ON by default (finding F5/H9)
1432
- rollbackOnFailure: !hasFlag('--no-rollback-on-failure', argv), // ADR 0100: auto-revert ON by default (task 2149)
1433
- };
1434
- }
1435
-
1436
- async function main(argv = process.argv.slice(2), deps = {}) {
1437
- if (hasFlag('--help', argv) || argv[0] === 'help') {
1438
- process.stdout.write([
1439
- 'bongos upgrade — pull the Cloud Bongos core to a new version and apply it.',
1440
- '',
1441
- 'Usage:',
1442
- ' bongos upgrade module-compat pre-check against the installed core (exit 1 on mismatch)',
1443
- ' bongos upgrade --to <version> [opts] pull + apply a new core version (the real channel)',
1444
- '',
1445
- ' --to <version> target core version — presence switches from pre-check to a real bump',
1446
- ' --from <tgz> source tarball to vendor into vendor/ (else it must already be there)',
1447
- ' --registry pull @bongos/core@<--to> from the public npm registry (no token needed) instead of vendoring a tarball; mutually exclusive with --from',
1448
- ' --instance <dir> consumer instance root (default: cwd)',
1449
- ' --service <unit> systemd unit to restart after applying',
1450
- ' --restart-cmd <cmd> explicit restart command (overrides --service)',
1451
- ' --health-url <url> poll after restart (~30s) until 2xx; a still-failing check fails the bump (auto-rollback). REQUIRED for a bump that restarts the service, unless --no-health-check.',
1452
- ' --version-url <url> read the RUNNING process\'s coreVersion back after restart and require it to equal --to (default: /version on the --health-url origin). A health check alone cannot tell a new core from an old one that never went down.',
1453
- ' --no-health-check explicitly skip the post-restart health confirmation (default: the check is ON — a bump that restarts the service must confirm it serves); also skips the served-version read-back',
1454
- ' --skip-migrate do not migrate (the default runs the instance\'s `migrate` script, else the core\'s scripts/migrate.sh)',
1455
- ' --migrate-as <user> run the database steps (identity pre-check, migrate, ledger) as this unix account via `sudo -n -u`. For a project whose checkout is owned by the operator account but whose database is owned by its OWN account: the move needs the first to write files, the migration needs the second to connect. Omit it and everything runs as the current user, as before',
1456
- ' --skip-materialize do not refresh .claude/',
1457
- ' --skip-regen-docs do not regenerate the OpenAPI spec + typed client from the new core',
1458
- ' --skip-pin-verify do not verify the integrity pin (tree_sha256 + tarball.sha256) after install',
1459
- ' --require-pin treat a MISSING reference manifest as fatal (default: warn — a MISMATCH is always fatal)',
1460
- ' --no-rollback-on-failure do NOT auto-revert on a failed install/pin-verify/migrate/health check (default: auto-rollback ON)',
1461
- ' --commit-pin commit + push package.json/-lock so a pull-deploy reset cannot revert the bump. The push rides the instance owner\'s stored GitHub token when one is stored (a PRIVATE instance\'s origin is a read-only deploy key — ADR 0176), else the git remote (--git-remote <name>, default origin); a refused push is reported loudly with the fix',
1462
- ' --pin-no-push with --commit-pin: commit the pin but do NOT push it — for an instance whose repo of record is not ours (a provisioned co-tenant), where the push is wrong and no pull-deploy can revert the commit',
1463
- ' --dry-run show the plan; change nothing',
1464
- ' --force skip the clean-tree + same-version guards (NOT the downgrade guard)',
1465
- ' --allow-downgrade let --to be OLDER than the installed core. Refused otherwise: a stale --to silently takes merged work off a live instance, and migrations are never reverted, so the DB stays ahead of the code',
1466
- '',
1467
- 'Full bump: pre-flight → bump pin → npm install → verify integrity pin → migrate → materialize .claude → regen API docs+client → restart → verify (health + served coreVersion).',
1468
- 'On a failure after the pin moves (install/pin-verify/migrate/restart/health/served-version), auto-rollback reverts the pin, reinstalls the previous core, restarts, and records a rolled_back ledger row (the DB is not rolled back — core migrations are additive).',
1469
- ].join('\n') + '\n');
1470
- return 0;
1471
- }
1472
- // Backward-compatible: bare `bongos upgrade` (no --to) is the documented module-compatibility
1473
- // PRE-CHECK — unchanged behavior, delegated to the module CLI. A --to switches to the real channel.
1474
- // task 1004596: from a builder's own checkout of a project its OPERATOR runs, say who upgrades it and how to ask — never a server-only refusal (upgrade-operator.js has the condition).
1475
- const operatorMsg = await (deps.operatorNotice || require('./upgrade-operator').operatorNotice)({ instanceDir: path.resolve(arg('--instance', argv) || process.cwd()) });
1476
- if (!arg('--to', argv)) {
1477
- const code = await (deps.cmdUpgrade || require('./module').cmdUpgrade)(argv);
1478
- if (operatorMsg) process.stdout.write(`\n${operatorMsg}`);
1479
- return code;
1480
- }
1481
- if (operatorMsg) { process.stderr.write(`\n✖ ${operatorMsg}`); return 1; }
1482
- const res = await runUpgrade(parseArgs(argv));
1483
- if (!res.ok) { process.stderr.write(`\n✖ ${res.error || 'upgrade failed'}\n${require('./upgrade-outcome').outcomeLine(res)}`); return 1; } // the outcome line: how far it got, for the deploy runner (task 1004446)
1484
- return 0;
1485
- }
1486
-
1487
- module.exports = {
1488
- runUpgrade, parseArgs, main, rollback,
1489
- versionFromTgzPath, versionFromDep, readInstalledCoreVersion, readPinnedCoreVersion, writePin, writeRegistryPin, restorePin,
1490
- vendorTarball, gitTreeClean, persistPin, dirtyPinFiles, gitCurrentBranch, PIN_FILES, API_ARTIFACT_FILES, preflightDbIdentity,
1491
- resolveInstanceDb, preflightModules, reportModulePreflight, npmInstall, runMigrate, regenerateApiArtifacts, regenerateNavDocs, NAV_WHOLE_FILE_GENERATORS, missingDocAssets, healDocAssets, DOC_ASSET_GENERATORS, restartService, recordLedger, ledgerInsert, LEDGER_ACTOR_COLS, pollHealth, deriveVersionUrl, pollServedVersion,
1492
- resolvePinPushAuth, remoteGithubRepo, pinnedDeployKey, // task 1003081 — the pin push prefers the owner's GitHub token (ADR 0176 follow-up)
1493
- readManifest, resolveReferenceManifest, verifyInstalledPin, // task 1002216 (audit H8) — integrity-pin verification
1494
- CORE_PKG, ARTIFACT, vendorRelFor,
1495
- };
1496
-
1497
- if (require.main === module) {
1498
- main().then((code) => { if (arg('--to', process.argv.slice(2))) process.exit(code); else process.exitCode = code; }).catch((e) => { process.stderr.write(`✖ ${e.message}\n`); process.exit(1); }); // bare pre-check drains: it ends after a store read (task 1003787), and a hard exit there aborts on Windows (task 1002734)
1499
- }
7
+ require('../bongos/forwarder.js').forward(module, 'upgrade.js');