@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
@@ -120,6 +120,32 @@ export function createClient(opts = {}) {
120
120
  // POST /agents/{name}/invoke — rank: any-builder — POST /agents/:name/invoke
121
121
  postAgentsNameInvoke: (args) => request("POST", "/agents/{name}/invoke", { hasBody: true }, args),
122
122
  },
123
+ "aiStudio": {
124
+ // GET /ai-studio/balance — rank: any-builder — GET /ai-studio/balance
125
+ getAiStudioBalance: (args) => request("GET", "/ai-studio/balance", { hasBody: false }, args),
126
+ // GET /ai-studio/files/{id} — rank: any-builder — GET /ai-studio/files/:id
127
+ getAiStudioFilesId: (args) => request("GET", "/ai-studio/files/{id}", { hasBody: false }, args),
128
+ // GET /ai-studio/keys — rank: any-builder — GET /ai-studio/keys
129
+ getAiStudioKeys: (args) => request("GET", "/ai-studio/keys", { hasBody: false }, args),
130
+ // DELETE /ai-studio/keys/{provider} — rank: any-builder — DELETE /ai-studio/keys/:provider
131
+ deleteAiStudioKeysProvider: (args) => request("DELETE", "/ai-studio/keys/{provider}", { hasBody: false }, args),
132
+ // PUT /ai-studio/keys/{provider} — rank: any-builder — PUT /ai-studio/keys/:provider
133
+ putAiStudioKeysProvider: (args) => request("PUT", "/ai-studio/keys/{provider}", { hasBody: true }, args),
134
+ // GET /ai-studio/requests — rank: any-builder — GET /ai-studio/requests
135
+ getAiStudioRequests: (args) => request("GET", "/ai-studio/requests", { hasBody: false }, args),
136
+ // POST /ai-studio/requests — rank: any-builder — POST /ai-studio/requests
137
+ postAiStudioRequests: (args) => request("POST", "/ai-studio/requests", { hasBody: true }, args),
138
+ // GET /ai-studio/requests/{id} — rank: any-builder — GET /ai-studio/requests/:id
139
+ getAiStudioRequestsId: (args) => request("GET", "/ai-studio/requests/{id}", { hasBody: false }, args),
140
+ // GET /ai-studio/status — rank: any-builder — GET /ai-studio/status
141
+ getAiStudioStatus: (args) => request("GET", "/ai-studio/status", { hasBody: false }, args),
142
+ // POST /ai-studio/topup — rank: any-builder — POST /ai-studio/topup
143
+ postAiStudioTopup: (args) => request("POST", "/ai-studio/topup", { hasBody: true }, args),
144
+ // GET /ai-studio/topup/quote — rank: any-builder — GET /ai-studio/topup/quote
145
+ getAiStudioTopupQuote: (args) => request("GET", "/ai-studio/topup/quote", { hasBody: false }, args),
146
+ // POST /ai-studio/uploads — rank: any-builder — POST /ai-studio/uploads
147
+ postAiStudioUploads: (args) => request("POST", "/ai-studio/uploads", { hasBody: true }, args),
148
+ },
123
149
  "analytics": {
124
150
  // GET /analytics/builder/{id} — rank: any-builder — GET /analytics/builder/:id
125
151
  getAnalyticsBuilderId: (args) => request("GET", "/analytics/builder/{id}", { hasBody: false }, args),
@@ -137,6 +163,10 @@ export function createClient(opts = {}) {
137
163
  postAuthBackchannelLogout: (args) => request("POST", "/auth/backchannel-logout", { hasBody: true }, args),
138
164
  // POST /auth/cli-token/issue — rank: any-builder — POST /auth/cli-token/issue
139
165
  postAuthCliTokenIssue: (args) => request("POST", "/auth/cli-token/issue", { hasBody: true }, args),
166
+ // GET /auth/device — rank: public — GET /auth/device
167
+ getAuthDevice: (args) => request("GET", "/auth/device", { hasBody: false }, args),
168
+ // POST /auth/device/approve — rank: any-builder — POST /auth/device/approve
169
+ postAuthDeviceApprove: (args) => request("POST", "/auth/device/approve", { hasBody: true }, args),
140
170
  // POST /auth/device/exchange — rank: public — POST /auth/device/exchange
141
171
  postAuthDeviceExchange: (args) => request("POST", "/auth/device/exchange", { hasBody: true }, args),
142
172
  // POST /auth/device/poll — rank: public — POST /auth/device/poll
@@ -149,6 +179,10 @@ export function createClient(opts = {}) {
149
179
  getAuthDiscordStart: (args) => request("GET", "/auth/discord/start", { hasBody: false }, args),
150
180
  // POST /auth/discord/unlink — rank: any-builder — POST /auth/discord/unlink
151
181
  postAuthDiscordUnlink: (args) => request("POST", "/auth/discord/unlink", { hasBody: true }, args),
182
+ // GET /auth/google/callback — rank: public — GET /auth/google/callback
183
+ getAuthGoogleCallback: (args) => request("GET", "/auth/google/callback", { hasBody: false }, args),
184
+ // GET /auth/google/start — rank: public — GET /auth/google/start
185
+ getAuthGoogleStart: (args) => request("GET", "/auth/google/start", { hasBody: false }, args),
152
186
  // POST /auth/logout — rank: any-builder — POST /auth/logout
153
187
  postAuthLogout: (args) => request("POST", "/auth/logout", { hasBody: true }, args),
154
188
  // POST /auth/revoke — rank: archon — POST /auth/revoke
@@ -225,6 +259,8 @@ export function createClient(opts = {}) {
225
259
  getBuildersIdActivity: (args) => request("GET", "/builders/{id}/activity", { hasBody: false }, args),
226
260
  // PATCH /builders/{id}/budget — rank: metic+archon — PATCH /builders/:id/budget
227
261
  patchBuildersIdBudget: (args) => request("PATCH", "/builders/{id}/budget", { hasBody: true }, args),
262
+ // PATCH /builders/{id}/capabilities — rank: archon — PATCH /builders/:id/capabilities
263
+ patchBuildersIdCapabilities: (args) => request("PATCH", "/builders/{id}/capabilities", { hasBody: true }, args),
228
264
  // GET /builders/{id}/onboarding — rank: public — GET /builders/:id/onboarding
229
265
  getBuildersIdOnboarding: (args) => request("GET", "/builders/{id}/onboarding", { hasBody: false }, args),
230
266
  // GET /builders/{id}/profile — rank: public — GET /builders/:id/profile
@@ -517,6 +553,10 @@ export function createClient(opts = {}) {
517
553
  postGovernmentAssignments: (args) => request("POST", "/government/assignments", { hasBody: true }, args),
518
554
  // DELETE /government/assignments/{builderId}/{rankKey} — rank: archon — DELETE /government/assignments/:builderId/:rankKey
519
555
  deleteGovernmentAssignmentsBuilderIdRankKey: (args) => request("DELETE", "/government/assignments/{builderId}/{rankKey}", { hasBody: false }, args),
556
+ // GET /government/blockers/for-me — rank: any-builder — GET /government/blockers/for-me
557
+ getGovernmentBlockersForMe: (args) => request("GET", "/government/blockers/for-me", { hasBody: false }, args),
558
+ // GET /government/blockers/people — rank: any-builder — GET /government/blockers/people
559
+ getGovernmentBlockersPeople: (args) => request("GET", "/government/blockers/people", { hasBody: false }, args),
520
560
  // POST /government/board/charter — rank: metic+archon — POST /government/board/charter
521
561
  postGovernmentBoardCharter: (args) => request("POST", "/government/board/charter", { hasBody: true }, args),
522
562
  // POST /government/board/decision-rules — rank: metic+archon — POST /government/board/decision-rules
@@ -737,6 +777,8 @@ export function createClient(opts = {}) {
737
777
  deleteMeFilterViewsId: (args) => request("DELETE", "/me/filter-views/{id}", { hasBody: false }, args),
738
778
  // PATCH /me/filter-views/{id} — rank: any-builder — PATCH /me/filter-views/:id
739
779
  patchMeFilterViewsId: (args) => request("PATCH", "/me/filter-views/{id}", { hasBody: true }, args),
780
+ // POST /me/guardian-cosigns — rank: any-builder — POST /me/guardian-cosigns
781
+ postMeGuardianCosigns: (args) => request("POST", "/me/guardian-cosigns", { hasBody: true }, args),
740
782
  // GET /me/guild-engagements — rank: any-builder — GET /me/guild-engagements
741
783
  getMeGuildEngagements: (args) => request("GET", "/me/guild-engagements", { hasBody: false }, args),
742
784
  // GET /me/guild-requests — rank: any-builder — GET /me/guild-requests
@@ -771,6 +813,12 @@ export function createClient(opts = {}) {
771
813
  postMePasskeysRemove: (args) => request("POST", "/me/passkeys/remove", { hasBody: true }, args),
772
814
  // POST /me/passkeys/rename — rank: any-builder — POST /me/passkeys/rename
773
815
  postMePasskeysRename: (args) => request("POST", "/me/passkeys/rename", { hasBody: true }, args),
816
+ // POST /me/payout-age — rank: any-builder — POST /me/payout-age
817
+ postMePayoutAge: (args) => request("POST", "/me/payout-age", { hasBody: true }, args),
818
+ // POST /me/payout-freezes/{id}/appeal — rank: any-builder — POST /me/payout-freezes/:id/appeal
819
+ postMePayoutFreezesIdAppeal: (args) => request("POST", "/me/payout-freezes/{id}/appeal", { hasBody: true }, args),
820
+ // GET /me/payouts — rank: any-builder — GET /me/payouts
821
+ getMePayouts: (args) => request("GET", "/me/payouts", { hasBody: false }, args),
774
822
  // PATCH /me/profile — rank: any-builder — PATCH /me/profile
775
823
  patchMeProfile: (args) => request("PATCH", "/me/profile", { hasBody: true }, args),
776
824
  // GET /me/profile-nudge — rank: any-builder — GET /me/profile-nudge
@@ -789,6 +837,8 @@ export function createClient(opts = {}) {
789
837
  postMeSessionsRevoke: (args) => request("POST", "/me/sessions/revoke", { hasBody: true }, args),
790
838
  // POST /me/sessions/revoke-all — rank: any-builder — POST /me/sessions/revoke-all
791
839
  postMeSessionsRevokeAll: (args) => request("POST", "/me/sessions/revoke-all", { hasBody: true }, args),
840
+ // GET /me/sign-in-methods — rank: any-builder — GET /me/sign-in-methods
841
+ getMeSignInMethods: (args) => request("GET", "/me/sign-in-methods", { hasBody: false }, args),
792
842
  // GET /me/skill-prefs — rank: any-builder — GET /me/skill-prefs
793
843
  getMeSkillPrefs: (args) => request("GET", "/me/skill-prefs", { hasBody: false }, args),
794
844
  // PATCH /me/skill-prefs — rank: any-builder — PATCH /me/skill-prefs
@@ -868,6 +918,16 @@ export function createClient(opts = {}) {
868
918
  // POST /my-projects/join — rank: any-builder — POST /my-projects/join
869
919
  postMyProjectsJoin: (args) => request("POST", "/my-projects/join", { hasBody: true }, args),
870
920
  },
921
+ "notes": {
922
+ // GET /notes — rank: any-builder — GET /notes
923
+ getNotes: (args) => request("GET", "/notes", { hasBody: false }, args),
924
+ // POST /notes — rank: any-builder — POST /notes
925
+ postNotes: (args) => request("POST", "/notes", { hasBody: true }, args),
926
+ // DELETE /notes/{id} — rank: any-builder — DELETE /notes/:id
927
+ deleteNotesId: (args) => request("DELETE", "/notes/{id}", { hasBody: false }, args),
928
+ // PATCH /notes/{id} — rank: any-builder — PATCH /notes/:id
929
+ patchNotesId: (args) => request("PATCH", "/notes/{id}", { hasBody: true }, args),
930
+ },
871
931
  "npmRelease": {
872
932
  // DELETE /npm-release/preview — rank: any-builder — DELETE /npm-release/preview
873
933
  deleteNpmReleasePreview: (args) => request("DELETE", "/npm-release/preview", { hasBody: false }, args),
@@ -914,6 +974,40 @@ export function createClient(opts = {}) {
914
974
  // GET /page-notes/site — rank: any-builder — GET /page-notes/site
915
975
  getPageNotesSite: (args) => request("GET", "/page-notes/site", { hasBody: false }, args),
916
976
  },
977
+ "payouts": {
978
+ // POST /payouts/age-records — rank: archon — POST /payouts/age-records
979
+ postPayoutsAgeRecords: (args) => request("POST", "/payouts/age-records", { hasBody: true }, args),
980
+ // GET /payouts/approvals — rank: archon — GET /payouts/approvals
981
+ getPayoutsApprovals: (args) => request("GET", "/payouts/approvals", { hasBody: false }, args),
982
+ // POST /payouts/approve — rank: archon — POST /payouts/approve
983
+ postPayoutsApprove: (args) => request("POST", "/payouts/approve", { hasBody: true }, args),
984
+ // POST /payouts/contracts — rank: archon — POST /payouts/contracts
985
+ postPayoutsContracts: (args) => request("POST", "/payouts/contracts", { hasBody: true }, args),
986
+ // POST /payouts/freezes — rank: archon — POST /payouts/freezes
987
+ postPayoutsFreezes: (args) => request("POST", "/payouts/freezes", { hasBody: true }, args),
988
+ // POST /payouts/freezes/{id}/decide — rank: archon — POST /payouts/freezes/:id/decide
989
+ postPayoutsFreezesIdDecide: (args) => request("POST", "/payouts/freezes/{id}/decide", { hasBody: true }, args),
990
+ // GET /payouts/gates/{builderId} — rank: archon — GET /payouts/gates/:builderId
991
+ getPayoutsGatesBuilderId: (args) => request("GET", "/payouts/gates/{builderId}", { hasBody: false }, args),
992
+ // POST /payouts/grants — rank: archon — POST /payouts/grants
993
+ postPayoutsGrants: (args) => request("POST", "/payouts/grants", { hasBody: true }, args),
994
+ // POST /payouts/guardians — rank: archon — POST /payouts/guardians
995
+ postPayoutsGuardians: (args) => request("POST", "/payouts/guardians", { hasBody: true }, args),
996
+ // GET /payouts/rules — rank: archon — GET /payouts/rules
997
+ getPayoutsRules: (args) => request("GET", "/payouts/rules", { hasBody: false }, args),
998
+ // POST /payouts/rules — rank: archon — POST /payouts/rules
999
+ postPayoutsRules: (args) => request("POST", "/payouts/rules", { hasBody: true }, args),
1000
+ // POST /payouts/rules/{id}/narrow — rank: archon — POST /payouts/rules/:id/narrow
1001
+ postPayoutsRulesIdNarrow: (args) => request("POST", "/payouts/rules/{id}/narrow", { hasBody: true }, args),
1002
+ // POST /payouts/rules/{id}/revoke — rank: archon — POST /payouts/rules/:id/revoke
1003
+ postPayoutsRulesIdRevoke: (args) => request("POST", "/payouts/rules/{id}/revoke", { hasBody: true }, args),
1004
+ // POST /payouts/rules/{id}/runs — rank: archon — POST /payouts/rules/:id/runs
1005
+ postPayoutsRulesIdRuns: (args) => request("POST", "/payouts/rules/{id}/runs", { hasBody: true }, args),
1006
+ // POST /payouts/rules/{id}/runs/{runKey}/hold — rank: archon — POST /payouts/rules/:id/runs/:runKey/hold
1007
+ postPayoutsRulesIdRunsRunKeyHold: (args) => request("POST", "/payouts/rules/{id}/runs/{runKey}/hold", { hasBody: true }, args),
1008
+ // POST /payouts/screenings — rank: archon — POST /payouts/screenings
1009
+ postPayoutsScreenings: (args) => request("POST", "/payouts/screenings", { hasBody: true }, args),
1010
+ },
917
1011
  "profiles": {
918
1012
  // GET /profiles/{handle} — rank: public — GET /profiles/:handle
919
1013
  getProfilesHandle: (args) => request("GET", "/profiles/{handle}", { hasBody: false }, args),
@@ -2,9 +2,11 @@
2
2
 
3
3
  **Date:** 2026-06-13
4
4
  **Context:** GDS-V4, task [#1005](https://example.com/builders#/task/1005). Builds on [ADR 0023](0023-kind-multipliers-and-idea-bonus.md) (per-task kind-multiplied credits), [ADR 0028](0028-honest-llm-spend-accounting.md) (the `llm-pricing.js` token→USD table + session-cost capture), and [ADR 0027](0027-bfg-session-inefficiency-evaluator.md) (the `session_records` upload-on-ship path this reward rides). Complements — does **not** replace — the per-task `credits_reward × kind_multiplier` path. Related future work: the full-transcript capture ADR (planned, task [#1004](https://example.com/builders#/task/1004)) will give this reward a more trustworthy raw-usage source, and the token-feed hardening scoped in task [#1005](https://example.com/builders#/task/1005) itself.
5
- **Status:** Accepted.
5
+ **Status:** Accepted. Superseded in part by [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) and [ADR 0387](0387-two-ledgers-credits-measure-work-money-stays-with-the-processor.md) (credits are a contribution meter, not equity or money).
6
6
  **Track:** `internal` (development system / methodology).
7
7
 
8
+ > **Superseded in part (owner ruling, 2026-10-29; [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) decision 2, [ADR 0387](0387-two-ledgers-credits-measure-work-money-stays-with-the-processor.md)).** The framing below that credits ("example") are **equity**, a stake or units of ownership, and the 2026-06-15 reading that **1 drachma = $1**, no longer hold. Credits are a project-scoped contribution meter: never money, never redeemable, never equity, and no dollar value is read off them. Equity, if a project offers any, is granted by that project separately. The formula itself is unchanged: the session reward is still *sized by* the session's cost in USD plus the margin. The waste mitigation in reason 2 below ("a builder who pads cost dilutes a pool they hold") rested on the equity framing and no longer applies. The rest of this ADR (server-side pricing, PASS gate, idempotency per session) stands.
9
+
8
10
  ## Problem
9
11
 
10
12
  We are about to onboard the first **incentivized** builders. Today the only payout is per-task `credits_reward` — a unitless number an author sets at task-creation time. It rewards declaring a big number, not doing expensive, real work. The owner's decision (2026-06-13) is to pay builders proportionally to the **true economic cost** of the work they did — the API token spend of the session — plus a margin, with example standing in as **equity** in the project. It must go live today, be idempotent and reversible, and be impossible to inflate with a client-sent dollar figure.
@@ -62,4 +62,4 @@ A **fine-grained GitHub PAT** scoped to the single repo: `Contents: read/write`
62
62
  confirmed->shipped flip.
63
63
 
64
64
  - **Residual:** the server verifies the bundle tip == the claimed sha and that the caller holds the claim, but does not cheaply prove every commit in the bundle was authored under the claim — branch protection + required checks on `main` (which the credential cannot bypass) are the real gate, exactly as for any PR.
65
- - **Operator action — DONE (blocker 31, resolved 2026-06-13):** the GitHub App was created and `GITHUB_APP_ID` + `GITHUB_APP_INSTALLATION_ID` + `GITHUB_APP_PRIVATE_KEY` set on the droplet (task 1043); `GITHUB_PUSH_TOKEN` then removed. To rotate the key: generate a new private key in the App's settings, replace `GITHUB_APP_PRIVATE_KEY` (single-line, literal `\n`) in `/etc/example/web-source.env`, restart `example`. To roll back to the PAT: restore `web-source.env.bak-task1043` and set a fresh `GITHUB_PUSH_TOKEN` (with the App vars absent, `resolveToken()` falls back to the PAT).
65
+ - **Operator action — DONE (blocker 31, resolved 2026-06-13):** the GitHub App was created and `GITHUB_APP_ID` + `GITHUB_APP_INSTALLATION_ID` + `GITHUB_APP_PRIVATE_KEY` set on the droplet (task 1043); `GITHUB_PUSH_TOKEN` then removed. To rotate the key: generate a new private key in the App's settings, replace `GITHUB_APP_PRIVATE_KEY` (single-line, literal `\n`, wrapped in double quotes — unquoted, systemd drops the backslashes and the key no longer decodes; task 1005009) in `/etc/example/web-source.env`, restart `example`. To roll back to the PAT: restore `web-source.env.bak-task1043` and set a fresh `GITHUB_PUSH_TOKEN` (with the App vars absent, `resolveToken()` falls back to the PAT).
@@ -0,0 +1,87 @@
1
+ # 0385 — Money lives with a processor, credits stay a project meter, and the project sets the pay
2
+
3
+ - **Status:** Accepted, except decision 4 (the signed payout rule), which is Proposed until counsel answers held item 1
4
+ - **Date:** 2026-10-28
5
+ - **Deciders:** The owner, who wrote the legal framework this applies and chose each point below in conversation: a licensed processor holds the money; projects set their own pay and funding rules; Cloud Bongos LLC takes 1% on top of module sales; the default credit system is Bongos's current one.
6
+ - **Tasks:** [task 1004905](https://cloudbongos.com/builders#/task/1004905) (the legal map), [task 1003180](https://cloudbongos.com/builders#/task/1003180) (one credit, one meaning), [task 1003181](https://cloudbongos.com/builders#/task/1003181) (where the wall sits), [task 1004909](https://cloudbongos.com/builders#/task/1004909) (module revenue split). Goal 1000092.
7
+ - **Interacts with:** [ADR 0054](0054-session-token-reward-cost-plus.md) (credit denomination), [ADR 0120](0120-pay-on-land-and-builder-owned-rebase-gate.md) (a claim-time refusal precedent).
8
+
9
+ The owner's legal framework is a confidential draft. This record cites it by Article only and quotes none of it. It is a product constraint for building, not legal advice; counsel confirms the items under "Held for counsel".
10
+
11
+ ## Context
12
+
13
+ Goal 1000092 pays real money for completed work: our own contractors first, then builders on projects and contributors to modules that sell. ADR 0054 left one credit meaning two things on one ledger, and the first design put a balance and a wallet inside Bongos. The legal framework forbids that shape: the platform may not hold user money (Art. II), nor build credits that redeem for cash, and it may not assign work or set rates (Art. IV).
14
+
15
+ ## Decision
16
+
17
+ **1. A licensed payment processor holds all user and project money. Bongos holds none.** Bongos shows balances read from the processor, records every movement and its cause (append-only), and instructs transfers on a project's authorisation. No wallet, no netting between users, no float.
18
+
19
+ **2. Credits are a project-scoped contribution meter, never money.** Credits belong to the project that issued them, are not transferable or purchasable, and are not redeemable for cash. The Bongos Standard Credit System is the default a project adopts; a project may change or replace it. Existing credit records keep their meaning and are not converted to dollars (this closes the double denomination in ADR 0054 by splitting the ledgers, not by re-denominating).
20
+
21
+ **3. The project decides what its work pays and in what form.** Cash through the processor, equity granted by the project, a share of module sales, or non-monetary credit. The project also sets its funding rule: refuse claims when funds run out, hold the estimate at claim, or continue with the shortfall recorded as the project's own obligation. Bongos suggests no rate. The builder sees the pay terms before claiming.
22
+
23
+ **4. Money moves under the project's signed instruction.** A person with the project's authority signs a payout rule once (caps, formula, schedule), and runs execute under it with a notice and a pause window before each. Equity grants and contracts keep one signature each. An AI never creates or widens an authorisation. The authorisations and runs sit in an append-only log. This is a proposal for counsel (item 1 below).
24
+
25
+ **5. Three payment paths.** Bongos rails, self-managed (the project pays on its own systems and Bongos only records contribution), or both per pay type. Bongos shows no balance or guarantee for money it does not move.
26
+
27
+ **6. Module sales carry a platform fee of the processor's cost plus 1 percent of the price** (amended by [ADR 0388](0388-a-module-sale-is-split-by-the-project-the-buyer-pays-the-platform-fee.md); first recorded here as a flat 1 percent). It is added on top of the price, paid by the buyer, collected for Cloud Bongos LLC through the processor, and is never deducted from a contributor or described as a share of pay. How a project prices and divides its modules is the project's choice. No percentage fee applies to wages, task pay or equity. Standard module licence and takedown contact must exist before the first sale.
28
+
29
+ **7. Crypto stays out.** Processor-converted stablecoin payouts are reserved for a later board decision with counsel.
30
+
31
+ **8. Each pay type clears its own legal gate before it can be switched on** (the table under "Pay-type gates" below). Age tiers and sanctions screening apply to every payout (Art. VII, X); a freeze notifies the person and offers an appeal.
32
+
33
+ **9. Credit and model wording.** Nothing the product or an AI writes about credits or valuation models may call them an investment, a return, appreciation or passive income (Art. III). Models are calculation tools with every input visible to the people affected; they create no payment obligation and no redemption price.
34
+
35
+ ## Per-flow map
36
+
37
+ Each flow names the processor primitive it maps to (a flow with none is redesigned, not custom-built), the legal actor, and the Article that limits it. The primitive names are generic processor terms; the processor is chosen in [task 1004906](https://cloudbongos.com/builders#/task/1004906), which confirms the exact product for each row.
38
+
39
+ | Flow | Processor primitive | Legal actor | Limits |
40
+ | --- | --- | --- | --- |
41
+ | Project funding | Charge to the funder, settled into the project's processor-held account | The funder and the project | Art. II no custody, no float |
42
+ | Balance view | Read of the processor-held balance | Nobody acts; display only | Art. II no wallet or internal ledger of user money |
43
+ | User-to-user payment | Transfer between processor-held accounts on the payer's instruction | The payer | Art. II no netting; sanctions and age checks (Art. VII, X) |
44
+ | Builder payout | Transfer from the project's account to the builder, under a signed rule | The project | Art. I signed authorisation and log; Art. IV no rate set by Bongos |
45
+ | Contractor pay (our own) | Same transfer, Cloud Bongos acting as a project | Cloud Bongos as the project | Art. XI NDA and tax details first; Art. IV classification |
46
+ | Cash-out | Payout from the processor-held account to the user's bank, on the user's instruction | The user | Art. II no custody; age and sanctions checks; a freeze notifies |
47
+ | Module sale | Charge to the buyer with an application fee, then transfers to seller and contributors | Buyer, seller and project | Art. VI licence and takedown first; fee only the buyer-paid platform fee of ADR 0388 |
48
+
49
+ The five gate questions (actor, custody, securities wording, control, advice) are answered per row above: the actor column is the actor test, "no custody" and "no wallet" are the custody test, decision 9 is the securities-wording test, decisions 3 and 4 are the control test, and models are tools, not advice (Art. V).
50
+
51
+ ## Pay-type gates
52
+
53
+ A pay type becomes switchable only after its gate is cleared and recorded.
54
+
55
+ | Pay type | Law that applies | Carried by | Must exist first |
56
+ | --- | --- | --- | --- |
57
+ | Cash for task work | Contractor classification, tax reporting, sanctions, age rules | Project; processor screens | Processor onboarding, tax details, age check, sanctions screening, signed rule |
58
+ | Equity or profit interests | Securities law; Art. III | Project; Bongos records at a flat fee | The project's own counsel-approved structure, one signature per grant, no percentage fee, wording filter |
59
+ | Module sales share | Marketplace venue, takedown, tax reporting | Seller and project; Cloud Bongos LLC as venue | Standard module licence, takedown contact, payee onboarding |
60
+ | Credit-weighted pool | Cash rules plus Art. III | Project | Decision 9 in force, model inputs visible, signed rule |
61
+ | Non-monetary tracks | Volunteer and learner rules; Art. VII | Project | Guardian consent for ages 13 to 15, no cash redemption of any credit |
62
+ | Self-managed payout | The project's own obligations | Project alone | A label saying Bongos moves and guarantees nothing |
63
+ | EU labour payments | EU Platform Work Directive | Project; Verro | Not enabled until the per-country analysis is complete (Art. IV) |
64
+
65
+ ## Held for counsel (these block building the money-moving tasks)
66
+
67
+ 1. Whether a standing signed payout rule satisfies the attributable-action requirement (Art. I).
68
+ 2. Whether a credit-weighted pool distribution creates stored value, a security, or a wage-style fee problem.
69
+ 3. Agent-of-payee versus full pass-through, and which processor (decided in [task 1004906](https://cloudbongos.com/builders#/task/1004906)).
70
+ 4. Which entity collects the fee and which is the payee's agent.
71
+ 5. Whether processor-converted stablecoin counts as touching crypto rails.
72
+ 6. Whether a sibling entity is needed for labour payouts.
73
+
74
+ ## Consequences
75
+
76
+ - [task 1003182](https://cloudbongos.com/builders#/task/1003182) (the project account) becomes a processor-held account with a record of its movements; it holds nothing itself.
77
+ - [task 1003183](https://cloudbongos.com/builders#/task/1003183) pays under a signed authorisation, once per builder and task.
78
+ - [task 1003185](https://cloudbongos.com/builders#/task/1003185) builds the funding rule as a per-project setting, with claim-time hold as an option and no wall by default imposed by Bongos.
79
+ - No task that moves real money ships before the processor is chosen and counsel clears items 1 to 4.
80
+ - Decisions 4 and 8 are intent until built. The tasks that build them ([task 1004913](https://cloudbongos.com/builders#/task/1004913) and [task 1004914](https://cloudbongos.com/builders#/task/1004914)) must enforce them on the server, with the rank and ownership check in the database, not in the screen (ADR 0016).
81
+
82
+ ## Rejected
83
+
84
+ - **A wallet inside Bongos.** Makes us the holder of user money (Art. II).
85
+ - **Converting credits to cents.** Turns the meter into stored value.
86
+ - **Bongos setting rates or a standard wall.** Breaks the contractor classification (Art. IV).
87
+ - **A per-run approval click on every payout.** Safest reading, but unworkable for recurring pools; replaced by the signed rule in decision 4, pending counsel.
@@ -0,0 +1,37 @@
1
+ # 0386 — The funding wall is a per-project rule, with a claim-time hold on offer
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-10-28
5
+ - **Deciders:** The owner, who first asked that a project not complete work without money in its account, was shown that a completion-only gate lands the loss on the builder, and then ruled that the rule belongs to each project: whether to halt, pay in another form, or carry on is the project's choice.
6
+ - **Task:** [task 1003181](https://cloudbongos.com/builders#/task/1003181)
7
+ - **Related:** [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) (money lives with a processor; projects set pay), [ADR 0120](0120-pay-on-land-and-builder-owned-rebase-gate.md) (a claim-time refusal with a stated reason).
8
+
9
+ ## Context
10
+
11
+ The owner's first design was a completion gate: a project should not be able to have work completed when it lacks the money. The concern recorded on the task is that cost is incurred during the work, so a completion-only gate lets a builder finish and only then learn the project cannot pay. A claim gate refuses before anyone has spent anything, and ADR 0120 already shows a claim refusal with a legible reason. A third shape holds the task's estimate against the balance so several simultaneous claims cannot overspend it.
12
+
13
+ The owner then settled that Bongos does not impose any one of these. A project sets what its work pays and what happens when it runs short (ADR 0385), and the legal framework bars the platform from setting or capping builder rates (Art. IV).
14
+
15
+ ## Decision
16
+
17
+ **The wall is a per-project setting with three options, and Bongos sets no wall of its own.**
18
+
19
+ 1. **Hold at claim.** A claim is refused, with the stated shortfall, when the project's available balance cannot cover the task's estimate. The estimate is held against the balance while the claim is open, so claims cannot over-commit it. The hold is released on ship or release.
20
+ 2. **Refuse at completion.** The task can be claimed and worked; completing it is refused while the balance is short. This is the owner's original design, kept as an option.
21
+ 3. **Carry on, record the shortfall.** Work continues and the unpaid amount is recorded as the project's own obligation. Bongos never funds it.
22
+
23
+ A project that sets nothing gets option 1, because it is the only option that protects the builder before work is done. Setting it is the project's to change at any time; each builder sees the project's rule on the task before claiming.
24
+
25
+ The balance the wall reads is the processor-held project balance (ADR 0385). A wall on a pay type that is not cash (equity, a share of module sales, non-monetary credit) reads the project's own terms for that pay type, not a dollar balance.
26
+
27
+ ## Consequences
28
+
29
+ - [task 1003185](https://cloudbongos.com/builders#/task/1003185) builds the wall as this setting, with the three options and the claim-time hold. It must put the refusal at the claim route, the one place the server can stop a claim, and show the shortfall in plain words.
30
+ - [task 1003182](https://cloudbongos.com/builders#/task/1003182) exposes the held amount alongside the balance so the owner can see what is reserved.
31
+ - The check is server-side. A screen that hides the Claim button is not the wall (ADR 0016).
32
+ - Option 3 creates an obligation on the project's side only. It must show as owed-but-unpaid in the outflow view ([task 1003184](https://cloudbongos.com/builders#/task/1003184)).
33
+
34
+ ## Rejected
35
+
36
+ - **A completion gate for every project.** Leaves the loss with the builder, who cannot check beforehand.
37
+ - **One wall chosen by Bongos.** Bongos would be setting terms of work, which the contractor classification depends on it not doing.
@@ -0,0 +1,39 @@
1
+ # 0387 — Two ledgers: credits measure work, money stays with the processor
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-10-28
5
+ - **Deciders:** The owner, who asked how credits can measure contribution while pay is set by each project, and chose to keep credits as a project-scoped meter and put money on a separate record held by a licensed processor.
6
+ - **Task:** [task 1003180](https://cloudbongos.com/builders#/task/1003180)
7
+ - **Related:** [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) (the money plan), [ADR 0054](0054-session-token-reward-cost-plus.md) (the double denomination this resolves), [ADR 0146](<redacted><redacted>.md) (reward mode per instance).
8
+
9
+ This applies the owner's confidential legal framework by Article only: credits are a work meter, never redeemable for cash, never bought or transferred (Art. II, III). It is a product constraint, not legal advice.
10
+
11
+ ## Context
12
+
13
+ ADR 0054 accepted a credit meaning two things on one ledger: a unitless author estimate (the per-task path) and a dollar-scale figure from real cost plus 20 percent (the session path). It named the way out: re-denominate per-task credits in cents, or split the ledgers, and said it must be settled before money moves. Paying cash against a number that means two things makes the first dispute unanswerable.
14
+
15
+ ## Decision
16
+
17
+ **Split the ledgers. Do not re-denominate credits into cents.**
18
+
19
+ 1. **Credits stay a work meter.** `credit_log` keeps measuring contribution, scoped to its project, non-transferable, non-purchasable, never redeemable. It gets no money column and no dollar conversion.
20
+ 2. **Money gets its own record, in cents, tied to the processor.** The project-account work ([task 1003182](https://cloudbongos.com/builders#/task/1003182)) adds a separate movement record: integer cents, the processor's transfer reference (the Transfer primitive in the per-flow map of [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md)), and the cause (who, which task or module or pool run, why). It records money held elsewhere and holds none itself. It is append-only and never edited; a correction is a new movement. The database enforces this (updates and deletes refused by a trigger or revoked privilege), not only the code that writes it.
21
+ 3. **No dollar value is ever read off a credit.** A payout reads the money record and the project's signed rule, not a credit delta. Where a project pays by contribution, the payout is a pool run: the project's pool of cents is divided by credit share, and the run is recorded on the money ledger with the shares used. Only the project's authorised person, acting under the signed rule of ADR 0385 decision 4, may start a pool run, and the server checks that authority against the database on every run; a screen that hides the button is not the check (ADR 0016).
22
+ 4. **Historic `credit_log` rows are not rewritten and not retro-classified.** They carry both old meanings and cannot be told apart by inspection, so they keep both and are used only as relative weight inside a project, never as a dollar amount. A pool run that includes them says so in the shares it shows the affected people.
23
+ 5. **A pool run says which credit rows it counts.** The default reward mode (ADR 0146, `cost-plus-and-estimate`) still writes two kinds of new rows to the same total: a per-task estimate row and a session cost-plus row. A project's model must name the row kinds it counts as weight. The default model counts the session cost-plus rows only, and a project that adds estimate rows says so in the shares it shows. Where an instance runs cost-plus-only, only the session rows exist. Estimate rows are never a basis for paying money by themselves.
24
+
25
+ ## Migration path
26
+
27
+ None for existing rows: no rewrite, no backfill, no new column on `credit_log`. The only schema change is the new money record, which lands with [task 1003182](https://cloudbongos.com/builders#/task/1003182) and its migration. Reading historic credits as weight needs no change. If a project later wants historic work weighed differently, it changes its model parameters; it does not edit the ledger.
28
+
29
+ ## Consequences
30
+
31
+ - A payout dispute has one answer: the money record names the cents, the processor reference and the signed rule; the credit record names the work.
32
+ - [task 1003182](https://cloudbongos.com/builders#/task/1003182) and [task 1004907](https://cloudbongos.com/builders#/task/1004907) build against the money record and never against `credit_log`.
33
+ - [task 1003182](https://cloudbongos.com/builders#/task/1003182) also owns the guard: a test that fails the build if any money path reads a credit delta as dollars, and one that fails if the money record accepts an update or delete.
34
+ - [task 1003186](https://cloudbongos.com/builders#/task/1003186), the end-to-end proof, must show a pool run that counts only the row kinds its model names.
35
+
36
+ ## Rejected
37
+
38
+ - **Re-denominate credits into cents.** Credits would carry a dollar value and become stored value (Art. II, III), and the old rows still could not be classified.
39
+ - **A conversion rate between credits and dollars.** The same problem with a rate on it; Bongos must not publish a redemption price for a credit.
@@ -0,0 +1,42 @@
1
+ # 0388 — A module sale is split by the project's own rule, and the buyer pays the platform fee on top
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-10-28
5
+ - **Deciders:** The owner, who set the platform's take at processing cost plus 1 percent on module sales, paid on top of the price, and ruled that each project decides how its modules are monetised and how the money is shared, including a project that is paid only through module sales.
6
+ - **Task:** [task 1004909](https://cloudbongos.com/builders#/task/1004909)
7
+ - **Amends:** [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) decision 6 and its module-sale row: the fee is the processor's cost plus 1 percent, not a flat 1 percent. ADR 0385 is updated to point here.
8
+ - **Related:** [ADR 0385](0385-money-lives-with-a-processor-credits-stay-a-project-meter.md) (the money plan and per-flow map), [ADR 0387](0387-two-ledgers-credits-measure-work-money-stays-with-the-processor.md) (pool runs by credit share).
9
+
10
+ This applies the owner's confidential legal framework by Article only (Art. IV, VI, VIII). It is a product constraint, not legal advice.
11
+
12
+ ## Context
13
+
14
+ A module that sells earns money for the people who built it and for whoever sells it. The question was how that money is divided between the contributors, the seller and the platform. The framework allows a venue and processing fee attached to a transaction and forbids describing any fee as a share of wages (Art. IV). Working area 5 owns module pricing and listing; this goal owns only how the money is divided and paid.
15
+
16
+ ## Decision
17
+
18
+ **1. The buyer pays the price plus a platform fee.** The platform fee is the processor's cost for that sale plus 1 percent of the price, added on top, shown as its own line before purchase, and collected for Cloud Bongos LLC through the processor's application fee. Nothing is deducted from the price the seller and contributors share. The fee is called a platform fee and nothing else. Which entity collects it stays held for counsel (ADR 0385 held item 4); Cloud Bongos LLC is the owner's intended collector, not a settled fact.
19
+
20
+ **2. The project that owns the module sets the split.** Before a paid listing goes live, the project records its rule: the seller's share and the contributors' pool, as percentages of the price. Only the project's authorised person may record or change the rule, and the server checks that authority against the database on every write (ADR 0016); a change is logged like a signed payout rule (ADR 0385 decision 4). Bongos suggests no percentage and does not list a paid module that has no rule. The project can change the rule for future sales; past sales keep the rule they sold under.
21
+
22
+ **3. The contributors' pool is divided by recorded contribution.** By default the weight is the credit each contributor earned on the module's own tasks, counted as ADR 0387 says (session cost-plus rows by default). A project may choose another model. Either way every input and each person's share is visible to the people it affects before money moves (Art. VIII). Only shipped, graded tasks the project placed on the module count, so a builder cannot raise their share by creating tasks for themselves, and the project sees the shares before each payout run. This default is subject to ADR 0385 held item 2 (whether a credit-weighted pool raises a legal problem).
23
+
24
+ **4. Module sales can be a project's only pay.** A project may choose module revenue as the pay form for its work (ADR 0385 decision 3). Builders see that before claiming.
25
+
26
+ **5. The money path is the module-sale row of ADR 0385's per-flow map.** A charge to the buyer with the application fee, then transfers from the project's processor-held account to the seller and to each contributor, under the project's signed payout rule. Bongos holds none of it.
27
+
28
+ **6. Refunds reverse the same way.** A refunded or charged-back sale reverses each transfer in the same proportion it was paid, and the reversal is recorded on the money record against the original sale.
29
+
30
+ **7. Nothing sells before its prerequisites exist.** The standard module licence, a registered copyright takedown agent, processor onboarding (identity and tax details) for every person who will be paid (Art. VI), and counsel's answers to ADR 0385 held items 2 and 4. No task tracks the licence or the takedown agent yet; they belong with Working area 5, and [task 1004910](https://cloudbongos.com/builders#/task/1004910) must not ship until they exist.
31
+
32
+ ## Consequences
33
+
34
+ - [task 1004910](https://cloudbongos.com/builders#/task/1004910) builds this: the split rule on the listing, the share calculation, and the transfers. Amounts are computed on the server from the recorded rule and the processor's reported sale, never taken from the buyer's or seller's screen.
35
+ - Working area 5 shows the platform fee line at checkout and refuses a paid listing with no split rule.
36
+ - [task 1004906](https://cloudbongos.com/builders#/task/1004906) confirms the processor supports an application fee and transfers to several recipients from one sale.
37
+
38
+ ## Rejected
39
+
40
+ - **A fixed 50/50 split chosen by Bongos.** Offered as a placeholder; the owner ruled the split is each project's to set.
41
+ - **Taking the platform fee out of the price.** It would be deducted from what contributors are paid, which the framework treats as a cut of wages (Art. IV).
42
+ - **Crypto settlement for higher margin.** Excluded by ADR 0385 decision 7; the fee is the same either way.
@@ -0,0 +1,33 @@
1
+ # 0392 — AI generation runs on a processor-held balance or the builder's own key
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-10-28
5
+ - **Task:** [task 1004916](https://cloudbongos.com/builders#/task/1004916) (goal 1000136)
6
+ - **Deciders:** the owner (prepaid balance, multiplier 1.08 final, funds secured before a run); Claude designed
7
+ - **Related:** ADR 0016 (trust boundary), 0022 (secrets), 0054 (credits), 0073 (BYOK Gemini key), 0083 (modules), **0385 (money lives with a processor)**
8
+
9
+ ## Context
10
+
11
+ Artists in the Studio want to submit a sketch or image set with a prompt, get a Gemini reply, and get images generated (OpenRouter) with the project's context added. Two ways to pay: our provider key (we charge the builder) or the builder's own key (we charge nothing).
12
+
13
+ There is no way to take money in the code today. Credits (ADR 0054) are what builders **earn**; `credit_log` is an earnings ledger, the wrong place for money a builder **pays**. And ADR 0385 rules that Bongos holds no user money: no wallet, no internal balance, no float. A balance table of our own is therefore not allowed.
14
+
15
+ Card processors also charge about 2.9% plus a fixed $0.30 per payment, so charging a card for each few-cent generation loses money unless that fee is passed on.
16
+
17
+ ## Decision
18
+
19
+ 1. **A new `ai-studio` module** owns keys, the ledger, requests and routes. `default: false` (the hub first), like `raise`.
20
+ 2. **The balance lives with the processor, never with us (ADR 0385).** A builder tops up a processor-held balance; Bongos only **reads** it and **instructs holds and captures** against it. We keep no balance column. What we do keep is the append-only ledger of every movement and its cause, which ADR 0385 requires.
21
+ 3. **Price = provider cost x `AI_PRICE_MULTIPLIER`**, one named constant in `modules/ai-studio/pricing.js`, **1.08** (owner, final: an 8% markup on the actual provider cost of every call: OpenRouter, Gemini, anything). Nothing else spells the number.
22
+ 4. **The processor's cost is added to the top-up, not eaten.** A builder who wants N dollars of balance pays `(N + fixed) / (1 - percent)`, rounded up, so what we receive after the processor's fee covers N. Fixed and percent are named constants beside the multiplier.
23
+ 5. **Hold, then capture.** Before any provider call the full estimated price is **held** on the processor-held balance. A short balance refuses cleanly and nothing runs. After the call the hold is captured at the real price (the difference released); if the provider fails the whole hold is released. A hold is exactly the guarantee the owner asked for: the funds are secured before the run and never touch a Bongos balance.
24
+ 6. **One append-only ledger.** Every movement (top-up, hold, capture, release) is a row with amount, provider cost, markup and processor fee as separate columns, so a builder sees exactly what a generation cost. Money is integer micro-dollars (millionths), never floats.
25
+ 7. **A payments port with two backends.** `fake` (test mode, deterministic, in memory, the only one built now; it stands in for the processor's held balance) and a real processor adapter, added later when the owner supplies keys in Settings. Everything else is backend-independent.
26
+ 8. **Bring your own key.** A builder's own provider key is entered **only in Settings**, encrypted with the existing secret box (ADR 0073), shown as its last four characters, **never returned to the browser or logged**. When one is set for the provider a generation needs, the generation runs on it with no hold and the ledger records a zero charge, with the real provider cost noted for the builder's information.
27
+ 9. **Project context is assembled on the server** from the project context doc, the branding pack and DESIGN.md; the browser never supplies it.
28
+
29
+ ## Consequences
30
+
31
+ - No parallel money system and no wallet: credits stay earnings, the ledger is an audit trail, the processor holds the money.
32
+ - The tests pin the arithmetic (cost x 1.08, top-up gross-up), hold / refuse / capture / release, and that a key never leaves the server.
33
+ - Real processor keys stay off until the owner adds them; going live waits for the owner.
@@ -0,0 +1,37 @@
1
+ # 0393 — A platform account is a person, and GitHub is one way in
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-10-29
5
+ - **Task:** [task 1004992](https://cloudbongos.com/builders#/task/1004992) (goal 1000095, work area 6)
6
+ - **Deciders:** the owner (Google as the only new way in, no email codes or passwords; GitHub and Google linkable both ways; never join accounts on a matching email); Claude designed
7
+ - **Related:** ADR 0016 (trust boundary), **0141 (the hub is an identity provider)**, 0171 (profile consent), 0205 (the hub's own sign-in witness), 0213 (terms acceptance)
8
+
9
+ ## Context
10
+
11
+ Every platform account on the hub was a GitHub account: `platform_identity_accounts` was keyed on GitHub's user id, and that column (`github_id`) is the join key of every other hub table and the identity every federated project receives at sign-in. A person without GitHub could not exist on the platform at all, so they could not ideate, do art or earn credits in any project, although none of that work touches GitHub.
12
+
13
+ The owner wants people to sign up with Google, and GitHub and Google to be linkable to one account either way. GitHub stays necessary for two things only: creating a project (its code lives on GitHub) and engineering work.
14
+
15
+ Renaming `github_id` everywhere was the obvious move and the wrong one: dozens of hub tables, every federated instance's `builders` table, and the wire format between them all carry it. A rename would be a breaking change across instances that upgrade on their own schedules.
16
+
17
+ ## Decision
18
+
19
+ 1. **An account is a person; its ways in are rows.** `platform_identity_account_logins` (migration 034) holds one row per provider identity: `(account, provider, subject)`, where `subject` is the provider's own stable user id (GitHub's numeric id, Google's `sub`). Never an email or a login: both can change hands.
20
+ 2. **The database enforces ownership.** `UNIQUE (provider, subject)`: a provider identity belongs to exactly one person. `UNIQUE (account, provider)`: a person holds at most one way in per provider. A `CHECK` lists the providers (`github`, `google`); a new one is a decision, not a string.
21
+ 3. **`github_id` keeps its name and becomes the person key.** Positive is the GitHub user id of a person who arrived through GitHub (every account before this change, unchanged). Negative is minted from `platform_identity_person_key_seq` for a person who arrived without GitHub. GitHub ids are positive, so a minted key can never collide with one, and a key never changes when a way in is linked or removed. No wire format changes.
22
+ 4. **`github_login` is NULL for a person with no GitHub linked.** Inventing a login would let a real GitHub user of that name be taken for this person by the invite-by-login path.
23
+ 5. **GitHub-born accounts need no writer change.** A trigger writes the `github` login row for every account inserted with a positive key, and the migration backfills every existing account. A non-GitHub account is born only through `createAccountForLogin`, which mints the key and writes the account and its way in in one transaction, and returns the existing person on a repeat or racing sign-up.
24
+ 6. **An email is shown, never looked up.** It is stored as the provider vouched for it, for the person's own settings. No lookup keys on it, so owning a matching address never reaches an account. Linking two ways in requires the person to be signed in to both (the owner: suggest a link on a matching email, never join one).
25
+ 7. **Identity, never authority.** Nothing here carries a rank, a credit or an admission (ADR 0016, ADR 0141).
26
+
27
+ ## Consequences
28
+
29
+ - A person key no longer says which provider someone used. Code that needs to talk to GitHub must ask for the linked GitHub login, never assume the key is a GitHub id. The hub's numeric-key guard (`isNumericGithubId`) now admits a negative key and still refuses a `system:*` principal.
30
+ - **Every sign-in must resolve the person through the logins table first** once linking exists. Until then the mapping is trivially exact (a GitHub-born key IS its GitHub id), but the moment GitHub can be linked to a Google-born account, a GitHub sign-in that keys straight on the GitHub id would create a second person. The linking task (task 1004995) must route GitHub sign-ins through `findPersonByLogin` before it lets anyone link.
31
+ - Federated projects will start receiving negative keys when Google-born people sign in to them. An instance's `builders.github_id` is text, so it stores one, but any instance code that assumes a GitHub-shaped id must be found and fixed before those people are admitted (task 1004994), and an older core should not be sent one.
32
+ - A minted key's fallback handle reads `builder--N`; the handle normally grows from the name the provider gave.
33
+ - The own-scope read `GET /me/sign-in-methods` lists a person's ways in for account settings. The provider ids never cross.
34
+
35
+ ## What this does not do
36
+
37
+ It adds no sign-in method by itself. Signing in with Google is task 1004993; halls admitting Google-born builders is task 1004994; linking both ways is task 1004995; the Link GitHub chip and the guided GitHub step are tasks 1004996 and 1004997.