@bongos/core 1.18.3 → 1.18.19

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 (471) hide show
  1. package/.bongos-core.json +1576 -286
  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 +4 -2
  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 +6 -1
  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/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  27. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  28. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  29. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  30. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  31. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  32. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  33. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  34. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  35. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  36. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  37. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  38. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  39. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  40. package/docs/adr/README.md +10 -0
  41. package/docs/api/openapi.json +843 -17
  42. package/docs/api-reference.md +23 -10
  43. package/docs/architecture.md +4 -2
  44. package/docs/branding-contract.md +3 -1
  45. package/docs/canonical-permissions.md +21 -8
  46. package/docs/file-map.md +8 -0
  47. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  48. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  49. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  50. package/docs/onboarding/diagrams/assertions.json +4 -7
  51. package/docs/onboarding/drachmae-and-karma.md +3 -3
  52. package/docs/onboarding/primer.md +17 -16
  53. package/docs/onboarding/slash-commands.md +124 -0
  54. package/docs/recipes/builder-box-lifecycle.md +23 -0
  55. package/docs/recipes/devbox-app-release.md +14 -4
  56. package/docs/recipes/instance-first-run.md +16 -0
  57. package/docs/recipes/local-dev.md +81 -0
  58. package/docs/recipes/ops-gotchas.md +19 -1
  59. package/docs/recipes/overnight-builder.md +1 -1
  60. package/docs/recipes/parallel-goal-waves.md +174 -0
  61. package/docs/recipes/ship-and-regrade.md +2 -2
  62. package/docs/recipes/standalone-live-docs.md +48 -0
  63. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  64. package/migrations/003_pms.sql +6 -7
  65. package/migrations/006_pms_v2.sql +3 -31
  66. package/migrations/core_193_task_needs_rebase.sql +28 -0
  67. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  68. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  69. package/migrations/core_196_session_reward_topup.sql +69 -0
  70. package/modules/autonomy/pollers/routine-timers.js +9 -8
  71. package/modules/builder-settings/wandering-prefs.js +61 -18
  72. package/modules/dev-box/app/README.md +73 -0
  73. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  74. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  75. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  76. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  77. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  78. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  79. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  80. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  81. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  82. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  83. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  84. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  85. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  86. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  87. package/modules/dev-box/app/build-resources/icon.png +0 -0
  88. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  89. package/modules/dev-box/app/electron-builder.yml +95 -0
  90. package/modules/dev-box/app/package-lock.json +5291 -0
  91. package/modules/dev-box/app/package.json +30 -0
  92. package/modules/dev-box/app/renderer/app.js +319 -0
  93. package/modules/dev-box/app/renderer/index.html +45 -0
  94. package/modules/dev-box/app/renderer/styles.css +246 -0
  95. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  96. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  97. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  98. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  99. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  100. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  101. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  102. package/modules/dev-box/app/src/box-controller.js +287 -0
  103. package/modules/dev-box/app/src/brand.generated.json +13 -0
  104. package/modules/dev-box/app/src/brand.js +16 -0
  105. package/modules/dev-box/app/src/config.js +19 -0
  106. package/modules/dev-box/app/src/gds-client.js +90 -0
  107. package/modules/dev-box/app/src/main.js +610 -0
  108. package/modules/dev-box/app/src/pairing.js +57 -0
  109. package/modules/dev-box/app/src/preload.js +29 -0
  110. package/modules/dev-box/app/src/session-store.js +58 -0
  111. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  112. package/modules/dev-box/app/src/task-picker.js +70 -0
  113. package/modules/dev-box/app/src/tray.js +99 -0
  114. package/modules/dev-box/app/src/updater.js +55 -0
  115. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  116. package/modules/dev-box/app/test/unit.mjs +526 -0
  117. package/modules/dev-box/box-access.js +121 -4
  118. package/modules/dev-box/boxes.js +20 -0
  119. package/modules/dev-box/module.json +1 -1
  120. package/modules/dev-box/routes/box.js +87 -3
  121. package/modules/economy/credits.js +116 -25
  122. package/modules/economy/reward.js +8 -0
  123. package/modules/economy/streak.js +2 -1
  124. package/modules/governance/CLAUDE.md +15 -0
  125. package/modules/governance/catalog.js +419 -0
  126. package/modules/governance/config.js +174 -0
  127. package/modules/governance/db.js +125 -0
  128. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  129. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  130. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  131. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  132. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  133. package/modules/governance/module.json +10 -0
  134. package/modules/governance/protected-surfaces.js +88 -0
  135. package/modules/governance/protected-surfaces.json +80 -0
  136. package/modules/governance/rank-roles.js +83 -0
  137. package/modules/governance/resolver.js +221 -0
  138. package/modules/governance/routes/governance.js +89 -0
  139. package/modules/governance/routes/role-sync.js +49 -0
  140. package/modules/governance/session-scopes.js +127 -0
  141. package/modules/governance/session-scopes.json +38 -0
  142. package/modules/hall-ui/public/atlas.css +117 -0
  143. package/modules/hall-ui/public/atlas.html +3 -114
  144. package/modules/hall-ui/public/brand-apply.js +34 -6
  145. package/modules/hall-ui/public/builders.js +187 -219
  146. package/modules/hall-ui/public/diagrams.html +2 -0
  147. package/modules/hall-ui/public/dom-utils.js +27 -0
  148. package/modules/hall-ui/public/drachmae.html +2 -0
  149. package/modules/hall-ui/public/drachmae.js +54 -1
  150. package/modules/hall-ui/public/gate.css +98 -0
  151. package/modules/hall-ui/public/gate.html +3 -95
  152. package/modules/hall-ui/public/goal-inbox.js +4 -1
  153. package/modules/hall-ui/public/goals-page.js +626 -114
  154. package/modules/hall-ui/public/goals.css +79 -1
  155. package/modules/hall-ui/public/goals.html +38 -11
  156. package/modules/hall-ui/public/hall-widgets.js +62 -52
  157. package/modules/hall-ui/public/harbor.css +123 -0
  158. package/modules/hall-ui/public/harbor.html +3 -120
  159. package/modules/hall-ui/public/index.html +11 -4
  160. package/modules/hall-ui/public/instances-panel.js +4 -1
  161. package/modules/hall-ui/public/modules.css +63 -0
  162. package/modules/hall-ui/public/modules.html +3 -60
  163. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  164. package/modules/hall-ui/public/not-ready.html +2 -0
  165. package/modules/hall-ui/public/pair.css +73 -0
  166. package/modules/hall-ui/public/pair.html +3 -70
  167. package/modules/hall-ui/public/palette.js +302 -0
  168. package/modules/hall-ui/public/primer.css +13 -0
  169. package/modules/hall-ui/public/primer.html +2 -0
  170. package/modules/hall-ui/public/profile.html +2 -0
  171. package/modules/hall-ui/public/ranks.html +2 -0
  172. package/modules/hall-ui/public/roadmap.css +179 -0
  173. package/modules/hall-ui/public/roadmap.html +9 -172
  174. package/modules/hall-ui/public/roadmap.js +329 -316
  175. package/modules/hall-ui/public/sessions.css +16 -0
  176. package/modules/hall-ui/public/sessions.html +3 -13
  177. package/modules/hall-ui/public/settings.html +2 -0
  178. package/modules/hall-ui/public/settings.js +4 -4
  179. package/modules/hall-ui/public/shell.js +143 -18
  180. package/modules/hall-ui/public/style.css +231 -39
  181. package/modules/hall-ui/public/task-detail.js +347 -26
  182. package/modules/hall-ui/public/task.html +6 -1
  183. package/modules/hall-ui/public/watch.html +2 -0
  184. package/modules/hall-ui/public/work.html +8 -6
  185. package/modules/hall-ui/public/work.js +1 -1
  186. package/modules/ideas/inbox.js +61 -11
  187. package/modules/ideas/routes/inbox.js +23 -0
  188. package/modules/lifecycle/claim-eligibility.js +72 -0
  189. package/modules/lifecycle/db.js +519 -139
  190. package/modules/lifecycle/done-when.js +18 -3
  191. package/modules/lifecycle/github-push.js +19 -2
  192. package/modules/lifecycle/goal-advisory.js +114 -0
  193. package/modules/lifecycle/goal-authz.js +62 -0
  194. package/modules/lifecycle/lifecycle.js +9 -0
  195. package/modules/lifecycle/publish-reconciler.js +109 -6
  196. package/modules/lifecycle/routes/claims.js +68 -23
  197. package/modules/lifecycle/routes/done-when.js +110 -15
  198. package/modules/lifecycle/routes/goals.js +8 -38
  199. package/modules/lifecycle/routes/tasks.js +38 -6
  200. package/modules/lifecycle/ship-card.js +6 -0
  201. package/modules/onboarding/onboarding-state.js +1 -1
  202. package/modules/platform-identity/CLAUDE.md +15 -0
  203. package/modules/platform-identity/hub-device.js +147 -0
  204. package/modules/platform-identity/hub-keys.js +151 -0
  205. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  206. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  207. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  208. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  209. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  210. package/modules/platform-identity/module.json +18 -0
  211. package/modules/platform-identity/platform-identity.js +531 -0
  212. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  213. package/modules/platform-identity/routes/my-projects.js +140 -0
  214. package/modules/platform-identity/routes/projects.js +107 -0
  215. package/modules/platform-identity/routes/scouting.js +35 -0
  216. package/modules/platform-identity/routes/sso.js +402 -0
  217. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  218. package/modules/platform-identity/ui/.gitkeep +0 -0
  219. package/modules/security/routes/reports.js +10 -0
  220. package/modules/sessions/db.js +166 -21
  221. package/modules/sessions/module.json +1 -1
  222. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  223. package/modules/sessions/routes/sessions.js +33 -0
  224. package/package-lock.json +2 -2
  225. package/package.json +1 -1
  226. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  227. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  228. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  229. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  230. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  231. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  232. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  233. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  234. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  235. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  236. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  237. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  238. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  239. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  270. package/public-landing/create.html +51 -58
  271. package/public-landing/gate/README.md +137 -0
  272. package/public-landing/gate/dispmaps/bar.png +0 -0
  273. package/public-landing/gate/dispmaps/flat.png +0 -0
  274. package/public-landing/gate/dispmaps/key.png +0 -0
  275. package/public-landing/gate/index.html +587 -0
  276. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  277. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  278. package/public-landing/gate/space.css +799 -0
  279. package/public-landing/gate/space.js +1826 -0
  280. package/public-landing/gate/sprites/enter.png +0 -0
  281. package/public-landing/gate/sprites/search.png +0 -0
  282. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  283. package/public-landing/gate/sprites/tile.png +0 -0
  284. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  285. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  286. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  287. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  288. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  289. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  290. package/scripts/gds/abandon.js +6 -4
  291. package/scripts/gds/api.js +10 -5
  292. package/scripts/gds/api.ps1 +26 -0
  293. package/scripts/gds/api.sh +6 -0
  294. package/scripts/gds/audit-ships.js +7 -1
  295. package/scripts/gds/backfill-sessions.js +78 -18
  296. package/scripts/gds/backup.js +23 -1
  297. package/scripts/gds/box-connect-lib.js +124 -31
  298. package/scripts/gds/box-sync.js +66 -0
  299. package/scripts/gds/box.js +225 -53
  300. package/scripts/gds/cf-tunnel.js +145 -6
  301. package/scripts/gds/claim.js +34 -3
  302. package/scripts/gds/cli-lib.js +161 -27
  303. package/scripts/gds/code.js +6 -2
  304. package/scripts/gds/deploy-divergence.js +209 -0
  305. package/scripts/gds/dev-lib.js +309 -0
  306. package/scripts/gds/dev.js +322 -0
  307. package/scripts/gds/doctor.js +90 -61
  308. package/scripts/gds/fetch-art-key.js +1 -1
  309. package/scripts/gds/fetch-sound-prefs.js +2 -2
  310. package/scripts/gds/fitness.js +228 -12
  311. package/scripts/gds/gds-db-backup.service +16 -1
  312. package/scripts/gds/gds-db-offsite.service +9 -1
  313. package/scripts/gds/gen-api-client.js +1 -1
  314. package/scripts/gds/gen-api-docs.js +36 -14
  315. package/scripts/gds/gen-diagrams.js +45 -28
  316. package/scripts/gds/gen-file-map.js +2 -1
  317. package/scripts/gds/gen-freshness.js +32 -0
  318. package/scripts/gds/gen-repo-map.js +3 -2
  319. package/scripts/gds/gen-session-index.js +14 -5
  320. package/scripts/gds/hooks/pre-push.js +2 -2
  321. package/scripts/gds/init.js +60 -3
  322. package/scripts/gds/install-git-hooks.js +1 -1
  323. package/scripts/gds/key-card.js +15 -6
  324. package/scripts/gds/key-status.js +1 -1
  325. package/scripts/gds/linkify-refs.js +35 -9
  326. package/scripts/gds/login.js +16 -1
  327. package/scripts/gds/paste-token.js +7 -1
  328. package/scripts/gds/preflight.js +126 -0
  329. package/scripts/gds/provision.js +123 -12
  330. package/scripts/gds/publish-manifest.js +7 -1
  331. package/scripts/gds/reauth.js +7 -3
  332. package/scripts/gds/regen-instance-docs.js +47 -0
  333. package/scripts/gds/run-unit-tests.js +4 -2
  334. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  335. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  336. package/scripts/gds/sequence.js +425 -0
  337. package/scripts/gds/session-cost.js +10 -1
  338. package/scripts/gds/setup.js +31 -5
  339. package/scripts/gds/shell.js +5 -3
  340. package/scripts/gds/ship.js +319 -29
  341. package/scripts/gds/smoke-gds.js +139 -8
  342. package/scripts/gds/start.js +171 -22
  343. package/scripts/gds/status.js +1 -1
  344. package/scripts/gds/triage.js +10 -9
  345. package/scripts/gds/upgrade.js +124 -2
  346. package/scripts/migrate.sh +99 -14
  347. package/scripts/status-mirror-sync.js +114 -84
  348. package/src/bongos/api-errors.js +1 -0
  349. package/src/bongos/auth.js +447 -102
  350. package/src/bongos/db-kernel.js +27 -0
  351. package/src/bongos/db.js +39 -0
  352. package/src/bongos/module-scope-map.js +27 -1
  353. package/src/bongos/permission-path-check.js +136 -102
  354. package/src/bongos/repo-info.js +47 -11
  355. package/src/bongos/route-rank-check.js +429 -46
  356. package/src/bongos/routes/_helpers.js +12 -1
  357. package/src/bongos/routes/auth.js +219 -2
  358. package/src/bongos/routes/backup.js +58 -2
  359. package/src/bongos/routes/me.js +35 -1
  360. package/src/bongos/serve-internal.js +84 -15
  361. package/src/branding.js +32 -0
  362. package/src/instance-config.js +30 -0
  363. package/src/module-api.js +124 -1
  364. package/src/platform-server.js +86 -9
  365. package/tests/abandon_task.mjs +59 -3
  366. package/tests/api_cli_flags.mjs +53 -0
  367. package/tests/auth_page_gate.mjs +13 -0
  368. package/tests/backfill_sessions.mjs +127 -1
  369. package/tests/backup_cli.mjs +54 -0
  370. package/tests/bongos_box_connect.mjs +77 -0
  371. package/tests/box_access.mjs +130 -1
  372. package/tests/box_credential.mjs +125 -0
  373. package/tests/box_host_keys.mjs +24 -0
  374. package/tests/box_infra_resolve.mjs +149 -0
  375. package/tests/box_scope_session.mjs +6 -2
  376. package/tests/box_sync.mjs +55 -0
  377. package/tests/box_task_scope.mjs +99 -0
  378. package/tests/branding.mjs +12 -0
  379. package/tests/cf_ruleset_preflight.mjs +142 -0
  380. package/tests/cf_tunnel.mjs +37 -0
  381. package/tests/claim_gate_rebase.mjs +98 -0
  382. package/tests/clawback_confirmed_backlog.mjs +103 -0
  383. package/tests/cli_lib_formatters.mjs +20 -0
  384. package/tests/confirm_attribution.mjs +30 -46
  385. package/tests/credit_grant.mjs +198 -10
  386. package/tests/criterion_authoring_gate.mjs +272 -0
  387. package/tests/criterion_progress.mjs +33 -1
  388. package/tests/dev_lib.mjs +253 -0
  389. package/tests/devbox_artifact_gate.mjs +75 -0
  390. package/tests/devbox_dmg_backdrop.mjs +137 -0
  391. package/tests/devbox_icons.mjs +304 -0
  392. package/tests/devbox_installer_brand.mjs +232 -0
  393. package/tests/devbox_key_register.mjs +234 -0
  394. package/tests/docs_openapi_route.mjs +110 -0
  395. package/tests/doctor_hooks.mjs +141 -0
  396. package/tests/extract_json.mjs +140 -0
  397. package/tests/fitness.mjs +89 -0
  398. package/tests/gen_freshness.mjs +96 -0
  399. package/tests/goal_advisory.mjs +251 -0
  400. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  401. package/tests/goal_routes.mjs +59 -4
  402. package/tests/goal_tier.mjs +12 -3
  403. package/tests/governance_catalog.mjs +129 -0
  404. package/tests/governance_claim_eligibility.mjs +262 -0
  405. package/tests/governance_config.mjs +187 -0
  406. package/tests/governance_ownership_scope.mjs +410 -0
  407. package/tests/governance_page_gates.mjs +324 -0
  408. package/tests/governance_parity.mjs +336 -0
  409. package/tests/governance_principals.mjs +232 -0
  410. package/tests/governance_protected_surfaces.mjs +208 -0
  411. package/tests/governance_require_permission.mjs +223 -0
  412. package/tests/governance_resolver.mjs +84 -0
  413. package/tests/governance_role_sync.mjs +231 -0
  414. package/tests/governance_seed.mjs +127 -0
  415. package/tests/governance_session_scope.mjs +434 -0
  416. package/tests/governance_vanilla_boot.mjs +203 -0
  417. package/tests/grade_attribution.mjs +7 -7
  418. package/tests/hall_audit.mjs +223 -0
  419. package/tests/hall_nav.mjs +191 -0
  420. package/tests/hall_palette.mjs +206 -0
  421. package/tests/hall_signout.mjs +124 -0
  422. package/tests/hook_user_agents.mjs +10 -0
  423. package/tests/idea_triage.mjs +162 -0
  424. package/tests/idp_device_exchange.mjs +93 -0
  425. package/tests/init.mjs +51 -0
  426. package/tests/instance_config.mjs +65 -0
  427. package/tests/instance_mismatch_guard.mjs +23 -6
  428. package/tests/instance_release_config.mjs +104 -0
  429. package/tests/linkify_refs.mjs +15 -2
  430. package/tests/migrate_root_resolution.mjs +124 -1
  431. package/tests/module_contributions.mjs +55 -0
  432. package/tests/module_loader.mjs +10 -5
  433. package/tests/module_scope_active_claims.mjs +94 -0
  434. package/tests/needs_rebase.mjs +92 -0
  435. package/tests/one_active_claim_per_session.mjs +76 -0
  436. package/tests/override_attribution.mjs +10 -8
  437. package/tests/override_request_ownership.mjs +8 -4
  438. package/tests/parse_cookie_decode.mjs +42 -0
  439. package/tests/pay_on_land.mjs +129 -0
  440. package/tests/platform_boot.mjs +100 -1
  441. package/tests/post_login_landing.mjs +42 -0
  442. package/tests/preflight_checks.mjs +72 -0
  443. package/tests/provision.mjs +132 -7
  444. package/tests/publish_branch_route.mjs +53 -0
  445. package/tests/publish_reconciler.mjs +187 -2
  446. package/tests/repo_info_binding.mjs +248 -0
  447. package/tests/reward_gate.mjs +11 -2
  448. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  449. package/tests/reward_mode_surfacing.mjs +168 -0
  450. package/tests/route_permission_check.mjs +301 -0
  451. package/tests/route_rank_check.mjs +254 -12
  452. package/tests/route_validation.mjs +30 -0
  453. package/tests/sequence.mjs +267 -0
  454. package/tests/session_digest.mjs +44 -0
  455. package/tests/session_index.mjs +18 -6
  456. package/tests/session_records.mjs +39 -1
  457. package/tests/session_reward_on_land.mjs +381 -0
  458. package/tests/session_reward_reconcile.mjs +229 -0
  459. package/tests/ship_api_client_pathspec.mjs +100 -0
  460. package/tests/ship_base_flag.mjs +93 -0
  461. package/tests/ship_ci_deploy.mjs +80 -3
  462. package/tests/ship_upstream_deletion.mjs +57 -0
  463. package/tests/smoke_target.mjs +233 -0
  464. package/tests/start_env_guard.mjs +87 -0
  465. package/tests/start_rebase_warning.mjs +103 -0
  466. package/tests/status_mirror_sync.mjs +122 -0
  467. package/tests/stop_refcheck.mjs +19 -1
  468. package/tests/task_goal_link.mjs +15 -6
  469. package/tests/upgrade.mjs +139 -0
  470. package/tests/web_admission_status.mjs +162 -0
  471. package/tests/write_validation_gaps.mjs +110 -0
@@ -0,0 +1,124 @@
1
+ # Slash commands: which are Claude's, which are this project's
2
+
3
+ *A reference page. Skim it once, come back when a command surprises you.*
4
+
5
+ When you type `/` in Claude Code you get one list, but the commands in it come from **two different places** and are maintained by two different people. Claude Code ships some of them; this project ships the rest. They look identical in the menu, which is why a few of them trip people up — see [Easy mix-ups](#easy-mix-ups) at the bottom.
6
+
7
+ ## The 10-second rule
8
+
9
+ | | **Claude Code's own** | **This project's** |
10
+ |---|---|---|
11
+ | Who ships it | Anthropic, inside the Claude Code app | This repository |
12
+ | Where it lives | Inside the app — nothing in this repo | [`.claude/skills/<name>/`](../../.claude/skills/) |
13
+ | What it acts on | Your *session* — context, model, config, account | The *build system* — tasks, claims, ships, ideas |
14
+ | Works in any repo? | Yes, everywhere | No — only in a folder that holds this code |
15
+ | Authoritative list | Type `/help` | The folder listing linked above |
16
+
17
+ **The short version:** if it changes your Claude session, it's Claude's. If it changes project state — a task, a claim, a ship — it's ours. If you can run it in an unrelated repo, it's Claude's.
18
+
19
+ > This is also why the commands "appear by magic" when you clone: they aren't a plugin or a download, they're files in `.claude/skills/` that Claude Code reads when a session **starts** on the folder. Clone mid-session and they won't show up until you start a fresh session — the wrinkle the [primer](primer.md) calls out in step 3.
20
+
21
+ ## This project's commands
22
+
23
+ Every one of these talks to the build system. They're grouped by when you'd reach for them, not alphabetically.
24
+
25
+ ### The work loop — the ones you'll use every session
26
+
27
+ | Command | What it does |
28
+ |---|---|
29
+ | `/builder-start` | List the tasks you can claim right now, filtered for parallel-safety |
30
+ | `/builder-claim N` | Lock task N to your session |
31
+ | `/builder-ship` | Grade, merge, and deploy your claimed task (credits land here) |
32
+ | `/builder-release` | Cancel a claim — the task returns to `ready`, no credits |
33
+ | `/builder-stage` | Preview your work-in-progress on your own sandbox before shipping |
34
+ | `/builder-end` | Close out the session safely — resolve the claim, seal the log |
35
+ | `/status` | Version / criterion progress — "what's left for C8?" |
36
+ | `/recall` | Search the docs + project knowledge before re-solving something |
37
+
38
+ ### Your account and your machine
39
+
40
+ | Command | What it does |
41
+ |---|---|
42
+ | `/builder-setup` | One-time enrolment — signs you in and registers you |
43
+ | `/builder-reauth` | Refresh an expired session |
44
+ | `/builder-key` | Check / set your own API key status |
45
+ | `/builder-box` | Your dev box control panel — wake, create, check cost |
46
+ | `/builder-connect` · `/builder-sync` · `/close-box` | Connect to, re-sync, and tear down that box |
47
+ | `/builder-cost` | Log a cost entry against your claim |
48
+ | `/builder-backup` | Check or trigger a database backup before risky work |
49
+ | `/builder-exit` | Offboard or reactivate a builder *(Archon only)* |
50
+
51
+ ### Triage and planning *(Metic and above)*
52
+
53
+ | Command | What it does |
54
+ |---|---|
55
+ | `/idea-triage` | Walk the idea inbox — promote, discard, or merge each |
56
+ | `/blocker-review` · `/blocker-solve` | Walk open blockers, or drive one to done |
57
+ | `/goal-create` | Plan and create one goal — scope wall, criteria, seed tasks |
58
+ | `/goal-review` | Confirm criteria that are flagged met-pending-review |
59
+ | `/planning-session` | Scope an upcoming version and seed its task list |
60
+ | `/priority-session` | Reweight the inbox from a few plain-speech answers |
61
+ | `/merge-mode` | Manual fallback when a confirmed task didn't land |
62
+
63
+ ### Discipline modes
64
+
65
+ `/dev` (engineering — the default loop), `/paint` (art), `/ideate` (ideation). A claimed task's discipline routes you to one of these.
66
+
67
+ ### Design and art pipeline
68
+
69
+ `/design-sync` and `/figma-design-sync` round-trip the UI design system. The `/otb-*` family — `otb-tile-generate`, `otb-design-review`, `otb-character-review`, `otb-feedback-capture`, `otb-figma-sync` — is the reference instance's pixel-art pipeline; it's only meaningful on an instance that runs that pipeline.
70
+
71
+ ### Session and meta
72
+
73
+ | Command | What it does |
74
+ |---|---|
75
+ | `/session-handoff` | Emit a paste-ready prompt to start a fresh session with |
76
+ | `/read-session-export` | Read a past session's `/export` zip |
77
+ | `/feedback` | Pull in the latest recorded walkthrough bundle |
78
+ | `/new-project` | Zero-to-live runbook for a brand-new instance |
79
+ | `/builder-redteam` | File a security / vulnerability report |
80
+
81
+ ## Claude Code's own commands
82
+
83
+ These work in **any** repository — they have nothing to do with this project. `/help` prints the live, authoritative list for your version; the ones below are simply the ones you'll actually meet.
84
+
85
+ | Command | What it does |
86
+ |---|---|
87
+ | `/help` | List every command available right now — **the authoritative list** |
88
+ | `/clear` · `/compact` | Wipe or condense the conversation context |
89
+ | `/model` · `/config` | Switch model; change app settings |
90
+ | `/login` · `/logout` | Sign in to your **Anthropic** account |
91
+ | `/init` | Write a `CLAUDE.md` for the current codebase |
92
+ | `/cost` · `/usage` · `/context` | Token spend, plan usage, context window |
93
+ | `/doctor` | Diagnose the **Claude Code install** |
94
+ | `/memory` | Edit Claude's memory files |
95
+ | `/mcp` · `/agents` · `/hooks` · `/permissions` | Configure MCP servers, subagents, hooks, tool permissions |
96
+ | `/export` · `/resume` · `/rewind` | Save the transcript; resume or roll back a session |
97
+ | `/review` | Review a GitHub pull request |
98
+ | `/status` | **Claude Code's** session/auth status — see the warning below |
99
+
100
+ ## Easy mix-ups
101
+
102
+ These are the ones that actually cause confusion.
103
+
104
+ **`/status` — the genuine collision.** Both sides define it. Claude Code's `/status` shows your session and auth state; this project's shows version and criterion progress. Which one wins depends on your Claude Code version and how it resolves the name. If you get the wrong one, say *"what's left for C8"* in plain English, or run `node scripts/gds/status.js` directly.
105
+
106
+ **`/login` is Anthropic, not us.** It signs you into your Claude account. To sign into a Cloud Bongos instance, use `bongos login <instance-url>`, or `/builder-setup` for a first-time enrolment.
107
+
108
+ **`/init` writes a `CLAUDE.md`.** It does *not* scaffold a new instance — that's `bongos init`, wrapped by `/new-project`. Running `/init` in this repo would overwrite the project's own `CLAUDE.md`.
109
+
110
+ **`/doctor` checks Claude Code.** For the build system's health — your session, toolchain, git plumbing, environment — run `node scripts/gds/doctor.js`.
111
+
112
+ **`/cost` is Claude's token spend.** To record a project cost against your claim, that's `/builder-cost`.
113
+
114
+ **`/export` vs `/read-session-export`.** Claude's `/export` *writes* a transcript zip; our `/read-session-export` *reads* one back.
115
+
116
+ **`/review` reviews a GitHub PR.** The project's review commands are `/goal-review`, `/blocker-review`, and `/idea-triage` — different jobs entirely.
117
+
118
+ ## Two more things worth knowing
119
+
120
+ **Every command has a plain-English twin.** Each skill lists trigger phrases, so *"what can I work on"* reaches `/builder-start` and *"ship it"* reaches `/builder-ship`. You never have to memorise the slash form.
121
+
122
+ **Same commands, outside Claude.** The work-loop commands are also a terminal CLI: `bongos start`, `bongos claim N`, `bongos ship`. Same actions, same API — usable from any terminal, a Chromebook, or CI. Run `bongos help` for the verb list.
123
+
124
+ **Rank gates are real.** Some commands above refuse below a certain rank — that's enforced by the server on every request, not by the presence of the file on your disk. See [`canonical-permissions.md`](../canonical-permissions.md).
@@ -138,6 +138,29 @@ These spend money and are intentionally manual.
138
138
  > **`box-drift-reconcile.timer` (task [#1289](https://example.com/builders#/task/1289)/[ADR 0071](../adr/<redacted>.md)) is the zombie backstop.** It runs `box.js reconcile-drift --apply` hourly, reading the live DO droplet list and repairing DO⇄DB drift both ways — force-deleting **zombie** droplets (running but no live box row claims them) and marking **ghost** rows destroyed (droplet gone from DO). Reads the SAME `/etc/example/box.env` (needs `DO_API_TOKEN` to enumerate droplets). Without it, the confirm-before-destroyed teardown still prevents *new* zombies, but a pre-existing one (or an out-of-band DO change) only heals on the next manual `reconcile-drift`. Confirm with `journalctl -u box-drift-reconcile.service`.
139
139
  > **Chromebook / browser terminal ([#760](https://example.com/builders#/task/760)/[ADR 0038](../adr/<redacted>.md), superseding the old `claude rc` pairing).** Research proved `claude rc` cannot run headless, so the box instead serves its OWN browser terminal — **ttyd** (127.0.0.1:7681, per-box basic-auth, drops into `/workspace`) exposed over an outbound-only **Cloudflare Tunnel** — where the builder runs normal interactive `claude`. A browser/Chromebook builder gets the URL + credential from `GET /api/gds/box/terminal` after their box is active — no SSH needed. The terminal/cloudflared units are inlined in cloud-init and start at first boot ([#774](https://example.com/builders#/task/774)). The deleted RC bits (`claude-rc.service`, `box-report-pairing.sh`, `/box/pairing(-link)`) are gone.
140
140
 
141
+ ## Cloudflare token: the edge cookie-strip rule (ADR 0053 / SR#11)
142
+
143
+ `provision` applies two zone **rulesets** best-effort: the **cookie-strip Transform Rule** (removes the `Cookie` request header on `term-*`/`sandbox-*`, so the apex session cookie never rides the tunnel onto a box — a host outside the trust boundary) and the **sandbox cache-bypass Cache Rule**. Both need scopes beyond Tunnel + DNS, and a token that lacks them fails **silently** — the box provisions fine and the security control simply isn't there.
144
+
145
+ Since task 1002511, `box.js provision` **read-probes** the ruleset phase before spending a cent (dry-run included) and prints a `⚠⚠ SECURITY` block naming the fix. Read the probe honestly: it is a `GET`, so it can only prove the scope is **missing** (401/403). A readable phase means *readable* — edit scope is not proven until the rule PUT actually runs, which is why the summary line after `✓ named tunnel ready` is the authoritative signal.
146
+
147
+ **Fix — widen the token** (account owner only):
148
+
149
+ > CF dashboard → **My Profile → API Tokens** → edit the token used as `CLOUDFLARE_API_TOKEN` → **Permissions** → add **Zone → Transform Rules → Edit** and **Zone → Cache Rules → Edit** → **Zone Resources → Include → Specific zone → `<your apex zone>`** → Continue → Save. Then re-run `node scripts/gds/box.js provision <login> --apply`.
150
+
151
+ **Fallback — apply the rule by hand** (no token change; do it once per zone):
152
+
153
+ > CF dashboard → the zone → **Rules → Transform Rules → Modify Request Header** → Create rule. Custom filter expression: `starts_with(http.host, "term-") or starts_with(http.host, "sandbox-")` (the exported `COOKIE_STRIP_EXPRESSION`). Action: **Remove** header `Cookie` (phase `http_request_late_transform`). Deploy. Give it the same description the code uses (`COOKIE_STRIP_RULE_DESC`) so a later widened-token run recognises and replaces it instead of adding a duplicate.
154
+
155
+ **Verify:**
156
+
157
+ ```bash
158
+ node scripts/gds/box.js provision <login> # dry-run — prints the probe verdict, spends nothing
159
+ curl -sI https://term-<login>.<apex>/ -H 'Cookie: x=1' # from a box-facing check, confirm the origin sees no Cookie
160
+ ```
161
+
162
+ > `/user/tokens/verify` is **not** a valid check here — an IP-locked token answers "Invalid API Token" there even when it is valid (see the [#725](https://example.com/builders#/task/725) note above). Always probe the real operation.
163
+
141
164
  ## Boundaries (other ADR-0031 tasks)
142
165
 
143
166
  - **[#596](https://example.com/builders#/task/596)** (done) — the devcontainer (box-as-code) this provisions.
@@ -10,7 +10,10 @@ releases repo → a one-line config bump re-points the branded
10
10
  - **Source:** `devbox-app/` in the main (private) repo.
11
11
  - **CI:** `.github/workflows/build-devbox-app.yml` — builds on every push
12
12
  touching `devbox-app/**` (mac dmg arm64+x64 on macos-14, NSIS exe x64+arm64 on
13
- windows-latest) and uploads workflow artifacts. No publishing from CI.
13
+ windows-latest). **Only `main` keeps the artifacts** (3-day retention); a
14
+ `claude/**` run builds both platforms as a CI signal and uploads nothing —
15
+ ~500MB per run had filled the shared Actions storage cap and blocked uploads
16
+ repo-wide. No publishing from CI either way.
14
17
  - **Public releases repo:** named in `config/devbox-app.json`
15
18
  (`releases_repo`). Assets live on GitHub releases there; GitHub's CDN
16
19
  serves the downloads, $0.
@@ -43,13 +46,20 @@ releases repo → a one-line config bump re-points the branded
43
46
 
44
47
  1. Bump `devbox-app/package.json` version (e.g. `1.1.0`) and regenerate
45
48
  icons only if they changed (`npm run icons`).
46
- 2. Push the branch; wait for `build-devbox-app` to go green.
47
- 3. Download the artifacts:
49
+ 2. Land the bump on `main` through the normal GDS flow, then wait for
50
+ `build-devbox-app` to go green **on the `main` run** — that is the run that
51
+ carries the installers.
52
+ 3. Download the artifacts (they expire after 3 days — re-run the workflow on
53
+ `main` via `gh workflow run build-devbox-app.yml --ref main` if they aged out):
48
54
  ```
49
55
  gh run download -R example-owner/example -n devbox-app-mac -D /tmp/devbox-rel
50
56
  gh run download -R example-owner/example -n devbox-app-win -D /tmp/devbox-rel
51
57
  ```
52
- (or build the mac side locally: `cd devbox-app && npm run dist:mac`).
58
+ **These commands only work against a `main` run.** Pointing them at a
59
+ `claude/**` run fails with nothing to download — the upload steps are gated to
60
+ `refs/heads/main` (see §0). To get an installer out of an unmerged branch,
61
+ build it locally instead: `cd modules/dev-box/app && npm run dist:mac` (or
62
+ `npm run dist:win` on Windows).
53
63
  4. Publish to the public releases repo (tag = `v<version>`, must match what
54
64
  `src/devbox-downloads.js` composes):
55
65
  ```
@@ -35,6 +35,22 @@ npx bongos start
35
35
 
36
36
  That's it — `bongos claim <id>` / `bongos ship` now work, scoped to this instance.
37
37
 
38
+ ## If the instance isn't hosted yet — a freshly-created, LOCALHOST project
39
+
40
+ The steps above assume the instance is already **running** at a reachable origin. A project
41
+ straight out of the creation flow is different: its `config/branding.json` `publicOrigin`
42
+ is `http://localhost:<port>`, and **nothing is serving it yet** — so step 2's
43
+ `bongos login http://localhost:<port>` fails with `fetch failed`. That repo is configured
44
+ to run on *your own machine*; stand it up with one command instead:
45
+
46
+ ```bash
47
+ npm install
48
+ npx bongos dev # Postgres → createdb → migrate → server → sign-in, in one step
49
+ ```
50
+
51
+ Full guide: [`docs/recipes/local-dev.md`](local-dev.md) (ADR 0149). Prefer a cloud dev box
52
+ over running locally? Use `bongos box` + `bongos code`.
53
+
38
54
  ## Notes
39
55
 
40
56
  - **Sign in to the RIGHT instance.** `bongos login <url>` writes a per-instance session
@@ -0,0 +1,81 @@
1
+ # Run a project on your own machine — `bongos dev`
2
+
3
+ > The one-command path from a freshly-cloned **standalone instance repo** (one whose
4
+ > `config/branding.json` points at `http://localhost:<port>`) to a running, signed-in
5
+ > instance on your Mac. This is the local counterpart of `bongos onboard` (which
6
+ > stands an instance up in the **cloud**) — see [ADR 0149](../adr/<redacted>.md).
7
+
8
+ ## TL;DR
9
+
10
+ ```bash
11
+ gh repo clone <owner>/<project>
12
+ cd <project>
13
+ npm install
14
+ npx bongos dev
15
+ ```
16
+
17
+ `bongos dev` starts the database, creates this project's database, builds its tables,
18
+ launches the server on the port in `config/branding.json`, and signs you in. Re-running
19
+ it is safe (idempotent). Stop it with `bongos dev stop`.
20
+
21
+ ## Prerequisites (one-time, per machine)
22
+
23
+ - **Node.js ≥ 22** — `node --version`
24
+ - **PostgreSQL 16** — `psql --version`. Install on a Mac with Homebrew:
25
+ ```bash
26
+ brew install postgresql@16
27
+ brew services start postgresql@16 # bongos dev will also try to start it for you
28
+ ```
29
+ - macOS or Linux (migrations use `bash`). On **Windows**, use WSL, or the Docker path in
30
+ [`self-host.md`](self-host.md).
31
+
32
+ ## What `bongos dev` does (and why it's needed)
33
+
34
+ A cloned project ships the code but nothing *running*. The server reads its port from an
35
+ env var and **not** from branding, the migrator and the server default to **different**
36
+ database names, and node-pg defaults to a Linux socket that doesn't exist on a Mac — so a
37
+ by-hand standup is a six-step assembly with three silent mismatches. `bongos dev` does all
38
+ of it from one source of truth (your `config/branding.json`):
39
+
40
+ 1. Ensures Postgres is running (starts it if it isn't).
41
+ 2. Creates the project's database if it doesn't exist.
42
+ 3. Runs migrations to build/refresh the tables.
43
+ 4. Starts the server on the branding port (e.g. `http://localhost:3006`).
44
+ 5. Signs you in to this instance (`--no-login` to skip).
45
+
46
+ ## Commands
47
+
48
+ ```bash
49
+ npx bongos dev # stand it up (idempotent) + sign in
50
+ npx bongos dev status # is it running? what URL? is sign-in configured?
51
+ npx bongos dev stop # stop the background server this launched
52
+ npx bongos dev --foreground # run attached instead (Ctrl-C stops it)
53
+ npx bongos dev --no-login # stand it up but don't sign in
54
+ npx bongos dev --skip-migrate # skip the migration step (already migrated)
55
+ npx bongos dev --port 3011 --db my_scratch # override the port / database name
56
+ ```
57
+
58
+ The server runs in the **background but managed** — `bongos dev status`/`stop` always find
59
+ it, and a second `bongos dev` is a no-op if it's already up. (This is deliberate: an
60
+ *unmanaged* leftover server is how you end up accidentally signing a new project into an
61
+ old one's server.)
62
+
63
+ ## The one step that can need you: a GitHub OAuth App
64
+
65
+ Sign-in uses a GitHub OAuth App. If your machine already ran another Cloud Bongos instance,
66
+ the credentials are usually already present and `bongos dev` just works. If not, it prints
67
+ exact steps: create an OAuth App (Homepage `http://localhost:<port>`, callback
68
+ `http://localhost:<port>/api/gds/auth/web/callback`, tick **Enable Device Flow**), then save
69
+ the Client ID + secret to `~/.config/<configDir>/gds-github.json` as
70
+ `{ "client_id": "…", "client_secret": "…" }` and re-run `bongos dev`.
71
+
72
+ ## Notes
73
+
74
+ - **Sign in as the owner.** `config/branding.json`'s `firstAdmin` is the GitHub account
75
+ auto-seated as owner on first sign-in — `bongos dev` tells you which one.
76
+ - **Switching instances.** Signing in to a local project points your CLI session at it; to
77
+ go back to a hosted instance later, `bongos login https://<that-instance>`.
78
+ - **Multiple projects at once** each get their own database + port, so their `bongos dev`
79
+ servers don't collide.
80
+ - **Prefer the cloud?** `bongos box` + `bongos code` give you a remote dev box instead — no
81
+ local database or server to run.
@@ -147,11 +147,29 @@ Organized by topic, not chronology. New entries go in the matching section; crea
147
147
 
148
148
  ---
149
149
 
150
+ ## Windows / local dev (PowerShell)
151
+
152
+ ### PowerShell 5.1 turns a clean `node scripts/gds/*.js` exit into a false failure
153
+
154
+ - **Symptom:** Running `node scripts/gds/api.js GET /api/gds/me 2>&1` (or the same on `claim.js`/`ship.js`) inside a PowerShell 5.1 session reports failure — `$?` is `$false` and the stderr line surfaces as a `NativeCommandError` — even though node exited 0 and the JSON on stdout is exactly right.
155
+ - **Root cause:** `api.js` prints its status banner to stderr unconditionally, by design (stdout stays clean JSON for piping); `claim.js`/`ship.js` also write diagnostics to stderr during a normal run. PS 5.1 wraps any stderr output from a native command into an `ErrorRecord` once the two streams are merged with `2>&1`, and sets `$?` false regardless of the actual exit code.
156
+ - **Fix:** Never merge streams on these calls. Prefer `scripts/gds/api.ps1` (a thin wrapper that discards stderr and writes clean JSON to stdout, safe to pipe into `ConvertFrom-Json`), or call `node scripts/gds/api.js ...` plain, with no `2>&1`.
157
+ - **Why it bites:** The exit code and JSON body are both fine — only the redirection is wrong — so the failure looks like a real API error and wastes time chasing a phantom bug in the call itself.
158
+
159
+ ### `Out-File`/`>` writes a UTF-8 BOM that breaks `JSON.parse` on re-read
160
+
161
+ - **Symptom:** A JSON body file written from PowerShell (`... | Out-File body.json` or `... > body.json`) and then read back with `--body-file` fails to parse, or parses with an invisible extra character before the first key.
162
+ - **Root cause:** PowerShell's `Out-File`/`>` redirection default to UTF-8 **with a byte-order-mark**. `JSON.parse` does not strip a leading BOM, so the file's first byte is invisible garbage as far as the parser is concerned.
163
+ - **Fix:** Don't write CLI JSON body files with `Out-File`/`>`. Use the Write tool, or `[IO.File]::WriteAllText($path, $json, (New-Object Text.UTF8Encoding($false)))` (explicit no-BOM encoding). `scripts/gds/api.js`'s `--body-file` reader now also strips a leading BOM defensively, but the safest fix is to never write one.
164
+ - **Why it bites:** The file looks completely normal in an editor — the BOM is invisible — so the parse failure looks like a JSON syntax problem, not an encoding one.
165
+
166
+ ---
167
+
150
168
  ## GDS build pipeline
151
169
 
152
170
  ### Two deterministic routines run as in-process server timers, not external cron
153
171
 
154
- - **What:** `peer-vote-tally` (weekly) runs inside the always-on Node process via the autonomy module's poller `modules/autonomy/pollers/routine-timers.js` (ADR 0078 amendment, task 1382; carved into `modules/autonomy/` at BV1.R83) — no `claude -p`, no external cron, no token. The loader's `startModulePollers` starts it (on the game/droplet boot only); it reaches `tallyPeerVotes` through the doorway. It's a no-op anywhere the DB is unreachable (builder machines), so it only does work on the prod droplet.
172
+ - **What:** `peer-vote-tally` (weekly) runs inside the always-on Node process via the autonomy module's poller `modules/autonomy/pollers/routine-timers.js` (ADR 0078 amendment, task 1382; carved into `modules/autonomy/` at BV1.R83) — no `claude -p`, no external cron, no token. The loader's `startModulePollers` starts it from `src/platform-server.js` at boot (task 1002419 — before that fix the call site had been lost with the retired `server.js` and no module poller started at all); it reaches `tallyPeerVotes` through the doorway. It's a no-op anywhere the DB is unreachable (builder machines), so it only does work on the prod droplet.
155
173
  - **Disable / move it out-of-process:** set `ROUTINE_TIMERS_DISABLED=1` in `/etc/example/web-source.env` and restart. Also set it on any **second** always-on instance that shares the `example` DB so the tally can't double-fold (the `FOR UPDATE OF pv` row lock is the hard guard if you forget).
156
174
  - **Run it manually now:** `node scripts/gds/run-routine.js peer-vote-tally` (the dispatcher front door still works). The cadence is boot-anchored ("~90s after boot, then weekly"), not a wall-clock Monday job — frequent deploys re-anchor it, which is harmless (the tally is idempotent).
157
175
 
@@ -33,7 +33,7 @@ curl -sS -X PATCH -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: applicat
33
33
  -d '{"parallel_safe": true}' https://example.com/api/gds/tasks/<id>
34
34
  ```
35
35
 
36
- In parallel mode each worker stops at `confirmed` (credits land) and the runner lands the merges **one at a time** — concurrent merges to `main` are never allowed.
36
+ In parallel mode each worker stops at `confirmed` (verified, not yet paid — [ADR 0120](../adr/<redacted>.md) books credits at land) and the runner lands the merges **one at a time** — concurrent merges to `main` are never allowed. Credits land as each merge completes.
37
37
 
38
38
  ## Reading the morning report
39
39
 
@@ -0,0 +1,174 @@
1
+ # Running a goal as parallel worktree waves
2
+
3
+ How to take a goal with ~20 tasks and ship it with several agents building at once, one worktree per claim.
4
+
5
+ Written from the 2026-07-30 session that shipped 14 tasks off goal 1000030 (Governance — configurable roles & permissions). **This records what actually worked, which differed from the plan we started with.** The differences are the point.
6
+
7
+ ---
8
+
9
+ ## The one-paragraph version
10
+
11
+ Dependencies tell you what must **ship** first. They tell you nothing about what can be **edited** at the same time. Work out the file-conflict graph yourself, run the disjoint set in parallel worktrees, and serialise anything that touches the same file. Claim the parallel set with `POST /claims/batch` (`claim.js` can only hold one claim per machine). Expect the plan's own dependency edges to be wrong somewhere, and expect one shared doc file to become the merge-conflict tax.
12
+
13
+ ---
14
+
15
+ ## 1. Read the DAG, then don't trust it
16
+
17
+ Start by pulling the real graph — status, `dependencies[]`, `dependents[]`, and `requires_rank` for every task on the goal:
18
+
19
+ ```
20
+ node scripts/gds/api.js GET "/api/gds/tasks?goal_id=<goal>&limit=100"
21
+ node scripts/gds/api.js GET "/api/gds/tasks/<id>" # includes dependencies + dependents
22
+ ```
23
+
24
+ > **Gotcha (cost us ~40 minutes).** The generated API client wraps responses as `{status, ok, data:{...}}`. Reading `res.tasks` gives `undefined` and every dependency array silently looks empty — which reads as "this goal has no dependencies at all". Unwrap `.data` first. An empty dependency graph should make you suspicious, not relieved.
25
+
26
+ Then **audit the edges for direction errors before scheduling anything**. Two of goal 1000030's edges were backwards, and each cost a full task cycle:
27
+
28
+ - **The checker recorded as depending on the thing it checks.** R109 (teach the CI fitness gate to understand the new gate form) was recorded as depending on R104 (migrate the gates). But migrating gates without teaching the checker made every migrated route classify as `any-builder` — a silent downgrade that tripped exact-rank pins. R104 could not pass its grade until R109 shipped, and R109 could not be claimed until R104 shipped. **Deadlock.** Fix: `PUT /tasks/:id/dependencies` to reverse it. The heuristic — *if task B validates task A's output, B is usually A's prerequisite, not its dependent.*
29
+ - **A migration racing ahead of a missing writer.** The plan migrated ~80 authority gates onto a new resolver, but nothing ever wrote the table the resolver reads outside a one-shot backfill. Any account created or re-ranked afterwards would have resolved to zero permissions — and a demoted account would have kept its old powers. Found only because one task's agent reported it instead of coding around it. Fix: file the missing work as a task, then `PUT /tasks/:id/dependencies` to gate the migration tasks behind it.
30
+
31
+ **Do not let a wrong edge stand because fixing it feels like process work.** A backwards edge deadlocks a whole chain, and the deadlock presents as an unexplained grade failure several hours later.
32
+
33
+ ---
34
+
35
+ ## 2. Build the file-conflict graph — this is the real gate
36
+
37
+ `dependencies[]` is a *ship* ordering. Parallel safety is a *file* question, and `touches[]` is advisory and frequently empty. So derive it yourself: read each task's description and predict the files it will edit.
38
+
39
+ Then group:
40
+
41
+ - **Parallel-safe** — no file overlap with anything else in the wave.
42
+ - **Serialised** — two tasks edit the same file, so they run back-to-back regardless of what the DAG says.
43
+
44
+ Worked example from goal 1000030:
45
+
46
+ | Wave | Ran in parallel | Why the rest was held |
47
+ |---|---|---|
48
+ | 0 | resolver + kernel port ‖ config loader | disjoint: new module files vs `config/*.json` |
49
+ | A | the gate primitive ‖ the protected-surface registry | both touched different core files; three others all edited `catalog.js`+`resolver.js` and were serialised behind them |
50
+ | B | a proof test ‖ the core-route migration | test files collide with nothing |
51
+ | C | module-route migration alone | it owns every `modules/*/routes/*.js`, so nothing else in that tree could move |
52
+
53
+ **Heuristics that held up:**
54
+ - A task whose whole output is a new test file is parallel-safe with everything. Schedule these freely.
55
+ - A task that "migrates all X" owns its entire tree for the duration. Run the narrow, specific tasks in that tree **first**, then let the sweep absorb the remainder and rebase onto them. Running the sweep first forces every narrow task to conflict with it.
56
+ - Two tasks extending the same registry/catalog file always serialise, even when their subject matter is unrelated.
57
+
58
+ ---
59
+
60
+ ## 3. Claiming a parallel set
61
+
62
+ `claim.js` **cannot hold concurrent claims from one machine.** The app-layer guard permits one claim per *worktree*, but `uniq_active_claim_per_session` (`migrations/180`) is keyed on `creator_session_id` alone — worktree-blind — and the stricter of the two wins. Every worktree on a box shares one CLI session token, so the second `claim.js` fails.
63
+
64
+ Worse, it fails with a **misleading** message: `claimTask` maps any Postgres `23505` to `ALREADY_CLAIMED`, so you are told *"Task #N was just claimed by another session"* when nothing is claimed and no retry will ever succeed. Two separate agents burned a full investigation each on this before the cause was found. (Filed as idea 1000617.)
65
+
66
+ **Use the batch endpoint**, which was built for exactly this:
67
+
68
+ ```
69
+ node scripts/gds/api.js POST /api/gds/claims/batch \
70
+ --body-file batch.json # {"task_ids":[111,222,333],"bind_session":false}
71
+ ```
72
+
73
+ `bind_session:false` stores each claim with a NULL session, which is the supported web-claim mode; many NULLs coexist. The safety property that matters — one task per worktree, one branch per ship, no commingled commits — is preserved, because you still give each task its own worktree.
74
+
75
+ ```bash
76
+ git worktree add .claude/worktrees/task-<id> -b worktree-task-<id> origin/main
77
+ ```
78
+
79
+ Always branch from a **freshly fetched `origin/main`**, not from local `main`.
80
+
81
+ ---
82
+
83
+ ## 4. Briefing an agent per worktree
84
+
85
+ Each agent gets one task, one worktree, and an explicit **do-not-touch list** naming the files its siblings own. That list is what makes parallelism safe, so keep it accurate as the wave progresses.
86
+
87
+ Include in every brief:
88
+
89
+ - the absolute worktree path, and "never edit the main checkout, never `git push origin main`, never merge to main yourself"
90
+ - the claim is **already held** — tell them not to run `claim.js` (it will fail, per §3)
91
+ - the **known-red test baseline**, by name. If the suite is red on `main` for environmental reasons, an agent that doesn't know will either chase ghosts or quietly assume its own regressions are pre-existing. Give them the exact list and the technique: `git stash push -u`, re-run the suspect test on the clean tree, compare.
92
+ - **report findings, don't fix them.** An agent that patches a defect in a sibling's file creates a conflict and hides a bug. Several of this session's most valuable findings came from agents that stopped and reported.
93
+ - **mutation-test your own tests.** The highest-value defect class here is a test that passes while proving nothing — one agent shipped a first draft where both sides of the comparison read the same field, so mutating it moved both sides together and nothing went red. Require: break the thing deliberately, confirm red, revert, report that you did it.
94
+
95
+ ---
96
+
97
+ ## 5. The merge-conflict tax
98
+
99
+ One file will become the contention point. Here it was the module's nested `CLAUDE.md`: four agents each appended to the same "build plan" line, and the resulting conflicts stalled two ships and needed manual recovery.
100
+
101
+ **Mitigations, best first:**
102
+
103
+ 1. **Don't share the file.** The task that avoided the problem entirely needed a new kernel port, and registered it from a **new** file rather than editing the contended one. Prefer adding a file over editing a shared one.
104
+ 2. **Assign disjoint regions.** If several agents must edit one doc, give each a *specific* slot ("one bullet appended at the end of the Gotchas list", "one paragraph immediately after the R95 block") and forbid reflowing anything else. Different regions usually auto-merge.
105
+ 3. **Accept and recover.** A conflict is a bail, not a corruption — the task parks at `confirmed` and nothing is lost.
106
+
107
+ **Generated files: always resolve by regenerating, never by picking a side.**
108
+
109
+ ```bash
110
+ git checkout --theirs <file>
111
+ node scripts/gds/gen-repo-map.js # or gen-api-docs.js, gen-diagrams.js
112
+ git add <file> && git commit --no-edit
113
+ ```
114
+
115
+ Picking a side leaves the artefact inconsistent with source, and the freshness fitness check fails on the *next* task instead of yours. The generated symbol blocks and the OpenAPI spec both bit us this way.
116
+
117
+ > If `ship.js` says *"auto-merge: bailed; task stays at confirmed"*, don't reach for `/merge-mode` first. Merge `origin/main` into the **task's own branch**, resolve there, re-run `fitness.js`, then re-run `ship.js <id>` — it resumes from `confirmed`. `/merge-mode` is an operator procedure that mutates the main worktree and assumes a bash/SSH environment.
118
+
119
+ ---
120
+
121
+ ## 6. Treat the ship grade as a noisy signal
122
+
123
+ The subagent grader gates on **forwarded confidence**, not just scores. A worker that times out returns no vote, which collapses confidence and fails work that has **no defect finding against it**.
124
+
125
+ Observed in one session: two tasks failed on a worker `SUBAGENT_TIMEOUT` and passed on retry **with zero code change**; another failed three times at 8.5–9.5/10 against a threshold of 6 with 4 of 5 workers passing every time.
126
+
127
+ Practical rules:
128
+
129
+ - **Capture the full grader output.** Do not pipe `ship.js` through `tail` — you will lose the finding and have to pay for another run. Redirect to a file.
130
+ - **Read the per-worker table before reacting.** "4/5 PASS, verdict CONCERNS, confidence 0.3" is an infrastructure failure. "1 worker FAIL" is a real defect.
131
+ - **A re-grade is the right first response** to a timeout-shaped failure. It is also not free — budget for it.
132
+ - **A pass is not evidence either.** A gate this noisy can wave things through. Run a separate adversarial review over the finished work.
133
+ - When the grader repeatedly flags a deliberate architecture decision, that is a signal to **record the decision** (an ADR or a triaged idea) rather than to keep re-litigating it per task — each re-grade costs real money.
134
+
135
+ ---
136
+
137
+ ## 7. Run an adversarial review at the end
138
+
139
+ Fan reviewers out over surfaces, then have **every finding attacked by an independent skeptic prompted to refute by default**. On this goal that pass killed 6 of the top 8 findings — including three that were confidently written and wrong. Two survived, both reproduced end-to-end against the live module, and both were real.
140
+
141
+ What made it work:
142
+
143
+ - Tell reviewers explicitly **not to inherit the ship grades' verdicts**, and to re-derive security claims from the code.
144
+ - Give the skeptics the failure modes to check: is the path actually reachable? is there a compensating control? is this a documented deliberate decision?
145
+ - Name the highest-value defect class up front. Here it was tests whose expectation derives from the same code under test.
146
+ - Findings that are never adversarially verified should be **recorded as unverified**, not reported as defects. With a 6-of-8 refutation rate, an unverified finding is more likely wrong than right.
147
+
148
+ ---
149
+
150
+ ## Checklist
151
+
152
+ ```
153
+ [ ] Pull the real DAG; unwrap .data; be suspicious of an empty dependency graph
154
+ [ ] Audit edge DIRECTION — does anything validate its own prerequisite?
155
+ [ ] Predict files per task; build the conflict graph; group parallel vs serialised
156
+ [ ] Narrow tasks in a tree BEFORE the sweep that owns that tree
157
+ [ ] git worktree per task, branched from a fresh origin/main
158
+ [ ] POST /claims/batch with bind_session:false (NOT claim.js)
159
+ [ ] Brief each agent: worktree path, do-not-touch list, known-red baseline,
160
+ report-don't-fix, mutation-test your tests
161
+ [ ] Assign disjoint regions in any shared doc; prefer a new file
162
+ [ ] Regenerate generated files on conflict; never pick a side
163
+ [ ] Capture full grader output to a file; read the per-worker table
164
+ [ ] Adversarial review at the end; record unverified findings as unverified
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Provenance
170
+
171
+ Goal 1000030 (Governance — configurable roles & permissions), 2026-07-30. 14 tasks shipped; 5 defects found that were outside any task's scope, the most serious being that a demoted builder retained their previous powers because nothing kept role assignments in sync with rank.
172
+
173
+ Related ideas: 1000617 (session-claim guard vs index), 1000618 (legacy ranks resolve to zero permissions), 1000624 (uncached per-request resolve — ADR 0016 tension), 1000625 (`guards` prose has no oracle), 1000626 (unverified review backlog).
174
+ Related tasks: 1002550, 1002551, 1002552, 1002553, 1002554.
@@ -11,8 +11,8 @@
11
11
  `/builder-ship` runs three transitions ([Phase 5](../session-logs/<redacted>.md)):
12
12
 
13
13
  1. **`completed`** — the claim resolves once local verification (smoke) passes. **The claim is consumed here.**
14
- 2. **`confirmed`** — the v2 subagent quality grader (the 4-worker panel: Narc · Quality · Hacker · Efficiency Monger) passes. **Credits land here.**
15
- 3. **`shipped`** — branch auto-merged to `main` + deployed; the Discord `#ship-news` broadcast fires.
14
+ 2. **`confirmed`** — the v2 subagent quality grader (the 4-worker panel: Narc · Quality · Hacker · Efficiency Monger) passes. **Verified, but not yet paid.**
15
+ 3. **`shipped`** — branch auto-merged to `main` + deployed; the Discord `#ship-news` broadcast fires. **Credits land here** ([ADR 0120](../adr/<redacted>.md) pays on land, not on confirm) — so a task stranded at `confirmed` is unpaid until it lands.
16
16
 
17
17
  The grader reads **committed history** (`merge-base origin/main HEAD`…`HEAD`), independent of touches[] — so the diff it judges is whatever you've committed on the branch, not your working tree.
18
18
 
@@ -0,0 +1,48 @@
1
+ # Recipe — live-updating docs on a STANDALONE instance
2
+
3
+ **Read before:** standing up / debugging a standalone instance whose `docs/` is empty or stale.
4
+ **Decision of record:** [ADR 0147](../adr/<redacted>.md) (builds on [ADR 0110](../adr/<redacted>.md) / [ADR 0108](../adr/<redacted>.md)).
5
+
6
+ ## The mental model — which doc refreshes where
7
+
8
+ A standalone instance (its own repo + `@bongos/core` vendored in `node_modules`) has several *generated* docs. They do **not** all refresh the same way:
9
+
10
+ | Doc | Kind | Refreshes | Committed? |
11
+ |---|---|---|---|
12
+ | `docs/session-log-index.md` | whole-file, instance content | **deploy** (`regen-instance-docs.js`) + `bongos upgrade` + init seed | **gitignored** |
13
+ | `docs/api/openapi.json`, `docs/api-reference.md`, `docs/routes-permissions.md` | generated from routes | `bongos init` + `bongos upgrade` | tracked/committed |
14
+ | `docs/file-map.md` | hybrid (prose + generated sections) | ship-time | tracked/committed |
15
+ | `docs/repo-map.md` | CORE symbol map | shipped with `@bongos/core` (core-scoped) | gitignored |
16
+ | onboarding diagrams (`.svg`/`.png`) | rendered | package/CI time (headless browser) | gitignored renders, tracked `.mmd` |
17
+
18
+ Only `session-log-index.md` is regenerated **on deploy** — it's the one whole-file doc whose content (the instance's own session logs) changes as work ships. Everything else is committed-at-ship, shipped-with-core, or rendered-at-package.
19
+
20
+ ## Wiring a standalone deploy to keep docs live
21
+
22
+ The one-liner every standalone deploy script must run **after** `git reset --hard origin/main` + migrate:
23
+
24
+ ```bash
25
+ node node_modules/@bongos/core/scripts/gds/regen-instance-docs.js
26
+ ```
27
+
28
+ Run it with `cwd` = the instance repo root (or set `CLOUDBONGOS_INSTANCE_ROOT=<instance-dir>`). It resolves the instance root, regenerates `docs/session-log-index.md` there, is **best-effort** (always exits 0), and is **LOUD** on failure (`::ERROR::` → journald). A stale nav doc is tolerable; a failed deploy is not (ADR 0110 §2 "accepted staleness").
29
+
30
+ `provision.js` already runs this on its standalone deploy path, and `bongos init` / `bongos upgrade` run it at standup / on a core bump. You only wire it by hand into a **bespoke** pull-deploy script (e.g. cloudbongos.com's `/home/lars/deploy.sh`).
31
+
32
+ ## `.gitignore` requirement
33
+
34
+ The instance repo must gitignore the whole-file docs so `git reset --hard` never wipes the regenerated copy and no branch can diff it:
35
+
36
+ ```
37
+ docs/session-log-index.md
38
+ docs/repo-map.md
39
+ ```
40
+
41
+ `provision.js`'s `INSTANCE_GITIGNORE` seeds these for new instances; an older instance (pre-ADR-0147) needs them added by hand.
42
+
43
+ ## Debugging "my instance's docs are empty / stale"
44
+
45
+ 1. **Empty `docs/` (only the 3 API files)?** The nav-doc seed never ran. Run `regen-instance-docs.js` once, and confirm the deploy script calls it (above).
46
+ 2. **`session-log-index.md` indexes the *core's* sessions, not the instance's?** You're on a core older than the ADR 0147 fix (`gen-session-index.js` hardcoded the core root). `bongos upgrade` to a fixed core.
47
+ 3. **The file keeps disappearing after deploy?** It isn't gitignored — `git reset --hard` wipes it. Add the `.gitignore` lines above.
48
+ 4. **`::ERROR:: regen-instance-docs` in journald?** A generator threw — the deploy still succeeded, but the doc is stale. Check the generator output; the instance must have `docs/session-logs/` and a resolvable instance root.