@bongos/core 1.18.0 → 1.18.18

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 (553) hide show
  1. package/.bongos-core.json +1740 -640
  2. package/.claude/skills/builder-box/SKILL.md +6 -0
  3. package/.claude/skills/builder-sequence/SKILL.md +97 -0
  4. package/.claude/skills/builder-ship/SKILL.md +8 -2
  5. package/.claude/skills/builder-start/SKILL.md +11 -0
  6. package/.claude/skills/builder-sync/SKILL.md +41 -0
  7. package/.claude/skills/fix-task/SKILL.md +64 -0
  8. package/.claude/skills/goal-create/SKILL.md +158 -0
  9. package/.claude/skills/goal-review/SKILL.md +3 -1
  10. package/.claude/skills/idea-triage/SKILL.md +14 -8
  11. package/.claude/skills/merge-mode/SKILL.md +2 -2
  12. package/.claude/skills/new-project/SKILL.md +1 -0
  13. package/.claude/skills/planning-session/SKILL.md +45 -18
  14. package/.env.local.example +4 -3
  15. package/README.md +5 -3
  16. package/bin/bongos.js +1 -0
  17. package/clients/bongos-client/README.md +2 -2
  18. package/clients/bongos-client/bongos-client.global.js +82 -18
  19. package/clients/bongos-client/index.cjs +82 -18
  20. package/clients/bongos-client/index.d.ts +131 -29
  21. package/clients/bongos-client/index.mjs +82 -18
  22. package/config/branding.neutral.json +11 -2
  23. package/config/governance.neutral.json +21 -0
  24. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +24 -0
  25. package/docs/adr/0090-metic-task-authoring.md +1 -1
  26. package/docs/adr/0142-project-context-is-prose-only.md +41 -0
  27. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  28. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  29. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  30. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  31. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  32. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  33. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  34. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  35. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  36. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  37. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  38. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  39. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  40. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  41. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  42. package/docs/adr/README.md +15 -2
  43. package/docs/api/openapi.json +2648 -483
  44. package/docs/api-reference.md +73 -13
  45. package/docs/architecture.md +4 -2
  46. package/docs/branding-contract.md +3 -1
  47. package/docs/canonical-permissions.md +21 -8
  48. package/docs/file-map.md +15 -7
  49. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  50. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  51. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  52. package/docs/onboarding/diagrams/assertions.json +4 -7
  53. package/docs/onboarding/drachmae-and-karma.md +3 -3
  54. package/docs/onboarding/primer.md +17 -16
  55. package/docs/onboarding/slash-commands.md +124 -0
  56. package/docs/recipes/builder-box-lifecycle.md +23 -0
  57. package/docs/recipes/devbox-app-release.md +14 -4
  58. package/docs/recipes/instance-first-run.md +16 -0
  59. package/docs/recipes/local-dev.md +81 -0
  60. package/docs/recipes/ops-gotchas.md +19 -1
  61. package/docs/recipes/overnight-builder.md +1 -1
  62. package/docs/recipes/packaging-the-core.md +13 -0
  63. package/docs/recipes/parallel-goal-waves.md +174 -0
  64. package/docs/recipes/ship-and-regrade.md +2 -2
  65. package/docs/recipes/standalone-live-docs.md +48 -0
  66. package/docs/recipes/upgrading-the-core.md +5 -2
  67. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  68. package/migrations/003_pms.sql +6 -7
  69. package/migrations/006_pms_v2.sql +3 -31
  70. package/migrations/039_newcomer_friendly_column.sql +5 -0
  71. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  72. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  73. package/migrations/core_193_task_needs_rebase.sql +28 -0
  74. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  75. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  76. package/migrations/core_196_session_reward_topup.sql +69 -0
  77. package/modules/autonomy/pollers/routine-timers.js +9 -8
  78. package/modules/builder-settings/wandering-prefs.js +61 -18
  79. package/modules/dev-box/app/README.md +73 -0
  80. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  81. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  82. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  83. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  84. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  85. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  86. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  87. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  88. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  89. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  90. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  91. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  92. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  93. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  94. package/modules/dev-box/app/build-resources/icon.png +0 -0
  95. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  96. package/modules/dev-box/app/electron-builder.yml +95 -0
  97. package/modules/dev-box/app/package-lock.json +5291 -0
  98. package/modules/dev-box/app/package.json +30 -0
  99. package/modules/dev-box/app/renderer/app.js +319 -0
  100. package/modules/dev-box/app/renderer/index.html +45 -0
  101. package/modules/dev-box/app/renderer/styles.css +246 -0
  102. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  103. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  104. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  105. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  106. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  107. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  108. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  109. package/modules/dev-box/app/src/box-controller.js +287 -0
  110. package/modules/dev-box/app/src/brand.generated.json +13 -0
  111. package/modules/dev-box/app/src/brand.js +16 -0
  112. package/modules/dev-box/app/src/config.js +19 -0
  113. package/modules/dev-box/app/src/gds-client.js +90 -0
  114. package/modules/dev-box/app/src/main.js +610 -0
  115. package/modules/dev-box/app/src/pairing.js +57 -0
  116. package/modules/dev-box/app/src/preload.js +29 -0
  117. package/modules/dev-box/app/src/session-store.js +58 -0
  118. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  119. package/modules/dev-box/app/src/task-picker.js +70 -0
  120. package/modules/dev-box/app/src/tray.js +99 -0
  121. package/modules/dev-box/app/src/updater.js +55 -0
  122. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  123. package/modules/dev-box/app/test/unit.mjs +526 -0
  124. package/modules/dev-box/box-access.js +121 -4
  125. package/modules/dev-box/boxes.js +20 -0
  126. package/modules/dev-box/module.json +1 -1
  127. package/modules/dev-box/routes/box.js +87 -3
  128. package/modules/economy/credits.js +116 -25
  129. package/modules/economy/reward.js +8 -0
  130. package/modules/economy/streak.js +2 -1
  131. package/modules/governance/CLAUDE.md +15 -0
  132. package/modules/governance/catalog.js +419 -0
  133. package/modules/governance/config.js +174 -0
  134. package/modules/governance/db.js +125 -0
  135. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  136. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  137. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  138. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  139. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  140. package/modules/governance/module.json +10 -0
  141. package/modules/governance/protected-surfaces.js +88 -0
  142. package/modules/governance/protected-surfaces.json +80 -0
  143. package/modules/governance/rank-roles.js +83 -0
  144. package/modules/governance/resolver.js +221 -0
  145. package/modules/governance/routes/governance.js +89 -0
  146. package/modules/governance/routes/role-sync.js +49 -0
  147. package/modules/governance/session-scopes.js +127 -0
  148. package/modules/governance/session-scopes.json +38 -0
  149. package/modules/hall-ui/public/atlas.css +117 -0
  150. package/modules/hall-ui/public/atlas.html +3 -114
  151. package/modules/hall-ui/public/brand-apply.js +34 -6
  152. package/modules/hall-ui/public/builders.js +187 -219
  153. package/modules/hall-ui/public/diagrams.html +2 -0
  154. package/modules/hall-ui/public/dom-utils.js +27 -0
  155. package/modules/hall-ui/public/drachmae.html +2 -0
  156. package/modules/hall-ui/public/drachmae.js +54 -1
  157. package/modules/hall-ui/public/gate.css +98 -0
  158. package/modules/hall-ui/public/gate.html +3 -95
  159. package/modules/hall-ui/public/goal-inbox.js +4 -1
  160. package/modules/hall-ui/public/goals-page.js +626 -114
  161. package/modules/hall-ui/public/goals.css +79 -1
  162. package/modules/hall-ui/public/goals.html +38 -11
  163. package/modules/hall-ui/public/hall-widgets.js +62 -52
  164. package/modules/hall-ui/public/harbor.css +123 -0
  165. package/modules/hall-ui/public/harbor.html +3 -120
  166. package/modules/hall-ui/public/index.html +11 -4
  167. package/modules/hall-ui/public/instances-panel.js +4 -1
  168. package/modules/hall-ui/public/modules.css +63 -0
  169. package/modules/hall-ui/public/modules.html +3 -60
  170. package/modules/hall-ui/public/my-projects.html +78 -0
  171. package/modules/hall-ui/public/my-projects.js +142 -0
  172. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  173. package/modules/hall-ui/public/not-ready.html +2 -0
  174. package/modules/hall-ui/public/pair.css +73 -0
  175. package/modules/hall-ui/public/pair.html +3 -70
  176. package/modules/hall-ui/public/palette.js +302 -0
  177. package/modules/hall-ui/public/primer.css +13 -0
  178. package/modules/hall-ui/public/primer.html +2 -0
  179. package/modules/hall-ui/public/profile.html +2 -0
  180. package/modules/hall-ui/public/ranks.html +2 -0
  181. package/modules/hall-ui/public/roadmap.css +179 -0
  182. package/modules/hall-ui/public/roadmap.html +9 -172
  183. package/modules/hall-ui/public/roadmap.js +329 -316
  184. package/modules/hall-ui/public/scouting.html +45 -0
  185. package/modules/hall-ui/public/scouting.js +73 -0
  186. package/modules/hall-ui/public/sessions.css +16 -0
  187. package/modules/hall-ui/public/sessions.html +3 -13
  188. package/modules/hall-ui/public/settings.html +2 -0
  189. package/modules/hall-ui/public/settings.js +4 -4
  190. package/modules/hall-ui/public/shell.js +143 -18
  191. package/modules/hall-ui/public/style.css +231 -39
  192. package/modules/hall-ui/public/task-detail.js +347 -26
  193. package/modules/hall-ui/public/task.html +6 -1
  194. package/modules/hall-ui/public/watch.html +2 -0
  195. package/modules/hall-ui/public/work.html +8 -6
  196. package/modules/hall-ui/public/work.js +1 -1
  197. package/modules/ideas/inbox.js +61 -11
  198. package/modules/ideas/routes/inbox.js +23 -0
  199. package/modules/lifecycle/claim-eligibility.js +72 -0
  200. package/modules/lifecycle/db.js +519 -139
  201. package/modules/lifecycle/done-when.js +18 -3
  202. package/modules/lifecycle/github-push.js +19 -2
  203. package/modules/lifecycle/goal-advisory.js +114 -0
  204. package/modules/lifecycle/goal-authz.js +62 -0
  205. package/modules/lifecycle/lifecycle.js +9 -0
  206. package/modules/lifecycle/publish-reconciler.js +109 -6
  207. package/modules/lifecycle/routes/claims.js +68 -23
  208. package/modules/lifecycle/routes/done-when.js +110 -15
  209. package/modules/lifecycle/routes/goals.js +8 -38
  210. package/modules/lifecycle/routes/tasks.js +38 -6
  211. package/modules/lifecycle/ship-card.js +6 -0
  212. package/modules/onboarding/onboarding-state.js +1 -1
  213. package/modules/platform-identity/CLAUDE.md +15 -0
  214. package/modules/platform-identity/hub-device.js +147 -0
  215. package/modules/platform-identity/hub-keys.js +151 -0
  216. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  217. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  218. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  219. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  220. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  221. package/modules/platform-identity/module.json +18 -0
  222. package/modules/platform-identity/platform-identity.js +531 -0
  223. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  224. package/modules/platform-identity/routes/my-projects.js +140 -0
  225. package/modules/platform-identity/routes/projects.js +107 -0
  226. package/modules/platform-identity/routes/scouting.js +35 -0
  227. package/modules/platform-identity/routes/sso.js +402 -0
  228. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  229. package/modules/platform-identity/ui/.gitkeep +0 -0
  230. package/modules/security/routes/reports.js +10 -0
  231. package/modules/sessions/db.js +166 -21
  232. package/modules/sessions/module.json +1 -1
  233. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  234. package/modules/sessions/routes/sessions.js +33 -0
  235. package/modules/status-ui/public/explore.html +54 -0
  236. package/modules/status-ui/public/explore.js +67 -0
  237. package/package-lock.json +2 -2
  238. package/package.json +1 -1
  239. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  270. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  271. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  272. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  273. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  274. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  275. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  276. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  277. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  278. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  279. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  280. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  281. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  282. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  283. package/public-landing/create.html +252 -62
  284. package/public-landing/gate/README.md +137 -0
  285. package/public-landing/gate/dispmaps/bar.png +0 -0
  286. package/public-landing/gate/dispmaps/flat.png +0 -0
  287. package/public-landing/gate/dispmaps/key.png +0 -0
  288. package/public-landing/gate/index.html +587 -0
  289. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  290. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  291. package/public-landing/gate/space.css +799 -0
  292. package/public-landing/gate/space.js +1826 -0
  293. package/public-landing/gate/sprites/enter.png +0 -0
  294. package/public-landing/gate/sprites/search.png +0 -0
  295. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  296. package/public-landing/gate/sprites/tile.png +0 -0
  297. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  298. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  299. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  300. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  301. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  302. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  303. package/scripts/gds/abandon.js +6 -4
  304. package/scripts/gds/api.js +10 -5
  305. package/scripts/gds/api.ps1 +26 -0
  306. package/scripts/gds/api.sh +6 -0
  307. package/scripts/gds/audit-ships.js +7 -1
  308. package/scripts/gds/backfill-sessions.js +78 -18
  309. package/scripts/gds/backup.js +23 -1
  310. package/scripts/gds/box-connect-lib.js +124 -31
  311. package/scripts/gds/box-sync.js +66 -0
  312. package/scripts/gds/box.js +225 -53
  313. package/scripts/gds/cf-tunnel.js +145 -6
  314. package/scripts/gds/claim.js +34 -3
  315. package/scripts/gds/cli-lib.js +161 -21
  316. package/scripts/gds/code.js +6 -2
  317. package/scripts/gds/deploy-divergence.js +209 -0
  318. package/scripts/gds/dev-lib.js +309 -0
  319. package/scripts/gds/dev.js +322 -0
  320. package/scripts/gds/doctor.js +90 -61
  321. package/scripts/gds/fetch-art-key.js +1 -1
  322. package/scripts/gds/fetch-sound-prefs.js +2 -2
  323. package/scripts/gds/fitness.js +228 -12
  324. package/scripts/gds/gds-db-backup.service +16 -1
  325. package/scripts/gds/gds-db-offsite.service +9 -1
  326. package/scripts/gds/gen-api-client.js +1 -1
  327. package/scripts/gds/gen-api-docs.js +36 -14
  328. package/scripts/gds/gen-diagrams.js +45 -28
  329. package/scripts/gds/gen-file-map.js +2 -1
  330. package/scripts/gds/gen-freshness.js +32 -0
  331. package/scripts/gds/gen-repo-map.js +3 -2
  332. package/scripts/gds/gen-session-index.js +14 -5
  333. package/scripts/gds/hooks/pre-push.js +2 -2
  334. package/scripts/gds/init.js +60 -3
  335. package/scripts/gds/install-git-hooks.js +1 -1
  336. package/scripts/gds/key-card.js +15 -6
  337. package/scripts/gds/key-status.js +1 -1
  338. package/scripts/gds/linkify-refs.js +35 -9
  339. package/scripts/gds/lint-migrations.js +102 -0
  340. package/scripts/gds/login.js +58 -11
  341. package/scripts/gds/mirror-redact.js +5 -0
  342. package/scripts/gds/package-core.js +263 -4
  343. package/scripts/gds/paste-token.js +7 -1
  344. package/scripts/gds/preflight.js +126 -0
  345. package/scripts/gds/provision.js +268 -19
  346. package/scripts/gds/publish-manifest.js +22 -1
  347. package/scripts/gds/reauth.js +7 -3
  348. package/scripts/gds/regen-instance-docs.js +47 -0
  349. package/scripts/gds/run-unit-tests.js +42 -16
  350. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  351. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  352. package/scripts/gds/sequence.js +425 -0
  353. package/scripts/gds/session-cost.js +10 -1
  354. package/scripts/gds/setup.js +72 -5
  355. package/scripts/gds/shell.js +5 -3
  356. package/scripts/gds/ship.js +433 -59
  357. package/scripts/gds/smoke-gds.js +139 -8
  358. package/scripts/gds/start.js +171 -22
  359. package/scripts/gds/status.js +1 -1
  360. package/scripts/gds/triage.js +10 -9
  361. package/scripts/gds/upgrade.js +271 -7
  362. package/scripts/migrate.sh +10 -0
  363. package/scripts/status-mirror-sync.js +114 -84
  364. package/src/bongos/api-errors.js +1 -0
  365. package/src/bongos/auth.js +809 -107
  366. package/src/bongos/db-kernel.js +27 -0
  367. package/src/bongos/db.js +105 -0
  368. package/src/bongos/github-repos.js +93 -0
  369. package/src/bongos/module-scope-map.js +27 -1
  370. package/src/bongos/permission-path-check.js +136 -102
  371. package/src/bongos/repo-info.js +47 -11
  372. package/src/bongos/route-rank-check.js +429 -46
  373. package/src/bongos/routes/_helpers.js +12 -1
  374. package/src/bongos/routes/auth.js +312 -13
  375. package/src/bongos/routes/backup.js +58 -2
  376. package/src/bongos/routes/github.js +90 -0
  377. package/src/bongos/routes/instance.js +15 -3
  378. package/src/bongos/routes/me.js +35 -1
  379. package/src/bongos/routes.js +2 -0
  380. package/src/bongos/serve-internal.js +84 -15
  381. package/src/branding.js +49 -2
  382. package/src/instance-config.js +46 -0
  383. package/src/module-api.js +140 -1
  384. package/src/platform-server.js +86 -9
  385. package/tests/abandon_task.mjs +59 -3
  386. package/tests/api_cli_flags.mjs +53 -0
  387. package/tests/auth_page_gate.mjs +13 -0
  388. package/tests/backfill_sessions.mjs +127 -1
  389. package/tests/backup_cli.mjs +54 -0
  390. package/tests/bongos_box_connect.mjs +77 -0
  391. package/tests/box_access.mjs +130 -1
  392. package/tests/box_credential.mjs +125 -0
  393. package/tests/box_host_keys.mjs +24 -0
  394. package/tests/box_infra_resolve.mjs +149 -0
  395. package/tests/box_scope_session.mjs +6 -2
  396. package/tests/box_sync.mjs +55 -0
  397. package/tests/box_task_scope.mjs +99 -0
  398. package/tests/branding.mjs +41 -23
  399. package/tests/cf_ruleset_preflight.mjs +142 -0
  400. package/tests/cf_tunnel.mjs +37 -0
  401. package/tests/claim_gate_rebase.mjs +98 -0
  402. package/tests/clawback_confirmed_backlog.mjs +103 -0
  403. package/tests/cli_lib_formatters.mjs +20 -0
  404. package/tests/confirm_attribution.mjs +30 -46
  405. package/tests/credit_grant.mjs +198 -10
  406. package/tests/criterion_authoring_gate.mjs +272 -0
  407. package/tests/criterion_progress.mjs +33 -1
  408. package/tests/dev_lib.mjs +253 -0
  409. package/tests/devbox_artifact_gate.mjs +75 -0
  410. package/tests/devbox_dmg_backdrop.mjs +137 -0
  411. package/tests/devbox_icons.mjs +304 -0
  412. package/tests/devbox_installer_brand.mjs +232 -0
  413. package/tests/devbox_key_register.mjs +234 -0
  414. package/tests/docs_openapi_route.mjs +110 -0
  415. package/tests/doctor_hooks.mjs +141 -0
  416. package/tests/extract_json.mjs +140 -0
  417. package/tests/fitness.mjs +89 -0
  418. package/tests/gen_freshness.mjs +96 -0
  419. package/tests/github_repos_helpers.mjs +91 -0
  420. package/tests/github_token_store.mjs +121 -0
  421. package/tests/goal_advisory.mjs +251 -0
  422. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  423. package/tests/goal_routes.mjs +59 -4
  424. package/tests/goal_tier.mjs +12 -3
  425. package/tests/governance_catalog.mjs +129 -0
  426. package/tests/governance_claim_eligibility.mjs +262 -0
  427. package/tests/governance_config.mjs +187 -0
  428. package/tests/governance_ownership_scope.mjs +410 -0
  429. package/tests/governance_page_gates.mjs +324 -0
  430. package/tests/governance_parity.mjs +336 -0
  431. package/tests/governance_principals.mjs +232 -0
  432. package/tests/governance_protected_surfaces.mjs +208 -0
  433. package/tests/governance_require_permission.mjs +223 -0
  434. package/tests/governance_resolver.mjs +84 -0
  435. package/tests/governance_role_sync.mjs +231 -0
  436. package/tests/governance_seed.mjs +127 -0
  437. package/tests/governance_session_scope.mjs +434 -0
  438. package/tests/governance_vanilla_boot.mjs +203 -0
  439. package/tests/grade_attribution.mjs +7 -7
  440. package/tests/hall_audit.mjs +223 -0
  441. package/tests/hall_nav.mjs +191 -0
  442. package/tests/hall_palette.mjs +206 -0
  443. package/tests/hall_signout.mjs +124 -0
  444. package/tests/hook_user_agents.mjs +10 -0
  445. package/tests/idea_triage.mjs +162 -0
  446. package/tests/idp_device_exchange.mjs +198 -0
  447. package/tests/idp_federation.mjs +100 -0
  448. package/tests/init.mjs +51 -0
  449. package/tests/instance_config.mjs +65 -0
  450. package/tests/instance_mismatch_guard.mjs +23 -6
  451. package/tests/instance_release_config.mjs +104 -0
  452. package/tests/linkify_refs.mjs +15 -2
  453. package/tests/migrations_forward_safe.mjs +86 -0
  454. package/tests/module_api.mjs +1 -1
  455. package/tests/module_contributions.mjs +55 -0
  456. package/tests/module_loader.mjs +10 -5
  457. package/tests/module_scope_active_claims.mjs +94 -0
  458. package/tests/needs_rebase.mjs +92 -0
  459. package/tests/one_active_claim_per_session.mjs +76 -0
  460. package/tests/override_attribution.mjs +10 -8
  461. package/tests/override_request_ownership.mjs +8 -4
  462. package/tests/package_core.mjs +246 -1
  463. package/tests/parse_cookie_decode.mjs +42 -0
  464. package/tests/pay_on_land.mjs +129 -0
  465. package/tests/platform_boot.mjs +100 -1
  466. package/tests/post_login_landing.mjs +42 -0
  467. package/tests/preflight_checks.mjs +72 -0
  468. package/tests/provision.mjs +289 -7
  469. package/tests/pruned_lockfile_integrity.mjs +79 -0
  470. package/tests/publish_branch_route.mjs +53 -0
  471. package/tests/publish_reconciler.mjs +187 -2
  472. package/tests/repo_info_binding.mjs +248 -0
  473. package/tests/reward_gate.mjs +11 -2
  474. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  475. package/tests/reward_mode_surfacing.mjs +168 -0
  476. package/tests/route_permission_check.mjs +301 -0
  477. package/tests/route_rank_check.mjs +254 -12
  478. package/tests/route_validation.mjs +30 -0
  479. package/tests/sequence.mjs +267 -0
  480. package/tests/session_digest.mjs +44 -0
  481. package/tests/session_index.mjs +18 -6
  482. package/tests/session_records.mjs +39 -1
  483. package/tests/session_reward_on_land.mjs +381 -0
  484. package/tests/session_reward_reconcile.mjs +229 -0
  485. package/tests/ship_api_client_pathspec.mjs +100 -0
  486. package/tests/ship_base_flag.mjs +93 -0
  487. package/tests/ship_ci_deploy.mjs +140 -3
  488. package/tests/ship_upstream_deletion.mjs +57 -0
  489. package/tests/smoke_target.mjs +233 -0
  490. package/tests/start_env_guard.mjs +87 -0
  491. package/tests/start_rebase_warning.mjs +103 -0
  492. package/tests/status_mirror_sync.mjs +122 -0
  493. package/tests/stop_refcheck.mjs +19 -1
  494. package/tests/task_goal_link.mjs +15 -6
  495. package/tests/upgrade.mjs +393 -5
  496. package/tests/web_admission_status.mjs +162 -0
  497. package/tests/write_validation_gaps.mjs +110 -0
  498. package/.gitignore +0 -91
  499. package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +0 -94
  500. package/docs/adr/0140-cloudbongos-standalone-reprovision.md +0 -43
  501. package/scripts/hall-preview/fixtures/access-requests.json +0 -20
  502. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  503. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  504. package/scripts/hall-preview/fixtures/audit-log.json +0 -68
  505. package/scripts/hall-preview/fixtures/blockers__detail.json +0 -12
  506. package/scripts/hall-preview/fixtures/box__me.json +0 -5
  507. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -69
  508. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  509. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  510. package/scripts/hall-preview/fixtures/builders__roster.json +0 -48
  511. package/scripts/hall-preview/fixtures/goals.json +0 -502
  512. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  513. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  514. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  515. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  516. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  517. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  518. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  519. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  520. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -32
  521. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  522. package/scripts/hall-preview/fixtures/inbox__detail.json +0 -15
  523. package/scripts/hall-preview/fixtures/instance.json +0 -124
  524. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  525. package/scripts/hall-preview/fixtures/me.json +0 -476
  526. package/scripts/hall-preview/fixtures/me__art-key__own.json +0 -6
  527. package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +0 -209
  528. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  529. package/scripts/hall-preview/fixtures/me__render.json +0 -5
  530. package/scripts/hall-preview/fixtures/me__skill-prefs.json +0 -143
  531. package/scripts/hall-preview/fixtures/me__sound-prefs.json +0 -67
  532. package/scripts/hall-preview/fixtures/me__wandering.json +0 -43
  533. package/scripts/hall-preview/fixtures/override-requests.json +0 -15
  534. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  535. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  536. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  537. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  538. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  539. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  540. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  541. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  542. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  543. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  544. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  545. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  546. package/scripts/hall-preview/fixtures/security__docs.json +0 -10
  547. package/scripts/hall-preview/fixtures/security__reports.json +0 -31
  548. package/scripts/hall-preview/fixtures/sessions__search.json +0 -9
  549. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  550. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  551. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  552. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  553. package/scripts/hall-preview/fixtures/versions.json +0 -89
@@ -0,0 +1,110 @@
1
+ // tests/write_validation_gaps.mjs — the three write routes the old route scanner
2
+ // could not see (BV1.R109c, task 1002552).
3
+ //
4
+ // ADR 0118 / R12 requires every body-reading write route to call validateOrRespond.
5
+ // Three routes were exempt not by decision but by accident: the route-discovery
6
+ // regex required the method and path on the SAME line, and these three are declared
7
+ // multi-line, so the fitness check never saw them. BV1.R109b fixed discovery and
8
+ // recorded them in a named, non-growing WRITE_VALIDATION_BASELINE; this closes them
9
+ // and empties that list.
10
+ //
11
+ // The risk being guarded here is NOT "is there a schema" (fitness asserts that) but
12
+ // "does the schema still accept exactly what the live contract accepted". Each route
13
+ // hand-coerced its one field, so a too-strict schema would silently break a caller.
14
+ import assert from 'node:assert/strict';
15
+ import { test } from 'node:test';
16
+ import { createRequire } from 'node:module';
17
+ import fs from 'node:fs';
18
+ import path from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ const require = createRequire(import.meta.url);
22
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
23
+ const read = (p) => fs.readFileSync(path.join(ROOT, p), 'utf8');
24
+
25
+ test('the baseline is empty — the invariant is back to hard-zero', () => {
26
+ const fit = require(path.join(ROOT, 'scripts', 'gds', 'fitness.js'));
27
+ const baseline = fit.WRITE_VALIDATION_BASELINE;
28
+ if (baseline !== undefined) {
29
+ assert.equal(baseline.size, 0, `still-exempt write routes: ${[...baseline].join(', ')}`);
30
+ } else {
31
+ // Deleted outright rather than emptied — also acceptable, and the fitness
32
+ // check below is the real assertion either way.
33
+ assert.doesNotMatch(read('scripts/gds/fitness.js'), /'POST \/inbox\/:id\/ratify'/,
34
+ 'the ratify entry must be gone from the baseline');
35
+ }
36
+ });
37
+
38
+ test('fitness reports ZERO unvalidated write routes', () => {
39
+ const fit = require(path.join(ROOT, 'scripts', 'gds', 'fitness.js'));
40
+ assert.equal(typeof fit.scanUnvalidatedWriteRoutes, 'function',
41
+ 'the scanner must stay exported so this cannot silently stop being checked');
42
+ const unvalidated = fit.scanUnvalidatedWriteRoutes();
43
+ assert.deepEqual(unvalidated, [], `unvalidated write routes: ${JSON.stringify(unvalidated)}`);
44
+ });
45
+
46
+ test('each of the three routes now calls validateOrRespond', () => {
47
+ const inbox = read('modules/ideas/routes/inbox.js');
48
+ const reports = read('modules/security/routes/reports.js');
49
+ // ratify
50
+ const ratify = inbox.slice(inbox.indexOf("'/inbox/:id/ratify'"));
51
+ assert.match(ratify.slice(0, 900), /validateOrRespond\(req, res, \{[\s\S]*notes_md/, 'ratify must validate notes_md');
52
+ // confirm
53
+ const confirm = reports.slice(reports.indexOf("'/security/reports/:id/confirm'"));
54
+ assert.match(confirm.slice(0, 1200), /validateOrRespond\(req, res, \{[\s\S]*drachmae_awarded/, 'confirm must validate drachmae_awarded');
55
+ // link-fix
56
+ const linkFix = reports.slice(reports.indexOf("'/security/reports/:id/link-fix'"));
57
+ assert.match(linkFix.slice(0, 1200), /validateOrRespond\(req, res, \{[\s\S]*task_id/, 'link-fix must validate task_id');
58
+ });
59
+
60
+ // ---- contract preservation: the schemas must not narrow what was accepted ----
61
+ //
62
+ // These assert the SHAPE of each declaration, because the live coercion happens in
63
+ // the handler and a type= on the schema would pre-empt it. A regression here means
64
+ // a caller that worked yesterday starts getting a 400.
65
+
66
+ test('drachmae_awarded stays UNTYPED — number, stringified number, "" and null all still reach the handler', () => {
67
+ const reports = read('modules/security/routes/reports.js');
68
+ const confirm = reports.slice(reports.indexOf("'/security/reports/:id/confirm'"), reports.indexOf("'/security/reports/:id/dispute'"));
69
+ assert.match(confirm, /drachmae_awarded:\s*\{\s*\}/,
70
+ 'declaring a type would reject the stringified/"" forms the handler accepts and coerces');
71
+ // The inline check remains the thing that enforces finite/non-negative.
72
+ assert.match(confirm, /Number\.isFinite\(n\)/, 'the handler-side numeric check must survive');
73
+ assert.match(confirm, /bad_drachmae_awarded/, 'its error code must be unchanged');
74
+ });
75
+
76
+ test('task_id stays REQUIRED but untyped — the stringified form still works', () => {
77
+ const reports = read('modules/security/routes/reports.js');
78
+ const linkFix = reports.slice(reports.indexOf("'/security/reports/:id/link-fix'"));
79
+ assert.match(linkFix, /task_id:\s*\{\s*required:\s*true\s*\}/,
80
+ 'same idiom as POST /tasks/:id/dependencies — required, coerced in-handler');
81
+ assert.match(linkFix, /Number\.isInteger\(taskId\)/, 'the handler-side integer check must survive');
82
+ assert.match(linkFix, /bad_task_id/, 'its error code must be unchanged');
83
+ });
84
+
85
+ test('notes_md stays OPTIONAL — a ratify with no body still works', () => {
86
+ const inbox = read('modules/ideas/routes/inbox.js');
87
+ const ratify = inbox.slice(inbox.indexOf("'/inbox/:id/ratify'"));
88
+ const decl = ratify.slice(0, 900);
89
+ assert.doesNotMatch(decl, /notes_md:\s*\{[^}]*required:\s*true/,
90
+ 'notes_md was optional (absent => empty string) and must stay optional');
91
+ assert.match(ratify, /typeof req\.body\.notes_md === 'string'/,
92
+ 'the absent-to-empty-string coercion must survive');
93
+ });
94
+
95
+ test('validation runs BEFORE the handler consumes the field', () => {
96
+ // A schema declared after the read would validate nothing on the path that matters.
97
+ for (const [file, route, field] of [
98
+ ['modules/ideas/routes/inbox.js', "'/inbox/:id/ratify'", 'notes_md'],
99
+ ['modules/security/routes/reports.js', "'/security/reports/:id/link-fix'", 'task_id'],
100
+ ]) {
101
+ const src = read(file);
102
+ const body = src.slice(src.indexOf(route));
103
+ const validateAt = body.indexOf('validateOrRespond');
104
+ const readAt = body.indexOf(`req.body?.${field}`) >= 0
105
+ ? body.indexOf(`req.body?.${field}`)
106
+ : body.indexOf(`req.body.${field}`);
107
+ assert.ok(validateAt > 0 && validateAt < readAt,
108
+ `${route}: validateOrRespond must precede the req.body.${field} read`);
109
+ }
110
+ });
package/.gitignore DELETED
@@ -1,91 +0,0 @@
1
- # Dependencies
2
- node_modules/
3
-
4
- # Per-session git worktrees live under here; each is itself a git checkout
5
- # and must NEVER be committed (would create embedded-repo references).
6
- .claude/worktrees/
7
-
8
- # Environment / secrets
9
- .env
10
- .env.local
11
- .env.*.local
12
-
13
- # Google Chat OAuth credentials — must NEVER be committed.
14
- # Live on the droplet at /etc/amazonprimea/ instead.
15
- google-chat-credentials.json
16
- google-chat-refresh-token.json
17
- *.credentials.json
18
-
19
- # Build output
20
- dist/
21
- build/
22
-
23
- # Logs
24
- *.log
25
- npm-debug.log*
26
-
27
- # OS files
28
- .DS_Store
29
-
30
- # Pixel art generation artifacts (iterations are huge; keep references + finals only)
31
- modules/art-pipeline/iterations/*
32
- # ...but keep the anti-grid FFT baselines tracked (idea 27): they're tiny + the smoke suite
33
- # (tests/anti_grid.mjs) compares against them. `modules/art-pipeline/iterations/*` (not the bare
34
- # dir) lets this negation re-include the file — git can't re-include under a fully-excluded dir.
35
- !modules/art-pipeline/iterations/anti_grid_baselines.json
36
- modules/art-pipeline/generated/raw/
37
- modules/art-pipeline/generated/*/raw/
38
- # Derived from references/ via slice_references.py — easy to regenerate, no need in git
39
- modules/art-pipeline/template/ref_tiles/
40
- modules/art-pipeline/template/ref_clusters/
41
- # Autotile cross-verify snapshot — regenerated on every smoke_test run.
42
- modules/art-pipeline/pipeline/_autotile_tables.json
43
- __pycache__/
44
- *.pyc
45
-
46
-
47
- # World snapshots — generated on the droplet by scripts/snapshots/render-world.mjs.
48
- # Untracked so git reset --hard on deploy doesn't wipe them.
49
- public-status/snapshots/*.png
50
- public-status/snapshots/manifest.json
51
-
52
- # Repo Atlas data — generated on the droplet by scripts/gds/gen-atlas.js on every
53
- # deploy (ADR 0094). Untracked so git reset --hard doesn't wipe it; the deploy
54
- # step rewrites it fresh each time, so a committed copy would only go stale.
55
- # (The hall surface carved to modules/hall-ui/public/ in BV1.R85.)
56
- modules/hall-ui/public/atlas.json
57
-
58
- # Whole-file generated navigation docs — untracked since ADR 0110 (task 1926), the
59
- # same reasoning as the atlas above. docs/repo-map.md (symbol skeleton, ADR 0063) and
60
- # docs/session-log-index.md (session index, ADR 0062 §8) are 100%-generated and were
61
- # regenerated + committed on EVERY ship, so two parallel builder branches collided on
62
- # them constantly. Untracked + regenerated at deploy (scripts/deploy/deploy-prod.sh) and
63
- # at box-source-fetch, they can never appear in a branch diff → the conflict class is
64
- # gone at the source. Their generators are dual-duty: the nested CLAUDE.md symbol blocks
65
- # and the CLAUDE.md §13 snippet stay TRACKED and CI-gated (gen-*.js --check-block).
66
- docs/repo-map.md
67
- docs/session-log-index.md
68
-
69
- # Onboarding diagram RENDERS — untracked since ADR 0110 pt.3 / ADR 0122 (task 2027),
70
- # the deferred diagram half of ADR 0110. The .svg/.png are regenerated + committed on
71
- # every render-capable ship, so parallel builder branches collided on them (same class
72
- # as the nav docs above). Untracked + re-rendered at deploy (scripts/deploy/deploy-prod.sh
73
- # runs scripts/render-diagrams.sh against the tracked .mmd, using the host's installed
74
- # Chrome — never puppeteer's own droplet-stalling download) and best-effort at
75
- # box-source-fetch. The .mmd SOURCES + assertions.json stay TRACKED (git reset --hard
76
- # restores them; the render regenerates the images from them), so the nightly
77
- # diagram-drift cron (reads assertions.json) is unaffected.
78
- docs/onboarding/diagrams/*.svg
79
- docs/onboarding/diagrams/*.png
80
-
81
- # Re-hosted #bugs screenshots (task #936). Downloaded from Discord and served
82
- # by routes/bug-attachments.js. Outside git so a deploy never wipes them.
83
- var/bug-attachments/
84
-
85
- # Custom merge-driver scratch files. The regen merge driver
86
- # (scripts/gds/git-merge-regen.js, installed by scripts/gds/install-git-hooks.js)
87
- # writes `.merge_file_*` temp files while resolving conflicts. They are pure
88
- # scratch — never source — but a `git add -A` once staged one onto main
89
- # (.merge_file_IKo9KW, merge 3e9f1f81). Ignore the pattern so it can't recur.
90
- .merge_file_*
91
- scratchpad/
@@ -1,94 +0,0 @@
1
- # ADR 0139 — Migrate the platform work-history from the Off the Boats instance DB to the cloudbongos DB
2
-
3
- - **Status:** Accepted — **MIGRATION COMPLETE 2026-07-11** (owner greenlit the production run + the cut). Load into cloudbongos + verification done; TIER-2 valuable-history sweep done; and the WS-6 clean cut **fired + verified on live amazonprimea** (now game-only). The CB↔OTB split is complete (code + data). See the **Execution record** at the end.
4
- - **Date:** 2026-07-10
5
- - **Track:** internal (platform)
6
- - **Decides:** whether — and how — the Cloud Bongos *platform* work-history (tasks, goals, done-when criteria, the credit ledger, builder identities + balances) is physically relocated from the `amazonprimea` (Off the Boats "customer zero") Postgres database to the `cloudbongos` database, so a builder signing into the cloudbongos hall with the same GitHub sees their earned balance.
7
- - **Builds on:** ADR 0103 (core-first extraction; cloud-bongos is the trunk), ADR 0108 (configurable-root; the code half), ADR 0100 §3 (per-repo GDS), ADR 0016 (server-enforced permissions / trust boundary).
8
- - **Supersedes framing of:** ADR 0107 §3, which *deferred* cross-instance identity/payout as an open question, and the goal-41 "identity federated, authority per-project" design string. This ADR is the deliberate, bounded decision those left open — see Context.
9
- - **Companion:** the **code half** of the CB↔OTB split (amazonprimea task 1728 / R89 cutover; cloud-bongos re-seeded to the authoritative source by amazonprimea task 2190). This ADR is the **data half**.
10
-
11
- ## Context
12
-
13
- Off the Boats (`amazonprimea` DB) is where Cloud Bongos itself was built — "customer zero." The R89 cutover already moved the platform **code** out: amazonprimea now consumes `@bongos/core` as a vendored dependency, and cloud-bongos is the authoritative editable core source. What remains inside the `amazonprimea` database is the platform's entire **work-history**: ~2,000+ platform tasks/goals/criteria, the credit ledger, and the builder identities that earned those credits — interleaved with the game's own ~57 tasks and game-earned credits.
14
-
15
- The requirement: a builder who signs into the cloudbongos hall with the same GitHub account should see the platform balance they earned. The platform's *own* design deliberately drew a line against this — goal-41's design says "identity is federated, authority (ranks/credits) is **not**," and ADR 0107 §3 explicitly defers cross-instance payout. So **relocating balances runs counter to that line and therefore needs its own decision record** — this ADR. It is *not* the future federation hub (goal 41), and it is not "finishing" an existing plan; it is a one-time, supervised data move.
16
-
17
- No cross-instance data-mover exists today. The only tooling is per-instance `pg_dump` backup; provisioning creates an *empty* DB; the public-mirror export moves *source code*, not data. The mover (WS-2) is therefore bespoke and is the bulk of the effort.
18
-
19
- ## Decision
20
-
21
- ### Locked decisions (owner)
22
-
23
- 1. **Clean move, not copy.** The platform history *leaves* Off the Boats. No frozen dual copy — two diverging ledgers would double-count balances and rot.
24
- 2. **Game credits stay at Off the Boats.** Everything else — platform credits, including orphan/no-task session & bonus awards — moves.
25
- 3. **Identity is keyed by `builders.github_id`** (a stable global value present in both DBs). The migrated balance surfaces automatically on the builder's *existing* per-instance GitHub sign-in — **no federation hub is required**.
26
- 4. **Currency: the number moves, the label adapts.** The reward unit is the integer `credits`; the label ("drachmae" at OTB, "credits" at the neutral starter) is pure instance config (`branding.currency.label`, ADR-referenced `<redacted>`). A 1,000 balance arrives as 1,000 in cloudbongos's unit automatically. *(Open: whether cloudbongos relabels to "drachmae" — see Open Questions.)*
27
- 5. **The cloudbongos DB is near-empty → clean load, not a merge.** Only `lars589` (auto-seated founding Archon) and one CB-V1 test task exist; preserve them.
28
- 6. **The ETL runs one-time, supervised, from the owner's Mac over SSH**, reaching both droplets' databases. It is not a builder-facing tool.
29
-
30
- ### Classification is decided at the version level
31
-
32
- Every task/goal/criterion/credit inherits its **version's** label. `versions.id` is a text PK, so version rows copy without renumbering.
33
-
34
- | MOVE → cloudbongos (platform) | STAY at Off the Boats (game) |
35
- |---|---|
36
- | PMS-V1, PMS-V2, GDS-V3, GDS-V4 → BONGOS-V1 and all their tasks/goals/criteria/credits | Off the Boats V1/V2/V3 and their tasks/goals/pixel-art |
37
- | The dependency graph among those records | Credits earned on game work |
38
- | A copy of each builder identity (keyed by github_id) carrying the platform balance | The live game world + Colyseus server (untouched) |
39
-
40
- Edge cases: work that *built* the art pipeline = platform (moves); *running* it to draw tiles = game (stays) — WS-1 includes a human review pass. Orphan credits (`task_id = NULL`) move with the platform (reversible if the owner disagrees).
41
-
42
- ## Workstreams (filed under switchover goal 26; execution owner-gated)
43
-
44
- - **WS-0 — Re-provision cloudbongos.com onto core 1.17.3 on a fresh DB, FIRST.** The box still runs a lift-and-shift clone whose deploy script references R89-removed paths; a re-provision *after* a load would wipe it. Must precede any data load. Preserve/re-seat the `lars589` Archon.
45
- - **WS-1 — Label every version game vs platform** (the single line that decides the move-set) + human pass over art-pipeline-style edge cases.
46
- - **WS-2 — Build the one-time mover (most effort).** Renumber bigint PKs; match builders by `github_id`; remap every FK; handle the polymorphic `dependencies` table per-kind; load with sync/promotion triggers OFF; preserve the `credit_log` idempotency key. **Prove on a throwaway copy first — never run blind on live.**
47
- - **WS-3 — This ADR.**
48
- - **WS-4 — Move day (OWNER GREENLIGHT REQUIRED).** Brief platform-write freeze at amazonprimea; full DB snapshots of both sides; run the mover into cloudbongos; rebuild balances from the ledger. Still reversible — amazonprimea untouched until WS-6.
49
- - **WS-5 — Prove it.** Reconcile record counts both sides; sample balances to the drachma; and the real test — a live GitHub sign-in at cloudbongos shows the right person with the right balance.
50
- - **WS-6 — Clean cut at Off the Boats.** Only after WS-5: delete the moved records from amazonprimea (reverse FK/dependency order), rebuild amazonprimea balances to game-only, repoint platform doc-links to cloudbongos.
51
- - **WS-7 — Close the switchover.** Tie off the goal; tell builders where their history now lives.
52
-
53
- ## DB mechanics (the production hazards the mover must respect)
54
-
55
- - **Schema lives in `@bongos/core`** under `package/migrations/*.sql` (not in the amazonprimea repo anymore). `003_pms.sql` is foundational.
56
- - **Bigserial PK collision.** Both DBs allocate 1,2,3…; a naive copy collides on PK and *silently mis-links* FKs. Collide: `builders/tasks/claims/goals/credit_log/cost_log/karma_log/done_when_criteria/builder_sessions/idea_inbox/learnings/goal_membership_requests/core_upgrades`. Only text/natural PKs copy cleanly (`versions`, `achievements`). People are re-keyed off the natural `builders.github_id` (UNIQUE); everything else gets a fresh offset, and **every FK is rewritten** to the remapped ids.
57
- - **Polymorphic `dependencies` table — highest risk.** `(from_kind, from_id, to_kind, to_id)` over {task, goal, criterion} has **NO foreign keys** — ids are bare bigints disambiguated only by `*_kind`. The mover must remap `from_id`/`to_id` **per-kind**, or edges silently repoint. (The older `020_task_dependencies` task→task list also needs remapping.)
58
- - **`credit_log` double-count trap.** `credit_log` is an append-only ledger; `builders.total_credits` is a trigger-maintained cache (`trg_credit_log_apply` → `+= delta` on INSERT). Authoritative balance = `SUM(credit_log.delta)` per builder. **Load with triggers OFF, then rebuild `total_credits` from `SUM(delta)`** — else balances double. Same shape for `karma_log` → `builders.karma`.
59
- - **Idempotency key must be preserved.** A partial unique index on `credit_log(session_id) WHERE reason='session.token_reward'` enforces one token-reward payout per session. If the index or `session_id` values are lost, the token-reward path **double-pays on replay**.
60
- - **Promotion triggers also fire on status writes** (auto-promote backlog→ready on ship/satisfy/achieve). Load with all triggers disabled, then re-enable.
61
-
62
- ## Consequences
63
-
64
- - **Positive:** the platform's work-history + rewards live at their true home; builders keep their earned balance across the sign-in they already use; the CB↔OTB separation is completed (data + code); no standing federation infrastructure is incurred.
65
- - **Reversibility:** everything through WS-5 is reversible — amazonprimea is untouched until WS-6, and both sides are snapshotted on move day. The point of no return is WS-6 (the clean cut).
66
- - **Risk:** a mistimed trigger or a missed FK/idempotency remap corrupts balances. Mitigation: prove the mover on a throwaway clone (WS-2), triggers-off load + ledger rebuild (WS-4), and full reconciliation before the cut (WS-5).
67
-
68
- ## Open questions (owner)
69
-
70
- 1. Confirm the exact game/platform version line (the single decision that fixes the move-set).
71
- 2. Currency label at cloudbongos — keep "credits" or relabel to "drachmae" (one-line config; balances identical either way).
72
- 3. Confirm tracking home for WS-0…WS-7 (proposed: switchover goal 26).
73
- 4. Greenlight to *execute* (WS-4 onward) — nothing runs against production until then.
74
- 5. WS-0 reality check — confirm cloudbongos.com was fully re-provisioned onto core 1.17.3 on a fresh DB, not merely code-updated.
75
- 6. Orphan credits (`task_id = NULL`) — confirm the "move with platform" rule.
76
-
77
- ### Open questions — RESOLVED (owner, 2026-07-11)
78
-
79
- 1. Version line: **game V1/V2/V3 stay; PMS-V1, PMS-V2, GDS-V3, GDS-V4, BONGOS-V1 move** (as tabled). 2. Currency: **keep label "credits" at cloudbongos, 1:1 with drachmae** (no relabel). 3. Tracking home: **cloudbongos**. 4. **Greenlight given** — execute through production. 5. WS-0 reality check delegated to the executor → **verified: cloudbongos.com already runs @bongos/core 1.17.4 on the dependency model; no re-provision performed** (would have wiped legit native data). 6. Orphan credits: **move with platform** (confirmed).
80
-
81
- ## Execution record (2026-07-11)
82
-
83
- Executed from the cloudbongos droplet (the ETL host): reads amazonprimea via the live `cohost-db-tunnel` (`127.0.0.1:5433`), writes the local cloudbongos DB. Scripts + full snapshots persist at `/home/lars/mig/` (`mover.js`, `verify.js`, `cut.js`, both pg_dumps, a pre-load cloudbongos snapshot). Tracked as amazonprimea switchover tasks 2192–2198.
84
-
85
- - **WS-0 (2192):** verified already-provisioned (core 1.17.4); no re-provision.
86
- - **WS-1 (2193):** per-table move-set classified (14 platform-history tables; ~50 OTB-instance-infra tables correctly stay).
87
- - **WS-2 (2194):** mover built (Node ETL: +1,000,000 PK offset; builders merged by `github_id`; versions upsert; deletes the target's core-seeded placeholder platform goals/criteria first; triggers-off load then rebuild `total_credits`/`karma` from `SUM(delta)`; `credit_log` `ON CONFLICT` on the token-reward partial index `DO NOTHING`). **Rehearsed on a throwaway copy: 25/25 checks pass.**
88
- - **WS-4 (2195):** **live load into cloudbongos COMMITTED** — 1,865 tasks, 27 goals, 69 criteria, 1,678 claims, 1,373 credit rows (1 token-reward idempotency skip), + full history; FK-check clean. Pre-load snapshot taken; amazonprimea untouched (fully reversible).
89
- - **WS-5 (2196):** **verified on live cloudbongos — 25/25.** All table counts + all six builder balances reconcile (lars589 **37,072**; jaxri 5,341; scootermack 2,389; IAMMASTERQUA 195; LarsCode 44; kingaonline 36). Game/native preserved; 0 FK orphans. `cloudbongos.com` leaderboard serves the migrated builders.
90
- - **WS-5b (2199) — TIER-2 valuable sweep (post-audit):** a full 59-table completeness audit confirmed the core move was 100% complete (2 flagged gaps were false positives), and surfaced ~13k deferred TIER-2 rows. Owner chose the valuable sweep → `sweep2.js` carried builder_memory, grading history, session_records/BFG, vulnerability_reports, builder_sessions (tokens redacted; restored 1,442 nulled claim links), + governance rows to cloudbongos; **verified 18/18**. Only the rebuildable `search_chunks` retrieval index was intentionally skipped.
91
- - **WS-6 (2197) — clean cut: FIRED + verified on live amazonprimea.** Pre-fire review found the first-draft cut too aggressive (it would delete live-game learnings/ideas/blockers), so it was rewritten **surgical** (`cut2.js`): deletes only platform-version-scoped work + the platform/orphan credit ledger, and preserves game + unlinked methodology, karma, builder-level tables, and all auth/game data. Run as the non-superuser app user (no trigger-disable) with children-before-parents + FK enforcement (safer). Rehearsed clean on a fresh copy, then fired after a final backup. Result: amazonprimea is game-only (versions V1/V2/V3, 157 game tasks, 123 game claims + auth intact, lars589 38,919→**1,824**, ledger reconciles, 0 platform residue, 0 FK orphans, app healthy).
92
- - **WS-7 (2198):** data + cut complete. Sole remaining owner step: announce to builders (Discord) where their history now lives.
93
-
94
- **Notes:** the migration's own bookkeeping tasks (2192–2199, all BONGOS-V1) moved to cloudbongos and were then removed from amazonprimea by the cut — self-referential, expected; their record lives here + in session memory. The 56-credit token-reward for the shared session `1b57dcb4` is dropped by the idempotency skip. Minor residue intentionally kept on amazonprimea (harmless, also on cloudbongos): platform karma, unlinked ideas/learnings, and vuln/achievement rows with nulled platform refs. Doc-links to platform tasks in the OTB repo now resolve on the cloudbongos hall. Scripts + backups: `/home/lars/mig/` on the cloudbongos droplet.
@@ -1,43 +0,0 @@
1
- # ADR 0140 — cloudbongos.com re-provisioned to the standalone model, DB-preserving (closes ADR 0139 WS-0)
2
-
3
- - **Status:** Accepted — executed 2026-07-12
4
- - **Date:** 2026-07-12
5
- - **Deciders:** Lars (owner)
6
- - **Track:** internal (platform / infra)
7
- - **Builds on:** ADR 0108 (configurable-root / standalone consumer model), ADR 0126 (dedicated cloudbongos.com droplet), ADR 0129 (pull-timer deploy), ADR 0139 (CB↔OTB data migration — this closes its WS-0)
8
-
9
- ## Context
10
-
11
- cloudbongos.com ran as a **lift-and-shift clone of the `amazonprimea` game repo** (ADR 0126): the `cloudbongos` systemd service executed `src/platform-server.js` out of `/home/lars/cloudbongos` (a checkout whose `origin` was `lars589/amazonprimea`), branded via `GDS_BRANDING_FILE`, against the separate `cloudbongos` DB.
12
-
13
- ADR 0139's **WS-0** called for re-provisioning cloudbongos.com onto the ADR 0108 standalone `@bongos/core` model *first, on a fresh DB*. WS-0 was recorded as "verified already-provisioned; no re-provision performed" — but that verification was wrong: the box kept running the amazonprimea clone. The data-half workstreams (WS-4/5/6) then loaded the platform history into the `cloudbongos` DB and cut OTB.
14
-
15
- The gap surfaced on 2026-07-12: `builders.cloudbongos.com` served a bare, unstyled shell — every `/builders/*` asset 404'd. Root cause: the running process was frozen on stale amazonprimea code (its pull-deploy silently no-op'd because `origin` tracked the unchanged amazonprimea repo, not a cloudbongos instance). The site had **never run the restored code**.
16
-
17
- The key constraint that inverts WS-0's original plan: the `cloudbongos` DB is now **full** — the migrated work-history and credit balances (e.g. `lars589` = 37,072). WS-0's "fresh DB" re-provision would wipe it. So the re-provision had to be **DB-preserving**.
18
-
19
- ## Decision
20
-
21
- We will convert cloudbongos.com to a proper ADR 0108 **standalone instance**, preserving the existing `cloudbongos` DB, via a **build-alongside-then-flip** procedure:
22
-
23
- 1. **Its own instance repo** — `cloudbongos/cloudbongos-instance` (private): lean `config/` (`branding.json` = the real cloudbongos.com domains over the neutral "Cloud Bongos" brand; `modules.json` = game-less + `provisioning`), a `bongos.config.json` instance-root pointer, and a **pinned `@bongos/core@1.17.3`** dependency. The engine, hall, and all platform code come from the package.
24
- 2. **Materialize beside the old checkout** — clone + `npm ci` into a new dir (`/home/lars/cloudbongos-instance`); the old `/home/lars/cloudbongos` stays untouched as rollback.
25
- 3. **Prove before flipping** — boot on a spare port against the live DB; confirm the hall serves and the leaderboard reads migrated balances; confirm `migrate` is a **no-op** (the DB already carries all 112 of 1.17.3's migrations).
26
- 4. **Flip the service** — `cloudbongos.service` `WorkingDirectory` → the instance, `ExecStart` → `node_modules/@bongos/core/src/platform-server.js`; drop `GDS_BRANDING_FILE`; add `CLOUDBONGOS_INSTANCE_ROOT`; keep `PGDATABASE` + OAuth via `/etc/cloudbongos/web.env`. Back up the old unit first.
27
- 5. **Repoint the ADR 0129 pull-deploy** — rewrite `/home/lars/deploy.sh` to fetch/reset the instance repo → `npm ci` (lockfile-gated) → core-package `migrate` → restart → healthz.
28
-
29
- The engine **source stays authoritative at `lars589/cloud-bongos`** (not relocated); the instance consumes `@bongos/core` from npm. A **verified DB backup precedes all changes**, and the old checkout + old unit + old deploy script are retained for instant rollback.
30
-
31
- ## Alternatives considered
32
-
33
- - **Run cloudbongos.com directly from the `cloud-bongos` engine repo.** Rejected: it forces one host's identity into the shared/authoritative engine (the very anti-pattern that entangled cloudbongos with the amazonprimea repo), and it would ride the engine's development `main` with no stable pin — any work-in-progress commit could take the live site down.
34
- - **Keep the amazonprimea lift-and-shift; just restart / repoint that checkout.** Rejected: leaves the intended standalone model unfinished and keeps cloudbongos coupled to the OTB repo.
35
- - **Vanilla WS-0 (fresh-DB re-provision).** Rejected now: it would wipe the freshly-migrated history and balances — the whole point of ADR 0139. Hence the DB-preserving variant.
36
- - **Reuse an existing repo for the site** — `cloud-bongos` (the engine) or `cloudbongos/bongos` (the public AGPL source mirror). Rejected: both hold load-bearing roles; a dedicated `cloudbongos/cloudbongos-instance` keeps host identity out of both.
37
-
38
- ## Consequences
39
-
40
- - cloudbongos.com runs the clean standalone model: hall renders, all three hosts (apex/builders/status) healthy, DB + balances intact. Future platform updates are a one-line `@bongos/core` pin bump, auto-deployed within ~2 min by the repointed pull-timer.
41
- - **Closes ADR 0139 WS-0** (belatedly, in DB-preserving form).
42
- - Deploy keys had to be **enabled org-wide on the `cloudbongos` org** so the box's read-only deploy key could attach to an org repo (they were disabled by default).
43
- - Follow-ups (non-blocking): retire `/home/lars/cloudbongos` + the backups after a soak; version `/home/lars/deploy.sh` into the instance repo and restore the ADR 0129 self-heal step; the packaged engine's `CORE_VERSION` constant lags its `package.json` (reports 1.17.2 while running 1.17.3) — cosmetic, flag upstream.
@@ -1,20 +0,0 @@
1
- {
2
- "requests": [
3
- {
4
- "id": "901",
5
- "display_name": "Preview Applicant",
6
- "github_login": "preview-applicant",
7
- "note": "Synthetic access request for the preview harness.",
8
- "created_at": "2026-07-08T14:02:00.000Z",
9
- "status": "pending"
10
- },
11
- {
12
- "id": "902",
13
- "display_name": null,
14
- "github_login": "sample-builder",
15
- "note": null,
16
- "created_at": "2026-07-09T09:41:00.000Z",
17
- "status": "pending"
18
- }
19
- ]
20
- }
@@ -1,76 +0,0 @@
1
- {
2
- "achievements": [
3
- {
4
- "id": "first-ship",
5
- "name": "First Ship",
6
- "description": "Ship your first task.",
7
- "icon": "📦",
8
- "credit_bonus": 1,
9
- "sort_order": 10
10
- },
11
- {
12
- "id": "first-claim",
13
- "name": "First Claim",
14
- "description": "Claim your first task.",
15
- "icon": "🪙",
16
- "credit_bonus": 1,
17
- "sort_order": 20
18
- },
19
- {
20
- "id": "first-parallel-claim",
21
- "name": "First Parallel Claim",
22
- "description": "Hold two simultaneous claims; ship both successfully.",
23
- "icon": "⚓",
24
- "credit_bonus": 2,
25
- "sort_order": 30
26
- },
27
- {
28
- "id": "streak-3",
29
- "name": "Streak: 3 Nights",
30
- "description": "Ship a task in 3 consecutive local-time nights (>=15min; cleanup/refactor now counts).",
31
- "icon": "🔥",
32
- "credit_bonus": 2,
33
- "sort_order": 40
34
- },
35
- {
36
- "id": "streak-7",
37
- "name": "Streak: 7 Nights",
38
- "description": "Ship a task in 7 consecutive local-time nights (>=15min; cleanup/refactor now counts).",
39
- "icon": "🌋",
40
- "credit_bonus": 5,
41
- "sort_order": 50
42
- },
43
- {
44
- "id": "art-pipeline-shipper",
45
- "name": "Art Pipeline Shipper",
46
- "description": "Ship a task whose touches[] include the art/ pipeline.",
47
- "icon": "🎨",
48
- "credit_bonus": 2,
49
- "sort_order": 60
50
- },
51
- {
52
- "id": "subtractor",
53
- "name": "Subtractor",
54
- "description": "Earn the net-negative ship bonus on 3 ships — across your work you have deleted more than you have added.",
55
- "icon": "🪓",
56
- "credit_bonus": 2,
57
- "sort_order": 65
58
- },
59
- {
60
- "id": "gds-shipper",
61
- "name": "GDS Shipper",
62
- "description": "Ship a task whose touches[] include src/gds/ or scripts/gds/.",
63
- "icon": "⚙️",
64
- "credit_bonus": 2,
65
- "sort_order": 70
66
- },
67
- {
68
- "id": "breaking-the-100c-bar",
69
- "name": "Breaking the 100c Bar",
70
- "description": "Cross 100 total credits.",
71
- "icon": "💯",
72
- "credit_bonus": 5,
73
- "sort_order": 80
74
- }
75
- ]
76
- }