@bongos/core 1.18.3 → 1.18.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/.bongos-core.json +1576 -286
  2. package/.claude/skills/builder-box/SKILL.md +6 -0
  3. package/.claude/skills/builder-sequence/SKILL.md +97 -0
  4. package/.claude/skills/builder-ship/SKILL.md +8 -2
  5. package/.claude/skills/builder-start/SKILL.md +11 -0
  6. package/.claude/skills/builder-sync/SKILL.md +41 -0
  7. package/.claude/skills/fix-task/SKILL.md +64 -0
  8. package/.claude/skills/goal-create/SKILL.md +158 -0
  9. package/.claude/skills/goal-review/SKILL.md +3 -1
  10. package/.claude/skills/idea-triage/SKILL.md +14 -8
  11. package/.claude/skills/merge-mode/SKILL.md +2 -2
  12. package/.claude/skills/new-project/SKILL.md +1 -0
  13. package/.claude/skills/planning-session/SKILL.md +45 -18
  14. package/.env.local.example +4 -3
  15. package/README.md +4 -2
  16. package/bin/bongos.js +1 -0
  17. package/clients/bongos-client/README.md +2 -2
  18. package/clients/bongos-client/bongos-client.global.js +82 -18
  19. package/clients/bongos-client/index.cjs +82 -18
  20. package/clients/bongos-client/index.d.ts +131 -29
  21. package/clients/bongos-client/index.mjs +82 -18
  22. package/config/branding.neutral.json +6 -1
  23. package/config/governance.neutral.json +21 -0
  24. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +24 -0
  25. package/docs/adr/0090-metic-task-authoring.md +1 -1
  26. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  27. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  28. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  29. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  30. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  31. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  32. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  33. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  34. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  35. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  36. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  37. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  38. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  39. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  40. package/docs/adr/README.md +10 -0
  41. package/docs/api/openapi.json +843 -17
  42. package/docs/api-reference.md +23 -10
  43. package/docs/architecture.md +4 -2
  44. package/docs/branding-contract.md +3 -1
  45. package/docs/canonical-permissions.md +21 -8
  46. package/docs/file-map.md +8 -0
  47. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  48. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  49. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  50. package/docs/onboarding/diagrams/assertions.json +4 -7
  51. package/docs/onboarding/drachmae-and-karma.md +3 -3
  52. package/docs/onboarding/primer.md +17 -16
  53. package/docs/onboarding/slash-commands.md +124 -0
  54. package/docs/recipes/builder-box-lifecycle.md +23 -0
  55. package/docs/recipes/devbox-app-release.md +14 -4
  56. package/docs/recipes/instance-first-run.md +16 -0
  57. package/docs/recipes/local-dev.md +81 -0
  58. package/docs/recipes/ops-gotchas.md +19 -1
  59. package/docs/recipes/overnight-builder.md +1 -1
  60. package/docs/recipes/parallel-goal-waves.md +174 -0
  61. package/docs/recipes/ship-and-regrade.md +2 -2
  62. package/docs/recipes/standalone-live-docs.md +48 -0
  63. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  64. package/migrations/003_pms.sql +6 -7
  65. package/migrations/006_pms_v2.sql +3 -31
  66. package/migrations/core_193_task_needs_rebase.sql +28 -0
  67. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  68. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  69. package/migrations/core_196_session_reward_topup.sql +69 -0
  70. package/modules/autonomy/pollers/routine-timers.js +9 -8
  71. package/modules/builder-settings/wandering-prefs.js +61 -18
  72. package/modules/dev-box/app/README.md +73 -0
  73. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  74. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  75. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  76. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  77. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  78. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  79. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  80. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  81. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  82. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  83. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  84. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  85. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  86. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  87. package/modules/dev-box/app/build-resources/icon.png +0 -0
  88. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  89. package/modules/dev-box/app/electron-builder.yml +95 -0
  90. package/modules/dev-box/app/package-lock.json +5291 -0
  91. package/modules/dev-box/app/package.json +30 -0
  92. package/modules/dev-box/app/renderer/app.js +319 -0
  93. package/modules/dev-box/app/renderer/index.html +45 -0
  94. package/modules/dev-box/app/renderer/styles.css +246 -0
  95. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  96. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  97. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  98. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  99. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  100. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  101. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  102. package/modules/dev-box/app/src/box-controller.js +287 -0
  103. package/modules/dev-box/app/src/brand.generated.json +13 -0
  104. package/modules/dev-box/app/src/brand.js +16 -0
  105. package/modules/dev-box/app/src/config.js +19 -0
  106. package/modules/dev-box/app/src/gds-client.js +90 -0
  107. package/modules/dev-box/app/src/main.js +610 -0
  108. package/modules/dev-box/app/src/pairing.js +57 -0
  109. package/modules/dev-box/app/src/preload.js +29 -0
  110. package/modules/dev-box/app/src/session-store.js +58 -0
  111. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  112. package/modules/dev-box/app/src/task-picker.js +70 -0
  113. package/modules/dev-box/app/src/tray.js +99 -0
  114. package/modules/dev-box/app/src/updater.js +55 -0
  115. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  116. package/modules/dev-box/app/test/unit.mjs +526 -0
  117. package/modules/dev-box/box-access.js +121 -4
  118. package/modules/dev-box/boxes.js +20 -0
  119. package/modules/dev-box/module.json +1 -1
  120. package/modules/dev-box/routes/box.js +87 -3
  121. package/modules/economy/credits.js +116 -25
  122. package/modules/economy/reward.js +8 -0
  123. package/modules/economy/streak.js +2 -1
  124. package/modules/governance/CLAUDE.md +15 -0
  125. package/modules/governance/catalog.js +419 -0
  126. package/modules/governance/config.js +174 -0
  127. package/modules/governance/db.js +125 -0
  128. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  129. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  130. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  131. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  132. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  133. package/modules/governance/module.json +10 -0
  134. package/modules/governance/protected-surfaces.js +88 -0
  135. package/modules/governance/protected-surfaces.json +80 -0
  136. package/modules/governance/rank-roles.js +83 -0
  137. package/modules/governance/resolver.js +221 -0
  138. package/modules/governance/routes/governance.js +89 -0
  139. package/modules/governance/routes/role-sync.js +49 -0
  140. package/modules/governance/session-scopes.js +127 -0
  141. package/modules/governance/session-scopes.json +38 -0
  142. package/modules/hall-ui/public/atlas.css +117 -0
  143. package/modules/hall-ui/public/atlas.html +3 -114
  144. package/modules/hall-ui/public/brand-apply.js +34 -6
  145. package/modules/hall-ui/public/builders.js +187 -219
  146. package/modules/hall-ui/public/diagrams.html +2 -0
  147. package/modules/hall-ui/public/dom-utils.js +27 -0
  148. package/modules/hall-ui/public/drachmae.html +2 -0
  149. package/modules/hall-ui/public/drachmae.js +54 -1
  150. package/modules/hall-ui/public/gate.css +98 -0
  151. package/modules/hall-ui/public/gate.html +3 -95
  152. package/modules/hall-ui/public/goal-inbox.js +4 -1
  153. package/modules/hall-ui/public/goals-page.js +626 -114
  154. package/modules/hall-ui/public/goals.css +79 -1
  155. package/modules/hall-ui/public/goals.html +38 -11
  156. package/modules/hall-ui/public/hall-widgets.js +62 -52
  157. package/modules/hall-ui/public/harbor.css +123 -0
  158. package/modules/hall-ui/public/harbor.html +3 -120
  159. package/modules/hall-ui/public/index.html +11 -4
  160. package/modules/hall-ui/public/instances-panel.js +4 -1
  161. package/modules/hall-ui/public/modules.css +63 -0
  162. package/modules/hall-ui/public/modules.html +3 -60
  163. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  164. package/modules/hall-ui/public/not-ready.html +2 -0
  165. package/modules/hall-ui/public/pair.css +73 -0
  166. package/modules/hall-ui/public/pair.html +3 -70
  167. package/modules/hall-ui/public/palette.js +302 -0
  168. package/modules/hall-ui/public/primer.css +13 -0
  169. package/modules/hall-ui/public/primer.html +2 -0
  170. package/modules/hall-ui/public/profile.html +2 -0
  171. package/modules/hall-ui/public/ranks.html +2 -0
  172. package/modules/hall-ui/public/roadmap.css +179 -0
  173. package/modules/hall-ui/public/roadmap.html +9 -172
  174. package/modules/hall-ui/public/roadmap.js +329 -316
  175. package/modules/hall-ui/public/sessions.css +16 -0
  176. package/modules/hall-ui/public/sessions.html +3 -13
  177. package/modules/hall-ui/public/settings.html +2 -0
  178. package/modules/hall-ui/public/settings.js +4 -4
  179. package/modules/hall-ui/public/shell.js +143 -18
  180. package/modules/hall-ui/public/style.css +231 -39
  181. package/modules/hall-ui/public/task-detail.js +347 -26
  182. package/modules/hall-ui/public/task.html +6 -1
  183. package/modules/hall-ui/public/watch.html +2 -0
  184. package/modules/hall-ui/public/work.html +8 -6
  185. package/modules/hall-ui/public/work.js +1 -1
  186. package/modules/ideas/inbox.js +61 -11
  187. package/modules/ideas/routes/inbox.js +23 -0
  188. package/modules/lifecycle/claim-eligibility.js +72 -0
  189. package/modules/lifecycle/db.js +519 -139
  190. package/modules/lifecycle/done-when.js +18 -3
  191. package/modules/lifecycle/github-push.js +19 -2
  192. package/modules/lifecycle/goal-advisory.js +114 -0
  193. package/modules/lifecycle/goal-authz.js +62 -0
  194. package/modules/lifecycle/lifecycle.js +9 -0
  195. package/modules/lifecycle/publish-reconciler.js +109 -6
  196. package/modules/lifecycle/routes/claims.js +68 -23
  197. package/modules/lifecycle/routes/done-when.js +110 -15
  198. package/modules/lifecycle/routes/goals.js +8 -38
  199. package/modules/lifecycle/routes/tasks.js +38 -6
  200. package/modules/lifecycle/ship-card.js +6 -0
  201. package/modules/onboarding/onboarding-state.js +1 -1
  202. package/modules/platform-identity/CLAUDE.md +15 -0
  203. package/modules/platform-identity/hub-device.js +147 -0
  204. package/modules/platform-identity/hub-keys.js +151 -0
  205. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  206. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  207. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  208. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  209. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  210. package/modules/platform-identity/module.json +18 -0
  211. package/modules/platform-identity/platform-identity.js +531 -0
  212. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  213. package/modules/platform-identity/routes/my-projects.js +140 -0
  214. package/modules/platform-identity/routes/projects.js +107 -0
  215. package/modules/platform-identity/routes/scouting.js +35 -0
  216. package/modules/platform-identity/routes/sso.js +402 -0
  217. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  218. package/modules/platform-identity/ui/.gitkeep +0 -0
  219. package/modules/security/routes/reports.js +10 -0
  220. package/modules/sessions/db.js +166 -21
  221. package/modules/sessions/module.json +1 -1
  222. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  223. package/modules/sessions/routes/sessions.js +33 -0
  224. package/package-lock.json +2 -2
  225. package/package.json +1 -1
  226. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  227. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  228. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  229. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  230. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  231. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  232. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  233. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  234. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  235. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  236. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  237. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  238. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  239. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  270. package/public-landing/create.html +51 -58
  271. package/public-landing/gate/README.md +137 -0
  272. package/public-landing/gate/dispmaps/bar.png +0 -0
  273. package/public-landing/gate/dispmaps/flat.png +0 -0
  274. package/public-landing/gate/dispmaps/key.png +0 -0
  275. package/public-landing/gate/index.html +587 -0
  276. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  277. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  278. package/public-landing/gate/space.css +799 -0
  279. package/public-landing/gate/space.js +1826 -0
  280. package/public-landing/gate/sprites/enter.png +0 -0
  281. package/public-landing/gate/sprites/search.png +0 -0
  282. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  283. package/public-landing/gate/sprites/tile.png +0 -0
  284. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  285. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  286. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  287. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  288. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  289. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  290. package/scripts/gds/abandon.js +6 -4
  291. package/scripts/gds/api.js +10 -5
  292. package/scripts/gds/api.ps1 +26 -0
  293. package/scripts/gds/api.sh +6 -0
  294. package/scripts/gds/audit-ships.js +7 -1
  295. package/scripts/gds/backfill-sessions.js +78 -18
  296. package/scripts/gds/backup.js +23 -1
  297. package/scripts/gds/box-connect-lib.js +124 -31
  298. package/scripts/gds/box-sync.js +66 -0
  299. package/scripts/gds/box.js +225 -53
  300. package/scripts/gds/cf-tunnel.js +145 -6
  301. package/scripts/gds/claim.js +34 -3
  302. package/scripts/gds/cli-lib.js +161 -27
  303. package/scripts/gds/code.js +6 -2
  304. package/scripts/gds/deploy-divergence.js +209 -0
  305. package/scripts/gds/dev-lib.js +309 -0
  306. package/scripts/gds/dev.js +322 -0
  307. package/scripts/gds/doctor.js +90 -61
  308. package/scripts/gds/fetch-art-key.js +1 -1
  309. package/scripts/gds/fetch-sound-prefs.js +2 -2
  310. package/scripts/gds/fitness.js +228 -12
  311. package/scripts/gds/gds-db-backup.service +16 -1
  312. package/scripts/gds/gds-db-offsite.service +9 -1
  313. package/scripts/gds/gen-api-client.js +1 -1
  314. package/scripts/gds/gen-api-docs.js +36 -14
  315. package/scripts/gds/gen-diagrams.js +45 -28
  316. package/scripts/gds/gen-file-map.js +2 -1
  317. package/scripts/gds/gen-freshness.js +32 -0
  318. package/scripts/gds/gen-repo-map.js +3 -2
  319. package/scripts/gds/gen-session-index.js +14 -5
  320. package/scripts/gds/hooks/pre-push.js +2 -2
  321. package/scripts/gds/init.js +60 -3
  322. package/scripts/gds/install-git-hooks.js +1 -1
  323. package/scripts/gds/key-card.js +15 -6
  324. package/scripts/gds/key-status.js +1 -1
  325. package/scripts/gds/linkify-refs.js +35 -9
  326. package/scripts/gds/login.js +16 -1
  327. package/scripts/gds/paste-token.js +7 -1
  328. package/scripts/gds/preflight.js +126 -0
  329. package/scripts/gds/provision.js +123 -12
  330. package/scripts/gds/publish-manifest.js +7 -1
  331. package/scripts/gds/reauth.js +7 -3
  332. package/scripts/gds/regen-instance-docs.js +47 -0
  333. package/scripts/gds/run-unit-tests.js +4 -2
  334. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  335. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  336. package/scripts/gds/sequence.js +425 -0
  337. package/scripts/gds/session-cost.js +10 -1
  338. package/scripts/gds/setup.js +31 -5
  339. package/scripts/gds/shell.js +5 -3
  340. package/scripts/gds/ship.js +319 -29
  341. package/scripts/gds/smoke-gds.js +139 -8
  342. package/scripts/gds/start.js +171 -22
  343. package/scripts/gds/status.js +1 -1
  344. package/scripts/gds/triage.js +10 -9
  345. package/scripts/gds/upgrade.js +124 -2
  346. package/scripts/migrate.sh +99 -14
  347. package/scripts/status-mirror-sync.js +114 -84
  348. package/src/bongos/api-errors.js +1 -0
  349. package/src/bongos/auth.js +447 -102
  350. package/src/bongos/db-kernel.js +27 -0
  351. package/src/bongos/db.js +39 -0
  352. package/src/bongos/module-scope-map.js +27 -1
  353. package/src/bongos/permission-path-check.js +136 -102
  354. package/src/bongos/repo-info.js +47 -11
  355. package/src/bongos/route-rank-check.js +429 -46
  356. package/src/bongos/routes/_helpers.js +12 -1
  357. package/src/bongos/routes/auth.js +219 -2
  358. package/src/bongos/routes/backup.js +58 -2
  359. package/src/bongos/routes/me.js +35 -1
  360. package/src/bongos/serve-internal.js +84 -15
  361. package/src/branding.js +32 -0
  362. package/src/instance-config.js +30 -0
  363. package/src/module-api.js +124 -1
  364. package/src/platform-server.js +86 -9
  365. package/tests/abandon_task.mjs +59 -3
  366. package/tests/api_cli_flags.mjs +53 -0
  367. package/tests/auth_page_gate.mjs +13 -0
  368. package/tests/backfill_sessions.mjs +127 -1
  369. package/tests/backup_cli.mjs +54 -0
  370. package/tests/bongos_box_connect.mjs +77 -0
  371. package/tests/box_access.mjs +130 -1
  372. package/tests/box_credential.mjs +125 -0
  373. package/tests/box_host_keys.mjs +24 -0
  374. package/tests/box_infra_resolve.mjs +149 -0
  375. package/tests/box_scope_session.mjs +6 -2
  376. package/tests/box_sync.mjs +55 -0
  377. package/tests/box_task_scope.mjs +99 -0
  378. package/tests/branding.mjs +12 -0
  379. package/tests/cf_ruleset_preflight.mjs +142 -0
  380. package/tests/cf_tunnel.mjs +37 -0
  381. package/tests/claim_gate_rebase.mjs +98 -0
  382. package/tests/clawback_confirmed_backlog.mjs +103 -0
  383. package/tests/cli_lib_formatters.mjs +20 -0
  384. package/tests/confirm_attribution.mjs +30 -46
  385. package/tests/credit_grant.mjs +198 -10
  386. package/tests/criterion_authoring_gate.mjs +272 -0
  387. package/tests/criterion_progress.mjs +33 -1
  388. package/tests/dev_lib.mjs +253 -0
  389. package/tests/devbox_artifact_gate.mjs +75 -0
  390. package/tests/devbox_dmg_backdrop.mjs +137 -0
  391. package/tests/devbox_icons.mjs +304 -0
  392. package/tests/devbox_installer_brand.mjs +232 -0
  393. package/tests/devbox_key_register.mjs +234 -0
  394. package/tests/docs_openapi_route.mjs +110 -0
  395. package/tests/doctor_hooks.mjs +141 -0
  396. package/tests/extract_json.mjs +140 -0
  397. package/tests/fitness.mjs +89 -0
  398. package/tests/gen_freshness.mjs +96 -0
  399. package/tests/goal_advisory.mjs +251 -0
  400. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  401. package/tests/goal_routes.mjs +59 -4
  402. package/tests/goal_tier.mjs +12 -3
  403. package/tests/governance_catalog.mjs +129 -0
  404. package/tests/governance_claim_eligibility.mjs +262 -0
  405. package/tests/governance_config.mjs +187 -0
  406. package/tests/governance_ownership_scope.mjs +410 -0
  407. package/tests/governance_page_gates.mjs +324 -0
  408. package/tests/governance_parity.mjs +336 -0
  409. package/tests/governance_principals.mjs +232 -0
  410. package/tests/governance_protected_surfaces.mjs +208 -0
  411. package/tests/governance_require_permission.mjs +223 -0
  412. package/tests/governance_resolver.mjs +84 -0
  413. package/tests/governance_role_sync.mjs +231 -0
  414. package/tests/governance_seed.mjs +127 -0
  415. package/tests/governance_session_scope.mjs +434 -0
  416. package/tests/governance_vanilla_boot.mjs +203 -0
  417. package/tests/grade_attribution.mjs +7 -7
  418. package/tests/hall_audit.mjs +223 -0
  419. package/tests/hall_nav.mjs +191 -0
  420. package/tests/hall_palette.mjs +206 -0
  421. package/tests/hall_signout.mjs +124 -0
  422. package/tests/hook_user_agents.mjs +10 -0
  423. package/tests/idea_triage.mjs +162 -0
  424. package/tests/idp_device_exchange.mjs +93 -0
  425. package/tests/init.mjs +51 -0
  426. package/tests/instance_config.mjs +65 -0
  427. package/tests/instance_mismatch_guard.mjs +23 -6
  428. package/tests/instance_release_config.mjs +104 -0
  429. package/tests/linkify_refs.mjs +15 -2
  430. package/tests/migrate_root_resolution.mjs +124 -1
  431. package/tests/module_contributions.mjs +55 -0
  432. package/tests/module_loader.mjs +10 -5
  433. package/tests/module_scope_active_claims.mjs +94 -0
  434. package/tests/needs_rebase.mjs +92 -0
  435. package/tests/one_active_claim_per_session.mjs +76 -0
  436. package/tests/override_attribution.mjs +10 -8
  437. package/tests/override_request_ownership.mjs +8 -4
  438. package/tests/parse_cookie_decode.mjs +42 -0
  439. package/tests/pay_on_land.mjs +129 -0
  440. package/tests/platform_boot.mjs +100 -1
  441. package/tests/post_login_landing.mjs +42 -0
  442. package/tests/preflight_checks.mjs +72 -0
  443. package/tests/provision.mjs +132 -7
  444. package/tests/publish_branch_route.mjs +53 -0
  445. package/tests/publish_reconciler.mjs +187 -2
  446. package/tests/repo_info_binding.mjs +248 -0
  447. package/tests/reward_gate.mjs +11 -2
  448. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  449. package/tests/reward_mode_surfacing.mjs +168 -0
  450. package/tests/route_permission_check.mjs +301 -0
  451. package/tests/route_rank_check.mjs +254 -12
  452. package/tests/route_validation.mjs +30 -0
  453. package/tests/sequence.mjs +267 -0
  454. package/tests/session_digest.mjs +44 -0
  455. package/tests/session_index.mjs +18 -6
  456. package/tests/session_records.mjs +39 -1
  457. package/tests/session_reward_on_land.mjs +381 -0
  458. package/tests/session_reward_reconcile.mjs +229 -0
  459. package/tests/ship_api_client_pathspec.mjs +100 -0
  460. package/tests/ship_base_flag.mjs +93 -0
  461. package/tests/ship_ci_deploy.mjs +80 -3
  462. package/tests/ship_upstream_deletion.mjs +57 -0
  463. package/tests/smoke_target.mjs +233 -0
  464. package/tests/start_env_guard.mjs +87 -0
  465. package/tests/start_rebase_warning.mjs +103 -0
  466. package/tests/status_mirror_sync.mjs +122 -0
  467. package/tests/stop_refcheck.mjs +19 -1
  468. package/tests/task_goal_link.mjs +15 -6
  469. package/tests/upgrade.mjs +139 -0
  470. package/tests/web_admission_status.mjs +162 -0
  471. package/tests/write_validation_gaps.mjs +110 -0
@@ -145,11 +145,38 @@
145
145
  // to it by id exactly as before.
146
146
  // Empty until something registers → builders.js renders the hall it does today
147
147
  // once it registers the core widgets unconditionally.
148
+ //
149
+ // task 2177 — placement governance. The rules and their rationale live in
150
+ // ../CLAUDE.md §Placement, which every reject message below links to; these
151
+ // vocabularies are the browser twin of builders.js VIEW_CONTAINERS/ZONE_BUDGETS.
152
+ // Violations console.error + return null rather than throw, so one bad
153
+ // third-party widget can't blank the hall (the structural id/label/mount
154
+ // contract below still throws — that one is first-party programmer error).
155
+ const HALL_ZONES = ['home-banner', 'home-stats', 'home-band', 'home-main'];
156
+ const HALL_VIEWS = ['home', 'standing', 'leaderboard'];
157
+
148
158
  const _hallWidgets = [];
149
159
  function contributeHallWidget(widget) {
150
160
  if (!widget || typeof widget.mount !== 'function' || !widget.id || !widget.label) {
151
161
  throw new Error('contributeHallWidget({ id, label, order?, rank?, module?, mount }) requires id + label + mount()');
152
162
  }
163
+ const reject = (why) => {
164
+ console.error(`[hall] widget "${widget.id}" rejected: ${why} See modules/hall-ui/CLAUDE.md §Placement.`);
165
+ return null;
166
+ };
167
+ if (widget.view && !HALL_VIEWS.includes(widget.view)) {
168
+ return reject(`unknown view "${widget.view}" — expected one of ${HALL_VIEWS.join(', ')}.`);
169
+ }
170
+ if (widget.zone && !HALL_ZONES.includes(widget.zone)) {
171
+ return reject(`unknown zone "${widget.zone}" — expected one of ${HALL_ZONES.join(', ')}.`);
172
+ }
173
+ const view = widget.view || 'home';
174
+ if (view === 'home' && !widget.zone) {
175
+ return reject(`Home widgets must declare a zone (${HALL_ZONES.join(', ')}); there is no default.`);
176
+ }
177
+ if (widget.zone === 'home-main' && !widget.core && !widget.summary && !widget.collapsedByDefault) {
178
+ return reject('a non-core home-main widget must declare summary:true (row-capped, no pager/filter) or collapsedByDefault:true.');
179
+ }
153
180
  if (widget.module && !moduleOn(widget.module)) return null; // off module → not registered
154
181
  _hallWidgets.push(widget);
155
182
  return widget;
@@ -61,6 +61,8 @@
61
61
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
62
62
 
63
63
  <script src="/builders/shell.js?v=2026-07-02-shell1"></script>
64
+ <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
65
+ <script src="/builders/palette.js" defer></script>
64
66
  <script src="/builders/md-reader.js?v=2026-07-05-mdreader-1"></script>
65
67
  <script src="/builders/drachmae.js?v=2026-07-05-drachmae-1" defer></script>
66
68
  <script src="/builders/copy-on-click.js?v=2026-06-01-copy-1" defer></script>
@@ -5,6 +5,14 @@
5
5
  // so builders can read exactly how they get paid without leaving the hall for
6
6
  // GitHub. Reuses the primer's layout/TOC/progress DOM + primer.css; no ack gate
7
7
  // (this is reference reading, not an onboarding checkpoint).
8
+ //
9
+ // task 2174: the red-team bounty rate card moved here off Standing. It is a
10
+ // published reward SCHEDULE — reference material that reads the same for every
11
+ // builder — so it belongs with the rest of the reward model, not in a personal
12
+ // standing view. The doc's §"Red-team / security bounty" describes it in prose;
13
+ // the LIVE numbers come from /public/bounty-table and are appended as a real
14
+ // section (h2 + table) so the TOC, scrollspy and progress bar pick it up like
15
+ // any other section of the article.
8
16
 
9
17
  (() => {
10
18
  'use strict';
@@ -12,6 +20,9 @@
12
20
  const DOC_URL = '/builders/drachmae-and-karma.md';
13
21
  // The doc lives at docs/onboarding/, so relative links resolve against it.
14
22
  const DOC_DIR = 'docs/onboarding/';
23
+ const BOUNTY_URL = '/api/gds/public/bounty-table';
24
+ const BOUNTY_SECTION_ID = 'security-bounty-rates';
25
+ const BOUNTY_SECTION_TITLE = 'Security bounty rates';
15
26
 
16
27
  let repoBlobBase = null;
17
28
  let repoTreeBase = null;
@@ -28,6 +39,45 @@
28
39
  } catch (_) { /* links degrade to the original href */ }
29
40
  }
30
41
 
42
+ // Append the live bounty rate card to the article and return its TOC heading,
43
+ // or null when the schedule can't be read (the prose section stays; we just
44
+ // don't show an empty table or a TOC entry that leads nowhere).
45
+ async function appendBountySection(article) {
46
+ let payload;
47
+ try {
48
+ const r = await fetch(BOUNTY_URL, { credentials: 'same-origin' });
49
+ if (!r.ok) throw new Error(`${BOUNTY_URL} → ${r.status}`);
50
+ payload = await r.json();
51
+ } catch (err) {
52
+ console.warn('[drachmae] bounty schedule unavailable:', err.message);
53
+ return null;
54
+ }
55
+ const rows = Array.isArray(payload && payload.table) ? payload.table : [];
56
+ if (!rows.length) return null;
57
+
58
+ const esc = window.OTBMdReader.escapeHtml;
59
+ const currency = payload.currency || 'credits';
60
+ const section = document.createElement('section');
61
+ section.innerHTML =
62
+ `<h2 id="${esc(BOUNTY_SECTION_ID)}">${esc(BOUNTY_SECTION_TITLE)}</h2>` +
63
+ `<p>Find a flaw in the system’s own walls and report it — rewards are paid in ` +
64
+ `${esc(currency)} by severity. These are the live numbers, read from the server ` +
65
+ `just now, so a tuned rate shows up here immediately.</p>` +
66
+ '<table><thead><tr><th>Severity</th>' +
67
+ `<th>${esc(currency.charAt(0).toUpperCase() + currency.slice(1))}</th>` +
68
+ '<th>What counts</th></tr></thead><tbody>' +
69
+ rows.map((r) => {
70
+ // `overridden` means this instance tuned the tier off its default.
71
+ const tuned = r.overridden ? ' <em>(tuned)</em>' : '';
72
+ return `<tr><td><strong>${esc(r.severity || '')}</strong></td>` +
73
+ `<td>${esc(String(r.drachmae ?? ''))}${tuned}</td>` +
74
+ `<td>${esc(r.blurb || '')}</td></tr>`;
75
+ }).join('') +
76
+ '</tbody></table>';
77
+ article.appendChild(section);
78
+ return { level: 2, id: BOUNTY_SECTION_ID, text: BOUNTY_SECTION_TITLE };
79
+ }
80
+
31
81
  function renderToc(headings) {
32
82
  const list = $('#primer-toc-list');
33
83
  if (!list) return [];
@@ -122,7 +172,10 @@
122
172
  const { html, headings } = window.OTBMdReader.parseMarkdown(md, resolveLinkHref);
123
173
  article.innerHTML = html;
124
174
  article.removeAttribute('aria-busy');
125
- const tocSections = renderToc(headings);
175
+ // Awaited before the TOC is built so the rate card gets a TOC entry and a
176
+ // scrollspy target; the article itself is already on screen by now.
177
+ const bountyHeading = await appendBountySection(article);
178
+ const tocSections = renderToc(bountyHeading ? [...headings, bountyHeading] : headings);
126
179
  setupTocToggle();
127
180
  setupScrollspy(tocSections);
128
181
  setupProgressBar(article);
@@ -0,0 +1,98 @@
1
+ /* gate.css — Page-local styles for the Gate page (Archon-only).
2
+ Lifted verbatim out of the page's inline <style> block (task 1002176);
3
+ the ?v= cache-bust is stamped automatically from this file's content hash
4
+ at boot (src/asset-version.js). */
5
+
6
+ /* Page-local styles for the Gate — approvals for held pull requests. Built
7
+ on the shared design tokens (style.css): each held PR is a card with a
8
+ verdict-colored top band and per-file reasons for the hold. */
9
+ .gate-summary {
10
+ display: grid;
11
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
12
+ gap: 14px;
13
+ margin: 6px 0 22px;
14
+ }
15
+ .gate-stat {
16
+ border: 1px solid var(--border); border-radius: var(--radius-sm);
17
+ background: var(--surface); padding: 12px 14px;
18
+ }
19
+ .gate-stat__label {
20
+ font-size: 11.5px; font-weight: 600;
21
+ letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft);
22
+ }
23
+ .gate-stat__value {
24
+ font-size: 1.6rem; font-weight: 600; color: var(--ink);
25
+ font-variant-numeric: tabular-nums; margin-top: 2px;
26
+ }
27
+
28
+ .gate-list { display: flex; flex-direction: column; gap: 16px; }
29
+
30
+ .gate-crate {
31
+ border: 1px solid var(--border); border-radius: var(--radius);
32
+ background: var(--surface); overflow: hidden;
33
+ }
34
+ /* Verdict band along the top, painted by the held-verdict. */
35
+ .gate-crate__seal { height: 4px; background-color: var(--danger); }
36
+ .gate-crate--needs_trust .gate-crate__seal { background-color: var(--warn); }
37
+ .gate-crate__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
38
+ .gate-crate__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
39
+ .gate-crate__title { font-weight: 600; color: var(--ink); font-size: 15px; }
40
+ .gate-crate__title a { color: inherit; text-decoration: none; }
41
+ .gate-crate__title a:hover { text-decoration: underline; }
42
+ .gate-crate__meta { color: var(--ink-soft); font-size: 12.5px; }
43
+ .gate-crate__meta a { color: var(--accent-text); }
44
+
45
+ .gate-pill {
46
+ font-size: 11px; font-weight: 600;
47
+ letter-spacing: 0.04em; text-transform: uppercase;
48
+ padding: 2px 8px; border-radius: 999px; white-space: nowrap;
49
+ border: 1px solid var(--border); color: var(--ink-soft); background: var(--surface-2);
50
+ }
51
+ .gate-pill--escalate { background: var(--danger-weak); border-color: color-mix(in srgb, var(--danger) 30%, transparent); color: var(--danger); }
52
+ .gate-pill--needs_trust { background: var(--warn-weak); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn); }
53
+ .gate-pill--trusted { background: var(--info-weak); border-color: color-mix(in srgb, var(--info) 30%, transparent); color: var(--info); }
54
+
55
+ .gate-reasons { list-style: none; padding: 0; margin: 0; }
56
+ .gate-reasons li {
57
+ padding: 6px 0; border-bottom: 1px solid var(--border);
58
+ font-size: 13px; color: var(--ink);
59
+ }
60
+ .gate-reasons li:last-child { border-bottom: 0; }
61
+ .gate-reasons code {
62
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
63
+ color: var(--accent-text); background: var(--surface-2);
64
+ padding: 1px 5px; border-radius: 4px;
65
+ }
66
+ .gate-reasons .floor { color: var(--danger); font-weight: 600; }
67
+
68
+ .gate-files { font-size: 12.5px; color: var(--ink-soft); }
69
+ .gate-files code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
70
+
71
+ .gate-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 2px; }
72
+ .gate-btn {
73
+ font: inherit; font-size: 13px; font-weight: 600;
74
+ padding: 7px 16px; border: 1px solid var(--accent);
75
+ background: var(--accent); color: #fff;
76
+ border-radius: var(--radius-sm); cursor: pointer;
77
+ }
78
+ .gate-btn:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); }
79
+ .gate-btn:disabled { opacity: 0.45; cursor: default; }
80
+ .gate-btn--ghost { background: var(--surface); color: var(--ink); border-color: var(--border-strong); }
81
+ .gate-btn--ghost:hover:not(:disabled) { background: var(--surface-2); border-color: var(--border-strong); }
82
+ .gate-approved-note { color: var(--ok); font-size: 13px; }
83
+
84
+ .gate-empty, .gate-sealed { color: var(--ink-soft); padding: 16px 0; }
85
+ .gate-checking { color: var(--ink-faint); font-size: 12.5px; margin-top: 10px; }
86
+
87
+ /* Lightweight confirm modal (mirrors harbor). */
88
+ .gate-modal-bg {
89
+ position: fixed; inset: 0; background: color-mix(in srgb, var(--ink) 40%, transparent);
90
+ display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px;
91
+ }
92
+ .gate-modal {
93
+ background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
94
+ max-width: 480px; width: 100%; padding: 20px 22px; box-shadow: var(--shadow-pop);
95
+ }
96
+ .gate-modal h2 { color: var(--ink); margin: 0 0 8px; font-size: 17px; font-weight: 600; }
97
+ .gate-modal p { color: var(--ink); font-size: 13.5px; margin: 0 0 12px; }
98
+ .gate-modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
@@ -10,101 +10,7 @@
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
12
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
13
- <style>
14
- /* Page-local styles for the Gate — approvals for held pull requests. Built
15
- on the shared design tokens (style.css): each held PR is a card with a
16
- verdict-colored top band and per-file reasons for the hold. */
17
- .gate-summary {
18
- display: grid;
19
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
20
- gap: 14px;
21
- margin: 6px 0 22px;
22
- }
23
- .gate-stat {
24
- border: 1px solid var(--border); border-radius: var(--radius-sm);
25
- background: var(--surface); padding: 12px 14px;
26
- }
27
- .gate-stat__label {
28
- font-size: 11.5px; font-weight: 600;
29
- letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft);
30
- }
31
- .gate-stat__value {
32
- font-size: 1.6rem; font-weight: 600; color: var(--ink);
33
- font-variant-numeric: tabular-nums; margin-top: 2px;
34
- }
35
-
36
- .gate-list { display: flex; flex-direction: column; gap: 16px; }
37
-
38
- .gate-crate {
39
- border: 1px solid var(--border); border-radius: var(--radius);
40
- background: var(--surface); overflow: hidden;
41
- }
42
- /* Verdict band along the top, painted by the held-verdict. */
43
- .gate-crate__seal { height: 4px; background-color: var(--danger); }
44
- .gate-crate--needs_trust .gate-crate__seal { background-color: var(--warn); }
45
- .gate-crate__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
46
- .gate-crate__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
47
- .gate-crate__title { font-weight: 600; color: var(--ink); font-size: 15px; }
48
- .gate-crate__title a { color: inherit; text-decoration: none; }
49
- .gate-crate__title a:hover { text-decoration: underline; }
50
- .gate-crate__meta { color: var(--ink-soft); font-size: 12.5px; }
51
- .gate-crate__meta a { color: var(--accent-text); }
52
-
53
- .gate-pill {
54
- font-size: 11px; font-weight: 600;
55
- letter-spacing: 0.04em; text-transform: uppercase;
56
- padding: 2px 8px; border-radius: 999px; white-space: nowrap;
57
- border: 1px solid var(--border); color: var(--ink-soft); background: var(--surface-2);
58
- }
59
- .gate-pill--escalate { background: var(--danger-weak); border-color: color-mix(in srgb, var(--danger) 30%, transparent); color: var(--danger); }
60
- .gate-pill--needs_trust { background: var(--warn-weak); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn); }
61
- .gate-pill--trusted { background: var(--info-weak); border-color: color-mix(in srgb, var(--info) 30%, transparent); color: var(--info); }
62
-
63
- .gate-reasons { list-style: none; padding: 0; margin: 0; }
64
- .gate-reasons li {
65
- padding: 6px 0; border-bottom: 1px solid var(--border);
66
- font-size: 13px; color: var(--ink);
67
- }
68
- .gate-reasons li:last-child { border-bottom: 0; }
69
- .gate-reasons code {
70
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
71
- color: var(--accent-text); background: var(--surface-2);
72
- padding: 1px 5px; border-radius: 4px;
73
- }
74
- .gate-reasons .floor { color: var(--danger); font-weight: 600; }
75
-
76
- .gate-files { font-size: 12.5px; color: var(--ink-soft); }
77
- .gate-files code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
78
-
79
- .gate-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 2px; }
80
- .gate-btn {
81
- font: inherit; font-size: 13px; font-weight: 600;
82
- padding: 7px 16px; border: 1px solid var(--accent);
83
- background: var(--accent); color: #fff;
84
- border-radius: var(--radius-sm); cursor: pointer;
85
- }
86
- .gate-btn:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); }
87
- .gate-btn:disabled { opacity: 0.45; cursor: default; }
88
- .gate-btn--ghost { background: var(--surface); color: var(--ink); border-color: var(--border-strong); }
89
- .gate-btn--ghost:hover:not(:disabled) { background: var(--surface-2); border-color: var(--border-strong); }
90
- .gate-approved-note { color: var(--ok); font-size: 13px; }
91
-
92
- .gate-empty, .gate-sealed { color: var(--ink-soft); padding: 16px 0; }
93
- .gate-checking { color: var(--ink-faint); font-size: 12.5px; margin-top: 10px; }
94
-
95
- /* Lightweight confirm modal (mirrors harbor). */
96
- .gate-modal-bg {
97
- position: fixed; inset: 0; background: color-mix(in srgb, var(--ink) 40%, transparent);
98
- display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px;
99
- }
100
- .gate-modal {
101
- background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
102
- max-width: 480px; width: 100%; padding: 20px 22px; box-shadow: var(--shadow-pop);
103
- }
104
- .gate-modal h2 { color: var(--ink); margin: 0 0 8px; font-size: 17px; font-weight: 600; }
105
- .gate-modal p { color: var(--ink); font-size: 13.5px; margin: 0 0 12px; }
106
- .gate-modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
107
- </style>
13
+ <link rel="stylesheet" href="/builders/gate.css">
108
14
  </head>
109
15
  <body data-page="gate" data-page-title="Gate">
110
16
 
@@ -137,6 +43,8 @@
137
43
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
138
44
 
139
45
  <script src="/builders/shell.js?v=2026-07-02-shell1"></script>
46
+ <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
47
+ <script src="/builders/palette.js" defer></script>
140
48
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
141
49
  <script src="/builders/gate.js?v=2026-07-03-gate-shell"></script>
142
50
  </body>
@@ -225,8 +225,11 @@
225
225
 
226
226
  // order 20 → the top of the Home main zone: personal + actionable beats
227
227
  // informational. hiddenByDefault so a quiet inbox costs nothing.
228
+ // core: true (task 2177) — this is the hall's own Needs-attention inbox, the
229
+ // designated landing place for anything awaiting the builder, so it is exempt
230
+ // from the summary/collapsed rule that keeps OTHER cards off home-main.
228
231
  window.OTB.contributeHallWidget({
229
- id: 'attention-scroll', label: 'Needs your attention', order: 20, mount,
232
+ id: 'attention-scroll', label: 'Needs your attention', order: 20, mount, core: true,
230
233
  labelledby: 'attention-h', view: 'home', zone: 'home-main', hiddenByDefault: true,
231
234
  });
232
235
  })();