@bongos/core 1.23.21 → 1.24.1

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 (457) hide show
  1. package/.bongos-core.json +983 -428
  2. package/.claude/skills/blocker-review/SKILL.md +9 -1
  3. package/.claude/skills/blocker-solve/SKILL.md +1 -1
  4. package/.claude/skills/builder-claim/SKILL.md +1 -1
  5. package/.claude/skills/builder-reauth/SKILL.md +1 -1
  6. package/.claude/skills/builder-redteam/SKILL.md +1 -1
  7. package/.claude/skills/builder-sequence/SKILL.md +1 -1
  8. package/.claude/skills/builder-setup/SKILL.md +1 -1
  9. package/.claude/skills/builder-ship/SKILL.md +1 -1
  10. package/.claude/skills/collab-review/SKILL.md +5 -2
  11. package/.claude/skills/design/SKILL.md +1 -1
  12. package/.claude/skills/goal-create/SKILL.md +6 -3
  13. package/.claude/skills/grade-recover/SKILL.md +1 -1
  14. package/.claude/skills/merge-mode/SKILL.md +1 -1
  15. package/.claude/skills/owner-review/SKILL.md +1 -1
  16. package/.claude/skills/planning-session/SKILL.md +11 -11
  17. package/.claude/skills/read-session-export/SKILL.md +1 -1
  18. package/.claude/skills/recall/SKILL.md +1 -1
  19. package/.claude/skills/scan-before-install/SKILL.md +1 -1
  20. package/.claude/skills/session-handoff/SKILL.md +1 -1
  21. package/.claude/skills/strand-fix/SKILL.md +13 -0
  22. package/.claude/skills/worktree-clean/SKILL.md +1 -1
  23. package/AGENTS.md +15 -0
  24. package/GEMINI.md +5 -0
  25. package/clients/bongos-client/README.md +1 -1
  26. package/clients/bongos-client/bongos-client.global.js +94 -0
  27. package/clients/bongos-client/index.cjs +94 -0
  28. package/clients/bongos-client/index.d.ts +154 -4
  29. package/clients/bongos-client/index.mjs +94 -0
  30. package/docs/adr/0054-session-token-reward-cost-plus.md +3 -1
  31. package/docs/adr/0055-server-mediated-branch-publish.md +1 -1
  32. package/docs/adr/0385-money-lives-with-a-processor-credits-stay-a-project-meter.md +87 -0
  33. package/docs/adr/0386-the-funding-wall-is-a-per-project-rule-claim-time-hold-by-default.md +37 -0
  34. package/docs/adr/0387-two-ledgers-credits-measure-work-money-stays-with-the-processor.md +39 -0
  35. package/docs/adr/0388-a-module-sale-is-split-by-the-project-the-buyer-pays-the-platform-fee.md +42 -0
  36. package/docs/adr/0392-ai-generation-runs-on-a-processor-held-balance-and-the-builders-own-keys.md +33 -0
  37. package/docs/adr/0393-a-platform-account-is-a-person-and-github-is-one-way-in.md +37 -0
  38. package/docs/adr/0394-market-watch-searches-through-the-messages-api-on-the-projects-key-and-runs-from-its-own-poller.md +102 -0
  39. package/docs/adr/0395-a-task-says-what-it-needs-and-lists-show-only-what-you-can-do.md +36 -0
  40. package/docs/adr/0396-google-sign-in-a-stand-in-login-and-a-browser-approved-cli-sign-in.md +41 -0
  41. package/docs/adr/README.md +10 -1
  42. package/docs/api/openapi.json +8619 -5885
  43. package/docs/api-reference.md +68 -9
  44. package/docs/architecture.md +37 -1
  45. package/docs/canonical-permissions.md +1 -1
  46. package/docs/copy-inventory.md +420 -337
  47. package/docs/copy-registry.json +1321 -500
  48. package/docs/file-map.md +4 -0
  49. package/docs/module-api-changelog.md +7 -0
  50. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +3 -3
  51. package/docs/onboarding/diagrams/README.md +1 -1
  52. package/docs/onboarding/drachmae-and-karma.md +15 -15
  53. package/docs/onboarding/primer.md +2 -2
  54. package/docs/page-inventory.json +55 -6
  55. package/docs/page-readings.json +1185 -1011
  56. package/docs/recipes/google-sign-in.md +60 -0
  57. package/docs/recipes/ops-gotchas.md +1 -1
  58. package/migrations/core_282_builders_lower_login_idx.sql +33 -0
  59. package/migrations/core_283_claimable_ignores_page_markers.sql +53 -0
  60. package/migrations/core_283_payout_approvals.sql +183 -0
  61. package/migrations/core_284_payout_gates.sql +179 -0
  62. package/migrations/core_285_task_needs.sql +74 -0
  63. package/modules/ai-studio/CLAUDE.md +15 -0
  64. package/modules/ai-studio/billing.js +67 -0
  65. package/modules/ai-studio/context.js +29 -0
  66. package/modules/ai-studio/db.js +172 -0
  67. package/modules/ai-studio/gemini.js +75 -0
  68. package/modules/ai-studio/generate.js +119 -0
  69. package/modules/ai-studio/keys.js +73 -0
  70. package/modules/ai-studio/migrations/ai_studio_001_keys.sql +22 -0
  71. package/modules/ai-studio/migrations/ai_studio_002_ledger.sql +48 -0
  72. package/modules/ai-studio/migrations/ai_studio_003_requests.sql +55 -0
  73. package/modules/ai-studio/module.json +26 -0
  74. package/modules/ai-studio/openrouter.js +90 -0
  75. package/modules/ai-studio/payments.js +105 -0
  76. package/modules/ai-studio/pricing.js +92 -0
  77. package/modules/ai-studio/routes/ai-studio.js +252 -0
  78. package/modules/ai-studio/studio.js +121 -0
  79. package/modules/autonomy/fence.js +64 -1
  80. package/modules/builder-settings/builder-needs.js +27 -1
  81. package/modules/copy-desk/routes/copy-desk.js +5 -0
  82. package/modules/economy/achievements.js +22 -10
  83. package/modules/economy/cost-classify.js +9 -0
  84. package/modules/economy/cost-write-guard.js +52 -0
  85. package/modules/economy/cost.js +2 -1
  86. package/modules/economy/credits.js +18 -15
  87. package/modules/economy/goal-reward.js +161 -0
  88. package/modules/economy/reward.js +4 -0
  89. package/modules/economy/routes/cost.js +33 -7
  90. package/modules/government/catalog.js +6 -0
  91. package/modules/government/db.js +108 -0
  92. package/modules/government/docket.js +36 -0
  93. package/modules/government/migrations/government_035_payout_approve.sql +29 -0
  94. package/modules/government/pollers/board-expiry.js +108 -20
  95. package/modules/government/protected-surfaces.json +1 -0
  96. package/modules/government/routes/government.js +50 -18
  97. package/modules/government/routing.js +39 -5
  98. package/modules/government/waiting.js +74 -0
  99. package/modules/grading/grader-subagent.js +30 -11
  100. package/modules/hall-ui/public/ai-studio-lib.js +268 -0
  101. package/modules/hall-ui/public/ai-studio.css +193 -0
  102. package/modules/hall-ui/public/ai-studio.html +98 -0
  103. package/modules/hall-ui/public/ai-studio.js +556 -0
  104. package/modules/hall-ui/public/ai-studio.states.json +94 -0
  105. package/modules/hall-ui/public/blockers-by-person.js +156 -0
  106. package/modules/hall-ui/public/blockers-lib.js +15 -1
  107. package/modules/hall-ui/public/blockers.html +8 -0
  108. package/modules/hall-ui/public/blockers.js +1 -1
  109. package/modules/hall-ui/public/city.html +15 -15
  110. package/modules/hall-ui/public/claim-action.js +3 -0
  111. package/modules/hall-ui/public/collab.html +12 -0
  112. package/modules/hall-ui/public/craft-mode.js +4 -1
  113. package/modules/hall-ui/public/criterion-uat-ui.js +4 -1
  114. package/modules/hall-ui/public/drachmae.html +1 -1
  115. package/modules/hall-ui/public/genesis/r5-life-1-primordial-sea.jpg +0 -0
  116. package/modules/hall-ui/public/genesis/r5-life-2-first-cells-cut.webp +0 -0
  117. package/modules/hall-ui/public/genesis/r5-life-2-first-cells.jpg +0 -0
  118. package/modules/hall-ui/public/genesis/r5-life-3-genome-cut.webp +0 -0
  119. package/modules/hall-ui/public/genesis/r5-life-3-genome.jpg +0 -0
  120. package/modules/hall-ui/public/genesis/r5-life-4-membrane-cut.webp +0 -0
  121. package/modules/hall-ui/public/genesis/r5-life-4-membrane.jpg +0 -0
  122. package/modules/hall-ui/public/genesis/r5-life-5-nervous-system-cut.webp +0 -0
  123. package/modules/hall-ui/public/genesis/r5-life-5-nervous-system.jpg +0 -0
  124. package/modules/hall-ui/public/goal-inbox.js +1 -1
  125. package/modules/hall-ui/public/goals-render.js +4 -0
  126. package/modules/hall-ui/public/goals.html +8 -0
  127. package/modules/hall-ui/public/gov-living.js +6 -2
  128. package/modules/hall-ui/public/hall-ask.css +5 -0
  129. package/modules/hall-ui/public/hall-ask.js +39 -3
  130. package/modules/hall-ui/public/notes-panel.css +20 -0
  131. package/modules/hall-ui/public/notes-panel.js +146 -0
  132. package/modules/hall-ui/public/project-settings.html +1 -1
  133. package/modules/hall-ui/public/project-settings.js +7 -5
  134. package/modules/hall-ui/public/settings-ai-keys.js +124 -0
  135. package/modules/hall-ui/public/settings.html +15 -0
  136. package/modules/hall-ui/public/street-deck.js +12 -3
  137. package/modules/hall-ui/public/studio.css +90 -8
  138. package/modules/hall-ui/public/studio.html +39 -10
  139. package/modules/hall-ui/public/studio.js +148 -18
  140. package/modules/hall-ui/public/task.html +2 -0
  141. package/modules/hall-ui/public/task.js +4 -0
  142. package/modules/hall-ui/public/tweak-editor.js +12 -3
  143. package/modules/hall-ui/public/welcome-boot.css +42 -6
  144. package/modules/hall-ui/public/welcome-boot.js +20 -6
  145. package/modules/hall-ui/public/work.js +20 -0
  146. package/modules/hall-ui/records/ai-studio.md +36 -0
  147. package/modules/hall-ui/records/blockers-people.md +24 -0
  148. package/modules/lifecycle/db-analytics.js +10 -3
  149. package/modules/lifecycle/db-claims.js +32 -4
  150. package/modules/lifecycle/db-goals.js +48 -18
  151. package/modules/lifecycle/db-shared.js +9 -0
  152. package/modules/lifecycle/db-tasks.js +15 -6
  153. package/modules/lifecycle/db-versions.js +21 -8
  154. package/modules/lifecycle/done-when.js +23 -1
  155. package/modules/lifecycle/lifecycle.js +5 -0
  156. package/modules/lifecycle/migrations/lifecycle_017_notes.sql +46 -0
  157. package/modules/lifecycle/module.json +2 -1
  158. package/modules/lifecycle/notes.js +219 -0
  159. package/modules/lifecycle/page-notice.js +124 -0
  160. package/modules/lifecycle/page-tweak-artist.js +18 -1
  161. package/modules/lifecycle/publish-reconciler.js +67 -20
  162. package/modules/lifecycle/routes/claims.js +5 -2
  163. package/modules/lifecycle/routes/goals.js +3 -1
  164. package/modules/lifecycle/routes/notes.js +91 -0
  165. package/modules/lifecycle/routes/project-settings.js +43 -35
  166. package/modules/lifecycle/routes/task-route-helpers.js +21 -0
  167. package/modules/lifecycle/routes/task-write-routes.js +21 -3
  168. package/modules/lifecycle/routes/tasks.js +12 -12
  169. package/modules/lifecycle/ship-assurance.js +4 -1
  170. package/modules/lifecycle/ship-card.js +8 -2
  171. package/modules/lifecycle/task-needs-gate.js +70 -0
  172. package/modules/market-watch/CLAUDE.md +15 -0
  173. package/modules/market-watch/db.js +340 -0
  174. package/modules/market-watch/key.js +58 -0
  175. package/modules/market-watch/migrations/market_watch_001_tables.sql +249 -0
  176. package/modules/market-watch/migrations/market_watch_002_run.sql +46 -0
  177. package/modules/market-watch/module.json +26 -0
  178. package/modules/market-watch/pollers/hub-seed.js +54 -0
  179. package/modules/market-watch/pollers/weekly-run.js +100 -0
  180. package/modules/market-watch/research.js +350 -0
  181. package/modules/market-watch/run.js +245 -0
  182. package/modules/market-watch/seed/market-data.json +38 -0
  183. package/modules/market-watch/seed/partners-data.json +497 -0
  184. package/modules/market-watch/seed.js +252 -0
  185. package/modules/market-watch/store.js +230 -0
  186. package/modules/memory/routes/memory.js +14 -2
  187. package/modules/memory/routes/search.js +8 -2
  188. package/modules/onboarding/howto-moments.js +8 -1
  189. package/modules/platform-identity/account-logins.js +192 -0
  190. package/modules/platform-identity/migrations/platform_identity_034_account_logins.sql +96 -0
  191. package/modules/platform-identity/platform-identity.js +5 -4
  192. package/modules/platform-identity/routes/my-projects.js +6 -0
  193. package/modules/platform-identity/routes/profile.js +18 -0
  194. package/modules/platform-identity/routes/public-profile.js +10 -1
  195. package/modules/platform-identity/routes/sso.js +26 -1
  196. package/modules/platform-identity/tests/platform-identity.mjs +2 -1
  197. package/modules/provisioning/credential-preflight.js +13 -3
  198. package/modules/provisioning/pollers/app-liveness.js +25 -5
  199. package/modules/provisioning/routes/provisioning.js +1 -1
  200. package/modules/provisioning/starter-bundles.js +8 -2
  201. package/modules/public-landing/public/account.html +10 -2
  202. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg +0 -0
  203. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg.json +1 -1
  204. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp +0 -0
  205. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp.json +1 -1
  206. package/modules/public-landing/public/assets/world/r2-chrome-blob-one-cut.webp +0 -0
  207. package/modules/public-landing/public/assets/world/r2-chrome-blob-one-cut.webp.json +1 -1
  208. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg +0 -0
  209. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg.json +1 -1
  210. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp +0 -0
  211. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp.json +1 -1
  212. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg +0 -0
  213. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg.json +1 -1
  214. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp +0 -0
  215. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp.json +1 -1
  216. package/modules/public-landing/public/assets/world/r3-frost-bead-cut.webp +0 -0
  217. package/modules/public-landing/public/assets/world/r3-frost-bead-cut.webp.json +1 -1
  218. package/modules/public-landing/public/assets/world/r3-frost-pair-cut.webp +0 -0
  219. package/modules/public-landing/public/assets/world/r3-frost-pair-cut.webp.json +1 -1
  220. package/modules/public-landing/public/assets/world/r3-gold-blob-cut.webp +0 -0
  221. package/modules/public-landing/public/assets/world/r3-gold-blob-cut.webp.json +1 -1
  222. package/modules/public-landing/public/assets/world/r3-gold-pair-cut.webp +0 -0
  223. package/modules/public-landing/public/assets/world/r3-gold-pair-cut.webp.json +1 -1
  224. package/modules/public-landing/public/assets/world/r3-obsidian-blob-cut.webp +0 -0
  225. package/modules/public-landing/public/assets/world/r3-obsidian-blob-cut.webp.json +1 -1
  226. package/modules/public-landing/public/assets/world/r3-obsidian-pair-cut.webp +0 -0
  227. package/modules/public-landing/public/assets/world/r3-obsidian-pair-cut.webp.json +1 -1
  228. package/modules/public-landing/public/assets/world/r3-space-nebula.jpg +0 -0
  229. package/modules/public-landing/public/assets/world/r3-space-nebula.jpg.json +1 -1
  230. package/modules/public-landing/public/assets/world/r4-card-chrome.jpg +0 -0
  231. package/modules/public-landing/public/assets/world/r4-card-chrome.jpg.json +1 -1
  232. package/modules/public-landing/public/assets/world/r4-card-nebula.jpg +0 -0
  233. package/modules/public-landing/public/assets/world/r4-card-nebula.jpg.json +1 -1
  234. package/modules/public-landing/public/assets/world/r5-life-1-primordial-sea.jpg +0 -0
  235. package/modules/public-landing/public/assets/world/r5-life-1-primordial-sea.jpg.json +1 -1
  236. package/modules/public-landing/public/assets/world/r5-life-2-first-cells-cut.webp +0 -0
  237. package/modules/public-landing/public/assets/world/r5-life-2-first-cells-cut.webp.json +1 -1
  238. package/modules/public-landing/public/assets/world/r5-life-2-first-cells.jpg +0 -0
  239. package/modules/public-landing/public/assets/world/r5-life-2-first-cells.jpg.json +1 -1
  240. package/modules/public-landing/public/assets/world/r5-life-3-genome-cut.webp +0 -0
  241. package/modules/public-landing/public/assets/world/r5-life-3-genome-cut.webp.json +1 -1
  242. package/modules/public-landing/public/assets/world/r5-life-3-genome.jpg +0 -0
  243. package/modules/public-landing/public/assets/world/r5-life-3-genome.jpg.json +1 -1
  244. package/modules/public-landing/public/assets/world/r5-life-4-membrane-cut.webp +0 -0
  245. package/modules/public-landing/public/assets/world/r5-life-4-membrane-cut.webp.json +1 -1
  246. package/modules/public-landing/public/assets/world/r5-life-4-membrane.jpg +0 -0
  247. package/modules/public-landing/public/assets/world/r5-life-4-membrane.jpg.json +1 -1
  248. package/modules/public-landing/public/assets/world/r5-life-5-nervous-system-cut.webp +0 -0
  249. package/modules/public-landing/public/assets/world/r5-life-5-nervous-system-cut.webp.json +1 -1
  250. package/modules/public-landing/public/assets/world/r5-life-5-nervous-system.jpg +0 -0
  251. package/modules/public-landing/public/assets/world/r5-life-5-nervous-system.jpg.json +1 -1
  252. package/modules/public-landing/public/community.html +1 -1
  253. package/modules/public-landing/public/connections.html +2 -2
  254. package/modules/public-landing/public/guild.html +1 -1
  255. package/modules/public-landing/public/invitations.html +2 -2
  256. package/modules/public-landing/public/projects.html +5 -5
  257. package/modules/raise/views/nda.html +2 -0
  258. package/modules/specialities/db.js +32 -1
  259. package/modules/specialities/routes/specialities.js +10 -6
  260. package/modules/status-ui/public/index.html +1 -1
  261. package/package-lock.json +2 -2
  262. package/package.json +1 -1
  263. package/release-notes.json +286 -0
  264. package/scripts/bongos/autobongos-tweak-lane.js +46 -1
  265. package/scripts/bongos/backfill-subagent-rewards.js +2 -2
  266. package/scripts/bongos/claim.js +22 -1
  267. package/scripts/bongos/db-backup-nightly.sh +29 -0
  268. package/scripts/bongos/deploy-divergence.js +7 -0
  269. package/scripts/bongos/doc-cli-guard.js +6 -0
  270. package/scripts/bongos/fitness.js +3 -2
  271. package/scripts/bongos/gen-diagrams.js +3 -3
  272. package/scripts/bongos/lib.sh +4 -5
  273. package/scripts/bongos/migration-namespace.js +13 -1
  274. package/scripts/bongos/plain-cards.js +4 -0
  275. package/scripts/bongos/provision-github-setup.js +3 -1
  276. package/scripts/bongos/provision-units.js +6 -1
  277. package/scripts/bongos/publish-manifest.js +4 -0
  278. package/scripts/bongos/release.js +2 -0
  279. package/scripts/bongos/run-unit-tests.js +268 -82
  280. package/scripts/bongos/seed-tasks.example.json +56 -0
  281. package/scripts/bongos/seed-tasks.js +222 -0
  282. package/scripts/bongos/seed-verify-criteria.js +1 -2
  283. package/scripts/bongos/ship-finish.js +2 -0
  284. package/scripts/bongos/ship-resume.js +2 -0
  285. package/scripts/bongos/strand-lease.js +250 -0
  286. package/scripts/bongos/strand-watch.js +129 -12
  287. package/scripts/bongos/version-literal-guard.js +2 -2
  288. package/scripts/discord/post.js +4 -3
  289. package/scripts/gds/seed-tasks.js +7 -0
  290. package/scripts/gds/{build-bongos.js → strand-lease.js} +3 -3
  291. package/scripts/hall-preview/server.js +21 -0
  292. package/src/bongos/auth-config.js +29 -1
  293. package/src/bongos/auth-discord.js +3 -3
  294. package/src/bongos/auth-github.js +3 -6
  295. package/src/bongos/auth-google.js +217 -0
  296. package/src/bongos/device-approval.js +140 -0
  297. package/src/bongos/llm-pricing.js +17 -1
  298. package/src/bongos/metrics.js +48 -2
  299. package/src/bongos/middleware/rate-limit.js +30 -11
  300. package/src/bongos/module-scope-map.js +16 -1
  301. package/src/bongos/optimizer.js +15 -1
  302. package/src/bongos/payout-approvals.js +342 -0
  303. package/src/bongos/payout-gates.js +364 -0
  304. package/src/bongos/prelaunch-gate.js +7 -9
  305. package/src/bongos/prelaunch-switch.js +20 -0
  306. package/src/bongos/route-rank-check.js +3 -0
  307. package/src/bongos/routes/auth-google.js +246 -0
  308. package/src/bongos/routes/auth.js +38 -1
  309. package/src/bongos/routes/backup.js +33 -9
  310. package/src/bongos/routes/builders.js +57 -30
  311. package/src/bongos/routes/github.js +9 -0
  312. package/src/bongos/routes/me.js +18 -0
  313. package/src/bongos/routes/my-payouts.js +133 -0
  314. package/src/bongos/routes/payout-approvals.js +312 -0
  315. package/src/bongos/routes/payout-gates.js +179 -0
  316. package/src/bongos/routes.js +15 -1
  317. package/src/bongos/secret-box.js +18 -3
  318. package/src/bongos/serve-internal.js +47 -19
  319. package/src/bongos/sign-in-pages.js +138 -0
  320. package/src/bongos/task-needs.js +146 -0
  321. package/src/bongos-downloads.js +18 -1
  322. package/src/instance-config.js +28 -0
  323. package/src/module-api.js +14 -1
  324. package/src/platform-server.js +27 -1
  325. package/tests/account_logins.mjs +326 -0
  326. package/tests/account_logins_db.mjs +161 -0
  327. package/tests/ai_studio_billing.mjs +253 -0
  328. package/tests/ai_studio_generate.mjs +282 -0
  329. package/tests/ai_studio_keys.mjs +159 -0
  330. package/tests/ai_studio_requests.mjs +319 -0
  331. package/tests/auth_backchannel_logout_route.mjs +201 -0
  332. package/tests/auto_satisfy_criteria.mjs +10 -1
  333. package/tests/autobongos_tweak_lane.mjs +144 -0
  334. package/tests/autobongos_tweak_pin_identity.mjs +137 -0
  335. package/tests/backfill_subagent_rewards.mjs +17 -1
  336. package/tests/backup_trigger_lock.mjs +119 -0
  337. package/tests/batched_writes_parity.mjs +340 -0
  338. package/tests/blockers_people.mjs +198 -0
  339. package/tests/bounded_rate_maps.mjs +184 -0
  340. package/tests/claimable_blocker_status.mjs +1 -1
  341. package/tests/claims_batch_routes.mjs +421 -0
  342. package/tests/conductor_main_e2e.mjs +4 -0
  343. package/tests/config_read_cache.mjs +171 -0
  344. package/tests/copy_desk_page_editor.mjs +12 -0
  345. package/tests/cost_write_guard.mjs +200 -0
  346. package/tests/craft_achievements.mjs +33 -10
  347. package/tests/criterion_goal_attach.mjs +1 -1
  348. package/tests/db_backup_nightly.mjs +73 -1
  349. package/tests/deploy_divergence_line.mjs +7 -0
  350. package/tests/effective_visibility_predicate.mjs +12 -0
  351. package/tests/fitness.mjs +19 -0
  352. package/tests/fixtures/per-row-loops-legacy.cjs +245 -0
  353. package/tests/fixtures/seed-tasks/bongos-v1-idea-routing.json +256 -0
  354. package/tests/fixtures/seed-tasks/bv1-profiles.json +592 -0
  355. package/tests/fixtures/seed-tasks/bv2-ideator-surface.json +373 -0
  356. package/tests/fixtures/seed-tasks/fake-api.mjs +80 -0
  357. package/tests/github_one_trip.mjs +34 -0
  358. package/tests/github_repo_visibility.mjs +20 -0
  359. package/tests/goal_achievement.mjs +30 -1
  360. package/tests/goal_achievement_reward.mjs +205 -0
  361. package/tests/goal_archive_disposition.mjs +5 -5
  362. package/tests/goal_sort_staleness.mjs +2 -1
  363. package/tests/goal_tier.mjs +11 -1
  364. package/tests/google_fonts_nonblocking.mjs +84 -0
  365. package/tests/google_sign_in.mjs +401 -0
  366. package/tests/government_board_expiry.mjs +94 -0
  367. package/tests/government_protected_surfaces.mjs +1 -1
  368. package/tests/government_routes.mjs +146 -23
  369. package/tests/grader.mjs +31 -0
  370. package/tests/hall_ai_studio.mjs +347 -0
  371. package/tests/hall_city.mjs +8 -0
  372. package/tests/hall_page_gate_map.mjs +3 -0
  373. package/tests/hall_studio_home.mjs +61 -2
  374. package/tests/home_attention_cards.mjs +1 -1
  375. package/tests/hook_shell_tools.mjs +8 -0
  376. package/tests/hooks_drain.mjs +1 -1
  377. package/tests/host_topology_skips.mjs +2 -0
  378. package/tests/howto_moments.mjs +17 -0
  379. package/tests/human_signal.mjs +141 -0
  380. package/tests/install_script_reader.mjs +51 -0
  381. package/tests/integration_fixture_ids.mjs +82 -0
  382. package/tests/invite_expiry_db.mjs +13 -1
  383. package/tests/lib_sh_resolution.mjs +0 -4
  384. package/tests/market_watch_data.mjs +244 -0
  385. package/tests/market_watch_data_db.mjs +308 -0
  386. package/tests/market_watch_module.mjs +114 -0
  387. package/tests/market_watch_run.mjs +503 -0
  388. package/tests/metrics.mjs +124 -0
  389. package/tests/migration_namespace.mjs +14 -0
  390. package/tests/module_api.mjs +2 -0
  391. package/tests/module_loader.mjs +1 -1
  392. package/tests/module_skills_hook.mjs +69 -0
  393. package/tests/notes.mjs +182 -0
  394. package/tests/own_scope_guard.mjs +5 -0
  395. package/tests/page_tweak_marker_sql.mjs +76 -0
  396. package/tests/page_tweak_no_block.mjs +135 -0
  397. package/tests/page_tweak_notice.mjs +103 -0
  398. package/tests/payout_approvals.mjs +253 -0
  399. package/tests/payout_approvals_db.mjs +106 -0
  400. package/tests/payout_gates.mjs +322 -0
  401. package/tests/payout_gates_db.mjs +113 -0
  402. package/tests/planning_session_skill.mjs +13 -3
  403. package/tests/project_settings_page.mjs +29 -5
  404. package/tests/project_settings_spend_cap_route.mjs +235 -0
  405. package/tests/promotion_sweep.mjs +29 -1
  406. package/tests/provision.mjs +3 -2
  407. package/tests/provisioning_app_status.mjs +18 -0
  408. package/tests/provisioning_credential_preflight.mjs +53 -0
  409. package/tests/provisioning_env_manifest_edit_delete.mjs +223 -0
  410. package/tests/public_landing_projects.mjs +37 -0
  411. package/tests/publish_reconciler_overlap.mjs +60 -0
  412. package/tests/rank_change_broadcast_port.mjs +151 -0
  413. package/tests/seed_tasks.mjs +176 -0
  414. package/tests/seed_verify_criteria.mjs +2 -6
  415. package/tests/session_start_freshness.mjs +66 -1
  416. package/tests/shell_hooks.mjs +209 -0
  417. package/tests/ship_assurance.mjs +28 -0
  418. package/tests/ship_card.mjs +20 -5
  419. package/tests/site_classified_once.mjs +142 -0
  420. package/tests/speciality_db_shape.mjs +23 -0
  421. package/tests/speciality_session_skills.mjs +48 -2
  422. package/tests/strand_lease.mjs +249 -0
  423. package/tests/strand_watch.mjs +58 -0
  424. package/tests/task_criteria_routes.mjs +275 -0
  425. package/tests/task_criteria_unlink_db.mjs +123 -0
  426. package/tests/task_needs.mjs +233 -0
  427. package/tests/task_needs_db.mjs +110 -0
  428. package/tests/unit_runner_serial.mjs +266 -43
  429. package/tests/version_close_route.mjs +1 -1
  430. package/tests/version_literals.mjs +5 -7
  431. package/tests/welcome_boot.mjs +16 -5
  432. package/tests/welcome_boot_browser.mjs +36 -4
  433. package/docs/recipes/bongos-cli-release.md +0 -66
  434. package/scripts/bongos/backfill-disciplines.js +0 -144
  435. package/scripts/bongos/backfill-session-earnings.js +0 -123
  436. package/scripts/bongos/backfill-session-types.js +0 -87
  437. package/scripts/bongos/build-bongos.js +0 -94
  438. package/scripts/bongos/cleanup-orphans.js +0 -74
  439. package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +0 -152
  440. package/scripts/bongos/seed-bv1-profiles-tasks.js +0 -135
  441. package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +0 -390
  442. package/scripts/bongos/smoke-batch-claim.sh +0 -238
  443. package/scripts/bongos/smoke-batch-release.sh +0 -316
  444. package/scripts/bongos/smoke-claim-consistency.sh +0 -222
  445. package/scripts/bongos/smoke-dependencies.sh +0 -143
  446. package/scripts/gds/backfill-disciplines.js +0 -7
  447. package/scripts/gds/backfill-session-earnings.js +0 -7
  448. package/scripts/gds/backfill-session-types.js +0 -7
  449. package/scripts/gds/cleanup-orphans.js +0 -7
  450. package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +0 -6
  451. package/scripts/gds/seed-bv1-profiles-tasks.js +0 -6
  452. package/scripts/gds/seed-bv2-ideator-surface-tasks.js +0 -6
  453. package/scripts/gds/smoke-batch-claim.sh +0 -8
  454. package/scripts/gds/smoke-batch-release.sh +0 -8
  455. package/scripts/gds/smoke-claim-consistency.sh +0 -8
  456. package/scripts/gds/smoke-dependencies.sh +0 -8
  457. package/tests/smoke_dependencies_witness.mjs +0 -46
@@ -1,152 +0,0 @@
1
- // DO NOT COPY THE `crit:` TOKENS FROM THIS FILE (task 1003108) — copy its
2
- // verifySeedCriteriaLinks tail instead, which is what this script is cited for.
3
- // Its positional "Cn" refs rank over the whole VERSION's criteria, so on a
4
- // multi-goal version they resolve to another goal's criterion silently (learning
5
- // 1000188). POST /tasks now refuses a positional ref there (400
6
- // ambiguous_criterion_ref). A new seed uses criterion_id SLUGS.
7
- //
8
- // Seed the tasks for goal 1000071 "Idea routing — work that has a home lands in it" (BONGOS-V1).
9
- // Source of truth: docs/specs/bongos-v1-idea-routing.md (status: final).
10
- // Idempotent on (source, source_ref). Re-running resolves to the existing rows.
11
- // Reference implementation (task 1003076) for the seeding contract's self-check:
12
- // ends by tallying the criterion_ids it actually POSTed and diffing that plan
13
- // against GET /goals/<id>'s real linked_tasks — see seed-verify-criteria.js.
14
- //
15
- // Run: node scripts/bongos/seed-bongos-v1-idea-routing-tasks.js
16
- const os = require('os');
17
- const { expectedCriterionCounts, verifySeedCriteriaLinks } = require('./seed-verify-criteria');
18
- const sess = require(os.homedir() + '/.config/cloudbongos/gds-session.json');
19
- const BASE = sess.api_base.replace(/\/$/, '');
20
- const TOKEN = sess.token;
21
- const VER = 'BONGOS-V1';
22
- const GOAL = 1000071;
23
- const SRC = 'planning-session';
24
- const META_TASK = 1003059; // this planning session's meta task — moved into the goal
25
- const DISCORD_BUGS_IDEA = 1000771; // subsumed by R11; marked promoted against it
26
- const H = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' };
27
-
28
- const { sleep } = require('../../src/sleep'); // the one shared sleep (task 1004893)
29
- async function api(method, path, body, _tries = 0) {
30
- await sleep(400); // base throttle to stay under the per-IP rate limit
31
- const res = await fetch(`${BASE}/api/bongos${path}`, {
32
- method, headers: H, body: body ? JSON.stringify(body) : undefined,
33
- });
34
- const text = await res.text();
35
- let json; try { json = JSON.parse(text); } catch { json = { _raw: text.slice(0, 300) }; }
36
- if (res.status === 429 && _tries < 8) {
37
- const wait = ((json.error && json.error.details && json.error.details.retry_after_seconds) || 30) + 1;
38
- console.log(` …rate-limited, waiting ${wait}s`);
39
- await sleep(wait * 1000);
40
- return api(method, path, body, _tries + 1);
41
- }
42
- return { status: res.status, ok: res.ok, json };
43
- }
44
-
45
- // Landing matrix (interview-decided): bugs hard-land (Metic+ filer → ready; sub-Metic → backlog);
46
- // every other goal-bound kind soft-lands (backlog, one Metic+ promote away); homeless → inbox.
47
- //
48
- // crit uses the goal's criterion SLUGS via CRIT — positional "Cn" tokens resolve against the
49
- // whole VERSION's criterion order (and even matched an old criterion literally slugged "C1"),
50
- // which mislinked the first seed run; slugs are position-independent.
51
- const CRIT = {
52
- C1: 'bug-lands-in-its-goal', C2: 'inbox-holds-only-homeless', C3: 'no-route-loses-the-author',
53
- C4: 'filing-cannot-outrun-rank', C5: 'system-offers-the-home', C6: 'triage-shrinks-to-judgment',
54
- };
55
- const TASKS = [
56
- // T1 — zero-dep layer — P5
57
- { ref:'R02', kind:'infra', disc:'engineer', prio:5, est:90, crit:['C1','C3'], deps:[], title:'R02 · Schema: idea_inbox.suggested_goal_id + lineage origin \'route\'', desc:'Core migration: nullable suggested_goal_id FK on idea_inbox (routing hint for soft-landed/Discord/homeless ideas). Module migration (ideas_*): extend ideas_task_lineage.origin CHECK with \'route\'. See docs/specs/bongos-v1-idea-routing.md.' },
58
- { ref:'R03', kind:'bug', disc:'engineer', prio:5, est:90, crit:['C1'], deps:[], title:'R03 · Catch-all fallback never resolves to a non-building version', desc:'generalGoalIdForVersion (modules/lifecycle/db.js:1343) + the null-goal fallback (:1414): a task create must never land in a shipped/frozen version\'s catch-all goal (the 1000771 failure shape). Routed creates with no goal go to the inbox instead. Done-when: test proves a create against a shipped version cannot resolve a catch-all.' },
59
- { ref:'R07', kind:'feature', disc:'engineer', prio:5, est:120, crit:['C5'], deps:[], title:'R07 · Capture-time goal suggester (advisory consulted BEFORE creation)', desc:'Expose candidate goals for a draft capture — reuse buildGoalAdvisory\'s candidate logic (modules/lifecycle/goal-advisory.js:89) as a pre-creation read (e.g. GET /inbox/goal-suggestions?title=&kind=&version=). Feeds the hall picker (R08), CLI (R09), and Discord suggestion (R11). Done-when: candidates returned for a draft title/kind without creating anything.' },
60
- { ref:'R10', kind:'feature', disc:'ui', prio:5, est:120, crit:['C5'], deps:[], title:'R10 · Hall move-a-task-to-goal affordance', desc:'PATCH /tasks/:id {goal_id} (task 1763) exists but has no hall UI. Add move-to-goal on the task overlay (Metic+, task.edit) so a wrong routing pick is one reassignment, never a re-file. Done-when: a Metic+ moves a task between same-version goals from the hall.' },
61
- { ref:'R14', kind:'decision', disc:'engineer', prio:5, est:60, crit:['C2'], deps:[], title:'R14 · ADR: idea routing — capture-time promotion, the landing matrix, the homeless-only inbox', desc:'Write the ADR recording: routing mechanism is capture-time promotion (never inbox bypass — the Discord #bugs lesson), the landing matrix (bugs hard-land by rank; other kinds soft-land; Full Ideas/criterion-proposals/decisions never auto-route), and the inbox\'s new identity (holds only work without a home). Source: docs/specs/bongos-v1-idea-routing.md interview decisions.' },
62
-
63
- // T2 — the core mechanism — P5
64
- { ref:'R01', kind:'feature', disc:'engineer', prio:5, est:240, crit:['C1','C3'], deps:['R02'], title:'R01 · Capture-time routing core: POST /inbox accepts goal_id and converts in one transaction', desc:'Extend inbox.captureIdea/route: when goal_id present and the landing matrix says route, one transaction writes the idea row (status=promoted, promoted_to_task_id), the task (in the goal, matrix-decided status), and ideas_task_lineage (origin=route). Validations: goal open + belongs to a building version; Full-grade and criterion-proposal/decision kinds never auto-route; goal-less capture behaves exactly as today. Deps R02.' },
65
-
66
- // T3 — enforcement + surfaces — P4
67
- { ref:'R05', kind:'feature', disc:'engineer', prio:4, est:150, crit:['C4'], deps:['R01'], title:'R05 · Rank-aware landing: matrix enforcement server-side', desc:'Metic+ filer\'s bug → status=ready; sub-Metic filer / any non-bug kind → backlog (awaiting any Metic+ promote via the existing task.promote, surfaced in the Needs-your-attention slice). Auto-derived requires_rank floors (ADR 0084) and the goal scope wall run on routed tasks exactly as on authored ones. Deps R01.' },
68
- { ref:'R11', kind:'feature', disc:'engineer', prio:4, est:180, crit:['C1','C3'], deps:['R01'], title:'R11 · Discord #bugs retired onto the routing path', desc:'Replace discord-bugs.js\'s direct createTask bypass (hardcoded GDS-V3 → goal 1000002 catch-all; destroys attribution) with capture-time routing: idea row + classifier-suggested goal (suggested_goal_id), soft-landing into the pending queue for a one-click Metic+ route. Unlinked authors still yield an attributable idea row (captured_by null). Closes inbox idea 1000771. Deps R01.' },
69
- { ref:'R12', kind:'feature', disc:'engineer', prio:4, est:120, crit:['C5'], deps:['R02'], title:'R12 · Discord #ideas carries routing hints', desc:'The #ideas inbound (discord-inbound.js) files with no suggested_version at all today. Add: default suggested_version (most-recent building), classifier-suggested suggested_goal_id. Deps R02.' },
70
- { ref:'R08', kind:'feature', disc:'ui', prio:4, est:240, crit:['C1','C5'], deps:['R01','R07'], title:'R08 · Hall filing surface: file a bug/idea with a goal picker', desc:'The hall has NO capture surface today (triage only). Add file-a-bug/idea: title, body, kind, goal picker fed by the suggester (R07); submits to POST /inbox with goal_id so goal-bound work routes at filing time. Grade capture untouched. Deps R01,R07.' },
71
- { ref:'R09', kind:'feature', disc:'engineer', prio:4, est:120, crit:['C1','C5'], deps:['R01','R07'], title:'R09 · CLI capture routing: --goal, suggester prompt, active-claim default', desc:'capture.js gains --goal; when the builder holds a claim the suggested goal defaults to the claim\'s goal (interview decision 4); suggester candidates offered otherwise. Deps R01,R07.' },
72
- { ref:'R13', kind:'feature', disc:'engineer', prio:4, est:120, crit:['C2','C6'], deps:['R07'], title:'R13 · Promote path passes goal_id; /idea-triage goes homeless-only', desc:'task-detail.js (:320) and triage.js (:160) finally send goal_id (suggester-fed default) so even triaged promotions land in a real goal; the /idea-triage skill doc is updated to the homeless-only contract. Deps R07.' },
73
-
74
- // T4 — proofs — P3
75
- { ref:'R04', kind:'verify', disc:'engineer', prio:3, est:90, crit:['C3'], deps:['R01'], title:'R04 · PROOF: attribution survives the route end-to-end', desc:'A routed bug\'s task ships; sourceIdeaForTask returns the filer; ideas_task_lineage (origin=route) + captured_by intact — the trail goal 1000067\'s ideator credit will pay against (test). Deps R01.' },
76
- { ref:'R06', kind:'verify', disc:'engineer', prio:3, est:120, crit:['C4'], deps:['R05'], title:'R06 · PROOF: abuse matrix — filing cannot escalate', desc:'A Xenos mass-filing bugs never lands claimable work, never reaches protected scope, rate limits hold; a sub-Metic cannot reach ready via any capture vector (test suite). Deps R05.' },
77
-
78
- // T5 — the measured close — P2
79
- { ref:'R15', kind:'verify', disc:'engineer', prio:2, est:120, crit:['C2','C6'], deps:['R01','R05','R13'], title:'R15 · PROOF: reclassification sweep of the open inbox', desc:'Walk the open idea_inbox (~50 rows at planning time; 14 bugs) under the new rules: every goal-bound bug homed in a real goal; residual inbox is homeless-only; before/after counts recorded in this task\'s notes as the goal\'s measured evidence. Deps R01,R05,R13.' },
80
- ];
81
-
82
- const ROOTS = ['R02', 'R03', 'R07', 'R10', 'R14']; // zero-dep, non-spike → open for claiming
83
-
84
- (async () => {
85
- const idByRef = {};
86
- let created = 0, existing = 0;
87
- // Resolved (post-CRIT-mapping) criterion_ids per task — the plan the final
88
- // self-check diffs against, kept in lockstep with what's actually POSTed
89
- // below rather than re-derived from the raw "Cn" tokens.
90
- const criterionIdListsPerTask = [];
91
- console.log(`Seeding ${TASKS.length} tasks under goal ${GOAL} (${VER})…`);
92
- for (const t of TASKS) {
93
- const criterionIds = t.crit.map((c) => CRIT[c]);
94
- const r = await api('POST', '/tasks', {
95
- version_id: VER, goal_id: GOAL, title: t.title, description: t.desc,
96
- kind: t.kind, discipline: t.disc, priority: t.prio, est_minutes: t.est,
97
- criterion_ids: criterionIds, source: SRC, source_ref: `bongos-v1-idea-routing-${t.ref}`,
98
- });
99
- if (!r.ok) { console.log(` ${t.ref}: FAILED ${r.status} ${JSON.stringify(r.json)}`); continue; }
100
- // Only a task that actually landed contributes to the self-check's plan —
101
- // a failed POST is already reported above as FAILED, not as a criterion
102
- // mismatch (task 1003076 grade finding: counting it here regardless of
103
- // r.ok blamed a real create failure on the wrong cause).
104
- criterionIdListsPerTask.push(criterionIds);
105
- const task = r.json.task || r.json;
106
- idByRef[t.ref] = task.id;
107
- if (r.json.idempotent || r.json.existing) existing++; else created++;
108
- console.log(` ${t.ref} → task ${task.id} (${t.kind}/${t.disc}, P${t.prio}, [${t.crit.join(',')}])`);
109
- }
110
-
111
- console.log('Wiring dependencies…');
112
- let edges = 0;
113
- for (const t of TASKS) {
114
- if (!t.deps.length) continue;
115
- const id = idByRef[t.ref];
116
- const depIds = t.deps.map((d) => idByRef[d]).filter(Boolean);
117
- if (!id || depIds.length !== t.deps.length) { console.log(` ${t.ref}: dep resolve gap, skipping`); continue; }
118
- const r = await api('POST', `/tasks/${id}/dependencies`, { depends_on_task_ids: depIds });
119
- if (!r.ok) { console.log(` ${t.ref}: dep FAILED ${r.status} ${JSON.stringify(r.json)}`); continue; }
120
- edges += (r.json.added || depIds.length);
121
- console.log(` ${t.ref} depends on ${t.deps.join(',')}`);
122
- }
123
-
124
- console.log('Promoting the zero-dep layer to ready…');
125
- for (const ref of ROOTS) {
126
- const id = idByRef[ref];
127
- if (!id) continue;
128
- const r = await api('POST', `/tasks/${id}/promote`, {});
129
- console.log(` ${ref} (task ${id}): ${r.ok ? 'ready' : 'promote note ' + JSON.stringify(r.json).slice(0, 120)}`);
130
- }
131
-
132
- console.log('Linking provenance…');
133
- if (idByRef.R11) {
134
- const r = await api('PATCH', `/inbox/${DISCORD_BUGS_IDEA}`, { status: 'promoted', promoted_to_task_id: Number(idByRef.R11) });
135
- console.log(` idea ${DISCORD_BUGS_IDEA} → ${r.ok ? `promoted against R11 (task ${idByRef.R11})` : 'PATCH note ' + JSON.stringify(r.json).slice(0, 160)}`);
136
- }
137
- const meta = await api('PATCH', `/tasks/${META_TASK}`, { goal_id: GOAL });
138
- console.log(` meta task ${META_TASK} → ${meta.ok ? `goal ${GOAL}` : 'PATCH note ' + JSON.stringify(meta.json).slice(0, 160)}`);
139
-
140
- console.log(`\nDONE. created=${created} existing=${existing} depEdges=${edges}. Roots opened: ${ROOTS.join(', ')}.`);
141
- console.log('ref→id:', JSON.stringify(idByRef));
142
-
143
- // Self-check (task 1003076): fetch the goal back and confirm every
144
- // criterion's linked_tasks matches what was actually POSTed — exits 1 loudly
145
- // on any mismatch instead of a seed that mislinks and reports success.
146
- console.log('Verifying criterion links against the plan…');
147
- await verifySeedCriteriaLinks({
148
- goalId: GOAL,
149
- expectedCounts: expectedCriterionCounts(criterionIdListsPerTask),
150
- fetchGoal: (id) => api('GET', `/goals/${id}`),
151
- });
152
- })();
@@ -1,135 +0,0 @@
1
- // DO NOT COPY THE `crit:` TOKENS FROM THIS FILE (task 1003108). Its positional
2
- // "Cn" refs were written when BONGOS-V1 held one goal, where they were unambiguous.
3
- // Cn ranks over the whole VERSION's criteria, so on a multi-goal version it resolves
4
- // to another goal's criterion silently — that is how all 15 tasks of goal 1000071 were
5
- // mislinked (learning 1000188). POST /tasks now refuses a positional ref on a
6
- // multi-goal version (400 ambiguous_criterion_ref). A new seed uses criterion_id
7
- // SLUGS. This file is kept as-is because it has already run and is idempotent on
8
- // source_ref — a re-run returns the existing rows before criterion resolution.
9
- //
10
- // Seed the tasks for goal 1000045 "Public builder profiles" (BONGOS-V1, internal).
11
- // Source of truth: docs/specs/bongos-v1-public-builder-profiles.md (status: final).
12
- // Idempotent on (source, source_ref). Re-running resolves to the existing rows.
13
- //
14
- // Run: node scripts/bongos/seed-bv1-profiles-tasks.js
15
- const os = require('os');
16
- const sess = require(os.homedir() + '/.config/cloudbongos/gds-session.json');
17
- const BASE = sess.api_base.replace(/\/$/, '');
18
- const TOKEN = sess.token;
19
- const VER = 'BONGOS-V1';
20
- const GOAL = 1000045;
21
- const SRC = 'planning-session';
22
- const H = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' };
23
-
24
- const { sleep } = require('../../src/sleep'); // the one shared sleep (task 1004893)
25
- async function api(method, path, body, _tries = 0) {
26
- await sleep(400); // base throttle to stay under the per-IP rate limit
27
- const res = await fetch(`${BASE}/api/bongos${path}`, {
28
- method, headers: H, body: body ? JSON.stringify(body) : undefined,
29
- });
30
- const text = await res.text();
31
- let json; try { json = JSON.parse(text); } catch { json = { _raw: text.slice(0, 300) }; }
32
- if (res.status === 429 && _tries < 8) {
33
- const wait = ((json.error && json.error.details && json.error.details.retry_after_seconds) || 30) + 1;
34
- console.log(` …rate-limited, waiting ${wait}s`);
35
- await sleep(wait * 1000);
36
- return api(method, path, body, _tries + 1);
37
- }
38
- return { status: res.status, ok: res.ok, json };
39
- }
40
-
41
- // disc: engineer (backend/API/spike) | ui (frontend). kind: spike | feature | verify (proofs).
42
- const TASKS = [
43
- // Phase 1 — profile shows cross-project record + hide (C1,C2) — P5
44
- { ref:'R01', kind:'spike', disc:'engineer', prio:5, est:180, crit:['C1','C2'], deps:[], title:'R01 · Design profile↔cross-project rollup join + consent model', desc:'Needs-exploration: how the public profile reads the platform-identity rollup (listScoutingRollup / platform_identity_builder_project_activity), public-by-default, and where the hide flag (C2) lives. Output an ADR + sub-tasks. See docs/specs/bongos-v1-public-builder-profiles.md.' },
45
- { ref:'R02', kind:'feature', disc:'engineer', prio:5, est:240, crit:['C1'], deps:['R01'], title:'R02 · Profile API returns cross-project record + project names', desc:'Extend GET /builders/:id/profile to include aggregated cross-project credits/ships/karma/disciplines + the list of projects by name, from the platform-identity rollup; public by default; respects the whitelist + leak test (tests/profile_route.mjs). Done-when: another account sees the aggregate + project names, no private columns. Deps R01.' },
46
- { ref:'R03', kind:'feature', disc:'engineer', prio:5, est:180, crit:['C2'], deps:['R01'], title:'R03 · Hide flag: builder hides cross-project stats (opt-out, live)', desc:'Self-serve opt-out that hides the cross-project record from the profile + applications, honored live everywhere. Default is shown. Deps R01.' },
47
- { ref:'R04', kind:'feature', disc:'ui', prio:5, est:180, crit:['C1','C2'], deps:['R02','R03'], title:'R04 · Profile UI: cross-project section + self hide-toggle', desc:'Render the cross-project section (totals + project names) on the profile; show the hide toggle to the profile owner. Deps R02,R03.' },
48
- { ref:'R05', kind:'feature', disc:'ui', prio:4, est:120, crit:['C1'], deps:['R02'], title:'R05 · Shareable-by-login profile URL (?builder=<login>)', desc:'Add a login-addressable profile URL alongside ?id=. Promotes idea #1000522. Deps R02.' },
49
- { ref:'R06', kind:'verify', disc:'engineer', prio:4, est:90, crit:['C1','C2'], deps:['R04','R03'], title:'R06 · PROOF: cross-project record shows to a viewer; hide removes it live', desc:'Verify a 2-project builder\'s combined record shows to another account, and hiding removes it within one load. Extends tests/profile_route.mjs. Deps R04,R03.' },
50
-
51
- // Phase 2 — apply from orbs + application carries profile (C3,C4) — P5
52
- { ref:'R07', kind:'spike', disc:'engineer', prio:5, est:180, crit:['C3','C4'], deps:[], title:'R07 · Design application model + "project owner (registrant+delegates)" authz', desc:'Needs-exploration: extend access_requests vs a new cross-project applications record; how the profile snapshot travels hub→target; the owner (registrant + delegates) authz; pending queue + approve/decline. Output an ADR + sub-tasks. Deps none.' },
53
- { ref:'R08', kind:'feature', disc:'engineer', prio:5, est:240, crit:['C3','C4'], deps:['R07'], title:'R08 · Application API: apply / list-pending / approve / decline', desc:'Cross-project application flow reusing the join relay (/my-projects/join → target /access-requests). Deps R07.' },
54
- { ref:'R09', kind:'feature', disc:'engineer', prio:5, est:150, crit:['C4'], deps:['R08','R02'], title:'R09 · Application carries the applicant\'s cross-project record (+note)', desc:'Attach the applicant\'s cross-project record (subject to the C2 hide, live) + optional note to the application the owner sees. Deps R08,R02.' },
55
- { ref:'R10', kind:'feature', disc:'ui', prio:5, est:180, crit:['C3'], deps:['R08'], title:'R10 · "Apply" affordance on the in-core browse surface', desc:'Apply action + state (applied/pending/member) on the project cards / My Projects. Deps R08.' },
56
- { ref:'R11', kind:'feature', disc:'ui', prio:5, est:180, crit:['C4'], deps:['R08'], title:'R11 · Owner pending-applications view (approve/decline)', desc:'A project owner sees pending applications for their project and approves/declines. Deps R08.' },
57
- { ref:'R12', kind:'feature', disc:'ui', prio:4, est:150, crit:['C3'], deps:['R10'], title:'R12 · Surface "Apply" on the orbs front door', desc:'Wire the Apply affordance onto the orbs page. NOTE: the orbs front door is a separate static site — this likely lands instance-side. Deps R10.' },
58
- { ref:'R13', kind:'verify', disc:'engineer', prio:5, est:90, crit:['C3','C4'], deps:['R10','R11','R09'], title:'R13 · PROOF: apply → owner sees record → approves → applicant joins', desc:'End-to-end verify of the apply→approve flow carrying the profile. Deps R10,R11,R09.' },
59
-
60
- // Phase 3 — owners browse builder profiles (C5) — P4
61
- { ref:'R14', kind:'feature', disc:'engineer', prio:4, est:210, crit:['C5'], deps:['R02'], title:'R14 · Graduate /scouting to project-owner-facing + opt-out-of-recruiting flag', desc:'Widen the Archon-only /scouting to a project owner (registrant+delegates); add a builder opt-out-of-recruiting flag. Touches authz → Metic+ floor. Deps R02.' },
62
- { ref:'R15', kind:'feature', disc:'ui', prio:4, est:210, crit:['C5'], deps:['R14'], title:'R15 · Owner recruiting UI (search/filter/sort; honors hide + opt-out)', desc:'Owner-facing recruiting surface: search/filter by discipline, sort by track record; honors C2 hide + recruiting opt-out. Deps R14.' },
63
- { ref:'R16', kind:'feature', disc:'ui', prio:4, est:150, crit:['C5'], deps:['R15','R08'], title:'R16 · Browse → invite/recruit a builder to your project', desc:'Invite/recruit a builder from the browse surface, tying into the application/invite flow. Deps R15,R08.' },
64
- { ref:'R17', kind:'verify', disc:'engineer', prio:4, est:90, crit:['C5'], deps:['R15','R16'], title:'R17 · PROOF: non-Archon owner browses, filters, invites', desc:'Verify a non-Archon project owner browses builder profiles, filters by discipline, invites one. Deps R15,R16.' },
65
-
66
- // Phase 4 — builder-to-builder connections + degrees (C6) — P4
67
- { ref:'R18', kind:'spike', disc:'engineer', prio:4, est:180, crit:['C6'], deps:[], title:'R18 · Design connections model incl. 1st/2nd/3rd-degree traversal', desc:'Needs-exploration: platform-level connections (account↔account) with request/accept/decline/remove; degree-of-separation traversal (1st/2nd/3rd); "people you may know" from native signals. Output an ADR + sub-tasks. Deps none.' },
68
- { ref:'R19', kind:'feature', disc:'engineer', prio:4, est:240, crit:['C6'], deps:['R18'], title:'R19 · Connections API: request/accept/decline/remove/list + degree queries', desc:'The connection graph API incl. degree-of-separation queries. Deps R18.' },
69
- { ref:'R20', kind:'feature', disc:'ui', prio:4, est:180, crit:['C6'], deps:['R19','R04'], title:'R20 · Connections on the profile (with degree labels) + connect button', desc:'Show a builder\'s connections (public) with 1st/2nd/3rd-degree labels; connect/pending/accept from the profile. Deps R19,R04.' },
70
- { ref:'R21', kind:'feature', disc:'engineer', prio:4, est:150, crit:['C6'], deps:['R19'], title:'R21 · "Builders you may know" from mutuals + shared projects/guilds', desc:'Suggest connections from mutual connections + shared projects/guilds (2nd/3rd degree). Deps R19.' },
71
- { ref:'R22', kind:'verify', disc:'engineer', prio:4, est:90, crit:['C6'], deps:['R20','R21'], title:'R22 · PROOF: two builders connect; each sees the other + a 2nd-degree suggestion', desc:'Verify request→accept, mutual visibility, and a 2nd-degree suggestion appears. Deps R20,R21.' },
72
-
73
- // Phase 5 — guilds + apply/invite + guild map (C7,C8,C9) — P3
74
- { ref:'R23', kind:'spike', disc:'engineer', prio:3, est:210, crit:['C7','C8','C9'], deps:['R18','R07'], title:'R23 · Design guild model (tables, roles, public/unlisted, rollup, map ranking)', desc:'Needs-exploration: platform-level guilds + guild_members (multi-guild, distinct from goal_members); roles; public/unlisted visibility; collective rollup (excludes hidden members); guild↔project application reuse; map ranking. Output an ADR + sub-tasks. Deps R18,R07.' },
75
- { ref:'R24', kind:'feature', disc:'engineer', prio:3, est:240, crit:['C7'], deps:['R23'], title:'R24 · Guild CRUD + membership API + public/unlisted visibility', desc:'Create guild, invite/accept/join-request, roster, leave; owner sets public/unlisted. Deps R23.' },
76
- { ref:'R25', kind:'feature', disc:'ui', prio:3, est:210, crit:['C7'], deps:['R24'], title:'R25 · Guild page UI (identity, roster, collective record)', desc:'Guild page: identity, roster, collective track record (N of M counted). Deps R24.' },
77
- { ref:'R26', kind:'feature', disc:'engineer', prio:3, est:180, crit:['C7'], deps:['R24','R02'], title:'R26 · Guild collective track-record rollup (excludes hidden members)', desc:'Aggregate members\' cross-project stats into the guild total; exclude C2-hidden members ("N of M counted"). Deps R24,R02.' },
78
- { ref:'R27', kind:'feature', disc:'engineer', prio:3, est:210, crit:['C8'], deps:['R24','R08'], title:'R27 · Guild → project applications + owner invites a guild (each-member-opt-in)', desc:'Guild applies to / is invited to a project (guild-level mirror of R08); each member opts in before being attached. Deps R24,R08.' },
79
- { ref:'R28', kind:'feature', disc:'ui', prio:3, est:150, crit:['C8'], deps:['R27','R11'], title:'R28 · Owner view: pending guild applications', desc:'Extends the owner application view (R11) to guild applications. Deps R27,R11.' },
80
- { ref:'R29', kind:'spike', disc:'engineer', prio:3, est:150, crit:['C9'], deps:['R26'], title:'R29 · Design guild map ranking + orb-sky viz approach', desc:'Needs-exploration: rank guilds by size/success; render on the orb-sky visual language (goal 1000044). Output design + sub-tasks. Deps R26.' },
81
- { ref:'R30', kind:'feature', disc:'engineer', prio:3, est:150, crit:['C9'], deps:['R26'], title:'R30 · Guild map API (ranked; public guilds only; honors hide)', desc:'Ranked guilds by size/success; only public (not unlisted) guilds; honors member hide. Deps R26.' },
82
- { ref:'R31', kind:'feature', disc:'ui', prio:3, est:210, crit:['C9'], deps:['R30','R29','R15'], title:'R31 · Guild map UI on the recruiting surface (orb-sky visual)', desc:'Visual guild map on the owner recruiting surface. Deps R30,R29,R15.' },
83
- { ref:'R32', kind:'verify', disc:'engineer', prio:3, est:120, crit:['C7','C8','C9'], deps:['R25','R27','R31'], title:'R32 · PROOF: form guild → applies (members opt in) → owner approves → ranked on map', desc:'End-to-end verify of the guild lifecycle incl. the map. Deps R25,R27,R31.' },
84
-
85
- // Phase 6 — connection proximity via orb-sky physics (C10) — P3
86
- { ref:'R33', kind:'spike', disc:'engineer', prio:3, est:210, crit:['C10'], deps:['R19','R23'], title:'R33 · Design connection→orb-physics proximity + degree model', desc:'Needs-exploration: connection strength (direct + mutuals + shared projects/guilds + co-shipped; no time-decay) feeding orb-world physics (goals 1000044/1000049); cluster detection. NOTE cross-goal dependency on orb-physics infra. Output an ADR + sub-tasks. Deps R19,R23.' },
87
- { ref:'R34', kind:'feature', disc:'engineer', prio:3, est:210, crit:['C10'], deps:['R33'], title:'R34 · Connection-strength + degree + cluster compute API', desc:'Compute connection strength + degrees + close-knit clusters; feeds orb physics + recruiting. Deps R33.' },
88
- { ref:'R35', kind:'feature', disc:'ui', prio:3, est:180, crit:['C10'], deps:['R34','R25'], title:'R35 · Builder-side: clusters in the orb sky → invite a close cluster to a guild', desc:'Close connections cluster in the orb sky; invite a cluster to form a guild from it. Deps R34,R25.' },
89
- { ref:'R36', kind:'feature', disc:'ui', prio:3, est:180, crit:['C10'], deps:['R34','R16'], title:'R36 · Project-side: recruit a close-knit cluster together', desc:'Surface close-knit clusters on the recruiting surface; recruit them together. Deps R34,R16.' },
90
- { ref:'R37', kind:'verify', disc:'engineer', prio:3, est:120, crit:['C10'], deps:['R35','R36'], title:'R37 · PROOF: cluster forms a guild from the sky; owner recruits a cluster', desc:'End-to-end verify of the proximity-driven guild-forming + cluster-recruiting. Deps R35,R36.' },
91
- ];
92
-
93
- const ROOTS = ['R01', 'R07', 'R18']; // zero-dep entry spikes to open for claiming
94
-
95
- (async () => {
96
- const idByRef = {};
97
- let created = 0, existing = 0;
98
- console.log(`Seeding ${TASKS.length} tasks under goal ${GOAL} (${VER})…`);
99
- for (const t of TASKS) {
100
- const r = await api('POST', '/tasks', {
101
- version_id: VER, goal_id: GOAL, title: t.title, description: t.desc,
102
- kind: t.kind, discipline: t.disc, priority: t.prio, est_minutes: t.est,
103
- criterion_ids: t.crit, source: SRC, source_ref: `bv1-profiles-${t.ref}`,
104
- });
105
- if (!r.ok) { console.log(` ${t.ref}: FAILED ${r.status} ${JSON.stringify(r.json)}`); continue; }
106
- const task = r.json.task || r.json;
107
- idByRef[t.ref] = task.id;
108
- if (r.json.idempotent || r.json.existing) existing++; else created++;
109
- console.log(` ${t.ref} → task ${task.id} (${t.kind}/${t.disc}, P${t.prio}, [${t.crit.join(',')}])`);
110
- }
111
-
112
- console.log('Wiring dependencies…');
113
- let edges = 0;
114
- for (const t of TASKS) {
115
- if (!t.deps.length) continue;
116
- const id = idByRef[t.ref];
117
- const depIds = t.deps.map((d) => idByRef[d]).filter(Boolean);
118
- if (!id || depIds.length !== t.deps.length) { console.log(` ${t.ref}: dep resolve gap, skipping`); continue; }
119
- const r = await api('POST', `/tasks/${id}/dependencies`, { depends_on_task_ids: depIds });
120
- if (!r.ok) { console.log(` ${t.ref}: dep FAILED ${r.status} ${JSON.stringify(r.json)}`); continue; }
121
- edges += (r.json.added || depIds.length);
122
- console.log(` ${t.ref} depends on ${t.deps.join(',')}`);
123
- }
124
-
125
- console.log('Promoting root spikes to ready…');
126
- for (const ref of ROOTS) {
127
- const id = idByRef[ref];
128
- if (!id) continue;
129
- const r = await api('POST', `/tasks/${id}/promote`, {});
130
- console.log(` ${ref} (task ${id}): ${r.ok ? 'ready' : 'promote note ' + JSON.stringify(r.json).slice(0,120)}`);
131
- }
132
-
133
- console.log(`\nDONE. created=${created} existing=${existing} depEdges=${edges}. Roots opened: ${ROOTS.join(', ')}.`);
134
- console.log('ref→id:', JSON.stringify(idByRef));
135
- })();