@bongos/core 1.21.175 → 1.21.177

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 (1719) hide show
  1. package/.bongos-core.json +3371 -1636
  2. package/.claude/skills/ask-for-help/SKILL.md +4 -4
  3. package/.claude/skills/backlog-review/SKILL.md +1 -1
  4. package/.claude/skills/blocker-review/SKILL.md +2 -2
  5. package/.claude/skills/blocker-solve/SKILL.md +4 -4
  6. package/.claude/skills/bongos-feedback/SKILL.md +1 -1
  7. package/.claude/skills/bug-triage/SKILL.md +8 -8
  8. package/.claude/skills/builder-backup/SKILL.md +3 -3
  9. package/.claude/skills/builder-claim/SKILL.md +5 -5
  10. package/.claude/skills/builder-cost/SKILL.md +5 -5
  11. package/.claude/skills/builder-end/SKILL.md +6 -6
  12. package/.claude/skills/builder-exit/SKILL.md +2 -2
  13. package/.claude/skills/builder-key/SKILL.md +6 -6
  14. package/.claude/skills/builder-reauth/SKILL.md +4 -4
  15. package/.claude/skills/builder-redteam/SKILL.md +3 -3
  16. package/.claude/skills/builder-release/SKILL.md +3 -3
  17. package/.claude/skills/builder-sequence/SKILL.md +8 -8
  18. package/.claude/skills/builder-setup/SKILL.md +4 -4
  19. package/.claude/skills/builder-ship/SKILL.md +7 -7
  20. package/.claude/skills/builder-stage/SKILL.md +8 -8
  21. package/.claude/skills/builder-start/SKILL.md +4 -4
  22. package/.claude/skills/collab-review/SKILL.md +5 -5
  23. package/.claude/skills/design/SKILL.md +6 -4
  24. package/.claude/skills/design-sync/SKILL.md +3 -3
  25. package/.claude/skills/figma-design-sync/SKILL.md +4 -4
  26. package/.claude/skills/fix-task/SKILL.md +8 -8
  27. package/.claude/skills/goal-close/SKILL.md +9 -9
  28. package/.claude/skills/goal-create/SKILL.md +18 -18
  29. package/.claude/skills/grade-recover/SKILL.md +8 -8
  30. package/.claude/skills/grade-sweep/SKILL.md +15 -15
  31. package/.claude/skills/idea-triage/SKILL.md +15 -15
  32. package/.claude/skills/merge-mode/SKILL.md +14 -14
  33. package/.claude/skills/new-project/SKILL.md +5 -5
  34. package/.claude/skills/owner-review/SKILL.md +1 -1
  35. package/.claude/skills/planning-session/SKILL.md +15 -15
  36. package/.claude/skills/priority-session/SKILL.md +6 -6
  37. package/.claude/skills/read-session-export/SKILL.md +3 -3
  38. package/.claude/skills/recall/SKILL.md +7 -7
  39. package/.claude/skills/scan-before-install/SKILL.md +3 -3
  40. package/.claude/skills/session-handoff/SKILL.md +1 -1
  41. package/.claude/skills/ship-check/SKILL.md +3 -3
  42. package/.claude/skills/status/SKILL.md +3 -3
  43. package/.claude/skills/strand-fix/SKILL.md +6 -6
  44. package/.claude/skills/worktree-clean/SKILL.md +4 -4
  45. package/.gitattributes +12 -32
  46. package/GOVERNMENT.md +1 -1
  47. package/README.md +8 -8
  48. package/bin/bongos.js +23 -23
  49. package/clients/bongos-client/README.md +2 -2
  50. package/clients/bongos-client/bongos-client.global.js +22 -4
  51. package/clients/bongos-client/index.cjs +22 -4
  52. package/clients/bongos-client/index.d.ts +33 -4
  53. package/clients/bongos-client/index.mjs +21 -3
  54. package/config/branding.neutral.json +1 -1
  55. package/config/design-tokens.schema.json +1 -1
  56. package/config/modules.neutral.json +1 -3
  57. package/config/scheduled-routines.json +3 -8
  58. package/docs/adr/0029-status-page-outage-resilience.md +6 -6
  59. package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +1 -1
  60. package/docs/adr/0093-tranche-2-core-carve-sequence.md +1 -1
  61. package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
  62. package/docs/adr/0294-cli-sessions-do-not-expire.md +1 -1
  63. package/docs/adr/0383-sessions-end-after-ten-idle-days.md +35 -0
  64. package/docs/adr/0384-the-raise-page-is-a-hub-module-builders-edit-in-place.md +31 -0
  65. package/docs/adr/README.md +2 -0
  66. package/docs/api/openapi.json +606 -44
  67. package/docs/api-reference.md +25 -12
  68. package/docs/architecture.md +8 -7
  69. package/docs/canonical-permissions.md +4 -4
  70. package/docs/copy-inventory.md +1370 -1411
  71. package/docs/copy-registry.json +2136 -2536
  72. package/docs/design/demonolith-plan.md +6 -6
  73. package/docs/design/modular-architecture/00-research-report.md +1 -1
  74. package/docs/design/project-startup-direction.md +2 -2
  75. package/docs/design/projects-hub-direction-v2.md +1 -1
  76. package/docs/design/reviews/hall-v2/README.md +2 -2
  77. package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
  78. package/docs/file-map.md +92 -96
  79. package/docs/handoff-template.md +5 -5
  80. package/docs/module-api-changelog.md +7 -3
  81. package/docs/modules-contract.md +8 -7
  82. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +1 -1
  83. package/docs/onboarding/diagrams/02-rank-ladder.mmd +1 -1
  84. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +1 -1
  85. package/docs/onboarding/diagrams/04-architecture.mmd +1 -1
  86. package/docs/onboarding/diagrams/05-versioning.mmd +1 -1
  87. package/docs/onboarding/diagrams/README.md +5 -9
  88. package/docs/onboarding/diagrams/assertions.json +3 -3
  89. package/docs/onboarding/slash-commands.md +2 -2
  90. package/docs/packs/artist.md +4 -4
  91. package/docs/packs/engineer.md +11 -10
  92. package/docs/packs/ideator.md +7 -7
  93. package/docs/page-inventory.json +20 -1
  94. package/docs/page-readings.json +4387 -4603
  95. package/docs/recipes/README.md +1 -1
  96. package/docs/recipes/audit-replay.md +4 -4
  97. package/docs/recipes/autobongos-windows-host.md +6 -6
  98. package/docs/recipes/bongos-cli-release.md +2 -2
  99. package/docs/recipes/claude-design-loop.md +7 -7
  100. package/docs/recipes/core-release-pipeline.md +19 -19
  101. package/docs/recipes/failed-ship-recovery-proof.md +2 -2
  102. package/docs/recipes/figma-design-loop.md +6 -6
  103. package/docs/recipes/gds-db-backup.md +9 -9
  104. package/docs/recipes/instance-deploy.md +3 -3
  105. package/docs/recipes/instance-first-run.md +1 -1
  106. package/docs/recipes/multi-builder-merge.md +2 -2
  107. package/docs/recipes/ops-gotchas.md +13 -10
  108. package/docs/recipes/packaging-the-core.md +6 -6
  109. package/docs/recipes/parallel-goal-waves.md +4 -4
  110. package/docs/recipes/private-npm-distribution.md +9 -9
  111. package/docs/recipes/redteam-patrol.md +5 -5
  112. package/docs/recipes/render-pilot.md +2 -2
  113. package/docs/recipes/reranking-a-goals-board.md +2 -2
  114. package/docs/recipes/search-index-ingestion.md +5 -5
  115. package/docs/recipes/self-host.md +1 -1
  116. package/docs/recipes/ship-and-regrade.md +4 -4
  117. package/docs/recipes/staging-environment.md +1 -1
  118. package/docs/recipes/standalone-live-docs.md +1 -1
  119. package/docs/recipes/ui-look-before-you-ship.md +2 -2
  120. package/docs/recipes/upgrading-the-core.md +11 -11
  121. package/docs/recipes/windows-builders.md +18 -18
  122. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +6 -6
  123. package/docs/research/task-network-map-readability.md +3 -3
  124. package/migrations/core_278_builder_tester_tag.sql +18 -0
  125. package/migrations/core_279_bongos_shipper_new_scripts_path.sql +13 -0
  126. package/modules/agents/lib/answer-hold.js +1 -1
  127. package/modules/agents/lib/gate.js +1 -1
  128. package/modules/agents/lib/validate.js +1 -1
  129. package/modules/autonomy/db.js +9 -0
  130. package/modules/autonomy/gauge.js +1 -1
  131. package/modules/autonomy/governor-docket.js +2 -2
  132. package/modules/autonomy/module.json +2 -2
  133. package/modules/autonomy/pollers/daily-checks.js +262 -0
  134. package/modules/autonomy/pollers/routine-timers.js +9 -7
  135. package/modules/autonomy/rank-roles.js +64 -0
  136. package/modules/autonomy/routes/autonomy.js +3 -3
  137. package/modules/autonomy/server-schedule.js +37 -0
  138. package/modules/builder-settings/interaction-prefs.js +1 -1
  139. package/modules/builder-settings/render-prefs.js +1 -1
  140. package/modules/builder-settings/routes/settings.js +1 -1
  141. package/modules/builder-settings/skill-prefs.js +2 -2
  142. package/modules/builder-settings/wandering-prefs.js +2 -2
  143. package/modules/copy-desk/module.json +2 -2
  144. package/modules/copy-desk/page-data.js +5 -5
  145. package/modules/copy-desk/page-decisions.js +13 -1
  146. package/modules/copy-desk/proposals.js +4 -4
  147. package/modules/copy-desk/registry.js +2 -2
  148. package/modules/copy-desk/routes/copy-desk-release.js +119 -0
  149. package/modules/copy-desk/routes/copy-desk.js +3 -12
  150. package/modules/copy-desk/skills/tweak/SKILL.md +12 -12
  151. package/modules/copy-desk/tests/copy_flags.mjs +1 -1
  152. package/modules/copy-desk/tests/copy_no_cms.mjs +7 -3
  153. package/modules/copy-desk/tests/copy_proposals.mjs +2 -2
  154. package/modules/copy-desk/tests/copy_queue.mjs +1 -1
  155. package/modules/design-styles/skills/README.md +4 -4
  156. package/modules/design-styles/skills/imagegen-frontend-mobile/SKILL.md +1 -1
  157. package/modules/design-styles/skills/imagegen-frontend-web/SKILL.md +1 -1
  158. package/modules/discord/bug-attachments.js +1 -1
  159. package/modules/discord/ship-broadcast.js +1 -1
  160. package/modules/economy/achievements.js +49 -7
  161. package/modules/economy/cost-classify.js +6 -6
  162. package/modules/economy/cost-report.js +1 -1
  163. package/modules/economy/cost.js +1 -1
  164. package/modules/economy/credits.js +2 -1
  165. package/modules/economy/idea-size.js +2 -2
  166. package/modules/economy/reward.js +2 -0
  167. package/modules/economy/routes/cost.js +1 -1
  168. package/modules/economy/streak.js +43 -4
  169. package/modules/government/asks.js +1 -1
  170. package/modules/government/board.js +19 -2
  171. package/modules/government/catalog.js +3 -0
  172. package/modules/government/migrations/government_033_idea_vote.sql +46 -0
  173. package/modules/government/protected-surfaces.json +48 -47
  174. package/modules/government/recommendations.js +6 -2
  175. package/modules/government/routes/government.js +1 -1
  176. package/modules/grading/generated-provenance.js +13 -5
  177. package/modules/grading/grade-engine.js +1 -1
  178. package/modules/grading/grader-rubric.json +1 -1
  179. package/modules/grading/grader-score.js +1 -1
  180. package/modules/grading/grader-workers/index.js +1 -1
  181. package/modules/grading/grader.js +1 -1
  182. package/modules/grading/routes/grade.js +1 -1
  183. package/modules/hall-ui/public/atlas.html +5 -7
  184. package/modules/hall-ui/public/atlas.js +1 -1
  185. package/modules/hall-ui/public/atlas.states.json +1 -1
  186. package/modules/hall-ui/public/blockers.css +9 -0
  187. package/modules/hall-ui/public/blockers.html +4 -4
  188. package/modules/hall-ui/public/blockers.js +29 -30
  189. package/modules/hall-ui/public/board-room.css +5 -17
  190. package/modules/hall-ui/public/board-room.html +5 -6
  191. package/modules/hall-ui/public/board-room.js +41 -23
  192. package/modules/hall-ui/public/board-room.states.json +1 -1
  193. package/modules/hall-ui/public/brand-apply.js +1 -1
  194. package/modules/hall-ui/public/brand-holes.js +1 -1
  195. package/modules/hall-ui/public/builders.js +40 -86
  196. package/modules/hall-ui/public/city-decide.js +18 -4
  197. package/modules/hall-ui/public/city.html +1 -1
  198. package/modules/hall-ui/public/collab.html +1 -1
  199. package/modules/hall-ui/public/commands.html +6 -9
  200. package/modules/hall-ui/public/copy-desk.html +1 -1
  201. package/modules/hall-ui/public/copy-desk.js +2 -2
  202. package/modules/hall-ui/public/craft-mode.js +4 -0
  203. package/modules/hall-ui/public/deploy.html +6 -2
  204. package/modules/hall-ui/public/deploy.js +21 -13
  205. package/modules/hall-ui/public/diagrams.css +1 -1
  206. package/modules/hall-ui/public/diagrams.html +5 -8
  207. package/modules/hall-ui/public/diagrams.states.json +1 -1
  208. package/modules/hall-ui/public/drachmae.html +3 -7
  209. package/modules/hall-ui/public/fleet.html +3 -2
  210. package/modules/hall-ui/public/fleet.js +0 -4
  211. package/modules/hall-ui/public/gate.html +7 -7
  212. package/modules/hall-ui/public/gate.js +58 -77
  213. package/modules/hall-ui/public/goal-map.html +1 -1
  214. package/modules/hall-ui/public/goals-page.js +5 -5
  215. package/modules/hall-ui/public/goals-render.js +10 -11
  216. package/modules/hall-ui/public/goals.css +10 -0
  217. package/modules/hall-ui/public/goals.html +14 -7
  218. package/modules/hall-ui/public/government.html +3 -5
  219. package/modules/hall-ui/public/government.js +1 -5
  220. package/modules/hall-ui/public/hall-render.js +117 -57
  221. package/modules/hall-ui/public/hall-widgets.js +11 -11
  222. package/modules/hall-ui/public/idea.html +1 -1
  223. package/modules/hall-ui/public/ideas.html +3 -1
  224. package/modules/hall-ui/public/ideas.js +1 -0
  225. package/modules/hall-ui/public/index.html +12 -6
  226. package/modules/hall-ui/public/index.states.json +1 -1
  227. package/modules/hall-ui/public/mine-lens.js +1 -1
  228. package/modules/hall-ui/public/modules.html +7 -10
  229. package/modules/hall-ui/public/modules.js +0 -2
  230. package/modules/hall-ui/public/my-agents.html +1 -1
  231. package/modules/hall-ui/public/palette.js +5 -5
  232. package/modules/hall-ui/public/primer.html +4 -9
  233. package/modules/hall-ui/public/profile-connections.js +10 -2
  234. package/modules/hall-ui/public/profile-roles.js +3 -10
  235. package/modules/hall-ui/public/profile.html +12 -10
  236. package/modules/hall-ui/public/profile.js +13 -17
  237. package/modules/hall-ui/public/project-settings.html +3 -4
  238. package/modules/hall-ui/public/project-settings.js +0 -3
  239. package/modules/hall-ui/public/ranks.html +5 -11
  240. package/modules/hall-ui/public/ranks.js +6 -8
  241. package/modules/hall-ui/public/roadmap.css +0 -2
  242. package/modules/hall-ui/public/roadmap.html +1 -1
  243. package/modules/hall-ui/public/roadmap.js +16 -51
  244. package/modules/hall-ui/public/roster.html +1 -1
  245. package/modules/hall-ui/public/sessions.html +6 -8
  246. package/modules/hall-ui/public/sessions.js +7 -7
  247. package/modules/hall-ui/public/settings.html +1 -1
  248. package/modules/hall-ui/public/shell-trail.js +1 -1
  249. package/modules/hall-ui/public/shell.js +17 -17
  250. package/modules/hall-ui/public/street-deck.css +2 -1
  251. package/modules/hall-ui/public/street-deck.js +10 -2
  252. package/modules/hall-ui/public/street-desk.js +16 -5
  253. package/modules/hall-ui/public/street.html +1 -1
  254. package/modules/hall-ui/public/studio-lib.js +4 -0
  255. package/modules/hall-ui/public/studio.css +2 -0
  256. package/modules/hall-ui/public/studio.html +1 -1
  257. package/modules/hall-ui/public/studio.js +27 -1
  258. package/modules/hall-ui/public/style.css +43 -26
  259. package/modules/hall-ui/public/task-detail.js +10 -7
  260. package/modules/hall-ui/public/task.css +2 -0
  261. package/modules/hall-ui/public/task.html +3 -1
  262. package/modules/hall-ui/public/task.js +23 -7
  263. package/modules/hall-ui/public/thinking.html +1 -1
  264. package/modules/hall-ui/public/tweak-editor.html +1 -1
  265. package/modules/hall-ui/public/vote-control.js +208 -0
  266. package/modules/hall-ui/public/watch.html +3 -5
  267. package/modules/hall-ui/public/watch.js +5 -4
  268. package/modules/hall-ui/public/welcome-boot.css +130 -0
  269. package/modules/hall-ui/public/welcome-boot.js +334 -0
  270. package/modules/hall-ui/public/welcome-day.webp +0 -0
  271. package/modules/hall-ui/public/welcome-night.webp +0 -0
  272. package/modules/hall-ui/public/work-summary.js +1 -1
  273. package/modules/hall-ui/public/work.css +1 -0
  274. package/modules/hall-ui/public/work.html +3 -1
  275. package/modules/hall-ui/public/work.js +2 -1
  276. package/modules/hall-ui/records/accomplishments.md +16 -0
  277. package/modules/hall-ui/records/hall-ask-card.md +9 -0
  278. package/modules/hall-ui/records/karma-vote-control.md +13 -0
  279. package/modules/hall-ui/records/oversight-family.md +1 -1
  280. package/modules/hall-ui/records/profile-connections.md +2 -0
  281. package/modules/hall-ui/records/profile-roles.md +1 -1
  282. package/modules/hall-ui/records/reading-rooms.md +1 -1
  283. package/modules/hall-ui/records/welcome-tower.md +50 -0
  284. package/modules/ideas/migrations/ideas_011_idea_votes.sql +31 -0
  285. package/modules/ideas/projection.js +1 -1
  286. package/modules/ideas/routes/blockers.js +3 -3
  287. package/modules/ideas/routes/inbox.js +29 -1
  288. package/modules/ideas/routes/ratify-goal.js +1 -1
  289. package/modules/ideas/routing.js +1 -1
  290. package/modules/ideas/templates.js +1 -1
  291. package/modules/ideas/trail-descent.js +1 -1
  292. package/modules/ideas/trail-size.js +1 -1
  293. package/modules/ideas/votes.js +93 -0
  294. package/modules/lifecycle/abandon-leftovers.js +1 -1
  295. package/modules/lifecycle/cascade.js +1 -1
  296. package/modules/lifecycle/conflict-resolve.js +13 -21
  297. package/modules/lifecycle/criterion-ref.js +1 -1
  298. package/modules/lifecycle/db-analytics.js +57 -4
  299. package/modules/lifecycle/db-deps-criteria.js +1 -1
  300. package/modules/lifecycle/db-ship.js +2 -2
  301. package/modules/lifecycle/db-tasks.js +2 -2
  302. package/modules/lifecycle/db-versions.js +1 -1
  303. package/modules/lifecycle/db.js +2 -0
  304. package/modules/lifecycle/dead-deps.js +3 -3
  305. package/modules/lifecycle/dependency-advisory.js +3 -3
  306. package/modules/lifecycle/goal-category.js +1 -1
  307. package/modules/lifecycle/goal-forest.js +1 -1
  308. package/modules/lifecycle/goal-task-relevance-advisory.js +1 -1
  309. package/modules/lifecycle/kickoff-checklist.js +1 -1
  310. package/modules/lifecycle/kickoff-seed.js +1 -1
  311. package/modules/lifecycle/lifecycle.js +2 -0
  312. package/modules/lifecycle/merge-reach.js +29 -15
  313. package/modules/lifecycle/missing-dep-classify.js +3 -3
  314. package/modules/lifecycle/module.json +2 -1
  315. package/modules/lifecycle/page-tweak-approve.js +85 -1
  316. package/modules/lifecycle/page-tweak-hold.js +1 -1
  317. package/modules/lifecycle/publish-reconciler.js +1 -2
  318. package/modules/lifecycle/rot.js +1 -1
  319. package/modules/lifecycle/routes/artist-gate.js +1 -1
  320. package/modules/lifecycle/routes/gate-approvals.js +22 -1
  321. package/modules/lifecycle/routes/goals.js +1 -1
  322. package/modules/lifecycle/routes/task-route-helpers.js +1 -1
  323. package/modules/lifecycle/routes/task-votes.js +54 -0
  324. package/modules/lifecycle/routes/task-write-routes.js +1 -1
  325. package/modules/lifecycle/routes/tasks.js +2 -2
  326. package/modules/lifecycle/routes/versions.js +2 -2
  327. package/modules/lifecycle/ship-card.js +4 -4
  328. package/modules/lifecycle/ship-preflight.js +1 -1
  329. package/modules/lifecycle/task-classifier.js +1 -1
  330. package/modules/lifecycle/task-status.js +1 -1
  331. package/modules/lifecycle/task-visual-db.js +1 -1
  332. package/modules/memory/learnings.js +1 -1
  333. package/modules/memory/pollers/search-index.js +2 -2
  334. package/modules/memory/routes/learnings.js +1 -1
  335. package/modules/memory/routes/memory.js +1 -1
  336. package/modules/memory/search.js +2 -2
  337. package/modules/npm-release/release.js +1 -1
  338. package/modules/onboarding/howto-moments.js +1 -1
  339. package/modules/onboarding/newcomer-restock.js +3 -3
  340. package/modules/onboarding/onboarding.js +1 -1
  341. package/modules/pixel-art/skills/otb-tile-generate/SKILL.md +1 -1
  342. package/modules/platform-identity/origin-containment.js +1 -1
  343. package/modules/platform-identity/publish-gate.js +1 -1
  344. package/modules/platform-identity/tests/platform-identity.mjs +1 -1
  345. package/modules/provisioning/capacity.js +1 -1
  346. package/modules/provisioning/core-upgrade.js +15 -9
  347. package/modules/provisioning/credential-preflight.js +3 -3
  348. package/modules/provisioning/disconnect.js +1 -1
  349. package/modules/provisioning/dns-resolves.js +1 -1
  350. package/modules/provisioning/module.json +1 -1
  351. package/modules/provisioning/onboard-plan.js +1 -1
  352. package/modules/provisioning/paid-shape-gate.js +2 -2
  353. package/modules/provisioning/planet-physics.js +11 -2
  354. package/modules/provisioning/pollers/liveness-sweep.js +1 -1
  355. package/modules/provisioning/pollers/runner-drift-notify.js +5 -5
  356. package/modules/provisioning/provisioning.js +2 -2
  357. package/modules/provisioning/render-lookup.js +1 -1
  358. package/modules/provisioning/render-standup.js +3 -3
  359. package/modules/provisioning/repo-private.js +1 -1
  360. package/modules/provisioning/routes/callback-page.js +1 -1
  361. package/modules/provisioning/routes/core-upgrade.js +23 -3
  362. package/modules/provisioning/routes/provisioning.js +2 -2
  363. package/modules/provisioning/routes/render-standup.js +1 -1
  364. package/modules/provisioning/routes/repo-private.js +1 -1
  365. package/modules/provisioning/soft-limits.js +1 -1
  366. package/modules/provisioning/starter-bundles.js +4 -2
  367. package/modules/provisioning/tests/provisioning.mjs +1 -1
  368. package/modules/public-landing/public/account.html +4 -6
  369. package/modules/public-landing/public/assets/cosmos.css +13 -6
  370. package/modules/public-landing/public/connections.html +4 -6
  371. package/modules/public-landing/public/contact.html +4 -6
  372. package/modules/public-landing/public/guild.html +4 -6
  373. package/modules/public-landing/public/index.html +11 -9
  374. package/modules/public-landing/public/invitations.html +4 -6
  375. package/modules/public-landing/public/privacy.html +4 -6
  376. package/modules/public-landing/public/projects.html +168 -46
  377. package/modules/public-landing/public/terms.html +4 -6
  378. package/modules/raise/content/copy.json +40 -0
  379. package/modules/raise/content/nda.html +39 -0
  380. package/modules/raise/content/settings.json +49 -0
  381. package/modules/raise/db.js +95 -0
  382. package/modules/raise/migrations/raise_001_tables.sql +71 -0
  383. package/modules/raise/module.json +28 -0
  384. package/modules/raise/page.js +194 -0
  385. package/modules/raise/public/edit.js +152 -0
  386. package/modules/raise/public/favicon.svg +1 -0
  387. package/modules/raise/public/logo-ink.svg +1 -0
  388. package/modules/raise/public/logo-night.svg +1 -0
  389. package/modules/raise/public/mode.js +8 -0
  390. package/modules/raise/public/raise.css +234 -0
  391. package/modules/raise/public/raise.js +91 -0
  392. package/modules/raise/raise.js +174 -0
  393. package/modules/raise/routes/raise.js +152 -0
  394. package/modules/raise/views/gate.html +39 -0
  395. package/modules/raise/views/nda.html +21 -0
  396. package/modules/raise/views/page.html +133 -0
  397. package/modules/raise/web.js +72 -0
  398. package/modules/render-deploy/deploys.js +1 -1
  399. package/modules/render-deploy/render.js +2 -2
  400. package/modules/security/secret-scrub.js +3 -3
  401. package/modules/security/security.js +1 -1
  402. package/modules/security/tests/artifact_scan.mjs +1 -1
  403. package/modules/security/tests/mirror.mjs +1 -1
  404. package/modules/security/tests/scan_store.mjs +1 -1
  405. package/modules/sessions/db.js +2 -2
  406. package/modules/sessions/pulse.js +2 -2
  407. package/modules/sessions/routes/sessions.js +1 -1
  408. package/modules/specialities/specialities.js +1 -1
  409. package/modules/status-ui/public/README.md +3 -4
  410. package/modules/status-ui/public/index.html +5 -31
  411. package/modules/status-ui/public/status.js +6 -174
  412. package/modules/status-ui/public/style.css +4 -133
  413. package/modules/ui-design/docs/design-contract.md +3 -3
  414. package/modules/ui-design/kit/README.md +1 -1
  415. package/modules/ui-design/kit/serve.js +13 -4
  416. package/modules/ui-design/scripts/design-sync.js +1 -1
  417. package/modules/ui-design/scripts/figma-design-sync.js +1 -1
  418. package/modules/ui-design/scripts/validate-design.js +1 -1
  419. package/package-lock.json +27 -11
  420. package/package.json +2 -3
  421. package/release-notes.json +186 -0
  422. package/scripts/bongos/CLAUDE.md +15 -0
  423. package/scripts/bongos/abandon.js +137 -0
  424. package/scripts/bongos/accessibility-replay.js +195 -0
  425. package/scripts/bongos/address-park-sweep.sh +91 -0
  426. package/scripts/bongos/adopt-detect.js +123 -0
  427. package/scripts/bongos/adopt-import.js +111 -0
  428. package/scripts/bongos/adopt-preflight.js +187 -0
  429. package/scripts/bongos/adr-namespace.js +273 -0
  430. package/scripts/bongos/agent-invoke.js +689 -0
  431. package/scripts/bongos/agents-sync.js +502 -0
  432. package/scripts/bongos/api-alias-caller-scan.js +256 -0
  433. package/scripts/bongos/api-artifacts.js +91 -0
  434. package/scripts/bongos/api.js +86 -0
  435. package/scripts/bongos/api.ps1 +26 -0
  436. package/scripts/bongos/architect-audit.js +294 -0
  437. package/scripts/bongos/artifact-audit.js +326 -0
  438. package/scripts/bongos/artifact-format.js +203 -0
  439. package/scripts/bongos/ask.js +231 -0
  440. package/scripts/bongos/audit-authorship.sh +324 -0
  441. package/scripts/bongos/audit-deps.js +189 -0
  442. package/scripts/bongos/audit-gate.js +121 -0
  443. package/scripts/bongos/audit-rank-roles.js +131 -0
  444. package/scripts/bongos/audit-replay.sh +205 -0
  445. package/scripts/bongos/autobongos-digest.js +123 -0
  446. package/scripts/bongos/autobongos-grade-cap.js +187 -0
  447. package/scripts/bongos/autobongos-loop.js +210 -0
  448. package/scripts/bongos/autobongos-run.js +1361 -0
  449. package/scripts/bongos/autobongos-service.cmd +50 -0
  450. package/scripts/bongos/autobongos-service.ps1 +270 -0
  451. package/scripts/bongos/autobongos-tweak-lane.js +262 -0
  452. package/scripts/bongos/autobongos-verify.js +618 -0
  453. package/scripts/bongos/autonomy-gate.js +135 -0
  454. package/scripts/bongos/autonomy-gauge-statusline.js +124 -0
  455. package/scripts/bongos/autonomy-gauge.js +84 -0
  456. package/scripts/bongos/backfill-cost.js +176 -0
  457. package/scripts/bongos/backfill-disciplines.js +144 -0
  458. package/scripts/bongos/backfill-session-earnings.js +123 -0
  459. package/scripts/bongos/backfill-session-types.js +87 -0
  460. package/scripts/bongos/backfill-sessions.js +411 -0
  461. package/scripts/bongos/backfill-subagent-rewards.js +485 -0
  462. package/scripts/bongos/backfill-task-rewards.js +413 -0
  463. package/scripts/bongos/backlog-review.js +399 -0
  464. package/scripts/bongos/backup-dropin-sweep.sh +95 -0
  465. package/scripts/bongos/backup.js +116 -0
  466. package/scripts/bongos/baseline-staleness.js +217 -0
  467. package/scripts/bongos/bfg-principal-token.js +65 -0
  468. package/scripts/bongos/bug-attachment-audit.js +149 -0
  469. package/scripts/bongos/bug-attachment-recover.js +198 -0
  470. package/scripts/bongos/bug-triage.js +292 -0
  471. package/scripts/bongos/build-bongos.js +94 -0
  472. package/scripts/bongos/bump-version.js +221 -0
  473. package/scripts/bongos/capture.js +481 -0
  474. package/scripts/bongos/category-advisory-guard.js +206 -0
  475. package/scripts/bongos/ci-grade.js +82 -0
  476. package/scripts/bongos/claim-recall.js +112 -0
  477. package/scripts/bongos/claim.js +789 -0
  478. package/scripts/bongos/claude-materialize.js +1200 -0
  479. package/scripts/bongos/claude-md-template.js +142 -0
  480. package/scripts/bongos/cleanup-orphans.js +74 -0
  481. package/scripts/bongos/cli-lib.js +1226 -0
  482. package/scripts/bongos/client-baseurl-guard.js +116 -0
  483. package/scripts/bongos/codemod-rename-scripts-gds.js +380 -0
  484. package/scripts/bongos/conductor-dispatch.js +535 -0
  485. package/scripts/bongos/context-pack.js +326 -0
  486. package/scripts/bongos/control-manifest.js +199 -0
  487. package/scripts/bongos/copy-apply.js +758 -0
  488. package/scripts/bongos/copy-inventory.js +571 -0
  489. package/scripts/bongos/core-origin-follow.js +185 -0
  490. package/scripts/bongos/core-pin-sync.js +260 -0
  491. package/scripts/bongos/cost-report.js +63 -0
  492. package/scripts/bongos/cost.js +47 -0
  493. package/scripts/bongos/credential-presence.js +296 -0
  494. package/scripts/bongos/cutover-codemod.js +240 -0
  495. package/scripts/bongos/db-backup-nightly.sh +232 -0
  496. package/scripts/bongos/db-backup-offsite.sh +267 -0
  497. package/scripts/bongos/demote.js +45 -0
  498. package/scripts/bongos/deploy-divergence.js +454 -0
  499. package/scripts/bongos/deploy-main-audit-gate.sh +97 -0
  500. package/scripts/bongos/design-sync.js +12 -0
  501. package/scripts/bongos/dev-box-guard.js +166 -0
  502. package/scripts/bongos/dev-lib.js +722 -0
  503. package/scripts/bongos/dev.js +645 -0
  504. package/scripts/bongos/device-flow-help.js +72 -0
  505. package/scripts/bongos/diagnose-achievements.js +118 -0
  506. package/scripts/bongos/diagram-facts.js +355 -0
  507. package/scripts/bongos/discord-channels.js +77 -0
  508. package/scripts/bongos/do-api.js +109 -0
  509. package/scripts/bongos/doc-cli-guard.js +274 -0
  510. package/scripts/bongos/doc-comment-coverage.js +139 -0
  511. package/scripts/bongos/doc-control-claims.js +170 -0
  512. package/scripts/bongos/docs-entropy.js +453 -0
  513. package/scripts/bongos/doctor.js +493 -0
  514. package/scripts/bongos/enroll-control-plane.js +101 -0
  515. package/scripts/bongos/exec-path-guard.js +564 -0
  516. package/scripts/bongos/feedback-send.js +249 -0
  517. package/scripts/bongos/fetch-art-key.js +106 -0
  518. package/scripts/bongos/fetch-sound-prefs.js +126 -0
  519. package/scripts/bongos/figma-design-sync.js +11 -0
  520. package/scripts/bongos/find-untested.js +371 -0
  521. package/scripts/bongos/fitness-checks-error-envelope.js +134 -0
  522. package/scripts/bongos/fitness-checks-identity.js +332 -0
  523. package/scripts/bongos/fitness-checks-packaging.js +132 -0
  524. package/scripts/bongos/fitness-checks-route-pins.js +76 -0
  525. package/scripts/bongos/fitness-checks-vocabulary.js +392 -0
  526. package/scripts/bongos/fitness-checks-write-validation.js +157 -0
  527. package/scripts/bongos/fitness-lib.js +127 -0
  528. package/scripts/bongos/fitness-migration-contraction.js +50 -0
  529. package/scripts/bongos/fitness-ratchets.js +594 -0
  530. package/scripts/bongos/fitness.js +1498 -0
  531. package/scripts/bongos/forwarder.js +80 -0
  532. package/scripts/bongos/gate-review.js +330 -0
  533. package/scripts/bongos/gating.js +348 -0
  534. package/scripts/{gds → bongos}/gds-db-backup.service +6 -6
  535. package/scripts/{gds → bongos}/gds-db-backup.timer +4 -4
  536. package/scripts/{gds → bongos}/gds-db-offsite.service +4 -4
  537. package/scripts/{gds → bongos}/gds-db-offsite.timer +4 -4
  538. package/scripts/bongos/gds-literal-scan.js +196 -0
  539. package/scripts/bongos/gen-api-client.js +576 -0
  540. package/scripts/bongos/gen-api-docs.js +1111 -0
  541. package/scripts/bongos/gen-atlas.js +366 -0
  542. package/scripts/bongos/gen-diagrams.js +608 -0
  543. package/scripts/bongos/gen-file-map.js +337 -0
  544. package/scripts/bongos/gen-freshness.js +32 -0
  545. package/scripts/bongos/gen-interaction-posture.js +122 -0
  546. package/scripts/bongos/gen-repo-map.js +540 -0
  547. package/scripts/bongos/gen-role-responsibilities.js +134 -0
  548. package/scripts/bongos/gen-session-index.js +243 -0
  549. package/scripts/bongos/gen-sounds.js +176 -0
  550. package/scripts/bongos/git-merge-regen.js +254 -0
  551. package/scripts/bongos/go-live.js +1071 -0
  552. package/scripts/bongos/goal.js +272 -0
  553. package/scripts/bongos/government-walk.js +1477 -0
  554. package/scripts/bongos/grade-correlation-audit.js +310 -0
  555. package/scripts/bongos/grade-replay.js +237 -0
  556. package/scripts/bongos/grade-smoke.js +205 -0
  557. package/scripts/bongos/home-isolation-guard.js +126 -0
  558. package/scripts/bongos/hooks/pre-push.js +211 -0
  559. package/scripts/bongos/howto.js +145 -0
  560. package/scripts/bongos/http-api-client.js +81 -0
  561. package/scripts/bongos/identity-strip.js +75 -0
  562. package/scripts/bongos/init.js +1159 -0
  563. package/scripts/bongos/install-git-hooks.js +200 -0
  564. package/scripts/bongos/instance-apex.js +38 -0
  565. package/scripts/bongos/intent-retry.js +52 -0
  566. package/scripts/bongos/key-card.js +222 -0
  567. package/scripts/bongos/key-status.js +126 -0
  568. package/scripts/bongos/land-watch.js +201 -0
  569. package/scripts/bongos/leak-scan-allowlist.js +293 -0
  570. package/scripts/bongos/learning-capture.js +145 -0
  571. package/scripts/bongos/lib.sh +74 -0
  572. package/scripts/bongos/linkify-refs.js +655 -0
  573. package/scripts/bongos/lint-infra-exec.js +70 -0
  574. package/scripts/bongos/lint-migrations.js +102 -0
  575. package/scripts/bongos/lint-workflow-exec.js +63 -0
  576. package/scripts/bongos/local-preview-lib.js +128 -0
  577. package/scripts/bongos/local-preview.js +82 -0
  578. package/scripts/bongos/login.js +360 -0
  579. package/scripts/bongos/main-audit.js +625 -0
  580. package/scripts/bongos/me.js +97 -0
  581. package/scripts/bongos/memory-map.js +176 -0
  582. package/scripts/bongos/merge-lock.js +71 -0
  583. package/scripts/bongos/migration-namespace.js +313 -0
  584. package/scripts/bongos/mirror-lineage-check.js +343 -0
  585. package/scripts/bongos/mirror-redact.js +350 -0
  586. package/scripts/bongos/module-artifact.js +289 -0
  587. package/scripts/bongos/module-assess-docs.js +238 -0
  588. package/scripts/bongos/module-assess-installs.js +228 -0
  589. package/scripts/bongos/module-assess-score.js +111 -0
  590. package/scripts/bongos/module-assess-security.js +252 -0
  591. package/scripts/bongos/module-assess-tests.js +278 -0
  592. package/scripts/bongos/module-assess-version.js +92 -0
  593. package/scripts/bongos/module-error-report.js +148 -0
  594. package/scripts/{gds → bongos}/module-test-runner/README.md +3 -3
  595. package/scripts/{gds → bongos}/module-test-runner/module-tests.yml +2 -2
  596. package/scripts/bongos/module-test-runner.js +414 -0
  597. package/scripts/bongos/module.js +1376 -0
  598. package/scripts/bongos/move-escalation.js +141 -0
  599. package/scripts/{gds → bongos}/newcomer-floor.config.json +1 -1
  600. package/scripts/bongos/newcomer-floor.js +421 -0
  601. package/scripts/{gds → bongos}/newcomer-floor.templates.json +13 -13
  602. package/scripts/bongos/newcomer-floor.test.js +235 -0
  603. package/scripts/bongos/next-number.js +163 -0
  604. package/scripts/bongos/oauth-secret.js +202 -0
  605. package/scripts/bongos/onboard.js +267 -0
  606. package/scripts/bongos/onboarding-analyze.js +226 -0
  607. package/scripts/bongos/onboarding-config.js +179 -0
  608. package/scripts/bongos/onboarding-ship.js +92 -0
  609. package/scripts/bongos/pack-env-prefix.js +73 -0
  610. package/scripts/bongos/package-core.js +1200 -0
  611. package/scripts/bongos/page-inventory.js +348 -0
  612. package/scripts/bongos/page-reader.js +722 -0
  613. package/scripts/bongos/paste-token.js +212 -0
  614. package/scripts/bongos/plain-cards.js +351 -0
  615. package/scripts/bongos/portability-smoke-art.sh +85 -0
  616. package/scripts/bongos/portability-smoke-memory.sh +176 -0
  617. package/scripts/bongos/preflight.js +214 -0
  618. package/scripts/bongos/probe-cache.js +246 -0
  619. package/scripts/bongos/prove-strict-versioning.js +284 -0
  620. package/scripts/bongos/provision-auto-upgrade.js +162 -0
  621. package/scripts/bongos/provision-byo-host.js +68 -0
  622. package/scripts/bongos/provision-capacity.js +79 -0
  623. package/scripts/bongos/provision-caps.js +63 -0
  624. package/scripts/bongos/provision-config.js +233 -0
  625. package/scripts/bongos/provision-core-upgrade.js +1166 -0
  626. package/scripts/bongos/provision-disconnect.js +88 -0
  627. package/scripts/bongos/provision-github-setup.js +168 -0
  628. package/scripts/bongos/provision-net.js +357 -0
  629. package/scripts/bongos/provision-pin-key.js +176 -0
  630. package/scripts/bongos/provision-pin-replay.js +126 -0
  631. package/scripts/bongos/provision-process.js +170 -0
  632. package/scripts/bongos/provision-render.js +201 -0
  633. package/scripts/bongos/provision-repo-auth.js +164 -0
  634. package/scripts/bongos/provision-repo-private.js +98 -0
  635. package/scripts/bongos/provision-repo.js +1337 -0
  636. package/scripts/bongos/provision-teardown.js +106 -0
  637. package/scripts/bongos/provision-units.js +469 -0
  638. package/scripts/bongos/provision.js +1479 -0
  639. package/scripts/bongos/publish-credential-check.js +66 -0
  640. package/scripts/bongos/publish-integration-gate.js +142 -0
  641. package/scripts/bongos/publish-manifest.js +440 -0
  642. package/scripts/bongos/publish-watch.js +268 -0
  643. package/scripts/bongos/pulse.js +338 -0
  644. package/scripts/bongos/push-main.js +56 -0
  645. package/scripts/bongos/push-path-brief.js +100 -0
  646. package/scripts/bongos/read-session-export.js +359 -0
  647. package/scripts/bongos/reauth.js +155 -0
  648. package/scripts/bongos/recall.js +183 -0
  649. package/scripts/bongos/redteam-patrol.js +437 -0
  650. package/scripts/bongos/regen-instance-docs.js +47 -0
  651. package/scripts/bongos/release-core.js +80 -0
  652. package/scripts/bongos/release-notes.js +271 -0
  653. package/scripts/bongos/release.js +139 -0
  654. package/scripts/bongos/rename-history-check.js +369 -0
  655. package/scripts/bongos/rename-ledger-prose.js +482 -0
  656. package/scripts/bongos/render-api.js +197 -0
  657. package/scripts/bongos/render-check.js +206 -0
  658. package/scripts/bongos/render-ideas.js +226 -0
  659. package/scripts/bongos/render-payload.js +85 -0
  660. package/scripts/bongos/repo-metrics.js +363 -0
  661. package/scripts/bongos/review-sheet.js +108 -0
  662. package/scripts/bongos/role-pack-guard.js +142 -0
  663. package/scripts/bongos/route-shadow-guard.js +175 -0
  664. package/scripts/bongos/routine-schedule.js +318 -0
  665. package/scripts/bongos/run-routine.js +257 -0
  666. package/scripts/bongos/run-unit-tests.js +654 -0
  667. package/scripts/bongos/runner-drift.js +151 -0
  668. package/scripts/bongos/sandbox-stage.js +459 -0
  669. package/scripts/bongos/scope-map-guard.js +300 -0
  670. package/scripts/bongos/scope-roster-guard.js +118 -0
  671. package/scripts/bongos/seam-wiring-guard.js +275 -0
  672. package/scripts/bongos/search-ingest-db.js +288 -0
  673. package/scripts/bongos/search-ingest-md.js +269 -0
  674. package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +152 -0
  675. package/scripts/bongos/seed-bv1-profiles-tasks.js +135 -0
  676. package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +390 -0
  677. package/scripts/bongos/seed-staging.sh +117 -0
  678. package/scripts/bongos/seed-verify-criteria.js +124 -0
  679. package/scripts/bongos/sequence.js +597 -0
  680. package/scripts/bongos/session-cost.js +430 -0
  681. package/scripts/bongos/session-digest-build.js +293 -0
  682. package/scripts/bongos/session-digest.js +200 -0
  683. package/scripts/bongos/session-eval.js +631 -0
  684. package/scripts/bongos/session-transcript-build.js +155 -0
  685. package/scripts/bongos/session-transcript-upload.js +29 -0
  686. package/scripts/bongos/session.js +404 -0
  687. package/scripts/bongos/setup.js +646 -0
  688. package/scripts/bongos/ship-check.js +89 -0
  689. package/scripts/bongos/ship-deploy-target.js +393 -0
  690. package/scripts/bongos/ship-escalation.js +167 -0
  691. package/scripts/bongos/ship-finish.js +420 -0
  692. package/scripts/bongos/ship-flow.js +1217 -0
  693. package/scripts/bongos/ship-git.js +100 -0
  694. package/scripts/bongos/ship-grade-steps.js +547 -0
  695. package/scripts/bongos/ship-grade.js +426 -0
  696. package/scripts/bongos/ship-honesty.js +314 -0
  697. package/scripts/bongos/ship-io.js +139 -0
  698. package/scripts/bongos/ship-land.js +1130 -0
  699. package/scripts/bongos/ship-memory-sync.js +249 -0
  700. package/scripts/bongos/ship-merge-gate.js +225 -0
  701. package/scripts/bongos/ship-merge.js +466 -0
  702. package/scripts/bongos/ship-mode-ask.js +138 -0
  703. package/scripts/bongos/ship-mode-manual.js +54 -0
  704. package/scripts/bongos/ship-preflight-steps.js +399 -0
  705. package/scripts/bongos/ship-regen.js +291 -0
  706. package/scripts/bongos/ship-resume.js +201 -0
  707. package/scripts/bongos/ship-session-upload.js +313 -0
  708. package/scripts/bongos/ship-state.js +110 -0
  709. package/scripts/bongos/ship-surprise.js +84 -0
  710. package/scripts/bongos/ship-visual.js +75 -0
  711. package/scripts/bongos/ship.js +382 -0
  712. package/scripts/bongos/shipping-mode.js +71 -0
  713. package/scripts/bongos/skill-lint.js +250 -0
  714. package/scripts/bongos/skill-preflight.js +361 -0
  715. package/scripts/bongos/smoke-batch-claim.sh +238 -0
  716. package/scripts/bongos/smoke-batch-release.sh +316 -0
  717. package/scripts/bongos/smoke-claim-consistency.sh +222 -0
  718. package/scripts/bongos/smoke-dependencies.sh +143 -0
  719. package/scripts/bongos/smoke-gds.js +256 -0
  720. package/scripts/bongos/smoke-write.sh +275 -0
  721. package/scripts/bongos/source-text-test-scan.js +106 -0
  722. package/scripts/bongos/spark.js +294 -0
  723. package/scripts/bongos/stale-worktrees.js +212 -0
  724. package/scripts/bongos/start-goals.js +102 -0
  725. package/scripts/bongos/start.js +1090 -0
  726. package/scripts/bongos/status.js +545 -0
  727. package/scripts/bongos/strand-watch.js +315 -0
  728. package/scripts/bongos/stranded-rows.js +200 -0
  729. package/scripts/bongos/stray-unit-sweep.sh +71 -0
  730. package/scripts/bongos/surface.js +101 -0
  731. package/scripts/bongos/task.js +273 -0
  732. package/scripts/bongos/test-path-guard.js +99 -0
  733. package/scripts/bongos/triage.js +742 -0
  734. package/scripts/bongos/turn-end-sound.js +74 -0
  735. package/scripts/bongos/tweak-halt.js +70 -0
  736. package/scripts/bongos/tweak-renders.js +200 -0
  737. package/scripts/bongos/uat.js +120 -0
  738. package/scripts/bongos/ui-kit-transform.js +43 -0
  739. package/scripts/bongos/update-channel.js +512 -0
  740. package/scripts/bongos/update-sweep.js +829 -0
  741. package/scripts/bongos/upgrade-artist-gate.js +46 -0
  742. package/scripts/bongos/upgrade-commit-identity.js +32 -0
  743. package/scripts/bongos/upgrade-migrate.js +224 -0
  744. package/scripts/bongos/upgrade-operator.js +73 -0
  745. package/scripts/bongos/upgrade-outcome.js +174 -0
  746. package/scripts/bongos/upgrade.js +1499 -0
  747. package/scripts/bongos/validate-design.js +12 -0
  748. package/scripts/bongos/version-close.js +621 -0
  749. package/scripts/bongos/version-literal-guard.js +140 -0
  750. package/scripts/bongos/version-select.js +79 -0
  751. package/scripts/bongos/visual-review-nudge.js +39 -0
  752. package/scripts/bongos/wedge-remedy.js +174 -0
  753. package/scripts/bongos/worktree-claim-guard.js +130 -0
  754. package/scripts/bongos/worktree.js +449 -0
  755. package/scripts/discord/post.js +1 -1
  756. package/scripts/gds/README.md +9 -0
  757. package/scripts/gds/abandon.js +6 -136
  758. package/scripts/gds/accessibility-replay.js +5 -194
  759. package/scripts/gds/address-park-sweep.sh +7 -90
  760. package/scripts/gds/adopt-detect.js +5 -121
  761. package/scripts/gds/adopt-import.js +5 -109
  762. package/scripts/gds/adopt-preflight.js +5 -185
  763. package/scripts/gds/adr-namespace.js +5 -271
  764. package/scripts/gds/agent-invoke.js +5 -687
  765. package/scripts/gds/agents-sync.js +5 -500
  766. package/scripts/gds/api-alias-caller-scan.js +5 -255
  767. package/scripts/gds/api-artifacts.js +6 -0
  768. package/scripts/gds/api.js +6 -85
  769. package/scripts/gds/api.ps1 +8 -26
  770. package/scripts/gds/architect-audit.js +6 -293
  771. package/scripts/gds/artifact-audit.js +5 -324
  772. package/scripts/gds/artifact-format.js +6 -203
  773. package/scripts/gds/ask.js +5 -229
  774. package/scripts/gds/audit-authorship.sh +7 -328
  775. package/scripts/gds/audit-deps.js +6 -188
  776. package/scripts/gds/audit-gate.js +5 -119
  777. package/scripts/gds/audit-rank-roles.js +6 -171
  778. package/scripts/gds/audit-replay.sh +7 -204
  779. package/scripts/gds/autobongos-digest.js +5 -121
  780. package/scripts/gds/autobongos-grade-cap.js +5 -186
  781. package/scripts/gds/autobongos-loop.js +5 -208
  782. package/scripts/gds/autobongos-run.js +5 -1359
  783. package/scripts/gds/autobongos-service.cmd +8 -49
  784. package/scripts/gds/autobongos-service.ps1 +8 -270
  785. package/scripts/gds/autobongos-tweak-lane.js +5 -261
  786. package/scripts/gds/autobongos-verify.js +5 -616
  787. package/scripts/gds/autonomy-gate.js +5 -133
  788. package/scripts/gds/autonomy-gauge-statusline.js +5 -122
  789. package/scripts/gds/autonomy-gauge.js +5 -82
  790. package/scripts/gds/backfill-cost.js +6 -175
  791. package/scripts/gds/backfill-disciplines.js +5 -142
  792. package/scripts/gds/backfill-session-earnings.js +5 -121
  793. package/scripts/gds/backfill-session-types.js +5 -85
  794. package/scripts/gds/backfill-sessions.js +5 -409
  795. package/scripts/gds/backfill-subagent-rewards.js +5 -483
  796. package/scripts/gds/backfill-task-rewards.js +5 -411
  797. package/scripts/gds/backlog-review.js +6 -398
  798. package/scripts/gds/backup-dropin-sweep.sh +7 -94
  799. package/scripts/gds/backup.js +6 -115
  800. package/scripts/gds/baseline-staleness.js +5 -215
  801. package/scripts/gds/bfg-principal-token.js +6 -64
  802. package/scripts/gds/bug-attachment-audit.js +5 -147
  803. package/scripts/gds/bug-attachment-recover.js +5 -196
  804. package/scripts/gds/bug-triage.js +6 -291
  805. package/scripts/gds/build-bongos.js +5 -92
  806. package/scripts/gds/bump-version.js +5 -219
  807. package/scripts/gds/capture.js +6 -480
  808. package/scripts/gds/category-advisory-guard.js +5 -205
  809. package/scripts/gds/ci-grade.js +6 -81
  810. package/scripts/gds/claim-recall.js +6 -111
  811. package/scripts/gds/claim.js +6 -788
  812. package/scripts/gds/claude-materialize.js +5 -1198
  813. package/scripts/gds/claude-md-template.js +5 -140
  814. package/scripts/gds/cleanup-orphans.js +6 -73
  815. package/scripts/gds/cli-lib.js +6 -1204
  816. package/scripts/gds/client-baseurl-guard.js +5 -114
  817. package/scripts/gds/conductor-dispatch.js +6 -534
  818. package/scripts/gds/context-pack.js +6 -325
  819. package/scripts/gds/control-manifest.js +5 -197
  820. package/scripts/gds/copy-apply.js +5 -756
  821. package/scripts/gds/copy-inventory.js +5 -569
  822. package/scripts/gds/core-origin-follow.js +5 -184
  823. package/scripts/gds/core-pin-sync.js +5 -258
  824. package/scripts/gds/cost-report.js +6 -62
  825. package/scripts/gds/cost.js +6 -46
  826. package/scripts/gds/credential-presence.js +5 -294
  827. package/scripts/gds/cutover-codemod.js +5 -239
  828. package/scripts/gds/db-backup-nightly.sh +7 -231
  829. package/scripts/gds/db-backup-offsite.sh +7 -266
  830. package/scripts/gds/demote.js +6 -44
  831. package/scripts/gds/deploy-divergence.js +6 -445
  832. package/scripts/gds/deploy-main-audit-gate.sh +7 -96
  833. package/scripts/gds/design-sync.js +5 -10
  834. package/scripts/gds/dev-box-guard.js +5 -164
  835. package/scripts/gds/dev-lib.js +5 -721
  836. package/scripts/gds/dev.js +5 -643
  837. package/scripts/gds/device-flow-help.js +5 -70
  838. package/scripts/gds/diagnose-achievements.js +5 -116
  839. package/scripts/gds/diagram-facts.js +6 -355
  840. package/scripts/gds/discord-channels.js +5 -75
  841. package/scripts/gds/do-api.js +6 -109
  842. package/scripts/gds/doc-cli-guard.js +5 -266
  843. package/scripts/gds/doc-comment-coverage.js +5 -137
  844. package/scripts/gds/doc-control-claims.js +5 -166
  845. package/scripts/gds/docs-entropy.js +5 -443
  846. package/scripts/gds/doctor.js +6 -492
  847. package/scripts/gds/enroll-control-plane.js +5 -99
  848. package/scripts/gds/exec-path-guard.js +5 -562
  849. package/scripts/gds/feedback-send.js +5 -247
  850. package/scripts/gds/fetch-art-key.js +5 -104
  851. package/scripts/gds/fetch-sound-prefs.js +5 -124
  852. package/scripts/gds/figma-design-sync.js +5 -9
  853. package/scripts/gds/find-untested.js +5 -369
  854. package/scripts/gds/fitness-checks-error-envelope.js +5 -133
  855. package/scripts/gds/fitness-checks-identity.js +5 -342
  856. package/scripts/gds/fitness-checks-packaging.js +5 -131
  857. package/scripts/gds/fitness-checks-route-pins.js +5 -75
  858. package/scripts/gds/fitness-checks-vocabulary.js +5 -391
  859. package/scripts/gds/fitness-checks-write-validation.js +5 -156
  860. package/scripts/gds/fitness-lib.js +5 -126
  861. package/scripts/gds/fitness-migration-contraction.js +5 -49
  862. package/scripts/gds/fitness-ratchets.js +5 -563
  863. package/scripts/gds/fitness.js +5 -1493
  864. package/scripts/gds/gate-review.js +5 -328
  865. package/scripts/gds/gating.js +5 -346
  866. package/scripts/gds/gds-literal-scan.js +5 -194
  867. package/scripts/gds/gen-api-client.js +5 -555
  868. package/scripts/gds/gen-api-docs.js +5 -1100
  869. package/scripts/gds/gen-atlas.js +5 -364
  870. package/scripts/gds/gen-diagrams.js +6 -607
  871. package/scripts/gds/gen-file-map.js +5 -335
  872. package/scripts/gds/gen-freshness.js +5 -31
  873. package/scripts/gds/gen-interaction-posture.js +5 -120
  874. package/scripts/gds/gen-repo-map.js +5 -538
  875. package/scripts/gds/gen-role-responsibilities.js +5 -133
  876. package/scripts/gds/gen-session-index.js +5 -241
  877. package/scripts/gds/gen-sounds.js +5 -174
  878. package/scripts/gds/git-merge-regen.js +6 -291
  879. package/scripts/gds/go-live.js +5 -1069
  880. package/scripts/gds/goal.js +6 -271
  881. package/scripts/gds/government-walk.js +5 -1475
  882. package/scripts/gds/grade-correlation-audit.js +5 -308
  883. package/scripts/gds/grade-replay.js +5 -235
  884. package/scripts/gds/grade-smoke.js +6 -204
  885. package/scripts/gds/home-isolation-guard.js +5 -125
  886. package/scripts/gds/hooks/pre-push.js +5 -209
  887. package/scripts/gds/howto.js +5 -143
  888. package/scripts/gds/http-api-client.js +6 -81
  889. package/scripts/gds/identity-strip.js +5 -74
  890. package/scripts/gds/init.js +5 -1157
  891. package/scripts/gds/install-git-hooks.js +5 -198
  892. package/scripts/gds/instance-apex.js +5 -37
  893. package/scripts/gds/intent-retry.js +5 -51
  894. package/scripts/gds/key-card.js +6 -221
  895. package/scripts/gds/key-status.js +5 -124
  896. package/scripts/gds/land-watch.js +5 -199
  897. package/scripts/gds/leak-scan-allowlist.js +5 -291
  898. package/scripts/gds/learning-capture.js +6 -144
  899. package/scripts/gds/lib.sh +7 -73
  900. package/scripts/gds/linkify-refs.js +6 -654
  901. package/scripts/gds/lint-infra-exec.js +5 -68
  902. package/scripts/gds/lint-migrations.js +5 -100
  903. package/scripts/gds/lint-workflow-exec.js +5 -61
  904. package/scripts/gds/local-preview-lib.js +6 -128
  905. package/scripts/gds/local-preview.js +6 -81
  906. package/scripts/gds/login.js +5 -358
  907. package/scripts/gds/main-audit.js +5 -623
  908. package/scripts/gds/me.js +6 -96
  909. package/scripts/gds/memory-map.js +5 -174
  910. package/scripts/gds/merge-lock.js +6 -70
  911. package/scripts/gds/migration-namespace.js +5 -311
  912. package/scripts/gds/mirror-lineage-check.js +5 -341
  913. package/scripts/gds/mirror-redact.js +5 -348
  914. package/scripts/gds/module-artifact.js +6 -289
  915. package/scripts/gds/module-assess-docs.js +6 -237
  916. package/scripts/gds/module-assess-installs.js +6 -227
  917. package/scripts/gds/module-assess-score.js +6 -110
  918. package/scripts/gds/module-assess-security.js +6 -251
  919. package/scripts/gds/module-assess-tests.js +6 -277
  920. package/scripts/gds/module-assess-version.js +6 -91
  921. package/scripts/gds/module-error-report.js +5 -146
  922. package/scripts/gds/module-test-runner.js +6 -413
  923. package/scripts/gds/module.js +5 -1374
  924. package/scripts/gds/move-escalation.js +5 -140
  925. package/scripts/gds/newcomer-floor.js +6 -420
  926. package/scripts/gds/newcomer-floor.test.js +6 -234
  927. package/scripts/gds/next-number.js +6 -162
  928. package/scripts/gds/oauth-secret.js +5 -200
  929. package/scripts/gds/onboard.js +5 -265
  930. package/scripts/gds/onboarding-analyze.js +6 -225
  931. package/scripts/gds/onboarding-config.js +6 -179
  932. package/scripts/gds/onboarding-ship.js +6 -91
  933. package/scripts/gds/pack-env-prefix.js +5 -72
  934. package/scripts/gds/package-core.js +5 -1102
  935. package/scripts/gds/page-inventory.js +5 -346
  936. package/scripts/gds/page-reader.js +5 -720
  937. package/scripts/gds/paste-token.js +6 -211
  938. package/scripts/gds/plain-cards.js +5 -350
  939. package/scripts/gds/portability-smoke-art.sh +7 -84
  940. package/scripts/gds/portability-smoke-memory.sh +7 -175
  941. package/scripts/gds/preflight.js +5 -212
  942. package/scripts/gds/probe-cache.js +5 -244
  943. package/scripts/gds/prove-strict-versioning.js +6 -283
  944. package/scripts/gds/provision-auto-upgrade.js +5 -161
  945. package/scripts/gds/provision-byo-host.js +5 -67
  946. package/scripts/gds/provision-capacity.js +5 -78
  947. package/scripts/gds/provision-caps.js +5 -62
  948. package/scripts/gds/provision-config.js +5 -232
  949. package/scripts/gds/provision-core-upgrade.js +5 -1165
  950. package/scripts/gds/provision-disconnect.js +5 -87
  951. package/scripts/gds/provision-github-setup.js +5 -167
  952. package/scripts/gds/provision-net.js +5 -356
  953. package/scripts/gds/provision-pin-key.js +5 -175
  954. package/scripts/gds/provision-pin-replay.js +5 -125
  955. package/scripts/gds/provision-process.js +5 -169
  956. package/scripts/gds/provision-render.js +5 -200
  957. package/scripts/gds/provision-repo-auth.js +5 -163
  958. package/scripts/gds/provision-repo-private.js +5 -97
  959. package/scripts/gds/provision-repo.js +5 -1336
  960. package/scripts/gds/provision-teardown.js +5 -105
  961. package/scripts/gds/provision-units.js +5 -468
  962. package/scripts/gds/provision.js +5 -1477
  963. package/scripts/gds/publish-credential-check.js +6 -65
  964. package/scripts/gds/publish-integration-gate.js +5 -140
  965. package/scripts/gds/publish-manifest.js +5 -437
  966. package/scripts/gds/publish-watch.js +5 -266
  967. package/scripts/gds/pulse.js +6 -335
  968. package/scripts/gds/push-main.js +5 -54
  969. package/scripts/gds/push-path-brief.js +5 -98
  970. package/scripts/gds/read-session-export.js +5 -357
  971. package/scripts/gds/reauth.js +6 -154
  972. package/scripts/gds/recall.js +6 -182
  973. package/scripts/gds/redteam-patrol.js +5 -435
  974. package/scripts/gds/regen-instance-docs.js +5 -45
  975. package/scripts/gds/release-core.js +5 -78
  976. package/scripts/gds/release-notes.js +5 -270
  977. package/scripts/gds/release.js +6 -138
  978. package/scripts/gds/rename-history-check.js +5 -367
  979. package/scripts/gds/rename-ledger-prose.js +5 -480
  980. package/scripts/gds/render-api.js +5 -196
  981. package/scripts/gds/render-check.js +5 -204
  982. package/scripts/gds/render-ideas.js +6 -225
  983. package/scripts/gds/render-payload.js +5 -84
  984. package/scripts/gds/repo-metrics.js +6 -362
  985. package/scripts/gds/review-sheet.js +5 -106
  986. package/scripts/gds/role-pack-guard.js +5 -141
  987. package/scripts/gds/route-shadow-guard.js +5 -173
  988. package/scripts/gds/routine-schedule.js +5 -281
  989. package/scripts/gds/run-routine.js +5 -255
  990. package/scripts/gds/run-unit-tests.js +6 -659
  991. package/scripts/gds/runner-drift.js +5 -149
  992. package/scripts/gds/sandbox-stage.js +6 -458
  993. package/scripts/gds/scope-map-guard.js +5 -299
  994. package/scripts/gds/scope-roster-guard.js +5 -117
  995. package/scripts/gds/seam-wiring-guard.js +5 -274
  996. package/scripts/gds/search-ingest-db.js +6 -287
  997. package/scripts/gds/search-ingest-md.js +6 -268
  998. package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +6 -152
  999. package/scripts/gds/seed-bv1-profiles-tasks.js +6 -135
  1000. package/scripts/gds/seed-bv2-ideator-surface-tasks.js +6 -390
  1001. package/scripts/gds/seed-staging.sh +7 -116
  1002. package/scripts/gds/seed-verify-criteria.js +6 -124
  1003. package/scripts/gds/sequence.js +6 -596
  1004. package/scripts/gds/session-cost.js +6 -429
  1005. package/scripts/gds/session-digest-build.js +6 -293
  1006. package/scripts/gds/session-digest.js +6 -199
  1007. package/scripts/gds/session-eval.js +6 -630
  1008. package/scripts/gds/session-transcript-build.js +6 -155
  1009. package/scripts/gds/session-transcript-upload.js +6 -29
  1010. package/scripts/gds/session.js +6 -403
  1011. package/scripts/gds/setup.js +6 -645
  1012. package/scripts/gds/ship-check.js +5 -85
  1013. package/scripts/gds/ship-deploy-target.js +5 -392
  1014. package/scripts/gds/ship-escalation.js +5 -166
  1015. package/scripts/gds/ship-finish.js +5 -419
  1016. package/scripts/gds/ship-flow.js +5 -1216
  1017. package/scripts/gds/ship-git.js +5 -99
  1018. package/scripts/gds/ship-grade-steps.js +5 -546
  1019. package/scripts/gds/ship-grade.js +5 -425
  1020. package/scripts/gds/ship-honesty.js +5 -312
  1021. package/scripts/gds/ship-io.js +5 -138
  1022. package/scripts/gds/ship-land.js +5 -1129
  1023. package/scripts/gds/ship-memory-sync.js +5 -248
  1024. package/scripts/gds/ship-merge-gate.js +5 -224
  1025. package/scripts/gds/ship-merge.js +5 -465
  1026. package/scripts/gds/ship-mode-ask.js +5 -137
  1027. package/scripts/gds/ship-mode-manual.js +5 -53
  1028. package/scripts/gds/ship-preflight-steps.js +5 -398
  1029. package/scripts/gds/ship-regen.js +5 -313
  1030. package/scripts/gds/ship-resume.js +5 -200
  1031. package/scripts/gds/ship-session-upload.js +5 -312
  1032. package/scripts/gds/ship-state.js +5 -109
  1033. package/scripts/gds/ship-surprise.js +5 -83
  1034. package/scripts/gds/ship-visual.js +5 -74
  1035. package/scripts/gds/ship.js +5 -380
  1036. package/scripts/gds/shipping-mode.js +5 -69
  1037. package/scripts/gds/skill-lint.js +5 -248
  1038. package/scripts/gds/skill-preflight.js +5 -359
  1039. package/scripts/gds/smoke-batch-claim.sh +7 -237
  1040. package/scripts/gds/smoke-batch-release.sh +7 -315
  1041. package/scripts/gds/smoke-claim-consistency.sh +7 -221
  1042. package/scripts/gds/smoke-dependencies.sh +7 -142
  1043. package/scripts/gds/smoke-gds.js +6 -255
  1044. package/scripts/gds/smoke-write.sh +7 -274
  1045. package/scripts/gds/source-text-test-scan.js +7 -0
  1046. package/scripts/gds/spark.js +6 -293
  1047. package/scripts/gds/stale-worktrees.js +5 -210
  1048. package/scripts/gds/start-goals.js +5 -101
  1049. package/scripts/gds/start.js +6 -1089
  1050. package/scripts/gds/status.js +6 -544
  1051. package/scripts/gds/strand-watch.js +5 -313
  1052. package/scripts/gds/stranded-rows.js +5 -198
  1053. package/scripts/gds/stray-unit-sweep.sh +7 -70
  1054. package/scripts/gds/surface.js +5 -100
  1055. package/scripts/gds/task.js +6 -272
  1056. package/scripts/gds/test-path-guard.js +5 -97
  1057. package/scripts/gds/triage.js +6 -741
  1058. package/scripts/gds/turn-end-sound.js +5 -72
  1059. package/scripts/gds/tweak-halt.js +5 -68
  1060. package/scripts/gds/tweak-renders.js +5 -198
  1061. package/scripts/gds/uat.js +6 -119
  1062. package/scripts/gds/ui-kit-transform.js +5 -41
  1063. package/scripts/gds/update-channel.js +5 -510
  1064. package/scripts/gds/update-sweep.js +5 -827
  1065. package/scripts/gds/upgrade-artist-gate.js +5 -45
  1066. package/scripts/gds/upgrade-commit-identity.js +5 -31
  1067. package/scripts/gds/upgrade-migrate.js +5 -223
  1068. package/scripts/gds/upgrade-operator.js +6 -73
  1069. package/scripts/gds/upgrade-outcome.js +5 -173
  1070. package/scripts/gds/upgrade.js +5 -1497
  1071. package/scripts/gds/validate-design.js +5 -10
  1072. package/scripts/gds/version-close.js +6 -620
  1073. package/scripts/gds/version-literal-guard.js +5 -138
  1074. package/scripts/gds/version-select.js +5 -77
  1075. package/scripts/gds/visual-review-nudge.js +5 -38
  1076. package/scripts/gds/wedge-remedy.js +5 -173
  1077. package/scripts/gds/worktree-claim-guard.js +5 -129
  1078. package/scripts/gds/worktree.js +6 -448
  1079. package/scripts/hall-preview/refresh-fixtures.js +1 -1
  1080. package/scripts/hall-preview/server.js +2 -2
  1081. package/scripts/migrate.sh +3 -3
  1082. package/scripts/public-mirror-export.js +3 -3
  1083. package/scripts/security/dep-audit.js +50 -124
  1084. package/scripts/setup-builder.js +7 -7
  1085. package/src/bongos/api-errors.js +1 -0
  1086. package/src/bongos/api-prefix.js +1 -1
  1087. package/src/bongos/auth-github.js +19 -3
  1088. package/src/bongos/auth-idp.js +7 -0
  1089. package/src/bongos/claim-attribution.js +2 -2
  1090. package/src/bongos/core-moves.js +1 -1
  1091. package/src/bongos/core-update.js +3 -3
  1092. package/src/bongos/craft-mode.js +2 -2
  1093. package/src/bongos/db-kernel.js +15 -3
  1094. package/src/bongos/db.js +30 -4
  1095. package/src/bongos/github-repos.js +1 -1
  1096. package/src/bongos/llm-cache.js +1 -1
  1097. package/src/bongos/llm-pricing.js +1 -1
  1098. package/src/bongos/metrics.js +1 -1
  1099. package/src/bongos/middleware/rate-limit.js +2 -2
  1100. package/src/bongos/module-listing.js +93 -1
  1101. package/src/bongos/module-scope-map.js +90 -85
  1102. package/src/bongos/module-store.js +1 -1
  1103. package/src/bongos/module-submissions.js +1 -1
  1104. package/src/bongos/optimizer.js +1 -1
  1105. package/src/bongos/package-registry.js +1 -1
  1106. package/src/bongos/path-match.js +1 -1
  1107. package/src/bongos/permission-path-check.js +3 -3
  1108. package/src/bongos/platform-visibility-gate.js +3 -5
  1109. package/src/bongos/prelaunch-gate.js +7 -6
  1110. package/src/bongos/route-rank-check.js +2 -2
  1111. package/src/bongos/routes/auth.js +15 -2
  1112. package/src/bongos/routes/backup.js +1 -1
  1113. package/src/bongos/routes/builders.js +29 -1
  1114. package/src/bongos/routes/me.js +49 -18
  1115. package/src/bongos/routes/modules.js +29 -9
  1116. package/src/bongos/routes/public.js +3 -72
  1117. package/src/bongos/schema-lag.js +1 -1
  1118. package/src/bongos/sensitive-surfaces.js +1 -1
  1119. package/src/bongos/serve-internal.js +65 -16
  1120. package/src/bongos/software-update.js +2 -2
  1121. package/src/bongos/upgrade-hold.js +3 -3
  1122. package/src/hall-look.js +6 -5
  1123. package/src/module-api.js +3 -3
  1124. package/src/module-loader/catalog.js +1 -1
  1125. package/src/module-loader/error-tally.js +3 -3
  1126. package/src/module-loader/manifest-schema.js +3 -3
  1127. package/src/platform-server.js +10 -0
  1128. package/src/role-responsibilities.js +1 -1
  1129. package/src/stale-timer.js +2 -2
  1130. package/tests/accessibility_replay.mjs +1 -1
  1131. package/tests/activity_rollup_order_db.mjs +1 -1
  1132. package/tests/activity_snapshots_db.mjs +1 -1
  1133. package/tests/adopt_detect.mjs +1 -1
  1134. package/tests/adopt_import.mjs +1 -1
  1135. package/tests/adopt_preflight.mjs +1 -1
  1136. package/tests/adr_0089_scope.mjs +10 -7
  1137. package/tests/adr_0162_citation.mjs +1 -1
  1138. package/tests/adr_0162_gate_citation.mjs +1 -1
  1139. package/tests/agent_invoke.mjs +1 -1
  1140. package/tests/agent_invoke_live.mjs +3 -3
  1141. package/tests/agents_cron_trigger.mjs +2 -2
  1142. package/tests/agents_roster.mjs +1 -1
  1143. package/tests/agents_sync.mjs +4 -4
  1144. package/tests/allow_rule_guard.mjs +20 -20
  1145. package/tests/api_alias_caller_ratchet.mjs +9 -10
  1146. package/tests/api_alias_exceptions.mjs +7 -6
  1147. package/tests/api_artifacts.mjs +214 -0
  1148. package/tests/api_cli_flags.mjs +3 -3
  1149. package/tests/api_client.mjs +56 -54
  1150. package/tests/api_docs.mjs +30 -9
  1151. package/tests/api_error_envelope_buildcheck.mjs +1 -1
  1152. package/tests/api_msys_path_repair.mjs +2 -2
  1153. package/tests/architect.mjs +1 -1
  1154. package/tests/art_stage.mjs +2 -2
  1155. package/tests/artifact_audit.mjs +2 -2
  1156. package/tests/atlas.mjs +1 -1
  1157. package/tests/audit_deps.mjs +1 -1
  1158. package/tests/audit_gate.mjs +1 -1
  1159. package/tests/auth_flow_slice1.mjs +3 -3
  1160. package/tests/auth_inactive_builder.mjs +43 -5
  1161. package/tests/auth_session_expiry_db.mjs +16 -4
  1162. package/tests/auth_session_ttl.mjs +23 -0
  1163. package/tests/authorship_audit.mjs +2 -2
  1164. package/tests/autobongos_cadence.mjs +1 -1
  1165. package/tests/autobongos_fence.mjs +1 -1
  1166. package/tests/autobongos_grade_cap.mjs +2 -2
  1167. package/tests/autobongos_heartbeat_head.mjs +1 -1
  1168. package/tests/autobongos_host_access.mjs +3 -3
  1169. package/tests/autobongos_loop.mjs +17 -17
  1170. package/tests/autobongos_service_ps1.mjs +3 -3
  1171. package/tests/autobongos_tweak_lane.mjs +2 -2
  1172. package/tests/autobongos_verify.mjs +2 -2
  1173. package/tests/autonomous_fit_protected_paths.mjs +3 -3
  1174. package/tests/autonomy_config_idle.mjs +1 -1
  1175. package/tests/autonomy_daily_checks.mjs +201 -0
  1176. package/tests/autonomy_digest.mjs +1 -1
  1177. package/tests/autonomy_gate.mjs +1 -1
  1178. package/tests/autonomy_gauge.mjs +2 -2
  1179. package/tests/autonomy_runner_identity.mjs +1 -1
  1180. package/tests/backfill_sessions.mjs +8 -8
  1181. package/tests/backfill_subagent_rewards.mjs +1 -1
  1182. package/tests/backfill_task_rewards.mjs +2 -2
  1183. package/tests/backlog_review.mjs +3 -3
  1184. package/tests/baseline_staleness.mjs +2 -2
  1185. package/tests/bfg.mjs +11 -5
  1186. package/tests/bfg_write.mjs +20 -11
  1187. package/tests/blockers_hall.mjs +14 -4
  1188. package/tests/blockers_page_ui.mjs +56 -12
  1189. package/tests/bongos_dispatch.mjs +5 -5
  1190. package/tests/bongos_login.mjs +2 -2
  1191. package/tests/bug_attachment_audit.mjs +1 -1
  1192. package/tests/bug_attachment_recover.mjs +2 -2
  1193. package/tests/bug_triage.mjs +3 -3
  1194. package/tests/build_info.mjs +1 -1
  1195. package/tests/builder_tester_tag.mjs +184 -0
  1196. package/tests/bump_version.mjs +3 -3
  1197. package/tests/canonical_profile_url.mjs +1 -1
  1198. package/tests/capture_error_format.mjs +1 -1
  1199. package/tests/capture_goal_routing.mjs +2 -2
  1200. package/tests/category_advisory_guard.mjs +3 -3
  1201. package/tests/claim_error_surface.mjs +2 -2
  1202. package/tests/claim_from_task_and_home.mjs +1 -1
  1203. package/tests/claim_gate_open_blocker.mjs +7 -4
  1204. package/tests/claim_gate_rebase.mjs +12 -8
  1205. package/tests/claim_recall.mjs +4 -4
  1206. package/tests/claim_resolve_worktree_lock.mjs +1 -1
  1207. package/tests/claude_materialize.mjs +68 -68
  1208. package/tests/clawback_confirmed_backlog.mjs +8 -5
  1209. package/tests/cli_allowlist_permissions.mjs +11 -11
  1210. package/tests/cli_dispatcher.mjs +2 -2
  1211. package/tests/cli_err_code.mjs +6 -6
  1212. package/tests/cli_exit_no_abort.mjs +7 -7
  1213. package/tests/cli_lib_formatters.mjs +2 -2
  1214. package/tests/cli_sessions.mjs +5 -5
  1215. package/tests/cli_surface.mjs +15 -15
  1216. package/tests/cli_token_reissue.mjs +2 -2
  1217. package/tests/client_baseurl_guard.mjs +1 -1
  1218. package/tests/client_bundle_route.mjs +35 -4
  1219. package/tests/cloud_bongos_pack.mjs +1 -1
  1220. package/tests/community_leaderboard_db.mjs +1 -1
  1221. package/tests/conductor.mjs +18 -18
  1222. package/tests/conflict_resolve.mjs +14 -16
  1223. package/tests/consumer_layout_boot.mjs +12 -12
  1224. package/tests/context_pack.mjs +6 -6
  1225. package/tests/control_manifest.mjs +4 -4
  1226. package/tests/copy_desk_page_reads.mjs +1 -1
  1227. package/tests/copy_desk_page_release.mjs +192 -0
  1228. package/tests/copy_inventory.mjs +2 -2
  1229. package/tests/core_auto_upgrade.mjs +1 -1
  1230. package/tests/core_move_notice.mjs +2 -2
  1231. package/tests/core_origin_follow.mjs +7 -7
  1232. package/tests/core_pin_sync.mjs +3 -3
  1233. package/tests/core_upgrade_door.mjs +2 -2
  1234. package/tests/core_upgrade_owner_door.mjs +34 -1
  1235. package/tests/core_upgrade_runner.mjs +19 -19
  1236. package/tests/credential_presence.mjs +2 -2
  1237. package/tests/credit_grant.mjs +3 -3
  1238. package/tests/credit_log_single_writer.mjs +5 -5
  1239. package/tests/criterion_ref_status.mjs +2 -2
  1240. package/tests/cross_discipline_priority_direction.mjs +3 -3
  1241. package/tests/cutover_codemod.mjs +2 -4
  1242. package/tests/db_backup_nightly.mjs +1 -1
  1243. package/tests/db_backup_offsite.mjs +1 -1
  1244. package/tests/db_ownership_handover.mjs +2 -2
  1245. package/tests/dead_deps.mjs +3 -3
  1246. package/tests/dependency_advisory.mjs +1 -1
  1247. package/tests/deploy_audit_gate.mjs +4 -4
  1248. package/tests/deploy_divergence_line.mjs +36 -16
  1249. package/tests/deploy_page_projects.mjs +35 -4
  1250. package/tests/dev_lib.mjs +2 -2
  1251. package/tests/dev_windows.mjs +2 -2
  1252. package/tests/diagram_facts_offset.mjs +1 -1
  1253. package/tests/diagram_repo_slug.mjs +1 -1
  1254. package/tests/diff_derived_signals.mjs +2 -2
  1255. package/tests/dns_preflight.mjs +2 -2
  1256. package/tests/do_api.mjs +3 -3
  1257. package/tests/doc_cli_guard.mjs +28 -28
  1258. package/tests/doc_comment_coverage.mjs +1 -1
  1259. package/tests/doc_control_claims.mjs +11 -11
  1260. package/tests/docs_entropy.mjs +2 -2
  1261. package/tests/docs_openapi_route.mjs +8 -6
  1262. package/tests/doctor_hooks.mjs +1 -1
  1263. package/tests/edit_hints.mjs +3 -2
  1264. package/tests/effective_visibility_predicate.mjs +1 -19
  1265. package/tests/env_knobs_neutral_prefix.mjs +13 -13
  1266. package/tests/exec_path_guard.mjs +4 -4
  1267. package/tests/executed_closure.mjs +18 -12
  1268. package/tests/file_map.mjs +1 -1
  1269. package/tests/find_untested.mjs +13 -13
  1270. package/tests/first_admin_bootstrap.mjs +1 -1
  1271. package/tests/fitness.mjs +16 -16
  1272. package/tests/fitness_gds_ratchet.mjs +2 -2
  1273. package/tests/fitness_installed_core.mjs +3 -3
  1274. package/tests/fitness_no_raw_nul.mjs +1 -1
  1275. package/tests/fitness_ratchets.mjs +3 -3
  1276. package/tests/fitness_scope_roster.mjs +2 -2
  1277. package/tests/fitness_two_root.mjs +8 -8
  1278. package/tests/fixtures/accessibility-replay.json +5 -5
  1279. package/tests/fixtures/grade-replay/recorded-panel-grades.json +1 -1
  1280. package/tests/fixtures/ideator-prefold/README.md +1 -1
  1281. package/tests/fixtures/page-ledger.mjs +22 -0
  1282. package/tests/fixtures/session-506-digest.json +5 -5
  1283. package/tests/gate_approvals.mjs +50 -0
  1284. package/tests/gate_review.mjs +8 -8
  1285. package/tests/gating_review_retired.mjs +2 -2
  1286. package/tests/gen_freshness.mjs +3 -3
  1287. package/tests/git_guard.mjs +3 -3
  1288. package/tests/git_merge_regen.mjs +41 -65
  1289. package/tests/github_one_trip.mjs +4 -4
  1290. package/tests/github_pick_up.mjs +2 -2
  1291. package/tests/github_push_merge_driver.mjs +1 -1
  1292. package/tests/go_live.mjs +3 -2
  1293. package/tests/goal_category.mjs +1 -1
  1294. package/tests/goal_cli.mjs +2 -2
  1295. package/tests/goal_create_spec_entry.mjs +1 -1
  1296. package/tests/goal_invite_consent.mjs +3 -1
  1297. package/tests/goal_move.mjs +1 -1
  1298. package/tests/goal_working_area.mjs +1 -1
  1299. package/tests/government_agent_asks.mjs +7 -7
  1300. package/tests/government_board_room_copy.mjs +6 -1
  1301. package/tests/government_board_view.mjs +39 -0
  1302. package/tests/government_board_vote_ui.mjs +39 -1
  1303. package/tests/government_config.mjs +2 -2
  1304. package/tests/government_live_proof_shape.mjs +1 -1
  1305. package/tests/government_protected_surfaces.mjs +54 -53
  1306. package/tests/government_require_permission.mjs +9 -1
  1307. package/tests/government_vanilla_boot.mjs +1 -1
  1308. package/tests/government_vocabulary.mjs +2 -2
  1309. package/tests/government_walk.mjs +2 -2
  1310. package/tests/grade_body_limit.mjs +6 -4
  1311. package/tests/grade_correlation_audit.mjs +3 -3
  1312. package/tests/grade_diff_hash.mjs +1 -1
  1313. package/tests/grade_engine_replay.mjs +2 -2
  1314. package/tests/grade_server_authoritative.mjs +1 -1
  1315. package/tests/grade_unavailable_display.mjs +1 -1
  1316. package/tests/grader.mjs +8 -24
  1317. package/tests/grader_generated_provenance.mjs +14 -14
  1318. package/tests/grader_no_artifact.mjs +1 -1
  1319. package/tests/grader_prompt_fencing.mjs +1 -1
  1320. package/tests/grader_quality_window_overflow.mjs +1 -1
  1321. package/tests/grader_reader_lens.mjs +3 -3
  1322. package/tests/grader_regrade_delta.mjs +1 -1
  1323. package/tests/grader_unbacked_score.mjs +2 -2
  1324. package/tests/hall_acclaim_vote_control.mjs +113 -0
  1325. package/tests/hall_asset_cache.mjs +127 -0
  1326. package/tests/hall_audit.mjs +63 -0
  1327. package/tests/hall_board_world.mjs +20 -0
  1328. package/tests/hall_city_card_words.mjs +61 -0
  1329. package/tests/hall_client_request_shape.mjs +5 -1
  1330. package/tests/hall_home_ships_bounded.mjs +160 -0
  1331. package/tests/hall_landing_boot.mjs +15 -2
  1332. package/tests/hall_nav.mjs +33 -0
  1333. package/tests/hall_onboarding_bongos_setup.mjs +1 -1
  1334. package/tests/hall_oversight_world.mjs +44 -4
  1335. package/tests/hall_palette.mjs +12 -9
  1336. package/tests/hall_preview_security.mjs +1 -1
  1337. package/tests/hall_profile_world.mjs +17 -0
  1338. package/tests/hall_reading_world.mjs +16 -1
  1339. package/tests/hall_roster_world.mjs +2 -1
  1340. package/tests/hall_studio_world.mjs +4 -1
  1341. package/tests/hall_work_history_id.mjs +39 -0
  1342. package/tests/held_tweak_reporting.mjs +4 -4
  1343. package/tests/helpers.mjs +3 -3
  1344. package/tests/home_bounded_reads.mjs +1 -1
  1345. package/tests/home_isolation_guard.mjs +1 -1
  1346. package/tests/hook_core_resolve.mjs +7 -7
  1347. package/tests/hook_user_agents.mjs +1 -1
  1348. package/tests/hooks_drain.mjs +2 -2
  1349. package/tests/host_topology_skips.mjs +1 -1
  1350. package/tests/howto_guide.mjs +1 -1
  1351. package/tests/howto_moments.mjs +3 -3
  1352. package/tests/hub_account_page.mjs +1 -1
  1353. package/tests/idea_capture_grades.mjs +2 -2
  1354. package/tests/idea_develop_spark.mjs +1 -1
  1355. package/tests/idea_filed_via.mjs +2 -2
  1356. package/tests/idea_ideate_full.mjs +1 -1
  1357. package/tests/idea_spark_mark.mjs +1 -1
  1358. package/tests/idea_spark_queue.mjs +1 -1
  1359. package/tests/idea_triage.mjs +1 -1
  1360. package/tests/idea_triage_grade.mjs +3 -3
  1361. package/tests/idea_vote_permission.mjs +113 -0
  1362. package/tests/idea_votes_fold_db.mjs +123 -0
  1363. package/tests/infra_exec_paths.mjs +12 -12
  1364. package/tests/init.mjs +2 -2
  1365. package/tests/instance_db_migrated_on_code_move.mjs +5 -5
  1366. package/tests/instance_feedback.mjs +9 -9
  1367. package/tests/instance_mismatch_guard.mjs +2 -2
  1368. package/tests/integration_parked_ratchet.mjs +24 -2
  1369. package/tests/intent_retry.mjs +1 -1
  1370. package/tests/interaction_posture.mjs +3 -3
  1371. package/tests/invite_expiry_db.mjs +1 -1
  1372. package/tests/joinability_invite_only.mjs +1 -1
  1373. package/tests/karma_vote_lists.mjs +270 -0
  1374. package/tests/key-card.mjs +2 -2
  1375. package/tests/key-status.mjs +2 -2
  1376. package/tests/knip_ratchet_ambient.mjs +2 -2
  1377. package/tests/known_failing_ratchet.mjs +1 -1
  1378. package/tests/land_watch.mjs +2 -2
  1379. package/tests/landing_legal_pages.mjs +1 -1
  1380. package/tests/landing_page.mjs +2 -2
  1381. package/tests/leaderboard_roles.mjs +4 -1
  1382. package/tests/leak_scan_allowlist.mjs +8 -8
  1383. package/tests/leak_scan_fail_closed.mjs +1 -1
  1384. package/tests/lib_sh_resolution.mjs +9 -9
  1385. package/tests/lifecycle-card.mjs +7 -7
  1386. package/tests/linkify_check.mjs +2 -2
  1387. package/tests/linkify_refs.mjs +1 -1
  1388. package/tests/llm-cache-route.mjs +1 -1
  1389. package/tests/local_preview.mjs +2 -2
  1390. package/tests/main_audit.mjs +3 -3
  1391. package/tests/main_audit_attestation.mjs +1 -1
  1392. package/tests/main_audit_db_roster.mjs +2 -2
  1393. package/tests/main_worktree_busy_reason.mjs +3 -3
  1394. package/tests/markdown_line_endings.mjs +2 -2
  1395. package/tests/me_streak_leaderboard_queries.mjs +193 -0
  1396. package/tests/membership_kind_lockstep.mjs +1 -1
  1397. package/tests/memory_isolation.mjs +16 -8
  1398. package/tests/memory_map.mjs +2 -2
  1399. package/tests/memory_pull.mjs +33 -25
  1400. package/tests/merge_driver_register.mjs +3 -3
  1401. package/tests/migration_allocation.mjs +2 -2
  1402. package/tests/migration_namespace.mjs +1 -1
  1403. package/tests/migrations_forward_safe.mjs +1 -1
  1404. package/tests/mingle.mjs +1 -1
  1405. package/tests/mirror_lineage_fulltree.mjs +3 -3
  1406. package/tests/mirror_lineage_proof.mjs +2 -2
  1407. package/tests/mirror_redact.mjs +4 -4
  1408. package/tests/missing_dep_classify.mjs +3 -3
  1409. package/tests/module-scope-map.mjs +22 -22
  1410. package/tests/module_api_lazy.mjs +1 -1
  1411. package/tests/module_assess_docs.mjs +2 -2
  1412. package/tests/module_assess_installs.mjs +3 -3
  1413. package/tests/module_assess_price_parity.mjs +5 -5
  1414. package/tests/module_assess_score.mjs +5 -5
  1415. package/tests/module_assess_security.mjs +4 -4
  1416. package/tests/module_assess_tests.mjs +3 -3
  1417. package/tests/module_assessments_migration.mjs +1 -1
  1418. package/tests/module_catalog.mjs +2 -2
  1419. package/tests/module_cli.mjs +3 -3
  1420. package/tests/module_entitlements.mjs +1 -1
  1421. package/tests/module_error_counts.mjs +1 -1
  1422. package/tests/module_install.mjs +4 -4
  1423. package/tests/module_loader.mjs +3 -1
  1424. package/tests/module_owned_tests.mjs +1 -1
  1425. package/tests/module_release_channels.mjs +1 -1
  1426. package/tests/module_store_howto.mjs +3 -3
  1427. package/tests/module_store_listing.mjs +139 -2
  1428. package/tests/module_store_publish.mjs +4 -4
  1429. package/tests/module_store_publish_route.mjs +1 -1
  1430. package/tests/module_store_reassess.mjs +1 -1
  1431. package/tests/module_store_registry_migration.mjs +1 -1
  1432. package/tests/module_test_runner.mjs +3 -3
  1433. package/tests/module_update.mjs +4 -4
  1434. package/tests/module_upgrade_updates.mjs +1 -1
  1435. package/tests/move_escalation.mjs +2 -2
  1436. package/tests/nav_permission_atoms.mjs +3 -2
  1437. package/tests/needs_rebase.mjs +7 -3
  1438. package/tests/newcomer_floor.mjs +1 -1
  1439. package/tests/next_number.mjs +1 -1
  1440. package/tests/no_artifact_escalation.mjs +3 -3
  1441. package/tests/npm_release_where.mjs +1 -1
  1442. package/tests/oauth_secret.mjs +2 -2
  1443. package/tests/onboard.mjs +6 -6
  1444. package/tests/onboarding_gate.mjs +2 -2
  1445. package/tests/opt_in_skill_modules.mjs +3 -3
  1446. package/tests/own_scope_guard.mjs +1 -1
  1447. package/tests/own_session_revoke.mjs +4 -1
  1448. package/tests/package_core.mjs +10 -11
  1449. package/tests/page_inventory.mjs +5 -5
  1450. package/tests/page_reader.mjs +7 -7
  1451. package/tests/page_tweak_hold.mjs +6 -6
  1452. package/tests/parallel-load.mjs +1 -1
  1453. package/tests/paste_token_api_base.mjs +1 -1
  1454. package/tests/paste_token_session_store.mjs +2 -2
  1455. package/tests/pending_invite_purge_db.mjs +1 -1
  1456. package/tests/permission_path.mjs +1 -1
  1457. package/tests/pin_replay.mjs +1 -1
  1458. package/tests/pin_write_key.mjs +7 -7
  1459. package/tests/plain_cards.mjs +15 -15
  1460. package/tests/pr_assign.mjs +1 -1
  1461. package/tests/pre_push_hook.mjs +3 -3
  1462. package/tests/preflight_checks.mjs +2 -2
  1463. package/tests/prelaunch_gate.mjs +1 -1
  1464. package/tests/privacy_matrix.mjs +1 -1
  1465. package/tests/probe_cache.mjs +6 -6
  1466. package/tests/profile_connections_ui.mjs +4 -3
  1467. package/tests/profile_fields.mjs +11 -1
  1468. package/tests/profile_privacy_owner_view.mjs +1 -1
  1469. package/tests/profile_role_headline.mjs +10 -9
  1470. package/tests/project_admin_console_model.mjs +1 -1
  1471. package/tests/projects_hub.mjs +1 -1
  1472. package/tests/projects_hub_cloud_hop.mjs +1 -1
  1473. package/tests/promote_goal_id.mjs +6 -6
  1474. package/tests/promotion_sweep.mjs +1 -1
  1475. package/tests/provision.mjs +24 -24
  1476. package/tests/provision_account_identity.mjs +2 -2
  1477. package/tests/provision_byo_host.mjs +1 -1
  1478. package/tests/provision_caddy_wiring.mjs +2 -2
  1479. package/tests/provision_disconnect.mjs +2 -2
  1480. package/tests/provision_dns_first.mjs +1 -1
  1481. package/tests/provision_render.mjs +9 -9
  1482. package/tests/provision_repo_private.mjs +3 -3
  1483. package/tests/provision_resource_caps.mjs +5 -5
  1484. package/tests/provision_restart.mjs +3 -3
  1485. package/tests/provision_settings_apply.mjs +7 -7
  1486. package/tests/provision_teardown_address.mjs +2 -2
  1487. package/tests/provisioning_capacity.mjs +5 -5
  1488. package/tests/provisioning_credential_preflight.mjs +1 -1
  1489. package/tests/provisioning_disconnect.mjs +1 -1
  1490. package/tests/provisioning_error_note_scope.mjs +4 -4
  1491. package/tests/provisioning_paid_shape_gate.mjs +2 -2
  1492. package/tests/provisioning_planet_physics.mjs +16 -0
  1493. package/tests/provisioning_runner_drift_notice.mjs +2 -2
  1494. package/tests/provisioning_settings_env.mjs +1 -1
  1495. package/tests/pruned_lockfile_integrity.mjs +1 -1
  1496. package/tests/public_mirror_export.mjs +1 -1
  1497. package/tests/publish_integration_gate.mjs +2 -2
  1498. package/tests/publish_manifest.mjs +6 -6
  1499. package/tests/publish_watch.mjs +1 -1
  1500. package/tests/push_path_brief.mjs +2 -2
  1501. package/tests/raise.mjs +248 -0
  1502. package/tests/rank_roles_audit.mjs +1 -1
  1503. package/tests/rank_tier_single_source.mjs +2 -2
  1504. package/tests/rate_limit_public.mjs +1 -1
  1505. package/tests/read_default_meter.mjs +2 -2
  1506. package/tests/read_session_export.mjs +1 -1
  1507. package/tests/rebase_gate_set_aside.mjs +1 -1
  1508. package/tests/recall_cli.mjs +1 -1
  1509. package/tests/recall_corpus_health.mjs +3 -2
  1510. package/tests/recall_hints.mjs +1 -1
  1511. package/tests/recruiter_sliver_boundary.mjs +1 -1
  1512. package/tests/redteam_patrol.mjs +2 -2
  1513. package/tests/regrade_actual_minutes.mjs +2 -2
  1514. package/tests/regrade_eligibility.mjs +2 -2
  1515. package/tests/release_core.mjs +2 -2
  1516. package/tests/release_notes.mjs +4 -4
  1517. package/tests/rename_history_restraint.mjs +3 -3
  1518. package/tests/rename_ledger_prose.mjs +6 -6
  1519. package/tests/render_api.mjs +1 -1
  1520. package/tests/render_check.mjs +4 -4
  1521. package/tests/render_deploy.mjs +1 -1
  1522. package/tests/repo_info_binding.mjs +1 -1
  1523. package/tests/repo_map.mjs +5 -5
  1524. package/tests/reward_mode_cost_plus_only.mjs +7 -3
  1525. package/tests/reward_mode_surfacing.mjs +1 -1
  1526. package/tests/role_responsibilities.mjs +1 -1
  1527. package/tests/route_permission_check.mjs +1 -1
  1528. package/tests/route_shadow_guard.mjs +1 -1
  1529. package/tests/route_validation.mjs +1 -1
  1530. package/tests/routine_capture_kind.mjs +24 -13
  1531. package/tests/routine_schedule.mjs +51 -9
  1532. package/tests/run_routine.mjs +5 -5
  1533. package/tests/run_routine_two_root.mjs +5 -5
  1534. package/tests/runner_drift.mjs +17 -17
  1535. package/tests/sandbox_stage.mjs +5 -5
  1536. package/tests/scope_map_guard.mjs +7 -7
  1537. package/tests/scouting_owner_access_and_reach.mjs +1 -1
  1538. package/tests/scripts_gds_forwarders.mjs +224 -0
  1539. package/tests/scrubber_corpus.mjs +2 -2
  1540. package/tests/seam_wiring_guard.mjs +1 -1
  1541. package/tests/search_ingest.mjs +2 -2
  1542. package/tests/search_ingest_db.mjs +1 -1
  1543. package/tests/search_ingest_nul.mjs +6 -6
  1544. package/tests/seed_verify_criteria.mjs +3 -3
  1545. package/tests/sequence.mjs +3 -3
  1546. package/tests/served_paths_shipped.mjs +3 -3
  1547. package/tests/session_506_regression.mjs +1 -1
  1548. package/tests/session_accessibility.mjs +1 -1
  1549. package/tests/session_caps.mjs +1 -1
  1550. package/tests/session_cost.mjs +1 -1
  1551. package/tests/session_digest.mjs +2 -2
  1552. package/tests/session_eval.mjs +6 -6
  1553. package/tests/session_index.mjs +1 -1
  1554. package/tests/session_records.mjs +4 -4
  1555. package/tests/session_rename_fallback.mjs +2 -2
  1556. package/tests/session_reward_on_land.mjs +7 -149
  1557. package/tests/session_reward_on_land_db.mjs +191 -0
  1558. package/tests/session_reward_reconcile.mjs +6 -88
  1559. package/tests/session_reward_reconcile_db.mjs +132 -0
  1560. package/tests/session_transcript.mjs +1 -1
  1561. package/tests/sessions_kit_pager.mjs +2 -1
  1562. package/tests/setup_device_flow_fallback.mjs +2 -2
  1563. package/tests/setup_smoke.mjs +12 -5
  1564. package/tests/setup_status_facts.mjs +54 -12
  1565. package/tests/ship_autolinkify.mjs +2 -2
  1566. package/tests/ship_automerge_injection.mjs +1 -1
  1567. package/tests/ship_base_flag.mjs +1 -1
  1568. package/tests/ship_broadcast_routing.mjs +1 -1
  1569. package/tests/ship_broadcast_server.mjs +2 -2
  1570. package/tests/ship_builder_model.mjs +1 -1
  1571. package/tests/ship_cannot_lie.mjs +9 -9
  1572. package/tests/ship_card.mjs +2 -2
  1573. package/tests/ship_ci_deploy.mjs +7 -7
  1574. package/tests/ship_error_shape.mjs +1 -1
  1575. package/tests/ship_land_ci_not_started.mjs +3 -3
  1576. package/tests/ship_land_conflict.mjs +3 -3
  1577. package/tests/ship_land_proof.mjs +3 -3
  1578. package/tests/ship_land_red_pr.mjs +5 -5
  1579. package/tests/ship_merge_gate.mjs +14 -14
  1580. package/tests/ship_mode.mjs +1 -1
  1581. package/tests/ship_mode_first_ship.mjs +4 -4
  1582. package/tests/ship_mode_hands_off.mjs +8 -8
  1583. package/tests/ship_post_land_verify.mjs +1 -1
  1584. package/tests/ship_preflight.mjs +19 -19
  1585. package/tests/ship_premerge.mjs +1 -1
  1586. package/tests/ship_publish_error.mjs +2 -2
  1587. package/tests/ship_push_diagnosis.mjs +1 -1
  1588. package/tests/ship_regen_copy_inventory.mjs +3 -3
  1589. package/tests/ship_resume.mjs +4 -4
  1590. package/tests/ship_smoke_gate.mjs +1 -1
  1591. package/tests/ship_upload_skip.mjs +1 -1
  1592. package/tests/ship_upstream_deletion.mjs +1 -1
  1593. package/tests/ship_vendored_instance.mjs +8 -8
  1594. package/tests/ship_visual_regrade.mjs +3 -3
  1595. package/tests/ship_zero_commit.mjs +1 -1
  1596. package/tests/skill_docs_unavailable_regrade.mjs +3 -3
  1597. package/tests/skill_friction_kind.mjs +1 -1
  1598. package/tests/skill_grade_recover.mjs +1 -1
  1599. package/tests/skill_grader_health.mjs +1 -1
  1600. package/tests/skill_lint.mjs +1 -1
  1601. package/tests/skill_menu_ruling.mjs +1 -1
  1602. package/tests/skill_preflight.mjs +7 -7
  1603. package/tests/skip_is_not_pass.mjs +22 -1
  1604. package/tests/smoke_dependencies_witness.mjs +2 -2
  1605. package/tests/smoke_preflight.mjs +1 -1
  1606. package/tests/smoke_target.mjs +2 -2
  1607. package/tests/smoke_write_contract.mjs +2 -2
  1608. package/tests/sound_player.mjs +8 -8
  1609. package/tests/source_text_test_ratchet.mjs +97 -0
  1610. package/tests/speciality_corpus_scope.mjs +1 -1
  1611. package/tests/speciality_session_skills.mjs +1 -1
  1612. package/tests/sso_checkin_legacy_field_gone.mjs +4 -2
  1613. package/tests/stale_timer.mjs +3 -3
  1614. package/tests/stale_worktrees.mjs +1 -1
  1615. package/tests/start_env_guard.mjs +1 -1
  1616. package/tests/start_goal_first.mjs +3 -3
  1617. package/tests/start_inbox_count.mjs +1 -1
  1618. package/tests/start_rebase_warning.mjs +1 -1
  1619. package/tests/status_default_version.mjs +3 -3
  1620. package/tests/status_mirror_sync.mjs +1 -1
  1621. package/tests/status_page_no_dead_uptime.mjs +80 -0
  1622. package/tests/stop_refcheck.mjs +1 -1
  1623. package/tests/strand_watch.mjs +1 -1
  1624. package/tests/stranded_rows.mjs +1 -1
  1625. package/tests/stuck_detector.mjs +14 -14
  1626. package/tests/sweep_app_account.mjs +3 -3
  1627. package/tests/task_cli.mjs +2 -2
  1628. package/tests/task_detail_ui.mjs +11 -1
  1629. package/tests/task_discipline_required.mjs +2 -2
  1630. package/tests/task_list_paging.mjs +1 -1
  1631. package/tests/task_visual_slots.mjs +2 -2
  1632. package/tests/terms_acceptance.mjs +1 -1
  1633. package/tests/terms_grandfather_db.mjs +1 -1
  1634. package/tests/test_path_guard.mjs +1 -1
  1635. package/tests/triage_development.mjs +1 -1
  1636. package/tests/tweak_batch_apply.mjs +2 -2
  1637. package/tests/tweak_land_heal.mjs +3 -3
  1638. package/tests/tweak_unattended.mjs +3 -3
  1639. package/tests/ui_design_skills.mjs +2 -2
  1640. package/tests/unit_report_status.mjs +2 -2
  1641. package/tests/unit_runner_serial.mjs +2 -2
  1642. package/tests/unit_runner_teardown_abort.mjs +1 -1
  1643. package/tests/update_channel.mjs +2 -2
  1644. package/tests/update_channel_db.mjs +4 -4
  1645. package/tests/update_subscription_engine.mjs +26 -26
  1646. package/tests/update_sweep_home.mjs +14 -14
  1647. package/tests/upgrade.mjs +11 -11
  1648. package/tests/upgrade_artist_gate.mjs +4 -4
  1649. package/tests/upgrade_commit_identity.mjs +2 -2
  1650. package/tests/upgrade_migrate.mjs +7 -7
  1651. package/tests/upgrade_operator.mjs +2 -2
  1652. package/tests/upgrade_outcome.mjs +2 -2
  1653. package/tests/upgrade_persist_pin.mjs +5 -5
  1654. package/tests/upkeep_home.mjs +1 -1
  1655. package/tests/version_close.mjs +2 -2
  1656. package/tests/version_close_cli.mjs +2 -2
  1657. package/tests/version_close_route.mjs +1 -1
  1658. package/tests/version_literals.mjs +23 -23
  1659. package/tests/visual_review.mjs +5 -5
  1660. package/tests/wedge_remedy.mjs +5 -5
  1661. package/tests/welcome_boot.mjs +116 -0
  1662. package/tests/welcome_boot_browser.mjs +271 -0
  1663. package/tests/wizard_born_first_board.mjs +3 -3
  1664. package/tests/wizard_demo.mjs +1 -1
  1665. package/tests/wizard_one_page.mjs +4 -3
  1666. package/tests/wizard_physics.mjs +3 -1
  1667. package/tests/wizard_physics_more.mjs +42 -3
  1668. package/tests/work_title_wrap.mjs +1 -1
  1669. package/tests/workflow_exec_paths.mjs +6 -6
  1670. package/tests/worktree_claim_guard.mjs +1 -1
  1671. package/tests/worktree_helper.mjs +2 -2
  1672. package/tests/write_validation_gaps.mjs +3 -3
  1673. package/scripts/gds/api.sh +0 -6
  1674. package/scripts/gds/artifact-staleness.js +0 -267
  1675. package/scripts/gds/audit-exports.js +0 -128
  1676. package/scripts/gds/classify-discipline.js +0 -153
  1677. package/scripts/gds/codemod-rename-src-gds.js +0 -145
  1678. package/scripts/gds/coreB-carve-proof.sh +0 -725
  1679. package/scripts/gds/goal-names.js +0 -102
  1680. package/scripts/gds/rename-goals.js +0 -109
  1681. package/scripts/gds/resolve-skill-model.js +0 -57
  1682. package/scripts/gds/security-baseline-check.sh +0 -180
  1683. package/scripts/gds/seed-adopt-tasks.js +0 -75
  1684. package/scripts/gds/seed-api-contract-goal-tasks.js +0 -141
  1685. package/scripts/gds/seed-board-room-tasks.js +0 -196
  1686. package/scripts/gds/seed-bongos-app-tasks.js +0 -294
  1687. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +0 -81
  1688. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +0 -100
  1689. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +0 -307
  1690. package/scripts/gds/seed-bongos-module-system-tasks.js +0 -346
  1691. package/scripts/gds/seed-bongos-tasks.js +0 -214
  1692. package/scripts/gds/seed-bongos-v1-seo-tasks.js +0 -104
  1693. package/scripts/gds/seed-bv1-community-tasks.js +0 -131
  1694. package/scripts/gds/seed-bv1-privacy-invites-tasks.js +0 -133
  1695. package/scripts/gds/seed-bv1-profile-page-tasks.js +0 -161
  1696. package/scripts/gds/seed-bv1-r01-delta-tasks.js +0 -154
  1697. package/scripts/gds/seed-bv2-tweak-mode-tasks.js +0 -277
  1698. package/scripts/gds/seed-gds-v4-tasks.js +0 -624
  1699. package/scripts/gds/seed-governance-tasks.js +0 -340
  1700. package/scripts/gds/seed-medusa-tasks.js +0 -440
  1701. package/scripts/gds/seed-module-upstreaming.js +0 -219
  1702. package/scripts/gds/seed-productization-tasks.js +0 -235
  1703. package/scripts/gds/seed-project-admin-console-tasks.js +0 -88
  1704. package/scripts/gds/seed-provisioning-tasks.js +0 -83
  1705. package/scripts/gds/seed-strict-versioning-tasks.js +0 -275
  1706. package/scripts/gds/seed-v2-world-tasks.js +0 -283
  1707. package/scripts/gds/spike-task-map.js +0 -899
  1708. package/scripts/migrate_cost_ledger.sh +0 -178
  1709. package/scripts/status-probe.mjs +0 -213
  1710. package/src/bongos/uptime-poller.js +0 -93
  1711. package/tests/artifact_staleness.mjs +0 -207
  1712. package/tests/goal_names.mjs +0 -120
  1713. package/tests/government_fold_bench.mjs +0 -50
  1714. package/tests/spike_task_map.mjs +0 -422
  1715. package/tests/status-probe.mjs +0 -89
  1716. /package/{scripts/gds → modules/raise}/CLAUDE.md +0 -0
  1717. /package/scripts/{gds → bongos}/cloudbongos-token-isolation.conf +0 -0
  1718. /package/scripts/{gds → bongos}/discipline-modes.json +0 -0
  1719. /package/scripts/{gds → bongos}/retired-core-skills.json +0 -0
@@ -0,0 +1,1498 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // fitness.js — architecture fitness functions (Path C / ADR 0062 §9, task 1225).
4
+ //
5
+ // The ENFORCEMENT layer for the Cloud Bongos decoupling. A dependency-cruiser/ArchUnit-style gate that
6
+ // keeps the architecture from silently rotting back together. Each check is a pure function over
7
+ // the repo on disk returning { name, ok, hardFail, violations[], warnings[], note }. The CLI runs
8
+ // them all, prints a report, and exits non-zero on any hard failure. tests/fitness.mjs asserts
9
+ // each check passes, so the DB-free unit gate (run-unit-tests.js → the `unit` required check)
10
+ // enforces them on every PR — no new workflow needed.
11
+ //
12
+ // RATCHET, not big-bang. The structural epics that physically separate the core (R51 entrypoint
13
+ // #1190, R52 DB carve-out #1191, R54 module system #1193) are not built yet, so the codebase is
14
+ // still fused (every src/bongos/*.js shares the game's pg Pool via require('../db')). These checks
15
+ // therefore lock in the boundary DIRECTION now and fail only on NEW violations beyond a documented
16
+ // grandfather list; as the epics land they SHRINK the grandfather list. Module-level boundary
17
+ // enforcement (§4) tightens once R54 (#1193) gives us a module manifest to check against.
18
+ //
19
+ // Usage:
20
+ // node scripts/bongos/fitness.js # run all checks, print report, exit 1 on any hard failure
21
+ // node scripts/bongos/fitness.js --json # machine-readable report
22
+
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+ const { execFileSync } = require('node:child_process');
26
+ const { checkRankGuards, checkModulePinKeysResolve } = require('./fitness-checks-route-pins.js'); // Checks 4 + 4b — carved out by task 1003192 (the 1,500-line ratchet)
27
+ const genApiDocs = require('./gen-api-docs'); // R12 (#1999): reuse the route model (readsBody/validated) that drives the OpenAPI spec
28
+ const { parseRoutineFrontmatter } = require('./run-routine'); // System 4 (ADR 0078): deterministic-routine boundary
29
+ const { filenameViolation, stemCollisions, numberCollisions, CORE_NS, INSTANCE_NS } = require('./migration-namespace'); // ADR 0108 §5: cross-repo migration namespacing
30
+ const { resolveCoreRoot, resolveInstanceRoot } = require('../../src/instance-config'); // ADR 0108 §1: configurable-root
31
+
32
+ // task 1003206 (goal 1000079): fitness.js was 2,004 lines. Four cohesive pieces now
33
+ // live beside it — the shared roots/walkers and three check clusters. They are
34
+ // IMPORTED (not registered by path) so the CHECKS array and module.exports below
35
+ // stay byte-identical to the single-file version every test was written against.
36
+ const { CORE_ROOT, INSTANCE_ROOT, MODULE_ROOTS, REPO_ROOT, keyTokenRe, rel, runChecks, walkJs, walkJsAllRoots } = require('./fitness-lib.js');
37
+ const { IDENTITY_SCAN_ALLOWED, IDENTITY_SCAN_EXCLUDE, IDENTITY_SCAN_EXTRA_FILES, IDENTITY_SCAN_EXTS, IDENTITY_SCAN_ROOTS, IDENTITY_SCAN_SKIP_DIRS, PROMPT_IDENTITY_LITERALS, checkDesignContract, checkKernelPromptsNoHardcodedIdentity, checkNeutralConfigsNoHostIdentity, collectIdentityFiles, scanPromptIdentity, stripCommentsForIdentity } = require('./fitness-checks-identity.js');
38
+ const { WRITE_VALIDATION_BASELINE, WRITE_VALIDATION_EXEMPT, checkWriteRoutesValidated, scanUnvalidatedWriteRoutes } = require('./fitness-checks-write-validation.js');
39
+ const { GOAL_VOCAB_CITATION, GOAL_VOCAB_LINE_SCOPED, GOAL_VOCAB_SURFACE, LIFECYCLE_DB_FILES, PRELAUNCH_SURFACE, RENAME_IDENTITY_RE, VOCAB_ALLOW, VOCAB_BANNED, VOCAB_CITATION, VOCAB_EXTS, VOCAB_HISTORICAL_REF, VOCAB_SURFACE, checkGoalMembershipVocabulary, checkGovernmentRenameIdentity, checkPrelaunchVocabulary, checkVocabularyWall, vocabFilesToScan } = require('./fitness-checks-vocabulary.js');
40
+ const { checkCoreRequiresExcludedConfig, checkCoreRequiresExcludedModule } = require('./fitness-checks-packaging.js'); // Checks 16 + 16b — carved out by task 1003825 (the 1,500-line ratchet)
41
+ const { FLAT_ERROR_BASELINE, checkErrorEnvelope, countFlatErrors, scanFlatErrorSites } = require('./fitness-checks-error-envelope.js'); // Check 17 — carved out by task 1003825
42
+ // ============================================================================
43
+ // Check 1 — core ↔ host/game import boundary (ADR 0062 §1 cut-line)
44
+ // ============================================================================
45
+ //
46
+ // The portable core (src/bongos/) must not import the HOST GAME runtime. After BV1.R49 the game
47
+ // module lives in modules/game/ (rooms, world, db, seats, public, migrations). The only game-
48
+ // related file that stays in src/ is src/preview-server.js (the game-only sandbox entrypoint).
49
+ // Imports into scripts/ (build tooling / engine) are NOT host-game coupling.
50
+ const HOST_GAME = [
51
+ /^modules\/game\//, // everything in the game module (moved from src/ by BV1.R49)
52
+ /^src\/preview-server\.js$/, // game-only sandbox entrypoint (stays in src/)
53
+ ];
54
+ // Empty as of R52/#1191 — the core owns its pool (src/bongos/pool.js) and no longer imports the
55
+ // game's db helper. The boundary now enforces with ZERO grandfathered exceptions.
56
+ const GRANDFATHERED = new Set([]);
57
+ const REQUIRE_RE = /require\(\s*['"](\.\.?\/[^'"]+)['"]\s*\)/g;
58
+
59
+ function resolvesToHostGame(fromAbsFile, spec) {
60
+ const abs = path.resolve(path.dirname(fromAbsFile), spec);
61
+ const r = rel(abs);
62
+ for (const cand of [r, r + '.js', r.replace(/\/$/, '') + '/index.js']) {
63
+ if (GRANDFATHERED.has(cand)) return null; // allowed (and not a violation)
64
+ if (HOST_GAME.some((re) => re.test(cand))) return cand;
65
+ }
66
+ return null;
67
+ }
68
+
69
+ function checkCoreHostBoundary() {
70
+ const coreDir = path.join(REPO_ROOT, 'src', 'bongos');
71
+ const violations = [];
72
+ for (const abs of walkJs(coreDir)) {
73
+ // scan line-by-line, skipping comment lines so a require(...) quoted in a doc comment
74
+ // (e.g. explaining the boundary) is never mistaken for a real import.
75
+ for (const raw of fs.readFileSync(abs, 'utf8').split('\n')) {
76
+ const trimmed = raw.trim();
77
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) continue;
78
+ let m;
79
+ REQUIRE_RE.lastIndex = 0;
80
+ while ((m = REQUIRE_RE.exec(raw))) {
81
+ const target = resolvesToHostGame(abs, m[1]);
82
+ if (target) violations.push(`${rel(abs)} → require('${m[1]}') reaches host-game code (${target}) — the core must not import the game runtime (ADR 0062 §1).`);
83
+ }
84
+ }
85
+ }
86
+ return {
87
+ name: 'core↔host import boundary',
88
+ ok: violations.length === 0,
89
+ hardFail: violations.length > 0,
90
+ violations,
91
+ warnings: [],
92
+ note: `src/bongos/ must not import the host game runtime (grandfathered: ${[...GRANDFATHERED].join(', ') || 'none'} — severed by R52/#1191).`,
93
+ };
94
+ }
95
+
96
+ // ============================================================================
97
+ // Check 2 — root CLAUDE.md size budget + charter presence (ADR 0061)
98
+ // ============================================================================
99
+ const ROOT_HARD_MAX = 300; // ceiling: the always-loaded file must never balloon past this. Ratcheted
100
+ // 360→310 when task 1226 generated the §13 session-log index (was a ~58-line
101
+ // hand-maintained list), then 310→300 when task 1283 trimmed the quick-nav
102
+ // table + §2/§8/§9/§10/§12 verbose prose down to ~294 lines. Lower further as
103
+ // more detail relocates to nested docs / ADRs (ADR 0061).
104
+ const ROOT_TARGET = 200; // the charter's stated aim; keep ratcheting toward it.
105
+
106
+ // The line count is a structure/readability proxy; the cost paid EVERY session is
107
+ // characters/tokens. A 600-char quick-nav row is one line but ~150 tokens, so
108
+ // within-line bloat slips past ROOT_HARD_MAX entirely (exactly what task 1283
109
+ // trimmed). Guard the real cost too (task 1286). Ratcheted just above the
110
+ // post-1283 size (~39.5K chars / ~9.9K tok); lower alongside ROOT_HARD_MAX as
111
+ // detail relocates to nested docs / ADRs.
112
+ const ROOT_CHAR_HARD_MAX = 42000; // ~10.5K tokens — the always-loaded file must never balloon past this.
113
+ const ROOT_CHAR_TARGET = 32000; // ~8K tokens — aspirational, mirrors the ~200-line aim.
114
+ const estTokens = (n) => Math.round(n / 4); // ~4 chars/token for markdown prose.
115
+
116
+ // Where the charter BODY lives since task 1003687. It is guidance for EDITING a
117
+ // CLAUDE.md, so it is paths-scoped (`paths:` frontmatter, same mechanism as
118
+ // .claude/rules/hook-authoring.md) and costs nothing in the sessions — the large
119
+ // majority — that never open one. The kernel keeps the heading and a pointer.
120
+ const CHARTER_RULE_REL = '.claude/rules/claudemd-authoring.md';
121
+
122
+ function checkClaudeMdBudget(opts = {}) {
123
+ const p = path.join(INSTANCE_ROOT, 'CLAUDE.md'); // the root CLAUDE.md is INSTANCE content (materialized per instance; ADR 0108)
124
+ const text = opts.text != null ? opts.text : fs.readFileSync(p, 'utf8');
125
+ const lines = text.split('\n').length;
126
+ const violations = [];
127
+ const warnings = [];
128
+ if (lines > ROOT_HARD_MAX) {
129
+ violations.push(`CLAUDE.md is ${lines} lines — over the ${ROOT_HARD_MAX}-line hard ceiling. It loads in full every session; relocate detail to a nested CLAUDE.md / ADR / recipe (ADR 0061).`);
130
+ } else if (lines > ROOT_TARGET) {
131
+ warnings.push(`CLAUDE.md is ${lines} lines — over the ~${ROOT_TARGET}-line target (still under the ${ROOT_HARD_MAX} ceiling). Relocate more detail to nested CLAUDE.md / ADRs / recipes (ADR 0061), then lower ROOT_HARD_MAX as it shrinks.`);
132
+ }
133
+ const chars = text.length;
134
+ const tok = estTokens(chars);
135
+ if (chars > ROOT_CHAR_HARD_MAX) {
136
+ violations.push(`CLAUDE.md is ${chars} chars (~${tok} tokens) — over the ${ROOT_CHAR_HARD_MAX}-char (~${estTokens(ROOT_CHAR_HARD_MAX)}-token) hard ceiling. The line count may be fine, but the per-session token cost is not — trim verbose prose WITHIN lines (long quick-nav rows, restated rationale), not just whole lines (ADR 0061).`);
137
+ } else if (chars > ROOT_CHAR_TARGET) {
138
+ warnings.push(`CLAUDE.md is ${chars} chars (~${tok} tokens) — over the ~${ROOT_CHAR_TARGET}-char (~${estTokens(ROOT_CHAR_TARGET)}-token) target. This is the true per-session cost; within-line bloat (a 600-char table row is one line) escapes the line check. Trim prose, then lower ROOT_CHAR_HARD_MAX.`);
139
+ }
140
+ if (!text.includes('## Working with this file (content charter)')) {
141
+ violations.push('CLAUDE.md is missing the content-charter section (ADR 0061) — the per-line test + "what goes where" table must stay.');
142
+ } else {
143
+ // Task 1003687 relocated the charter BODY to a paths-scoped rule, so the kernel
144
+ // keeps the heading and a pointer. That makes the heading cheap to fake: a section
145
+ // with nothing behind it satisfies a substring check while the rules it names are
146
+ // gone. So the charter must resolve to something — either inline here, or through a
147
+ // pointer whose target actually exists and still carries the two rules + the table.
148
+ const namesRule = text.includes(CHARTER_RULE_REL);
149
+ const inlineCharter = text.includes('Per-line test:');
150
+ if (namesRule) {
151
+ const rulePath = path.join(INSTANCE_ROOT, CHARTER_RULE_REL); // .claude/ is materialized INSTANCE content (ADR 0108 §3)
152
+ if (!fs.existsSync(rulePath)) {
153
+ violations.push(`CLAUDE.md points its content charter at ${CHARTER_RULE_REL}, but that file does not exist — a pointer to nothing is worse than no pointer (ADR 0061 / task 1003687).`);
154
+ } else {
155
+ const rule = fs.readFileSync(rulePath, 'utf8');
156
+ const missing = [];
157
+ if (!/^---\r?\n[\s\S]*?\bpaths:[\s\S]*?["']\*\*\/CLAUDE\.md["'][\s\S]*?^---$/m.test(rule)) {
158
+ missing.push('`paths:` frontmatter matching `**/CLAUDE.md` (without it the rule never loads, and the charter is simply gone)');
159
+ }
160
+ if (!rule.includes('Per-line test:')) missing.push('the per-line test');
161
+ if (!rule.includes('## What goes where')) missing.push('the "what goes where" table');
162
+ if (missing.length) {
163
+ violations.push(`${CHARTER_RULE_REL} is missing ${missing.join(', ')} — the kernel delegates the charter to it, so the charter is only as real as that file (ADR 0061 / task 1003687).`);
164
+ }
165
+ }
166
+ } else if (!inlineCharter) {
167
+ violations.push('The CLAUDE.md content-charter section is hollow — it has the heading but neither the per-line test inline nor a pointer to `' + CHARTER_RULE_REL + '`. The heading exists to make the rules findable; on its own it only satisfies this check (ADR 0061).');
168
+ }
169
+ }
170
+ return { name: 'root CLAUDE.md budget + charter', ok: violations.length === 0, hardFail: violations.length > 0, violations, warnings, note: `≤ ${ROOT_HARD_MAX} lines / ${ROOT_CHAR_HARD_MAX} chars (~${estTokens(ROOT_CHAR_HARD_MAX)} tok); targets ~${ROOT_TARGET} lines / ~${estTokens(ROOT_CHAR_TARGET)} tok; charter resolves (inline or via ${CHARTER_RULE_REL}).` };
171
+ }
172
+
173
+ // ============================================================================
174
+ // Check 3 — nested per-module CLAUDE.md presence for high-traffic dirs (ADR 0061)
175
+ // ============================================================================
176
+ const HIGH_TRAFFIC = ['src/bongos', 'src/bongos/routes', 'scripts/bongos'];
177
+
178
+ function checkNestedDocsPresent() {
179
+ const violations = [];
180
+ for (const dir of HIGH_TRAFFIC) {
181
+ // HIGH_TRAFFIC dirs (src/bongos, src/bongos/routes, scripts/bongos) are CORE-package dirs — resolve
182
+ // against the core root, not the instance repo (ADR 0108 §Consequences #4).
183
+ const doc = path.join(CORE_ROOT, dir, 'CLAUDE.md');
184
+ if (!fs.existsSync(doc)) violations.push(`${dir}/CLAUDE.md is missing — high-traffic dirs must carry a nested altitude map (ADR 0061).`);
185
+ }
186
+ return { name: 'nested CLAUDE.md presence', ok: violations.length === 0, hardFail: violations.length > 0, violations, warnings: [], note: `present for: ${HIGH_TRAFFIC.join(', ')}.` };
187
+ }
188
+
189
+ // ============================================================================
190
+ // Check 5 — generated artifacts are fresh (Path C enforces Path B; ADR 0063 + ADR 0062 §8)
191
+ // ============================================================================
192
+ // Deterministic file-reads with a `--check` mode (regenerate in-memory, diff, exit non-zero on
193
+ // drift). This gate fails a PR that committed a stale artifact so the "generate, don't hand-maintain"
194
+ // contract can't rot.
195
+ // ADR 0110 (task 1926): docs/repo-map.md + docs/session-log-index.md are now GITIGNORED and
196
+ // regenerated at deploy/box-fetch (the gen-atlas.js model), so parallel branches never collide on
197
+ // them — and there is no committed copy to gate. Their generators are DUAL-DUTY, though: each also
198
+ // refreshes a TRACKED embedded block (the nested CLAUDE.md symbol blocks; the CLAUDE.md §13 snippet).
199
+ // Those blocks stay committed, so we gate the BLOCK bucket HARD via `--check-block`. A naive `--check`
200
+ // here would false-fail every PR (the gitignored whole file is absent from a clean checkout, so it
201
+ // always reads as "would change"); `--check-block` is the exact, non-noisy gate. (docs/file-map.md +
202
+ // the OpenAPI docs are still fully committed and unchanged by ADR 0110 — they keep the plain --check.)
203
+ function checkGeneratedArtifactsFresh() {
204
+ const violations = [];
205
+ try {
206
+ execFileSync(process.execPath, [path.join(__dirname, 'gen-repo-map.js'), '--check-block'], { cwd: REPO_ROOT, stdio: 'pipe' });
207
+ } catch {
208
+ violations.push('The tracked nested-doc symbol blocks (src/bongos/CLAUDE.md, src/bongos/routes/CLAUDE.md) are STALE — run `node scripts/bongos/gen-repo-map.js` and commit (ADR 0063 / ADR 0110). NB docs/repo-map.md itself is gitignored + deploy-regenerated, not gated here.');
209
+ }
210
+ try {
211
+ execFileSync(process.execPath, [path.join(__dirname, 'gen-session-index.js'), '--check-block'], { cwd: REPO_ROOT, stdio: 'pipe' });
212
+ } catch {
213
+ violations.push('The tracked CLAUDE.md §13 recent-sessions snippet is STALE — run `node scripts/bongos/gen-session-index.js` and commit (ADR 0062 §8 / ADR 0110). NB docs/session-log-index.md itself is gitignored + deploy-regenerated, not gated here.');
214
+ }
215
+ try {
216
+ // task 1002515 (criterion `accessibility-fluency-profile`, clause 2): the CLAUDE.md §2
217
+ // fallback posture is generated from the interaction knob's own defaults, so the kernel
218
+ // and modules/builder-settings/interaction-prefs.js cannot drift into two copies of one
219
+ // rule — which is what they were. Fully tracked (unlike the ADR 0110 pair above), so a
220
+ // plain --check is the right gate.
221
+ execFileSync(process.execPath, [path.join(__dirname, 'gen-interaction-posture.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' });
222
+ } catch {
223
+ violations.push('The CLAUDE.md §2 interaction-posture block is STALE — it is generated from modules/builder-settings/interaction-prefs.js. Run `node scripts/bongos/gen-interaction-posture.js` and commit (task 1002515).');
224
+ }
225
+ try {
226
+ execFileSync(process.execPath, [path.join(__dirname, 'gen-file-map.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' });
227
+ } catch {
228
+ violations.push('docs/file-map.md generated sections (.claude/skills/, .claude/scheduled-tasks/) are STALE, a skill/routine has no note in docs/file-map.notes.json, or a directory under modules/ has no file-map entry at all — run `node scripts/bongos/gen-file-map.js --check` for the exact list, then fix and commit (ADR 0066; module coverage: task 1004066).');
229
+ }
230
+ try {
231
+ // Also structurally validates the spec (exit 1 on invalid OpenAPI 3.1) beyond the drift check (exit 2). Task 1918.
232
+ execFileSync(process.execPath, [path.join(__dirname, 'gen-api-docs.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' });
233
+ } catch {
234
+ violations.push('The API spec generated from the routes is not valid OpenAPI 3.1, or the committed docs/routes-permissions.md stub is STALE — run `node scripts/bongos/gen-api-docs.js --check` for the detail (task 1918). The spec + reference themselves are gitignored (task 1004866).');
235
+ }
236
+ // task 1004866: the client is gitignored, so the gate is "a client built from the routes compiles".
237
+ try { execFileSync(process.execPath, [path.join(__dirname, 'gen-api-client.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' }); }
238
+ catch { violations.push('The typed API client could not be generated from the routes — run `node scripts/bongos/gen-api-client.js --check` for the detail (task 1004866).'); }
239
+ try {
240
+ // task 1003556: the copy registry's rows carry LINE NUMBERS, so editing any scanned
241
+ // UI file stales it. It was covered only by ship-check's OPTIONAL step, which a
242
+ // builder has to remember to run — so the first signal was CI failing on the PR's
243
+ // MERGE ref, where the shift is hardest to attribute. Gated here so a local fitness
244
+ // run says so first.
245
+ execFileSync(process.execPath, [path.join(__dirname, 'copy-inventory.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' });
246
+ } catch {
247
+ violations.push('docs/copy-registry.json + docs/copy-inventory.md are STALE — every row carries a line number, so editing any scanned UI file shifts them. Run `node scripts/bongos/copy-inventory.js` and commit (task 1003556).');
248
+ }
249
+ try {
250
+ // task 1004314 (BV2.TW02): the page inventory is the key Tweak Mode's page status,
251
+ // claims and pay join on, so a page added, renamed or retitled without it would
252
+ // be a page the chain cannot see. --check also fails on a duplicate or malformed id.
253
+ execFileSync(process.execPath, [path.join(__dirname, 'page-inventory.js'), '--check'], { cwd: REPO_ROOT, stdio: 'pipe' });
254
+ } catch {
255
+ violations.push('docs/page-inventory.json + docs/page-inventory.md are STALE (or two pages claim one id) — a page was added, renamed, retitled or changed its scripts/states. Run `node scripts/bongos/page-inventory.js` and commit (task 1004314).');
256
+ }
257
+ // NB the role packs' responsibility blocks are generated too, but their freshness
258
+ // is asserted by role-pack-guard.js — one check owns "the packs are correct".
259
+ return { name: 'generated artifacts fresh', ok: violations.length === 0, hardFail: violations.length > 0, violations, warnings: [], note: 'Tracked generated content matches source: nested CLAUDE.md symbol blocks (code) + the CLAUDE.md §13 snippet (sessions) via --check-block, plus the CLAUDE.md §2 interaction-posture block (the knob defaults), docs/file-map.md skills/scheduled-tasks sections, the API spec + typed client GENERATE from the routes (both gitignored, task 1004866), docs/copy-registry.json + copy-inventory.md (the reader-facing copy, task 1003556) and docs/page-inventory.json + page-inventory.md (every page and its stable id, task 1004314). The gitignored docs/repo-map.md + docs/session-log-index.md are deploy-regenerated (ADR 0110), not gated here.' };
260
+ }
261
+
262
+ // ---- deterministic cron routine boundary (System 4 / ADR 0078) -------------
263
+ //
264
+ // A `mode: deterministic` routine runs as plain node via run-routine.js — NO
265
+ // model session reads its SKILL body. So that body must not rot back into a
266
+ // wrapped session: it may not instruct a model to mutate (Edit/Write/git
267
+ // push/commit/deploy) or synthesize free text, and its documented commands must
268
+ // not diverge from its declared steps. Keeps the markdown-graveyard pattern out.
269
+
270
+ const SCHEDULED_TASKS_DIR = path.join(INSTANCE_ROOT, '.claude', 'scheduled-tasks'); // .claude/ is materialized INSTANCE content (ADR 0108 §3)
271
+
272
+ // Judgment/mutation instructions illegal in a deterministic body. Negated
273
+ // mentions ("never pushes", "does NOT edit") are descriptive boundaries — allowed.
274
+ const JUDGMENT_PATTERNS = [
275
+ { re: /\bgit\s+(push|commit|add)\b/i, label: 'a git push/commit/add' },
276
+ { re: /deploy\.sh\b/i, label: 'a deploy.sh invocation' },
277
+ { re: /`(Edit|Write|MultiEdit|NotebookEdit)`/, label: 'an Edit/Write tool instruction' },
278
+ { re: /\bsynthesi[sz]e\b/i, label: 'free-text synthesis' },
279
+ { re: /\b(write|compose|draft)\s+(a|an|the)\s+(summary|report|analysis|narrative|note)\b/i, label: 'free-text synthesis' },
280
+ ];
281
+ const NEGATION_RE = /\b(never|not|no|without|cannot|can't|don'?t|doesn'?t|won'?t)\b/i;
282
+
283
+ // Pure: scan one routine's parsed (mode, steps, body). Returns violation strings.
284
+ // Only inspects deterministic routines; others return []. Exported for tests.
285
+ function scanDeterministicBody(name, { mode, steps, body }) {
286
+ if (mode !== 'deterministic') return [];
287
+ const violations = [];
288
+ if (!steps || steps.length === 0) {
289
+ violations.push(`${name}: mode: deterministic but no steps: — run-routine.js would launch nothing (ADR 0078).`);
290
+ }
291
+ const text = String(body == null ? '' : body);
292
+ for (const raw of text.split('\n')) {
293
+ const line = raw.trim();
294
+ if (!line || NEGATION_RE.test(line)) continue; // skip blank + negated (boundary) lines
295
+ for (const p of JUDGMENT_PATTERNS) {
296
+ if (p.re.test(line)) {
297
+ violations.push(`${name}: deterministic SKILL body contains ${p.label} ("${line.slice(0, 70)}") — it runs as plain node with no model; move remediation/judgment to a separate claimed task (ADR 0078).`);
298
+ }
299
+ }
300
+ }
301
+ // Divergence: every `node …` command in a fenced code block must be a declared step.
302
+ const stepCmds = (steps || []).map((s) => String(s.command).replace(/\s+/g, ' ').trim());
303
+ for (const fence of text.match(/```[\s\S]*?```/g) || []) {
304
+ for (const fl of fence.split('\n')) {
305
+ const cmd = fl.trim().replace(/\s+/g, ' ');
306
+ if (!cmd.startsWith('node ')) continue;
307
+ if (!stepCmds.some((s) => cmd === s || cmd.startsWith(s) || s.startsWith(cmd))) {
308
+ violations.push(`${name}: deterministic SKILL body documents \`${cmd.slice(0, 70)}\` which is not in its steps: — prose and steps must not diverge (ADR 0078).`);
309
+ }
310
+ }
311
+ }
312
+ return violations;
313
+ }
314
+
315
+ function checkDeterministicRoutines() {
316
+ const violations = [];
317
+ let detCount = 0;
318
+ let dirs = [];
319
+ try {
320
+ dirs = fs.readdirSync(SCHEDULED_TASKS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
321
+ } catch (_) { /* no scheduled-tasks dir → nothing to check */ }
322
+ for (const name of dirs) {
323
+ let md;
324
+ try { md = fs.readFileSync(path.join(SCHEDULED_TASKS_DIR, name, 'SKILL.md'), 'utf8'); } catch (_) { continue; }
325
+ const { mode, steps } = parseRoutineFrontmatter(md);
326
+ if (mode !== 'deterministic') continue;
327
+ detCount += 1;
328
+ const body = md.replace(/^---\n[\s\S]*?\n---\n?/, ''); // strip frontmatter
329
+ violations.push(...scanDeterministicBody(name, { mode, steps, body }));
330
+ }
331
+ return {
332
+ name: 'deterministic cron routines (ADR 0078)',
333
+ ok: violations.length === 0,
334
+ hardFail: violations.length > 0,
335
+ violations,
336
+ warnings: [],
337
+ note: `${detCount} mode:deterministic routine(s): steps declared, no judgment instructions, prose↔steps aligned.`,
338
+ };
339
+ }
340
+
341
+ // ============================================================================
342
+ // Check 7/8 — module boundary (the one-way rule, ADR 0083 / design 04§3)
343
+ // ============================================================================
344
+ //
345
+ // The module system's one-way rule: a module imports ONLY src/module-api.js (the
346
+ // published doorway); the core NEVER imports a module; a module NEVER imports a
347
+ // sibling module. These two checks enforce it.
348
+ //
349
+ // Both were GREEN through the strangler: the first two moved modules (M07/M08)
350
+ // imported only the doorway, and the core imported neither. The boundary
351
+ // shipped in WARN mode so a half-moved module mid-migration couldn't red the
352
+ // build; BV1.R45 (task 1414) flips it to ENFORCING now that the first move
353
+ // (M07) proved clean — the monotonic ratchet (ADR 0062 §9 / design
354
+ // 04§3). A NEW cross-boundary import is now a red build; warn-mode is gone.
355
+ let MODULE_BOUNDARY_ENFORCING = true;
356
+ const MODULE_API_REL = 'src/module-api.js';
357
+
358
+ // If `spec` (a relative require) from `fromAbsFile` resolves into modules/<key>/,
359
+ // return <key>; else null. Pure path math — no fs.
360
+ function resolvesToModule(fromAbsFile, spec) {
361
+ const abs = path.resolve(path.dirname(fromAbsFile), spec);
362
+ const r = rel(abs);
363
+ const m = /^modules\/([^/]+)(\/|$)/.exec(r);
364
+ return m ? m[1] : null;
365
+ }
366
+
367
+ // The module a core/module file belongs to, or null if it isn't under modules/.
368
+ function moduleOwnerOf(absFile) {
369
+ const m = /^modules\/([^/]+)\//.exec(rel(absFile));
370
+ return m ? m[1] : null;
371
+ }
372
+
373
+ // For a require `spec` inside a MODULE file, return a violation string or null.
374
+ // Allowed: src/module-api.js (the doorway), intra-module relatives, and bare
375
+ // (npm/node) specs. Forbidden: deep core imports + sibling-module imports.
376
+ function moduleImportViolation(fromAbsFile, spec) {
377
+ const ownKey = moduleOwnerOf(fromAbsFile);
378
+ if (!ownKey) return null; // not a module file
379
+ const absTarget = path.resolve(path.dirname(fromAbsFile), spec);
380
+ const r = rel(absTarget);
381
+ // resolve possible file forms
382
+ const forms = [r, r + '.js', r.replace(/\/$/, '') + '/index.js'];
383
+ if (forms.includes(MODULE_API_REL)) return null; // the doorway — allowed
384
+ const otherKey = (() => { const m = /^modules\/([^/]+)(\/|$)/.exec(r); return m ? m[1] : null; })();
385
+ if (otherKey) {
386
+ if (otherKey === ownKey) return null; // intra-module — allowed
387
+ return `${rel(fromAbsFile)} → require('${spec}') reaches sibling module "${otherKey}" — modules must not import each other (use a kernel seam; ADR 0083).`;
388
+ }
389
+ if (/^src\//.test(r)) {
390
+ return `${rel(fromAbsFile)} → require('${spec}') reaches core internals (${r}) — a module may import only the published doorway src/module-api.js (ADR 0083).`;
391
+ }
392
+ return null; // outside the repo (node/npm) — not our concern
393
+ }
394
+
395
+ function checkCoreNeverImportsModule() {
396
+ const findings = [];
397
+ const roots = [path.join(REPO_ROOT, 'src'), path.join(REPO_ROOT, 'server.js')];
398
+ for (const root of roots) {
399
+ for (const abs of walkJs(root)) {
400
+ if (moduleOwnerOf(abs)) continue; // module files are scanned by the other check
401
+ if (HOST_GAME.some((re) => re.test(rel(abs)))) continue; // game-owned files that live in src/ (e.g. preview-server.js) may import game module
402
+ for (const raw of fs.readFileSync(abs, 'utf8').split('\n')) {
403
+ const t = raw.trim();
404
+ if (t.startsWith('//') || t.startsWith('*') || t.startsWith('/*')) continue;
405
+ let m; REQUIRE_RE.lastIndex = 0;
406
+ while ((m = REQUIRE_RE.exec(raw))) {
407
+ const key = resolvesToModule(abs, m[1]);
408
+ if (key) findings.push(`${rel(abs)} → require('${m[1]}') reaches module "${key}" — the core must never import a module (ADR 0083).`);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ const enforcing = MODULE_BOUNDARY_ENFORCING;
414
+ return {
415
+ name: 'core never imports a module',
416
+ ok: findings.length === 0,
417
+ hardFail: enforcing && findings.length > 0,
418
+ violations: enforcing ? findings : [],
419
+ warnings: enforcing ? [] : findings,
420
+ note: `core (src/, server.js) must not require modules/* — ${enforcing ? 'ENFORCING' : 'warn-mode until BV1.R45'} (ADR 0083).`,
421
+ };
422
+ }
423
+
424
+ function checkModulesImportOnlyApi() {
425
+ const findings = [];
426
+ for (const abs of walkJsAllRoots('modules')) { // modules ship from BOTH roots (ADR 0108 §Consequences #4)
427
+ for (const raw of fs.readFileSync(abs, 'utf8').split('\n')) {
428
+ const t = raw.trim();
429
+ if (t.startsWith('//') || t.startsWith('*') || t.startsWith('/*')) continue;
430
+ let m; REQUIRE_RE.lastIndex = 0;
431
+ while ((m = REQUIRE_RE.exec(raw))) {
432
+ const v = moduleImportViolation(abs, m[1]);
433
+ if (v) findings.push(v);
434
+ }
435
+ }
436
+ }
437
+ const enforcing = MODULE_BOUNDARY_ENFORCING;
438
+ return {
439
+ name: 'modules import only the published API',
440
+ ok: findings.length === 0,
441
+ hardFail: enforcing && findings.length > 0,
442
+ violations: enforcing ? findings : [],
443
+ warnings: enforcing ? [] : findings,
444
+ note: `modules/** may require only src/module-api.js (no deep core, no sibling) — ${enforcing ? 'ENFORCING' : 'warn-mode until BV1.R45'} (ADR 0083).`,
445
+ };
446
+ }
447
+
448
+ // ============================================================================
449
+ // Check 9 — the goal scope map imports PROTECTED_GLOBS, never re-declares it
450
+ // (ADR 0086 §7; the SEC #863 "second list that drifts" failure mode)
451
+ // ============================================================================
452
+ //
453
+ // src/bongos/module-scope-map.js (BV1.R54) derives each module's `protected` flag
454
+ // from PROTECTED_GLOBS. That derivation is only trustworthy if it reads the ONE
455
+ // source (permission-path-check.js) — a hand-copied second list would silently
456
+ // drift from the real protected set and quietly de-protect a module. This check
457
+ // reds the build if the scope map stops importing PROTECTED_GLOBS, or copies it.
458
+ const SCOPE_MAP_REL = 'src/bongos/module-scope-map.js';
459
+
460
+ // Pure: scan the scope-map source for the import contract. Exported for the
461
+ // "actually catches a violation" test (mirrors scanDeterministicBody).
462
+ function scanScopeMapSource(src) {
463
+ const violations = [];
464
+ const text = String(src || '');
465
+ const importsFrom = /require\(\s*['"]\.\/permission-path-check['"]\s*\)/.test(text);
466
+ const namesIt = /\bPROTECTED_GLOBS\b/.test(text);
467
+ if (!importsFrom || !namesIt) {
468
+ violations.push(`${SCOPE_MAP_REL} must IMPORT PROTECTED_GLOBS from ./permission-path-check and derive \`protected\` from it — never hand-maintain a second protected list (ADR 0086 §7).`);
469
+ }
470
+ if (/\b(?:const|let|var)\s+PROTECTED_GLOBS\s*=/.test(text)) {
471
+ violations.push(`${SCOPE_MAP_REL} re-declares PROTECTED_GLOBS — it must import the single source from permission-path-check.js, not copy it (ADR 0086 §7; the SEC #863 second-list failure mode).`);
472
+ }
473
+ return violations;
474
+ }
475
+
476
+ function checkScopeMapImportsProtected() {
477
+ const abs = path.join(REPO_ROOT, SCOPE_MAP_REL);
478
+ let src = null;
479
+ try { src = fs.readFileSync(abs, 'utf8'); } catch (_) { /* absent → skip */ }
480
+ // Absent → clean pass: the scope map is a BV1.R54 deliverable; until it exists
481
+ // there is no import contract to enforce (its own unit test asserts existence).
482
+ const violations = src == null ? [] : scanScopeMapSource(src);
483
+ return {
484
+ name: 'scope map imports PROTECTED_GLOBS (ADR 0086)',
485
+ ok: violations.length === 0,
486
+ hardFail: violations.length > 0,
487
+ violations,
488
+ warnings: [],
489
+ note: src == null
490
+ ? `${SCOPE_MAP_REL} absent — skipped (created by BV1.R54).`
491
+ : `${SCOPE_MAP_REL} derives \`protected\` from the imported PROTECTED_GLOBS (single source; no copied list).`,
492
+ };
493
+ }
494
+
495
+ // ============================================================================
496
+ // Check 10 — core carries no module-specific code (ADR 0083 §Decision #4 / design 04§3)
497
+ // ============================================================================
498
+ //
499
+ // The module-system MACHINERY (the doorway + loader + seam registry) must stay
500
+ // module-AGNOSTIC: it discovers, validates, and mounts modules uniformly and may
501
+ // never special-case one by name. The import checks (Check 7/8) stop a module's
502
+ // CODE from being reached by `require`; this stops a module's IDENTITY from being
503
+ // hardcoded into the kernel (`if (key === 'art-pipeline') …`, a copied module helper,
504
+ // a registry entry that should have moved out). "No module-specific code" is
505
+ // operationalized as the one drift-free signal — the kernel names no discovered
506
+ // module KEY (the canonical id from modules/<key>/module.json). Domain terms are
507
+ // deliberately NOT pattern-matched: they're non-deterministic and the doorway
508
+ // legitimately re-exports capability accessors (getBuilderGeminiKeyRow, …); the
509
+ // KEY is the precise thing a generic kernel never needs to write.
510
+ //
511
+ // Scope (BV1.R70 / ADR 0091 §1): the real ~3.5k-LOC TRUST KERNEL — the module-
512
+ // system machinery PLUS the trust primitives + data substrate + config/identity
513
+ // the rest of core depends on. This replaces the original 6-file machinery-only
514
+ // roster (the kernel was unbounded before — the audit's finding). Deliberately
515
+ // EXCLUDED: the still-fused monolith remnants (src/bongos/db.js, routes/me.js,
516
+ // routes.js, server.js) still carry un-stranglered module seams by design
517
+ // (lifecycle + tranche-2 domains leave later) — scanning them would red the
518
+ // build on intentional state. Comment lines are skipped (a key named in a
519
+ // doc/example comment is documentation, not code), and the scope-map registry is
520
+ // exempt from the no-module-keys scan (see KERNEL_NAMES_MODULES_OK).
521
+ const KERNEL_FILES = [
522
+ // module-system machinery (the original roster)
523
+ 'src/module-api.js', // the published doorway
524
+ 'src/modules.js', // the registry/resolver facade
525
+ 'src/module-seams.js', // the seam registry (ports/events/contributions)
526
+ 'src/role-responsibilities.js', // the owner's written role statements (task 1003732) — modules.js reads it; imports nothing
527
+ 'src/module-loader/loader.js', // the disk loader (discover → validate → mount)
528
+ 'src/module-loader/manifest-schema.js', // the manifest validator
529
+ 'src/module-loader/semver.js', // coreVersion compatibility
530
+ 'src/module-loader/error-tally.js', // per-module runtime-error counts the loader feeds (task 1004637)
531
+ 'src/bongos/module-scope-map.js', // the module→path registry (it NAMES every module — exempt below)
532
+ // trust primitives (ADR 0091 §1) — the authz boundary + data substrate
533
+ 'src/bongos/auth.js', // authz gates (requireBuilder/requireRank, ADR 0016)
534
+ // task 1003206 (goal 1000079) split auth.js's 1,867 lines into these five sign-in
535
+ // flow modules. They are the SAME kernel machinery, not new domain — auth.js is a
536
+ // kernel file, so if they were left off this roster the boundary check would read
537
+ // its own carve as five kernel→non-kernel leaks. Being on the roster also means
538
+ // each of them is itself held to the kernel import rule, which is the point.
539
+ 'src/bongos/auth-config.js', // provider config + OAuth scope selection
540
+ 'src/bongos/auth-admission.js', // membership kind, admission gate, first-admin seating
541
+ 'src/bongos/auth-github.js', // GitHub device + web OAuth flows
542
+ 'src/bongos/auth-idp.js', // hub federation, assertion + logout-token verification
543
+ 'src/bongos/auth-discord.js', // Discord OAuth link + guild membership
544
+ 'src/bongos/route-rank-check.js', // deterministic route→rank classification
545
+ 'src/bongos/permission-path-check.js', // protected-path matcher (PROTECTED_GLOBS, ADR 0043)
546
+ 'src/bongos/goal-scope-check.js', // goal create-gate scope wall (composes the 3 matchers above; ADR 0086 §3, BV1.R60)
547
+ 'src/bongos/secret-box.js', // AES-256-GCM per-builder secret box
548
+ 'src/bongos/pool.js', // the singleton Postgres pool accessor
549
+ // task 1003208: the structured logger is kernel infrastructure in the same sense
550
+ // the pool is — src/module-api.js hands every module a child of it, so it sits
551
+ // BELOW the module boundary, not beside a domain. It imports only node built-ins
552
+ // and pino, so joining the roster costs nothing and buys the import-direction
553
+ // guarantee on the file every module now logs through.
554
+ 'src/bongos/logger.js', // pino + request correlation + ADR 0022 redaction
555
+ // task 1003339 (ADR 0209): the abuse ceiling is a trust primitive in the same
556
+ // sense the authz gates are — authz says WHO may ask, this says HOW OFTEN, and
557
+ // an unauthenticated read route has nothing else holding it. src/module-api.js
558
+ // now hands modules the shared account-existence limiter (the onboarding
559
+ // module's account-existence probe spends the same budget as core's), so it
560
+ // sits BELOW the module boundary exactly as logger.js does. It requires NOTHING
561
+ // — no relative imports at all — so joining the roster costs nothing and buys
562
+ // the import-direction guarantee on a file two surfaces now trust.
563
+ 'src/bongos/middleware/rate-limit.js', // the sliding-window abuse ceilings (write + per-surface read)
564
+ 'src/bongos/db-kernel.js', // the kernel db slice — identity/audit/rank/withTx (BV1.R69)
565
+ // task 1002969 (ADR 0356): when an invite's door closes is part of the admission
566
+ // gate db-kernel.js runs, and the doorway hands the same definition to the
567
+ // onboarding and hub modules. It requires NOTHING, so joining costs nothing.
568
+ 'src/bongos/invite-expiry.js', // the read-time invite expiry (INVITE_EXPIRY_DAYS + its SQL)
569
+ 'src/bongos/routes/_helpers.js', // shared request validators the doorway re-exports
570
+ // config / identity (host context a module reads, never hardcodes)
571
+ 'src/instance-config.js',
572
+ 'src/branding.js',
573
+ // task 1004421 (ADR 0358): branding.js lays the chosen look over the pack through this
574
+ // file — the same identity/config category, requiring only instance-config and node
575
+ // built-ins, so it joins the roster rather than reading as a kernel→domain leak.
576
+ 'src/hall-look.js',
577
+ 'src/build-info.js',
578
+ // task 1003476 (goal 1000072): the project's stale-claim timer — host configuration
579
+ // a module reads rather than hardcodes, exactly the category instance-config.js and
580
+ // branding.js are in. The doorway (a KERNEL_FILE) re-exports it, so leaving it off
581
+ // this roster would read as a kernel->non-kernel leak; it imports only
582
+ // instance-config + node built-ins, so joining costs nothing.
583
+ 'src/stale-timer.js',
584
+ // task 1003279 (goal 1000072, ADR 0232): the project's live knob store and the ROT
585
+ // timer resolver over it — the same category as stale-timer.js directly above (host
586
+ // configuration a module reads rather than hardcodes), differing only in living in
587
+ // the DB instead of the env, because task 1003280 requires that knob be changeable
588
+ // from a page without a redeploy. The doorway re-exports it, so leaving it off this
589
+ // roster reads as a kernel->non-kernel leak; it imports only pool.js (itself on this
590
+ // roster) + node built-ins, so joining costs nothing and buys the import-direction
591
+ // guarantee on the file every future project knob will be read through.
592
+ 'src/bongos/project-settings.js',
593
+ // BV1.R86: the git-remote/slug + publish-target identity the doorway exposes
594
+ // (api.repoInfo) for the carved lifecycle github-push/conflict-resolve. It is
595
+ // KERNEL (already in the module-scope-map kernel key) and imports only the
596
+ // kernel (instance-config) + node built-ins, so it joins the roster cleanly.
597
+ 'src/bongos/repo-info.js',
598
+ // task 1002331 (ADR 0182 D6 / ADR 0247): the project's composed join/apply door — a
599
+ // deterministic classifier over three policy values, the same category as
600
+ // route-rank-check.js and goal-scope-check.js above (a trust decision the doorway
601
+ // hands to modules so no module re-derives it). The doorway re-exports it, so
602
+ // leaving it off this roster reads as a kernel->non-kernel leak; it imports only
603
+ // branding.js, instance-config.js and logger.js — all on this roster — so joining
604
+ // costs nothing and buys the import-direction guarantee on the file that decides
605
+ // who may knock. (Task 1003579 moved joinabilityMode the other way: the gate reads
606
+ // the composed door, so reader and composer had to sit together or the two would
607
+ // cycle.) The ARTIST GATE joins for the same reason — task 1003575, ADR 0241.
608
+ 'src/bongos/project-door.js', 'src/bongos/artist-gate.js',
609
+ // task 1004296 (ADR 0340 D5): the npm registry reader — packument, the in-process
610
+ // tarball stream and its small tar reader. It moved INTO the core because Settings →
611
+ // Software update needs it in every hall, and the doorway re-exports it
612
+ // (readPackageRegistry) for the module that publishes a package, so leaving it off
613
+ // this roster reads as a kernel->non-kernel leak. It imports only node built-ins
614
+ // (https, zlib), so joining costs nothing.
615
+ 'src/bongos/package-registry.js',
616
+ // task 1004657 (ADR 0363 D5): requireActAlone, the gate a building's own page mounts
617
+ // after its permission gate — the same trust-gate category as auth.js, re-exported
618
+ // by the doorway, so leaving it off reads as a kernel->non-kernel leak. It imports
619
+ // only module-seams.js and logger.js (both on this roster) and reaches the
620
+ // government module through its port, never by require.
621
+ 'src/bongos/act-alone.js',
622
+ ];
623
+
624
+ // Kernel files exempt from the no-module-keys scan (Check 10) because naming a
625
+ // module is, for them, the JOB — they stay in KERNEL_FILES for the import check
626
+ // (Check 12), which guards dependency *direction* (a much stronger guarantee than
627
+ // "never write the string 'art-pipeline'"). Two legitimate reasons a kernel file names
628
+ // a module:
629
+ // • the REGISTRY — module-scope-map.js IS the module→path map (and
630
+ // checkScopeMapImportsProtected already guards how it derives `protected`).
631
+ // • the TRUST BOUNDARY — auth.js carries the Discord OAuth account-LINK flow
632
+ // (core by design — see modules/discord/CLAUDE.md "NOT in this module"); and
633
+ // permission-path-check.js / route-rank-check.js MUST name module path
634
+ // subtrees ('modules/grading/', …) to protect + rank-gate them. Forbidding
635
+ // these the string would force the trust layer to stop protecting module
636
+ // surfaces — exactly backwards. The generic machinery + data + config files
637
+ // (module-api, the loader, db-kernel, secret-box, pool, _helpers, branding,
638
+ // instance-config, build-info) are NOT exempt and must stay module-agnostic.
639
+ const KERNEL_NAMES_MODULES_OK = new Set([
640
+ 'src/bongos/module-scope-map.js', // the module→path registry
641
+ // auth.js and the auth-*.js flow modules task 1003206 split out of it: the
642
+ // sign-in path legitimately names modules — it resolves the 'onboarding' and
643
+ // 'government' PORTS by key, and carries the Discord OAuth account-link flow
644
+ // (core by design — see modules/discord/CLAUDE.md "NOT in this module"). The
645
+ // exemption follows the code, exactly as the KERNEL_FILES roster above does;
646
+ // Check 12 still guards these files' dependency DIRECTION, which is the
647
+ // stronger guarantee.
648
+ 'src/bongos/auth.js', // Discord OAuth account-link flow (core by design)
649
+ 'src/bongos/auth-config.js',
650
+ 'src/bongos/auth-admission.js', // resolves the 'government' rank-role port by key
651
+ 'src/bongos/auth-github.js', // ticks the 'onboarding' port on first sign-in
652
+ 'src/bongos/auth-idp.js', // same, on the federated path
653
+ 'src/bongos/auth-discord.js', // the Discord account-link flow itself
654
+ 'src/bongos/act-alone.js', // resolves the 'government' port by key for checkActAlone (task 1004657)
655
+ 'src/bongos/permission-path-check.js', // names module path subtrees to PROTECT them
656
+ 'src/bongos/route-rank-check.js', // names module route dirs to rank-gate them
657
+ 'src/role-responsibilities.js', // the ideator's VERBATIM statement reads "Make good ideas" — the English word, colliding with the `ideas` key. Owner text; unparaphrasable.
658
+ ]);
659
+
660
+ // The discovered module keys = the directory names under modules/ (a manifest's
661
+ // `key` must equal its dir name — manifest-schema). Empty before any move. With no explicit
662
+ // `modulesDir` it UNIONS every module root (core package + instance repo, ADR 0108 §Consequences
663
+ // #4); an explicit dir keeps the old single-dir behavior (tests). Deduped — a key resolves to
664
+ // exactly one root (the loader errors on a cross-root collision), and today the roots coincide.
665
+ function _moduleKeysIn(modulesDir) {
666
+ try {
667
+ return fs.readdirSync(modulesDir, { withFileTypes: true })
668
+ .filter((d) => d.isDirectory())
669
+ .map((d) => d.name);
670
+ } catch { return []; }
671
+ }
672
+ function discoveredModuleKeys(modulesDir) {
673
+ if (modulesDir) return _moduleKeysIn(modulesDir);
674
+ const keys = new Set();
675
+ for (const root of MODULE_ROOTS) for (const k of _moduleKeysIn(path.join(root, 'modules'))) keys.add(k);
676
+ return [...keys];
677
+ }
678
+ // task 1002790: two questions, previously conflated and asserted EQUAL. BROAD
679
+ // (every dir) stays broad — the migration checks need it, since a .sql in a
680
+ // manifest-less dir must still be namespace/stem-checked (schema_migrations is
681
+ // stem-keyed; a collision is silently SKIPPED). NARROW = carries module.json,
682
+ // which is what makes a module a module (ADR 0083) and what kernel-naming means.
683
+ function manifestModuleKeys(modulesDir) {
684
+ const manifested = (dir) => _moduleKeysIn(dir).filter((k) => fs.existsSync(path.join(dir, k, 'module.json')));
685
+ if (modulesDir) return manifested(modulesDir);
686
+ return [...new Set(MODULE_ROOTS.flatMap((r) => manifested(path.join(r, 'modules'))))];
687
+ }
688
+ // The DIFFERENCE as an instruction, not a bare diff — and a WARNING, because a
689
+ // dir without a manifest is the normal transient shape of scaffolding a module.
690
+ function manifestlessModuleDirs(modulesDir) {
691
+ const narrow = new Set(manifestModuleKeys(modulesDir));
692
+ return discoveredModuleKeys(modulesDir).filter((k) => !narrow.has(k)).sort().map((k) =>
693
+ `modules/${k}/ has no module.json — it is a directory, not a module. Add the manifest (ADR 0083) or remove the dir. Warning, not a failure: scaffolding a module dir before its manifest is normal and must not red CI.`);
694
+ }
695
+ // Absolute path to a discovered module's dir, resolving WHICH root holds it (core package or
696
+ // instance repo). Today both roots coincide → the single checkout.
697
+ function moduleDir(key) {
698
+ for (const root of MODULE_ROOTS) {
699
+ const d = path.join(root, 'modules', key);
700
+ if (fs.existsSync(d)) return d;
701
+ }
702
+ return path.join(CORE_ROOT, 'modules', key);
703
+ }
704
+
705
+ // Pure: scan kernel source text for any hardcoded module key, skipping comment
706
+ // lines. Returns violation strings (one per hit). Exported for the negative test
707
+ // (mirrors scanScopeMapSource / scanDeterministicBody).
708
+ function scanKernelForModuleKeys(text, keys) {
709
+ const violations = [];
710
+ if (!keys || keys.length === 0) return violations;
711
+ const probes = keys.map((k) => ({ key: k, re: keyTokenRe(k) }));
712
+ String(text == null ? '' : text).split('\n').forEach((raw, i) => {
713
+ const t = raw.trim();
714
+ if (!t || t.startsWith('//') || t.startsWith('*') || t.startsWith('/*')) return;
715
+ for (const { key, re } of probes) {
716
+ if (re.test(raw)) {
717
+ violations.push(`names module "${key}" at line ${i + 1} — the kernel/module-system machinery must stay module-agnostic; no module key may be hardcoded in core (ADR 0083 §Decision #4).`);
718
+ }
719
+ }
720
+ });
721
+ return violations;
722
+ }
723
+
724
+ function checkCoreCarriesNoModuleCode() {
725
+ const keys = manifestModuleKeys(); // task 1002790 — NARROW: a manifest-less dir is not a module
726
+ const violations = [];
727
+ for (const relFile of KERNEL_FILES) {
728
+ if (KERNEL_NAMES_MODULES_OK.has(relFile)) continue; // the registry legitimately names every module
729
+ let text;
730
+ try { text = fs.readFileSync(path.join(REPO_ROOT, relFile), 'utf8'); } catch { continue; }
731
+ for (const v of scanKernelForModuleKeys(text, keys)) violations.push(`${relFile} ${v}`);
732
+ }
733
+ return {
734
+ name: 'core carries no module code',
735
+ ok: violations.length === 0,
736
+ hardFail: violations.length > 0,
737
+ violations,
738
+ warnings: manifestlessModuleDirs(), // task 1002790 — named, and never a hard fail
739
+ note: `kernel machinery (${KERNEL_FILES.length} files) names no module key${keys.length ? ` (keys: ${keys.join(', ')})` : ' (none yet)'} (ADR 0083 §Decision #4). A key is a modules/ dir carrying module.json; the migration checks deliberately scan every dir (task 1002790).`,
740
+ };
741
+ }
742
+
743
+ // ============================================================================
744
+ // Check 12 — the kernel imports no domain (ADR 0091 §1 / BV1.R70)
745
+ // ============================================================================
746
+ //
747
+ // A bounded kernel is only real if it DEPENDS on nothing but itself. This check
748
+ // walks every KERNEL_FILE's relative requires and flags any that reach a
749
+ // non-kernel core file (a soon-to-be-module domain). Kernel→kernel is fine;
750
+ // kernel→grandfathered-infra (the raw base pg pool, the pure path-match util) is
751
+ // fine; a bare npm/node spec is fine. Everything else is a tracked leak.
752
+ //
753
+ // ENFORCING (ADR 0102): the tranche-2 ratchet reached zero, so this is now a hard
754
+ // gate — the kernel imports only itself + grandfathered infra, and any NEW
755
+ // kernel→domain import fails the build (violations). The last leaks cleared were
756
+ // auth.js→db (carved to db-kernel), the doorway's Gemini-key re-exports (→ the
757
+ // art-pipeline 'art.getBuilderGeminiKeyRow' port) and builderRollingAvgGrade (→ the
758
+ // grading 'grade.builderRollingAvgGrade' port), plus reclassifying llm-cache /
759
+ // llm-pricing as kernel-adjacent infra. Adding a leak back reds the build.
760
+
761
+ // Grandfathered kernel-adjacent targets a KERNEL_FILE may import without it
762
+ // counting as a domain leak. The still-fused src/bongos/db.js monolith is NOT here:
763
+ // a kernel file reaching into it IS a real (tracked) leak until the identity/
764
+ // session slices finish carving into db-kernel.js.
765
+ const KERNEL_IMPORT_ALLOWLIST = new Set([
766
+ 'src/db.js', // the raw shared pg Pool (base infra; pool.js wraps it)
767
+ 'src/bongos/path-match.js', // pure touches-overlap matcher (no domain logic)
768
+ // Cross-cutting LLM-cost infra (ADR 0102): a stateless token→USD pricing table
769
+ // (llm-pricing) + a best-effort content-addressed cache (llm-cache), consumed by
770
+ // core, the grading module, and the CLI cost tooling ALIKE — no domain logic and
771
+ // no domain state beyond a cache table. Same category as the pg pool / path-match,
772
+ // not a domain module core would have to depend on anyway. The doorway may import
773
+ // them; they never flip the kernel→domain leak.
774
+ 'src/bongos/llm-cache.js',
775
+ 'src/bongos/llm-pricing.js',
776
+ // The cheapest-model-first cascade router (task 1001691 / ADR 0101 Part 1):
777
+ // a pure ladder + an INJECTED runner (never a domain call itself — its own
778
+ // header says so: "nothing calls it but its mock unit test" until this
779
+ // task), holding no domain state of its own. Its first real caller is the
780
+ // lifecycle module's relevance judge, which reaches it through the doorway
781
+ // exactly as grading reaches llm-cache — same category as the pg pool /
782
+ // path-match / llm-cache above, not a domain module core would otherwise
783
+ // depend on.
784
+ 'src/bongos/cascade-dispatch.js',
785
+ ]);
786
+
787
+ // Pure: for relative require `spec` from kernel file `fromRel` (repo-relative),
788
+ // return the offending non-kernel target relpath, or null if the import is clean
789
+ // (kernel→kernel, kernel→allowlisted-infra, or a bare npm/node spec). Exported
790
+ // for the "actually catches a leak" negative test (mirrors scanScopeMapSource).
791
+ function kernelDomainImport(fromRel, spec, kernelSet = new Set(KERNEL_FILES), allow = KERNEL_IMPORT_ALLOWLIST) {
792
+ if (!/^\.\.?\//.test(spec)) return null; // bare npm/node spec — not our concern
793
+ const absTarget = path.resolve(path.dirname(path.join(REPO_ROOT, fromRel)), spec);
794
+ const r = rel(absTarget);
795
+ const forms = [r, r + '.js', r.replace(/\/$/, '') + '/index.js'];
796
+ if (forms.some((f) => kernelSet.has(f))) return null; // kernel → kernel
797
+ if (forms.some((f) => allow.has(f))) return null; // grandfathered infra/util
798
+ if (!/^src\//.test(r)) return null; // only flag app-source targets
799
+ return r.endsWith('.js') || r.endsWith('.json') ? r : `${r}.js`; // name the real file
800
+ }
801
+
802
+ function checkKernelImportsNoDomain() {
803
+ const kernelSet = new Set(KERNEL_FILES);
804
+ const findings = [];
805
+ for (const relFile of KERNEL_FILES) {
806
+ let text;
807
+ try { text = fs.readFileSync(path.join(REPO_ROOT, relFile), 'utf8'); } catch { continue; }
808
+ for (const raw of text.split('\n')) {
809
+ const t = raw.trim();
810
+ if (t.startsWith('//') || t.startsWith('*') || t.startsWith('/*')) continue;
811
+ let m; REQUIRE_RE.lastIndex = 0;
812
+ while ((m = REQUIRE_RE.exec(raw))) {
813
+ const target = kernelDomainImport(relFile, m[1], kernelSet);
814
+ if (target) findings.push(`${relFile} → require('${m[1]}') reaches non-kernel core file ${target} — a kernel file must depend only on the kernel (ADR 0091 §1). Carve ${target}'s domain out (or promote it into the kernel) to clear this.`);
815
+ }
816
+ }
817
+ }
818
+ return {
819
+ name: 'kernel imports no domain',
820
+ ok: findings.length === 0,
821
+ hardFail: findings.length > 0, // ENFORCING (ADR 0102): the ratchet reached zero — any new kernel→domain import now reds the build
822
+ violations: findings,
823
+ warnings: [],
824
+ note: `every KERNEL_FILE (${KERNEL_FILES.length}) must import only the kernel + grandfathered infra — ENFORCING (ADR 0091 §1 / ADR 0102).${findings.length ? ` ${findings.length} leak(s).` : ' Boundary clean.'}`,
825
+ };
826
+ }
827
+
828
+ // ============================================================================
829
+ // Check 11 — module migrations are additive + namespaced (ADR 0083 §Decision #5 / design 04§3)
830
+ // ============================================================================
831
+ //
832
+ // A module owns its DB slice through migrations under modules/<key>/migrations/.
833
+ // Two invariants keep that slice from clobbering core or a sibling:
834
+ // • ADDITIVE — no destructive DDL. "Disable a module" means "stop applying its
835
+ // migrations," never "drop its tables" (ADR 0083 §Module-owned migrations);
836
+ // there is no down path, so a DROP/TRUNCATE can only be an accident.
837
+ // • NAMESPACED — every object it CREATEs lives under the <key>_ prefix
838
+ // (art-pipeline → art_pipeline_), and it may only ALTER its own namespaced tables;
839
+ // core/sibling state is reached through the doorway/seams, never raw DDL.
840
+ //
841
+ // LEGACY_NAMESPACED: tables that predate the <key>_-prefix convention (created before the module
842
+ // system existed). Grandfathered per-module to avoid requiring a rename migration for legacy prod
843
+ // data. The fitness rule applies in full to any NEW migration a module ships.
844
+ const LEGACY_NAMESPACED = {
845
+ // game module: world_events + players were created before the module system (V1 schema). The
846
+ // schema_migrations table is a core tracking table that every migration may re-create idempotently.
847
+ game: new Set(['world_events', 'players', 'schema_migrations']),
848
+ // government module: the module KEY was renamed governance→government (ADR 0174, goal 1000068),
849
+ // so its own historical migrations now read as "outside the namespace" purely because the key
850
+ // moved underneath them. These three tables ARE this module's — under the name it used to have.
851
+ // They are not renamed in place because schema_migrations is keyed by filename STEM: renaming an
852
+ // already-applied migration file makes it look unapplied and re-runs it, and governance_002 is a
853
+ // seed/backfill. government_001_rename_from_governance.sql renames the live tables forward; these
854
+ // entries let the historical files that created them keep describing what actually happened.
855
+ government: new Set([
856
+ 'governance_roles', 'governance_builder_roles', 'governance_role_permissions',
857
+ ]),
858
+ };
859
+ const DESTRUCTIVE_DDL = [
860
+ { re: /\bdrop\s+table\b/i, label: 'DROP TABLE' },
861
+ { re: /\balter\s+table\b[\s\S]*?\bdrop\s+(?:column|constraint)\b/i, label: 'ALTER TABLE … DROP COLUMN/CONSTRAINT' },
862
+ { re: /\bdrop\s+(?:column|constraint)\b/i, label: 'DROP COLUMN/CONSTRAINT' },
863
+ { re: /\bdrop\s+(?:index|type|view|sequence|schema|materialized\s+view)\b/i, label: 'DROP <object>' },
864
+ { re: /\btruncate\b/i, label: 'TRUNCATE' },
865
+ ];
866
+ const CREATE_OBJ_RE = /\bcreate\s+(?:or\s+replace\s+)?(?:unique\s+)?(?:materialized\s+)?(table|view|sequence|type)\s+(?:if\s+not\s+exists\s+)?("?[\w.]+"?)/gi;
867
+ const CREATE_INDEX_RE = /\bcreate\s+(?:unique\s+)?index\s+(?:concurrently\s+)?(?:if\s+not\s+exists\s+)?(?:"?[\w.]+"?)\s+on\s+(?:only\s+)?("?[\w.]+"?)/gi;
868
+ const ALTER_TABLE_RE = /\balter\s+table\s+(?:if\s+exists\s+)?(?:only\s+)?("?[\w.]+"?)/gi;
869
+
870
+ // SQL object-namespace prefix for a module key: art-pipeline → art_pipeline (SQL-safe).
871
+ function moduleNamespace(key) { return key.replace(/-/g, '_'); }
872
+
873
+ // strip SQL comments so a commented-out statement is never scanned
874
+ function stripSqlComments(sql) {
875
+ return String(sql == null ? '' : sql)
876
+ .replace(/\/\*[\s\S]*?\*\//g, ' ')
877
+ .replace(/--[^\n]*/g, ' ');
878
+ }
879
+
880
+ // is `rawName` (possibly quoted / schema-qualified) under the <ns>_ namespace?
881
+ function inNamespace(rawName, ns, legacySet) {
882
+ const name = String(rawName).replace(/"/g, '').replace(/^[A-Za-z_]\w*\./, '');
883
+ return name.startsWith(ns + '_') || (legacySet && legacySet.has(name));
884
+ }
885
+
886
+ // A CHECK-enum WIDENING is additive-in-spirit: `DROP CONSTRAINT IF EXISTS <c>` PAIRED
887
+ // with a re-`ADD CONSTRAINT <c>` (SAME name) in the SAME migration only PERMITS more
888
+ // values — no existing row changes, no data is lost (task 1978: provisioning gains a
889
+ // 'standalone' hosting_shape). Allow that exact pattern; a BARE `DROP CONSTRAINT` (no
890
+ // re-add), or any DROP TABLE/COLUMN/TRUNCATE, stays destructive. PURE.
891
+ function reAddedConstraintNames(sql) {
892
+ const names = new Set();
893
+ const re = /\badd\s+constraint\s+("?[\w.]+"?)/gi;
894
+ let m;
895
+ while ((m = re.exec(sql))) names.add(m[1].replace(/"/g, ''));
896
+ return names;
897
+ }
898
+ function isConstraintWidening(stmt, reAdded) {
899
+ const m = /\bdrop\s+constraint\s+(?:if\s+exists\s+)?("?[\w.]+"?)/i.exec(stmt);
900
+ if (!m) return false; // not a DROP CONSTRAINT at all
901
+ // never let a DROP CONSTRAINT statement smuggle a table/column drop past the gate
902
+ if (/\bdrop\s+(?:table|column|index|type|view|sequence|schema|materialized\s+view)\b/i.test(stmt)) return false;
903
+ if (/\btruncate\b/i.test(stmt)) return false;
904
+ return reAdded.has(m[1].replace(/"/g, '')); // re-added same-named constraint → widening
905
+ }
906
+
907
+ // The ONE destructive shape a module may carry: an ACKNOWLEDGED contract-phase
908
+ // `ALTER TABLE <own table> DROP COLUMN <c>` (task 1003092 — the expand-then-contract
909
+ // rename of ADR 0177 has to finish; ADR 0083 §Module-owned migrations, amended). The
910
+ // pragma is read off the RAW sql (it is a comment); everything else here still runs.
911
+ const { acknowledgedContraction, isAcknowledgedColumnContraction } = require('./fitness-migration-contraction.js');
912
+
913
+ // Pure: violations for ONE module's migration SQL. Exported for the negative test.
914
+ function moduleMigrationViolations(key, sql) {
915
+ const ns = moduleNamespace(key);
916
+ const legacy = LEGACY_NAMESPACED[key] || null;
917
+ const clean = stripSqlComments(sql);
918
+ const violations = [];
919
+ // additive — scan per statement so an ALTER…DROP never spans a `;`
920
+ const reAdded = reAddedConstraintNames(clean);
921
+ const acknowledged = acknowledgedContraction(sql);
922
+ const ownTable = (t) => inNamespace(t, ns, legacy);
923
+ for (const stmt of clean.split(';')) {
924
+ if (isConstraintWidening(stmt, reAdded)) continue; // additive CHECK-enum widening (task 1978)
925
+ if (isAcknowledgedColumnContraction(stmt, { acknowledged, inNamespace: ownTable })) continue; // contract phase (task 1003092)
926
+ for (const d of DESTRUCTIVE_DDL) {
927
+ if (d.re.test(stmt)) {
928
+ violations.push(`module "${key}" migration uses destructive DDL (${d.label}) — module migrations must be ADDITIVE; disabling a module stops applying, it never drops (ADR 0083 §Decision #5).`);
929
+ break; // one destructive flag per statement is enough
930
+ }
931
+ }
932
+ }
933
+ // namespaced — CREATEd objects + ALTER targets must live under <ns>_ (or be grandfathered)
934
+ let m;
935
+ CREATE_OBJ_RE.lastIndex = 0;
936
+ while ((m = CREATE_OBJ_RE.exec(clean))) {
937
+ if (!inNamespace(m[2], ns, legacy)) {
938
+ violations.push(`module "${key}" migration creates ${m[1].toUpperCase()} ${m[2]} outside its namespace — module objects must be ${ns}_-prefixed (ADR 0083 §Decision #5).`);
939
+ }
940
+ }
941
+ CREATE_INDEX_RE.lastIndex = 0;
942
+ while ((m = CREATE_INDEX_RE.exec(clean))) {
943
+ if (!inNamespace(m[1], ns, legacy)) {
944
+ violations.push(`module "${key}" migration indexes a non-namespaced table ${m[1]} — a module migration may only touch its own ${ns}_ tables (ADR 0083 §Decision #5).`);
945
+ }
946
+ }
947
+ ALTER_TABLE_RE.lastIndex = 0;
948
+ while ((m = ALTER_TABLE_RE.exec(clean))) {
949
+ if (!inNamespace(m[1], ns, legacy)) {
950
+ violations.push(`module "${key}" migration alters a non-namespaced table ${m[1]} — a module migration may only touch its own ${ns}_ tables; reach core state through the doorway/seams, not DDL (ADR 0083 §Decision #5).`);
951
+ }
952
+ }
953
+ return violations;
954
+ }
955
+
956
+ function checkModuleMigrationsAdditive() {
957
+ const violations = [];
958
+ let scanned = 0;
959
+ for (const key of discoveredModuleKeys()) { // union across module roots (ADR 0108 §Consequences #4)
960
+ const migDir = path.join(moduleDir(key), 'migrations');
961
+ let files = [];
962
+ try { files = fs.readdirSync(migDir).filter((f) => f.endsWith('.sql')); } catch { continue; }
963
+ for (const f of files.sort()) {
964
+ scanned += 1;
965
+ const sql = fs.readFileSync(path.join(migDir, f), 'utf8');
966
+ for (const v of moduleMigrationViolations(key, sql)) {
967
+ violations.push(`modules/${key}/migrations/${f}: ${v}`);
968
+ }
969
+ }
970
+ }
971
+ return {
972
+ name: 'module migrations additive + namespaced',
973
+ ok: violations.length === 0,
974
+ hardFail: violations.length > 0,
975
+ violations,
976
+ warnings: [],
977
+ note: `${scanned} module migration file(s): additive (no destructive DDL) + <key>_-namespaced objects (ADR 0083 §Decision #5).`,
978
+ };
979
+ }
980
+
981
+ // ============================================================================
982
+ // Check 11b — migration FILENAMES are namespaced + no cross-root stem collision
983
+ // (ADR 0108 §5; extends Check 11 to the cross-repo layer)
984
+ // ============================================================================
985
+ //
986
+ // Check 11 (above) guards a module migration's OBJECTS (additive + <key>_-namespaced
987
+ // tables). THIS check guards migration FILENAMES across all three roots — the
988
+ // discipline that lets the core repo and the instance repo version independently
989
+ // (ADR 0108) without their migrations colliding:
990
+ // • migrations/*.sql (CORE) → NEW files must be core_-prefixed
991
+ // • migrations/instance/*.sql (INSTANCE) → stay bare (or instance_-prefixed)
992
+ // • modules/<key>/migrations/ (MODULE) → NEW files must be <key>_-prefixed
993
+ // Existing bare files are grandfathered (migration-namespace.js LEGACY_BARE_*). The
994
+ // second invariant is the real bug guard: migrate.sh keys schema_migrations by
995
+ // filename STEM, so two migrations from different sources sharing a stem would apply
996
+ // ONCE and the other be SILENTLY SKIPPED (never applied). Single-root today; W6/task
997
+ // 1886 makes the root resolution two-root-aware once the core installs from node_modules.
998
+ function sqlFilesIn(absDir) {
999
+ try { return fs.readdirSync(absDir).filter((f) => f.endsWith('.sql')).sort(); }
1000
+ catch { return []; } // dir absent (e.g. no migrations/instance in a vanilla instance) → nothing to scan
1001
+ }
1002
+
1003
+ function checkMigrationNamespacing() {
1004
+ const violations = [];
1005
+ const files = []; // { source, moduleKey?, basename } — fed to the stem-collision scan
1006
+
1007
+ const coreFiles = sqlFilesIn(path.join(CORE_ROOT, 'migrations')); // core migrations ship in the core package
1008
+ for (const f of coreFiles) {
1009
+ const v = filenameViolation(CORE_NS, f);
1010
+ if (v) violations.push(`migrations/${f}: ${v}`);
1011
+ files.push({ source: CORE_NS, basename: f });
1012
+ }
1013
+
1014
+ const instFiles = sqlFilesIn(path.join(INSTANCE_ROOT, 'migrations', 'instance')); // instance seeds live in the host repo
1015
+ for (const f of instFiles) {
1016
+ const v = filenameViolation(INSTANCE_NS, f);
1017
+ if (v) violations.push(`migrations/instance/${f}: ${v}`);
1018
+ files.push({ source: INSTANCE_NS, basename: f });
1019
+ }
1020
+
1021
+ let moduleCount = 0;
1022
+ for (const key of discoveredModuleKeys()) {
1023
+ for (const f of sqlFilesIn(path.join(moduleDir(key), 'migrations'))) {
1024
+ moduleCount += 1;
1025
+ const v = filenameViolation('module', f, { moduleKey: key });
1026
+ if (v) violations.push(`modules/${key}/migrations/${f}: ${v}`);
1027
+ files.push({ source: 'module', moduleKey: key, basename: f });
1028
+ }
1029
+ }
1030
+
1031
+ for (const c of stemCollisions(files)) {
1032
+ violations.push(`migration stem "${c.stem}" is produced by more than one source (${c.files.join(', ')}) — schema_migrations is stem-keyed, so one applies and the rest are SILENTLY SKIPPED; namespace them (ADR 0108 §5).`);
1033
+ }
1034
+
1035
+ // Two DIFFERENT stems at one number inside ONE series (task 1003646). Not the
1036
+ // silent-skip above — all of them apply — but migrate.sh orders by basename, so
1037
+ // their relative order is the alphabetical accident of the slug, and a from-scratch
1038
+ // replay can order them differently from the merge order prod applied. Renumbering an
1039
+ // APPLIED migration re-runs it, so the fix for a new one is to renumber BEFORE it
1040
+ // lands; the single pre-existing case is grandfathered in migration-namespace.js.
1041
+ for (const c of numberCollisions(files)) {
1042
+ violations.push(`migration number ${String(c.number).padStart(3, '0')} is used by ${c.files.length} different migrations in one series (${c.series}): ${c.files.join(', ')} — each was allocated max+1 from its own branch point. migrate.sh applies in BASENAME order, so their order is decided by the slug alphabetically and a fresh replay can differ from the order prod applied. Renumber the one that has NOT landed yet (renaming an applied migration re-runs it) (task 1003646).`);
1043
+ }
1044
+
1045
+ return {
1046
+ name: 'migration filenames namespaced + no stem/number collision (ADR 0108 §5)',
1047
+ ok: violations.length === 0,
1048
+ hardFail: violations.length > 0,
1049
+ violations,
1050
+ warnings: [],
1051
+ note: `${coreFiles.length} core + ${instFiles.length} instance + ${moduleCount} module migration file(s): new core→core_, new module→<key>_, instance bare; no cross-root stem collision, and no two migrations share a number within one series.`,
1052
+ };
1053
+ }
1054
+
1055
+ // ============================================================================
1056
+ // Check — hall sections are registry-owned, not hardcoded (BV1.R75 / ADR 0062 §4)
1057
+ // ============================================================================
1058
+ // The builders'-hall widgets are now a REGISTRY (modules/hall-ui/public/dom-utils.js
1059
+ // contributeHallWidget; the core set in modules/hall-ui/public/hall-widgets.js, modules
1060
+ // via their own client script). The hall's <main> is filled by builders.js from that
1061
+ // registry. So no widget may be hardcoded as a literal <section class="scroll"> inside
1062
+ // <main> in index.html — that was the pre-R75 second copy this carve removed. This
1063
+ // gate fails if one creeps back, keeping the registry the single source of truth (so a
1064
+ // reskin/module-toggle reaches every widget). Self-contained: a pure scan of
1065
+ // index.html's <main>, no module/registry state needed. Exported for the unit test.
1066
+ // (The hall surface itself carved to modules/hall-ui/public/ in BV1.R85.)
1067
+ //
1068
+ // task 2177 — the check also asserts the HOME ZONE BUDGETS. builders.js caps how
1069
+ // many widgets each Home zone mounts (ZONE_BUDGETS); past the cap a widget still
1070
+ // mounts, but into a hidden overflow behind a "More" link. That graceful degrade
1071
+ // is the runtime safety net — it is NOT a licence to keep adding cards, and
1072
+ // because nothing goes red, a Home that has quietly outgrown its budget looks
1073
+ // fine. So CI counts the registrations statically and fails on a breach: the
1074
+ // budget becomes a decision someone has to make deliberately (raise the number
1075
+ // in builders.js, with a reason) instead of one that erodes.
1076
+ //
1077
+ // NOT statically checkable, by design: the `home-banner` rule is "at most ONE
1078
+ // VISIBLE", not "at most one registered" — both banner widgets (welcome,
1079
+ // getting-started) are hiddenByDefault and reveal themselves from onboarding
1080
+ // state, so only runtime knows the count. It is documented as a runtime
1081
+ // invariant in modules/hall-ui/CLAUDE.md rather than faked with a static count
1082
+ // that would either fail today or assert nothing.
1083
+ const HALL_INDEX = path.join(moduleDir('hall-ui'), 'public', 'index.html'); // hall-ui is a module — resolve its root (ADR 0108)
1084
+ const HALL_PUBLIC = path.join(moduleDir('hall-ui'), 'public');
1085
+ // task 1003206 split the hall page script: builders.js keeps state/loading/wiring
1086
+ // and hall-render.js holds the view painters — ZONE_BUDGETS travelled with the
1087
+ // widget mounting. Read whichever of the pair actually declares it, so this
1088
+ // check follows the code instead of a filename (it went vacuous on the move).
1089
+ const HALL_BUILDERS_JS = path.join(HALL_PUBLIC, 'builders.js');
1090
+ const HALL_RENDER_JS = path.join(HALL_PUBLIC, 'hall-render.js');
1091
+ function hallWidgetSource() {
1092
+ const parts = [];
1093
+ for (const f of [HALL_BUILDERS_JS, HALL_RENDER_JS]) {
1094
+ try { parts.push(fs.readFileSync(f, 'utf8')); } catch { /* absent → skip */ }
1095
+ }
1096
+ return parts.join('\n');
1097
+ }
1098
+
1099
+ // Parse builders.js's ZONE_BUDGETS object literal — the single source of truth
1100
+ // for the caps (this check must never carry its own copy of the numbers).
1101
+ function parseZoneBudgets(js) {
1102
+ const block = js.match(/const\s+ZONE_BUDGETS\s*=\s*\{([^}]*)\}/);
1103
+ if (!block) return null;
1104
+ const budgets = {};
1105
+ for (const [, zone, n] of block[1].matchAll(/['"]([\w-]+)['"]\s*:\s*(\d+)/g)) {
1106
+ budgets[zone] = Number(n);
1107
+ }
1108
+ return Object.keys(budgets).length ? budgets : null;
1109
+ }
1110
+
1111
+ // Count registrations per Home zone across every hall client script that calls
1112
+ // contributeHallWidget. The zones are static string literals in the registration
1113
+ // object, so a literal scan is exact for the code we have (and a computed zone
1114
+ // would be a placement smell in its own right — dom-utils' runtime validation
1115
+ // still rejects an unknown one). Requiring the contributeHallWidget mention is
1116
+ // what keeps an unrelated `zone:` key in some other object from eating budget.
1117
+ function scanHallZoneCounts(dir = HALL_PUBLIC, fsImpl = fs) {
1118
+ const counts = {};
1119
+ let files = [];
1120
+ try { files = fsImpl.readdirSync(dir).filter((f) => f.endsWith('.js')); } catch { return counts; }
1121
+ for (const file of files) {
1122
+ let src = '';
1123
+ try { src = fsImpl.readFileSync(path.join(dir, file), 'utf8'); } catch { continue; }
1124
+ if (!src.includes('contributeHallWidget')) continue;
1125
+ for (const [, zone] of src.matchAll(/\bzone:\s*['"]([\w-]+)['"]/g)) {
1126
+ counts[zone] = (counts[zone] || 0) + 1;
1127
+ }
1128
+ }
1129
+ return counts;
1130
+ }
1131
+
1132
+ function checkHallZoneBudgets(fsImpl = fs) {
1133
+ let js = '';
1134
+ try {
1135
+ js = [HALL_BUILDERS_JS, HALL_RENDER_JS]
1136
+ .map((f) => { try { return fsImpl.readFileSync(f, 'utf8'); } catch { return ''; } })
1137
+ .join('\n');
1138
+ } catch { return []; }
1139
+ const budgets = parseZoneBudgets(js);
1140
+ if (!budgets) {
1141
+ return ['modules/hall-ui/public/{builders,hall-render}.js no longer declares a parseable ZONE_BUDGETS literal — the Home zone budgets are unenforced (task 2177).'];
1142
+ }
1143
+ const counts = scanHallZoneCounts(HALL_PUBLIC, fsImpl);
1144
+ const violations = [];
1145
+ for (const [zone, budget] of Object.entries(budgets)) {
1146
+ const n = counts[zone] || 0;
1147
+ if (n > budget) {
1148
+ violations.push(
1149
+ `Home zone "${zone}" has ${n} registered hall widgets but its budget is ${budget} — the extras mount into the hidden overflow, so Home silently grew. Move it to its own page (see modules/hall-ui/CLAUDE.md §Placement), or raise ZONE_BUDGETS['${zone}'] in modules/hall-ui/public/builders.js deliberately (task 2177).`);
1150
+ }
1151
+ }
1152
+ return violations;
1153
+ }
1154
+
1155
+ function hallMainSlice(html) {
1156
+ // Strip HTML comments first so a comment that merely MENTIONS <main> or a
1157
+ // <section class="scroll"> (e.g. the carve's own explanatory note) never trips
1158
+ // the scan — only real, rendered markup counts.
1159
+ const stripped = html.replace(/<!--[\s\S]*?-->/g, '');
1160
+ const open = stripped.indexOf('<main');
1161
+ if (open === -1) return '';
1162
+ const start = stripped.indexOf('>', open);
1163
+ const close = stripped.indexOf('</main>', start === -1 ? open : start);
1164
+ if (start === -1 || close === -1) return '';
1165
+ return stripped.slice(start + 1, close);
1166
+ }
1167
+
1168
+ function scanHallSectionRegistry(html) {
1169
+ const main = hallMainSlice(html);
1170
+ // A hall widget section carries class="scroll" (possibly with modifiers, e.g.
1171
+ // "scroll scroll--welcome"). Catch any <section ... class="...scroll..."> in <main>.
1172
+ const re = /<section\b[^>]*\bclass\s*=\s*"(?:[^"]*\b)?scroll\b[^"]*"/gi;
1173
+ const hits = main.match(re) || [];
1174
+ return hits.map((h) => h.replace(/\s+/g, ' ').trim());
1175
+ }
1176
+
1177
+ function checkHallSectionRegistry() {
1178
+ let html = '';
1179
+ try { html = fs.readFileSync(HALL_INDEX, 'utf8'); }
1180
+ catch { return { name: 'hall widgets are registry-owned (ADR 0062 §4)', ok: true, hardFail: false, violations: [], warnings: ['modules/hall-ui/public/index.html not found — skipped'], note: 'index.html absent.' }; }
1181
+ const hardcoded = scanHallSectionRegistry(html);
1182
+ const violations = hardcoded.map((s) =>
1183
+ `modules/hall-ui/public/index.html <main> hardcodes a hall section "${s}" — register it via window.OTB.contributeHallWidget (modules/hall-ui/public/hall-widgets.js for core, a module's client script otherwise), don't inline the markup (BV1.R75 / ADR 0062 §4).`);
1184
+ violations.push(...checkHallZoneBudgets());
1185
+ return {
1186
+ name: 'hall widgets are registry-owned + within zone budget (ADR 0062 §4, task 2177)',
1187
+ ok: violations.length === 0,
1188
+ hardFail: violations.length > 0,
1189
+ violations,
1190
+ warnings: [],
1191
+ note: 'modules/hall-ui/public/index.html <main> contains no hardcoded <section class="scroll">, and every Home zone is within the ZONE_BUDGETS cap builders.js declares — the registry is the single source of truth and Home cannot grow unnoticed.',
1192
+ };
1193
+ }
1194
+
1195
+
1196
+ // ============================================================================
1197
+ // Check 2c — every SKILL.md frontmatter parses the way Claude Code's YAML reader reads it (task 1003548)
1198
+ // ============================================================================
1199
+ // Ten of fifty skills shipped with an unquoted description holding ": " or " #": YAML dropped or
1200
+ // truncated EVERY field, the skill matched on its body text, and nothing in CI noticed. A parse
1201
+ // error is a hard fail; description length and the listing budget are advisory (the listing is
1202
+ // resident in every session, ~1% of context, and gets truncated past ~8k chars). The check reads
1203
+ // every skill Claude Code can load — the instance's .claude/skills/ AND the module-owned
1204
+ // modules/*/skills/ that claude-materialize.js copies into it (task 1003587: scanning only the
1205
+ // tracked root meant 14 ui-design skills went unlinted until the untracked copy existed, so four
1206
+ // unparseable frontmatters shipped and fitness only went red on a checkout that had materialized).
1207
+ // A quiet pass when a checkout carries none (published core).
1208
+ function checkSkillFrontmatter() {
1209
+ const violations = [];
1210
+ const warnings = [];
1211
+ let lint;
1212
+ try { lint = require('./skill-lint'); } catch (e) {
1213
+ return { name: 'skill frontmatter parses (task 1003548)', ok: true, hardFail: false, violations, warnings: [`skill-lint unavailable: ${e.message}`], note: 'linter missing — check skipped.' };
1214
+ }
1215
+ const files = lint.listSkillFiles(INSTANCE_ROOT);
1216
+ // Lint every file; count the listing over the skills RESIDENT here (task 1004470).
1217
+ const report = lint.lintSkills(files, { resident: lint.residentSkillFiles(INSTANCE_ROOT, { files }) });
1218
+ const rel = (f) => path.relative(INSTANCE_ROOT, f).replace(/\\/g, '/');
1219
+ const long = [];
1220
+ for (const r of report.results) {
1221
+ for (const e of r.errors) violations.push(`${rel(r.file)}: ${e}`);
1222
+ if (r.description.length > lint.DESC_WARN_CHARS) long.push({ file: rel(r.file), n: r.description.length });
1223
+ }
1224
+ if (long.length) {
1225
+ long.sort((a, b) => b.n - a.n);
1226
+ // The skill's own name is its PARENT dir — a fixed path index would read "skills"
1227
+ // for a module-owned path (modules/<key>/skills/<name>/SKILL.md).
1228
+ const skillName = (f) => f.split('/').slice(-2, -1)[0] || f;
1229
+ warnings.push(`${long.length} description(s) over ${lint.DESC_WARN_CHARS} chars (longest: ${long.slice(0, 4).map((l) => `${skillName(l.file)} ${l.n}`).join(', ')}) — every char is resident in every session; run node scripts/bongos/skill-lint.js.`);
1230
+ }
1231
+ if (report.overBudget) warnings.push(`the skill listing is ${report.listingChars} chars (~${estTokens(report.listingChars)} tokens) against a ~${report.budgetChars}-char budget — Claude Code truncates entries past it and routing degrades.`);
1232
+ return {
1233
+ name: 'skill frontmatter parses (task 1003548)',
1234
+ ok: violations.length === 0,
1235
+ hardFail: violations.length > 0,
1236
+ violations,
1237
+ warnings,
1238
+ note: `${report.results.length} SKILL.md file(s) under .claude/skills/ + modules/*/skills/ parse as YAML (name + description present, no ": " / " #" in a plain scalar); length + listing budget advisory.`,
1239
+ };
1240
+ }
1241
+
1242
+ // ============================================================================
1243
+ // Check 35 — no raw NUL byte in tracked publishable text (task 1002854)
1244
+ // ============================================================================
1245
+ //
1246
+ // scripts/public-mirror-export.js decides binary-vs-text by sniffing for a NUL byte in
1247
+ // the first 8 KiB (`isBinary`, ~line 86), and `redactBlob` skips `redactText` entirely
1248
+ // for anything it classifies binary. So a TEXT source containing a raw NUL is published
1249
+ // to the public AGPL mirror WITHOUT REDACTION.
1250
+ //
1251
+ // WHAT THIS IS AND IS NOT. The binary branch is not unguarded: it still leak-scans the
1252
+ // blob's latin1 view, so an embedded instance literal trips the gate. But the gate uses
1253
+ // `sensitiveLiterals` — raw substrings — while `redactText` applies the full `rules` set.
1254
+ // The exposure is therefore the DELTA between them: anything redaction would have
1255
+ // rewritten but the literal gate does not recognise ships verbatim. That is a latent
1256
+ // unredacted-publish, not a live one, which is why this is a lint rather than a fix.
1257
+ //
1258
+ // THE CLASS RECURS, WHICH IS THE ARGUMENT FOR A LINT RATHER THAN ANOTHER FIX.
1259
+ // Task 1703 found and fixed three instances, all the same mistake: a raw NUL used as a
1260
+ // join delimiter instead of the `\u0000` escape. Task 1002507 fixed a fourth in session
1261
+ // digests. Open idea 1000523 covers a fifth (search-ingest rollback). This check found
1262
+ // four more — modules/copy-desk/proposals.js, scripts/bongos/claim.js,
1263
+ // scripts/bongos/probe-cache.js and tests/copy_inventory.mjs — fixed in the same commit so
1264
+ // the check lands green. Nothing prevented any of them; nothing would prevent the next.
1265
+ //
1266
+ // The fix is always the same and never changes behaviour: `\u0000` compiles to exactly
1267
+ // the same string, so hashes, joins and regex ranges are byte-identical at runtime. Only
1268
+ // the SOURCE stops carrying the byte.
1269
+ //
1270
+ // SCOPE. Tracked files only (git ls-files — an untracked scratch file is not published),
1271
+ // with publishable text extensions. Binary formats are out of scope by definition: a PNG
1272
+ // is *supposed* to contain NULs and the mirror is right to pass it through.
1273
+ const NUL_TEXT_EXTS = ['.js', '.mjs', '.cjs', '.mts', '.md', '.sql', '.json'];
1274
+
1275
+ // Exemptions must be justified, not just listed. There are none today, and that is the
1276
+ // preferred state: the fix is a one-character escape with no behavioural cost, so
1277
+ // "exempt it" should always lose to "escape it". Kept as a named, empty constant so a
1278
+ // future addition is a visible, reviewable edit rather than a quiet change to a regex.
1279
+ const NUL_EXEMPT_PATHS = [];
1280
+
1281
+ function scanForRawNul(root, { listFiles, readFile } = {}) {
1282
+ const list = listFiles || (() => execFileSync('git', ['ls-files', '-z'], {
1283
+ cwd: root, encoding: 'latin1', maxBuffer: 1 << 26,
1284
+ }).split('\u0000').filter(Boolean));
1285
+ const read = readFile || ((f) => fs.readFileSync(path.join(root, f)));
1286
+
1287
+ const hits = [];
1288
+ for (const f of list()) {
1289
+ if (!NUL_TEXT_EXTS.includes(path.extname(f))) continue;
1290
+ if (NUL_EXEMPT_PATHS.some((e) => f === e || f.startsWith(e))) continue;
1291
+ let buf;
1292
+ try { buf = read(f); } catch (_) { continue; } // deleted-but-tracked, or unreadable
1293
+ const at = buf.indexOf(0);
1294
+ if (at === -1) continue;
1295
+ // Report the LINE, not the byte offset — a byte offset is not actionable.
1296
+ const line = buf.slice(0, at).toString('latin1').split('\n').length;
1297
+ hits.push(`${f}:${line} — raw NUL byte; use the \\u0000 escape (same string at runtime, no NUL in source)`);
1298
+ }
1299
+ return hits;
1300
+ }
1301
+
1302
+ function checkNoRawNulInText() {
1303
+ let violations = [];
1304
+ let note = '';
1305
+ try {
1306
+ violations = scanForRawNul(REPO_ROOT);
1307
+ note = `tracked ${NUL_TEXT_EXTS.join('/')} sources carry no raw NUL byte, so none can be misclassified `
1308
+ + 'as binary and skip public-mirror redaction (task 1002854).';
1309
+ } catch (e) {
1310
+ // Never let the scan itself fail the build — a git failure is not a boundary breach.
1311
+ return {
1312
+ name: 'no raw NUL byte in tracked publishable text (task 1002854)',
1313
+ ok: true, hardFail: false, violations: [], warnings: [`skipped: ${e.message}`],
1314
+ note: 'could not list tracked files — check skipped.',
1315
+ };
1316
+ }
1317
+ return {
1318
+ name: 'no raw NUL byte in tracked publishable text (task 1002854)',
1319
+ ok: violations.length === 0,
1320
+ hardFail: violations.length > 0,
1321
+ violations,
1322
+ warnings: [],
1323
+ note,
1324
+ };
1325
+ }
1326
+
1327
+ const CHECKS = [
1328
+ checkCoreHostBoundary,
1329
+ checkNoRawNulInText, // Check 35 — task 1002854: a raw NUL makes the mirror skip redaction
1330
+ checkClaudeMdBudget,
1331
+ // Check 32 — task 1002990 / criterion wa6-kernel-and-packs: the root CLAUDE.md is
1332
+ // now a role-neutral KERNEL and each craft's playbook lives in a pack under
1333
+ // docs/packs/. claim.js resolves the pack through the role registry and fails
1334
+ // OPEN, so a pack path that points at nothing is invisible at runtime — CI is the
1335
+ // only place a hollowed-out role can be caught. Rationale in that file.
1336
+ require('./role-pack-guard.js').checkRolePacks,
1337
+ checkSkillFrontmatter,
1338
+ checkNestedDocsPresent,
1339
+ checkRankGuards,
1340
+ checkModulePinKeysResolve,
1341
+ checkGeneratedArtifactsFresh,
1342
+ checkDeterministicRoutines,
1343
+ checkCoreNeverImportsModule,
1344
+ checkModulesImportOnlyApi,
1345
+ checkScopeMapImportsProtected,
1346
+ // Check 36 — task 1002900: a carved module with no roster key walls nothing. Extracted
1347
+ // to its own file (the role-pack-guard.js precedent) to keep fitness.js under the size ratchet.
1348
+ () => require('./scope-roster-guard.js').checkScopeRosterCoversModules({ repoRoot: REPO_ROOT, discoveredModuleKeys }),
1349
+ checkCoreCarriesNoModuleCode,
1350
+ checkKernelImportsNoDomain,
1351
+ checkModuleMigrationsAdditive,
1352
+ checkMigrationNamespacing, // Check 11b — ADR 0108 §5 cross-repo migration filenames + stem collision
1353
+ checkDesignContract,
1354
+ checkKernelPromptsNoHardcodedIdentity, // BV1.R76 — kernel prompts read identity from branding()
1355
+ checkNeutralConfigsNoHostIdentity, // Check 15b — BV1.R102: .json is outside the scan above
1356
+ checkHallSectionRegistry,
1357
+ checkCoreRequiresExcludedConfig, // task 1824 — core→instance-config require guard
1358
+ checkCoreRequiresExcludedModule, // Check 16b — task 2135: core→excluded-module require guard (R89 split)
1359
+ checkErrorEnvelope, // Check 17 — BV1 R03 / task 1990: no route hand-rolls a flat error (ADR 0116)
1360
+ checkVocabularyWall, // Check 19 — ADR 0174 / goal 1000068 R07: "role" is a craft, never a rank
1361
+ checkGoalMembershipVocabulary, // Check 19b — ADR 0177 / task 1003013: the FOURTH "role" (goal membership)
1362
+ checkGovernmentRenameIdentity, checkPrelaunchVocabulary, // 19c task 1003120 (`X`→`X` rename arrow) + 19d task 1003152 ("stealth" is the product's word) — sharing a line: this file is AT the 1,500 budget (Check 23/24 precedent below; task 1003825 buys it back)
1363
+ checkWriteRoutesValidated, // Check 18 — BV1 R12 / task 1999: every body-reading write route validates (ADR 0118)
1364
+ require('./fitness-ratchets.js').checkQualityRatchets, // Check 20 — task 1003129: quality budgets only tighten (mechanics + knip CI step live in fitness-ratchets.js)
1365
+ require('./doc-control-claims.js').checkDocControlClaims, // Check 37 — task 1003418 / audit A14: a doc cannot describe an enforcement control that does not exist (derived from the docs, not a hand list)
1366
+ require('./doc-cli-guard.js').checkDocNamesRealCli, // Check 22 — task 1003165 / G01: a doc that names a CLI invocation must match the real CLI
1367
+ require('./skill-preflight.js').checkOpsSkillsDeclareMachine, // Check 23 — task 1003167 / G03: an ops skill declares the machine it needs
1368
+ // Check 24 — task 1003166 / G02: no ops script hardcodes a version id. It landed
1369
+ // sharing Check 23's line, deliberately, because fitness.js was ~500 lines over
1370
+ // the excess-lines ratchet and a new check could not afford one (idea 1000810).
1371
+ // Task 1003206 carved this file from 2,004 lines to ~1,350, so that toll is paid
1372
+ // and the check gets its own line back.
1373
+ require('./version-literal-guard.js').checkNoVersionLiterals,
1374
+ require('./dev-box-guard.js').checkNoDevBox, // task 1003899 / ADR 0346: the retired dev box stays out (its exemption list lives in that file)
1375
+ require('./control-manifest.js').checkControlsExist, // Check 21 — task 1003131: goal-1000076 controls assert their own existence (the ADR 0022 assurance-of-assurance)
1376
+ require('./routine-schedule.js').checkRoutineCadencesScheduled, // Check 25 — task 1003209: a routine that declares a cadence must have a scheduler firing it AT that period (ADR 0188)
1377
+ require('./baseline-staleness.js').checkBaselineFloors, // Check 26 — task 1003210: a shrink-only baseline that never shrinks is unmanaged debt; a floor exempting one must say why
1378
+ require('./client-baseurl-guard.js').checkClientBaseUrl,
1379
+ require('./route-shadow-guard.js').checkNoRouteShadowing, // Check 31 — task 1003747: a `:param` route must not swallow a literal route mounted after it (cross-module mount order; the rot feed shipped dead this way). Rationale in that file.
1380
+ require('./test-path-guard.js').checkTestsUseFileUrlToPath, // Check 30 — task 1002889: a test builds its repo root with fileURLToPath, never URL.pathname (a %20 or a Windows drive slash makes require() throw at load; CI's spaceless checkout can't see it)
1381
+ // Check 29 — task 1003275 / ADR 0189: a work category ORIENTS a human and steers
1382
+ // Claude; it authorises nothing. The owner said so twice, and the goal's own prose
1383
+ // predicts the failure: a second thing that looks like a hierarchy gets mistaken
1384
+ // for one within a release. A comment cannot refuse the line that does it.
1385
+ require('./category-advisory-guard.js').checkCategoryIsAdvisory, // Check 27 — task 1003263: a page must not combine baseUrl:'' with a generated namespaced call (that pairing 404s every request; three pages shipped it, two of them dead in prod)
1386
+ // Check 28 — task 1001654 / ADR 0095: does each source file open with a module
1387
+ // header saying what it does and why. ADVISORY ONLY (never hardFail) — a
1388
+ // doc-comment gate that blocks a ship buys filler prose, not understanding.
1389
+ // Making it blocking is an owner decision and needs its own ADR.
1390
+ require('./doc-comment-coverage.js').checkDocCommentCoverage,
1391
+ // Check 31 — task 1003164: two ADRs may not share a number, and docs/adr/README.md
1392
+ // must agree with the tree. The ADR half of the guard Check 11b already gives
1393
+ // migrations: same shared, monotonic, human-allocated number line, and until this
1394
+ // landed only one of the two was enforced. An ADR number is a citation target, so a
1395
+ // duplicate is wrong forever (ADR 0195).
1396
+ // Check 33 — task 1003819: a module declares what it contributes, and nothing
1397
+ // checked that a declared seam is actually WIRED. verifyPortsSatisfied asks the
1398
+ // opposite question (every `consumes` has a provider) and validateManifest checks
1399
+ // only the SHAPE, so a contributes entry whose artifact was never shipped — or was
1400
+ // renamed out from under the manifest — boots silent: every consumer skips it the
1401
+ // same way it correctly skips a real declarative-only entry. CI, not boot: nothing
1402
+ // crashes later, so a start-up refusal would trade an outage risk for a cosmetic
1403
+ // one (ADR 0289). Rationale + the seam→consumer table live in that file.
1404
+ require('./seam-wiring-guard.js').checkSeamWiring,
1405
+ require('./home-isolation-guard.js').checkHomeIsolation, // Check 34 — task 1003763: a test that sets HOME for a child without USERPROFILE isolates NOTHING on win32, so it silently stops testing what its comment says. Three tasks fixed this one site at a time. Rationale in that file.
1406
+ ...['checkDevsecopsOwnsItsChecks', 'checkEveryModuleDirIsScoped', 'checkNoNewUnownedRoot'].map((k) => require('./scope-map-guard.js')[k]), // Check 35 — task 1003949: a check file no MODULE_SCOPE_MAP key owns cannot be authorized by the goal scoped to own it, and the list drifts once per new check. Check 36 — task 1004132: the same defect one level up, a carved module whose own directory no key claims (modules/specialities/ shipped that way). Sharing the line per the ratchet convention above. Rationale in that file.
1407
+ require('./adr-namespace.js').checkAdrNumbering, require('./exec-path-guard.js').checkExecPathsStatic, // Check 32 — task 1003371 / B50: what the server EXECUTES, out of whose tree — the blind spot all three 2026-08-29 CRITICALs shared. Rationale + reviewed exemptions live in that file. Sharing Check 31's line (the 19c/19d + 23/24 precedent above): fitness.js is AT the 1,500 ratchet and a new check cannot afford a line until task 1003825 buys it back.
1408
+ ];
1409
+
1410
+ function runAll() {
1411
+ return runChecks(CHECKS); // task 1004737: an installed core has no core source to measure — one skipped result, not a crash
1412
+ }
1413
+
1414
+ function main() {
1415
+ const results = runAll();
1416
+ if (process.argv.includes('--json')) {
1417
+ process.stdout.write(JSON.stringify(results, null, 2) + '\n');
1418
+ } else {
1419
+ console.log('Architecture fitness functions (Path C / ADR 0062 §9)\n');
1420
+ for (const r of results) {
1421
+ const mark = r.hardFail ? '✗ FAIL' : (r.warnings.length ? '! WARN' : '✓ PASS');
1422
+ console.log(`${mark} ${r.name}`);
1423
+ console.log(` ${r.note}`);
1424
+ for (const v of r.violations) console.log(` ✗ ${v}`);
1425
+ for (const w of r.warnings) console.log(` ! ${w}`);
1426
+ }
1427
+ const failed = results.filter((r) => r.hardFail).length;
1428
+ console.log(`\n${failed ? `${failed} check(s) FAILED` : 'all checks passed'}.`);
1429
+ }
1430
+ process.exit(results.some((r) => r.hardFail) ? 1 : 0);
1431
+ }
1432
+
1433
+ if (require.main === module) main();
1434
+
1435
+ module.exports = {
1436
+ scanForRawNul,
1437
+ checkVocabularyWall, VOCAB_ALLOW, VOCAB_CITATION, VOCAB_EXTS, vocabFilesToScan,
1438
+ checkGoalMembershipVocabulary, GOAL_VOCAB_SURFACE, checkGovernmentRenameIdentity, RENAME_IDENTITY_RE, checkPrelaunchVocabulary, PRELAUNCH_SURFACE, // 19c task 1003120, 19d task 1003152
1439
+ runAll,
1440
+ resolvesToHostGame,
1441
+ checkCoreHostBoundary,
1442
+ checkClaudeMdBudget,
1443
+ checkNestedDocsPresent,
1444
+ checkRankGuards,
1445
+ checkModulePinKeysResolve,
1446
+ checkGeneratedArtifactsFresh,
1447
+ checkDeterministicRoutines,
1448
+ checkCoreNeverImportsModule,
1449
+ checkModulesImportOnlyApi,
1450
+ checkScopeMapImportsProtected,
1451
+ checkCoreCarriesNoModuleCode,
1452
+ checkKernelImportsNoDomain,
1453
+ checkModuleMigrationsAdditive,
1454
+ checkMigrationNamespacing, // Check 11b — ADR 0108 §5 cross-repo migration filenames
1455
+ checkAdrNumbering: require('./adr-namespace.js').checkAdrNumbering, // Check 31 — task 1003164 / ADR 0195: ADR numbers unique + index agrees with the tree
1456
+ checkDesignContract,
1457
+ checkKernelPromptsNoHardcodedIdentity, // BV1.R76 / task 1705
1458
+ scanPromptIdentity, // BV1.R76 — negative-test hook
1459
+ stripCommentsForIdentity, // task 1705 — comment-strip helper (tested)
1460
+ checkNeutralConfigsNoHostIdentity, // Check 15b — BV1.R102 (tested)
1461
+ checkHallSectionRegistry,
1462
+ scanHallSectionRegistry,
1463
+ hallMainSlice,
1464
+ parseZoneBudgets, // task 2177 — hall Home zone budgets (tested)
1465
+ scanHallZoneCounts,
1466
+ checkHallZoneBudgets,
1467
+ checkErrorEnvelope, // Check 17 — BV1 R03 / task 1990 (ADR 0116)
1468
+ scanFlatErrorSites, // shared with the R04 sweep + its test
1469
+ countFlatErrors, // per-text detector (tested)
1470
+ FLAT_ERROR_BASELINE,
1471
+ checkWriteRoutesValidated, // Check 18 — BV1 R12 / task 1999 (ADR 0118)
1472
+ scanUnvalidatedWriteRoutes, // shared with its test
1473
+ WRITE_VALIDATION_EXEMPT,
1474
+ scanScopeMapSource,
1475
+ scanKernelForModuleKeys,
1476
+ kernelDomainImport,
1477
+ KERNEL_FILES,
1478
+ discoveredModuleKeys,
1479
+ manifestModuleKeys, manifestlessModuleDirs, // task 1002790 — narrow defn + the difference
1480
+ moduleMigrationViolations,
1481
+ moduleNamespace,
1482
+ resolvesToModule,
1483
+ moduleImportViolation,
1484
+ moduleOwnerOf,
1485
+ // test/ratchet hook: toggle the module boundary enforce flag. Default is now
1486
+ // ENFORCING (BV1.R45 / task 1414); tests that need warn-mode restore the
1487
+ // default in a finally.
1488
+ _setModuleBoundaryEnforcing: (v) => { MODULE_BOUNDARY_ENFORCING = !!v; },
1489
+ scanDeterministicBody,
1490
+ HOST_GAME,
1491
+ GRANDFATHERED,
1492
+ LEGACY_NAMESPACED,
1493
+ ROOT_HARD_MAX,
1494
+ ROOT_TARGET,
1495
+ ROOT_CHAR_HARD_MAX,
1496
+ ROOT_CHAR_TARGET,
1497
+ HIGH_TRAFFIC,
1498
+ };