@bongos/core 1.18.0 → 1.18.18

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 (553) hide show
  1. package/.bongos-core.json +1740 -640
  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 +5 -3
  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 +11 -2
  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/0142-project-context-is-prose-only.md +41 -0
  27. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  28. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  29. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  30. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  31. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  32. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  33. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  34. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  35. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  36. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  37. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  38. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  39. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  40. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  41. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  42. package/docs/adr/README.md +15 -2
  43. package/docs/api/openapi.json +2648 -483
  44. package/docs/api-reference.md +73 -13
  45. package/docs/architecture.md +4 -2
  46. package/docs/branding-contract.md +3 -1
  47. package/docs/canonical-permissions.md +21 -8
  48. package/docs/file-map.md +15 -7
  49. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  50. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  51. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  52. package/docs/onboarding/diagrams/assertions.json +4 -7
  53. package/docs/onboarding/drachmae-and-karma.md +3 -3
  54. package/docs/onboarding/primer.md +17 -16
  55. package/docs/onboarding/slash-commands.md +124 -0
  56. package/docs/recipes/builder-box-lifecycle.md +23 -0
  57. package/docs/recipes/devbox-app-release.md +14 -4
  58. package/docs/recipes/instance-first-run.md +16 -0
  59. package/docs/recipes/local-dev.md +81 -0
  60. package/docs/recipes/ops-gotchas.md +19 -1
  61. package/docs/recipes/overnight-builder.md +1 -1
  62. package/docs/recipes/packaging-the-core.md +13 -0
  63. package/docs/recipes/parallel-goal-waves.md +174 -0
  64. package/docs/recipes/ship-and-regrade.md +2 -2
  65. package/docs/recipes/standalone-live-docs.md +48 -0
  66. package/docs/recipes/upgrading-the-core.md +5 -2
  67. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  68. package/migrations/003_pms.sql +6 -7
  69. package/migrations/006_pms_v2.sql +3 -31
  70. package/migrations/039_newcomer_friendly_column.sql +5 -0
  71. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  72. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  73. package/migrations/core_193_task_needs_rebase.sql +28 -0
  74. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  75. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  76. package/migrations/core_196_session_reward_topup.sql +69 -0
  77. package/modules/autonomy/pollers/routine-timers.js +9 -8
  78. package/modules/builder-settings/wandering-prefs.js +61 -18
  79. package/modules/dev-box/app/README.md +73 -0
  80. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  81. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  82. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  83. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  84. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  85. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  86. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  87. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  88. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  89. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  90. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  91. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  92. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  93. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  94. package/modules/dev-box/app/build-resources/icon.png +0 -0
  95. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  96. package/modules/dev-box/app/electron-builder.yml +95 -0
  97. package/modules/dev-box/app/package-lock.json +5291 -0
  98. package/modules/dev-box/app/package.json +30 -0
  99. package/modules/dev-box/app/renderer/app.js +319 -0
  100. package/modules/dev-box/app/renderer/index.html +45 -0
  101. package/modules/dev-box/app/renderer/styles.css +246 -0
  102. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  103. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  104. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  105. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  106. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  107. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  108. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  109. package/modules/dev-box/app/src/box-controller.js +287 -0
  110. package/modules/dev-box/app/src/brand.generated.json +13 -0
  111. package/modules/dev-box/app/src/brand.js +16 -0
  112. package/modules/dev-box/app/src/config.js +19 -0
  113. package/modules/dev-box/app/src/gds-client.js +90 -0
  114. package/modules/dev-box/app/src/main.js +610 -0
  115. package/modules/dev-box/app/src/pairing.js +57 -0
  116. package/modules/dev-box/app/src/preload.js +29 -0
  117. package/modules/dev-box/app/src/session-store.js +58 -0
  118. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  119. package/modules/dev-box/app/src/task-picker.js +70 -0
  120. package/modules/dev-box/app/src/tray.js +99 -0
  121. package/modules/dev-box/app/src/updater.js +55 -0
  122. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  123. package/modules/dev-box/app/test/unit.mjs +526 -0
  124. package/modules/dev-box/box-access.js +121 -4
  125. package/modules/dev-box/boxes.js +20 -0
  126. package/modules/dev-box/module.json +1 -1
  127. package/modules/dev-box/routes/box.js +87 -3
  128. package/modules/economy/credits.js +116 -25
  129. package/modules/economy/reward.js +8 -0
  130. package/modules/economy/streak.js +2 -1
  131. package/modules/governance/CLAUDE.md +15 -0
  132. package/modules/governance/catalog.js +419 -0
  133. package/modules/governance/config.js +174 -0
  134. package/modules/governance/db.js +125 -0
  135. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  136. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  137. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  138. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  139. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  140. package/modules/governance/module.json +10 -0
  141. package/modules/governance/protected-surfaces.js +88 -0
  142. package/modules/governance/protected-surfaces.json +80 -0
  143. package/modules/governance/rank-roles.js +83 -0
  144. package/modules/governance/resolver.js +221 -0
  145. package/modules/governance/routes/governance.js +89 -0
  146. package/modules/governance/routes/role-sync.js +49 -0
  147. package/modules/governance/session-scopes.js +127 -0
  148. package/modules/governance/session-scopes.json +38 -0
  149. package/modules/hall-ui/public/atlas.css +117 -0
  150. package/modules/hall-ui/public/atlas.html +3 -114
  151. package/modules/hall-ui/public/brand-apply.js +34 -6
  152. package/modules/hall-ui/public/builders.js +187 -219
  153. package/modules/hall-ui/public/diagrams.html +2 -0
  154. package/modules/hall-ui/public/dom-utils.js +27 -0
  155. package/modules/hall-ui/public/drachmae.html +2 -0
  156. package/modules/hall-ui/public/drachmae.js +54 -1
  157. package/modules/hall-ui/public/gate.css +98 -0
  158. package/modules/hall-ui/public/gate.html +3 -95
  159. package/modules/hall-ui/public/goal-inbox.js +4 -1
  160. package/modules/hall-ui/public/goals-page.js +626 -114
  161. package/modules/hall-ui/public/goals.css +79 -1
  162. package/modules/hall-ui/public/goals.html +38 -11
  163. package/modules/hall-ui/public/hall-widgets.js +62 -52
  164. package/modules/hall-ui/public/harbor.css +123 -0
  165. package/modules/hall-ui/public/harbor.html +3 -120
  166. package/modules/hall-ui/public/index.html +11 -4
  167. package/modules/hall-ui/public/instances-panel.js +4 -1
  168. package/modules/hall-ui/public/modules.css +63 -0
  169. package/modules/hall-ui/public/modules.html +3 -60
  170. package/modules/hall-ui/public/my-projects.html +78 -0
  171. package/modules/hall-ui/public/my-projects.js +142 -0
  172. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  173. package/modules/hall-ui/public/not-ready.html +2 -0
  174. package/modules/hall-ui/public/pair.css +73 -0
  175. package/modules/hall-ui/public/pair.html +3 -70
  176. package/modules/hall-ui/public/palette.js +302 -0
  177. package/modules/hall-ui/public/primer.css +13 -0
  178. package/modules/hall-ui/public/primer.html +2 -0
  179. package/modules/hall-ui/public/profile.html +2 -0
  180. package/modules/hall-ui/public/ranks.html +2 -0
  181. package/modules/hall-ui/public/roadmap.css +179 -0
  182. package/modules/hall-ui/public/roadmap.html +9 -172
  183. package/modules/hall-ui/public/roadmap.js +329 -316
  184. package/modules/hall-ui/public/scouting.html +45 -0
  185. package/modules/hall-ui/public/scouting.js +73 -0
  186. package/modules/hall-ui/public/sessions.css +16 -0
  187. package/modules/hall-ui/public/sessions.html +3 -13
  188. package/modules/hall-ui/public/settings.html +2 -0
  189. package/modules/hall-ui/public/settings.js +4 -4
  190. package/modules/hall-ui/public/shell.js +143 -18
  191. package/modules/hall-ui/public/style.css +231 -39
  192. package/modules/hall-ui/public/task-detail.js +347 -26
  193. package/modules/hall-ui/public/task.html +6 -1
  194. package/modules/hall-ui/public/watch.html +2 -0
  195. package/modules/hall-ui/public/work.html +8 -6
  196. package/modules/hall-ui/public/work.js +1 -1
  197. package/modules/ideas/inbox.js +61 -11
  198. package/modules/ideas/routes/inbox.js +23 -0
  199. package/modules/lifecycle/claim-eligibility.js +72 -0
  200. package/modules/lifecycle/db.js +519 -139
  201. package/modules/lifecycle/done-when.js +18 -3
  202. package/modules/lifecycle/github-push.js +19 -2
  203. package/modules/lifecycle/goal-advisory.js +114 -0
  204. package/modules/lifecycle/goal-authz.js +62 -0
  205. package/modules/lifecycle/lifecycle.js +9 -0
  206. package/modules/lifecycle/publish-reconciler.js +109 -6
  207. package/modules/lifecycle/routes/claims.js +68 -23
  208. package/modules/lifecycle/routes/done-when.js +110 -15
  209. package/modules/lifecycle/routes/goals.js +8 -38
  210. package/modules/lifecycle/routes/tasks.js +38 -6
  211. package/modules/lifecycle/ship-card.js +6 -0
  212. package/modules/onboarding/onboarding-state.js +1 -1
  213. package/modules/platform-identity/CLAUDE.md +15 -0
  214. package/modules/platform-identity/hub-device.js +147 -0
  215. package/modules/platform-identity/hub-keys.js +151 -0
  216. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  217. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  218. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  219. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  220. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  221. package/modules/platform-identity/module.json +18 -0
  222. package/modules/platform-identity/platform-identity.js +531 -0
  223. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  224. package/modules/platform-identity/routes/my-projects.js +140 -0
  225. package/modules/platform-identity/routes/projects.js +107 -0
  226. package/modules/platform-identity/routes/scouting.js +35 -0
  227. package/modules/platform-identity/routes/sso.js +402 -0
  228. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  229. package/modules/platform-identity/ui/.gitkeep +0 -0
  230. package/modules/security/routes/reports.js +10 -0
  231. package/modules/sessions/db.js +166 -21
  232. package/modules/sessions/module.json +1 -1
  233. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  234. package/modules/sessions/routes/sessions.js +33 -0
  235. package/modules/status-ui/public/explore.html +54 -0
  236. package/modules/status-ui/public/explore.js +67 -0
  237. package/package-lock.json +2 -2
  238. package/package.json +1 -1
  239. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  270. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  271. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  272. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  273. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  274. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  275. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  276. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  277. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  278. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  279. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  280. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  281. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  282. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  283. package/public-landing/create.html +252 -62
  284. package/public-landing/gate/README.md +137 -0
  285. package/public-landing/gate/dispmaps/bar.png +0 -0
  286. package/public-landing/gate/dispmaps/flat.png +0 -0
  287. package/public-landing/gate/dispmaps/key.png +0 -0
  288. package/public-landing/gate/index.html +587 -0
  289. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  290. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  291. package/public-landing/gate/space.css +799 -0
  292. package/public-landing/gate/space.js +1826 -0
  293. package/public-landing/gate/sprites/enter.png +0 -0
  294. package/public-landing/gate/sprites/search.png +0 -0
  295. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  296. package/public-landing/gate/sprites/tile.png +0 -0
  297. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  298. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  299. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  300. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  301. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  302. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  303. package/scripts/gds/abandon.js +6 -4
  304. package/scripts/gds/api.js +10 -5
  305. package/scripts/gds/api.ps1 +26 -0
  306. package/scripts/gds/api.sh +6 -0
  307. package/scripts/gds/audit-ships.js +7 -1
  308. package/scripts/gds/backfill-sessions.js +78 -18
  309. package/scripts/gds/backup.js +23 -1
  310. package/scripts/gds/box-connect-lib.js +124 -31
  311. package/scripts/gds/box-sync.js +66 -0
  312. package/scripts/gds/box.js +225 -53
  313. package/scripts/gds/cf-tunnel.js +145 -6
  314. package/scripts/gds/claim.js +34 -3
  315. package/scripts/gds/cli-lib.js +161 -21
  316. package/scripts/gds/code.js +6 -2
  317. package/scripts/gds/deploy-divergence.js +209 -0
  318. package/scripts/gds/dev-lib.js +309 -0
  319. package/scripts/gds/dev.js +322 -0
  320. package/scripts/gds/doctor.js +90 -61
  321. package/scripts/gds/fetch-art-key.js +1 -1
  322. package/scripts/gds/fetch-sound-prefs.js +2 -2
  323. package/scripts/gds/fitness.js +228 -12
  324. package/scripts/gds/gds-db-backup.service +16 -1
  325. package/scripts/gds/gds-db-offsite.service +9 -1
  326. package/scripts/gds/gen-api-client.js +1 -1
  327. package/scripts/gds/gen-api-docs.js +36 -14
  328. package/scripts/gds/gen-diagrams.js +45 -28
  329. package/scripts/gds/gen-file-map.js +2 -1
  330. package/scripts/gds/gen-freshness.js +32 -0
  331. package/scripts/gds/gen-repo-map.js +3 -2
  332. package/scripts/gds/gen-session-index.js +14 -5
  333. package/scripts/gds/hooks/pre-push.js +2 -2
  334. package/scripts/gds/init.js +60 -3
  335. package/scripts/gds/install-git-hooks.js +1 -1
  336. package/scripts/gds/key-card.js +15 -6
  337. package/scripts/gds/key-status.js +1 -1
  338. package/scripts/gds/linkify-refs.js +35 -9
  339. package/scripts/gds/lint-migrations.js +102 -0
  340. package/scripts/gds/login.js +58 -11
  341. package/scripts/gds/mirror-redact.js +5 -0
  342. package/scripts/gds/package-core.js +263 -4
  343. package/scripts/gds/paste-token.js +7 -1
  344. package/scripts/gds/preflight.js +126 -0
  345. package/scripts/gds/provision.js +268 -19
  346. package/scripts/gds/publish-manifest.js +22 -1
  347. package/scripts/gds/reauth.js +7 -3
  348. package/scripts/gds/regen-instance-docs.js +47 -0
  349. package/scripts/gds/run-unit-tests.js +42 -16
  350. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  351. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  352. package/scripts/gds/sequence.js +425 -0
  353. package/scripts/gds/session-cost.js +10 -1
  354. package/scripts/gds/setup.js +72 -5
  355. package/scripts/gds/shell.js +5 -3
  356. package/scripts/gds/ship.js +433 -59
  357. package/scripts/gds/smoke-gds.js +139 -8
  358. package/scripts/gds/start.js +171 -22
  359. package/scripts/gds/status.js +1 -1
  360. package/scripts/gds/triage.js +10 -9
  361. package/scripts/gds/upgrade.js +271 -7
  362. package/scripts/migrate.sh +10 -0
  363. package/scripts/status-mirror-sync.js +114 -84
  364. package/src/bongos/api-errors.js +1 -0
  365. package/src/bongos/auth.js +809 -107
  366. package/src/bongos/db-kernel.js +27 -0
  367. package/src/bongos/db.js +105 -0
  368. package/src/bongos/github-repos.js +93 -0
  369. package/src/bongos/module-scope-map.js +27 -1
  370. package/src/bongos/permission-path-check.js +136 -102
  371. package/src/bongos/repo-info.js +47 -11
  372. package/src/bongos/route-rank-check.js +429 -46
  373. package/src/bongos/routes/_helpers.js +12 -1
  374. package/src/bongos/routes/auth.js +312 -13
  375. package/src/bongos/routes/backup.js +58 -2
  376. package/src/bongos/routes/github.js +90 -0
  377. package/src/bongos/routes/instance.js +15 -3
  378. package/src/bongos/routes/me.js +35 -1
  379. package/src/bongos/routes.js +2 -0
  380. package/src/bongos/serve-internal.js +84 -15
  381. package/src/branding.js +49 -2
  382. package/src/instance-config.js +46 -0
  383. package/src/module-api.js +140 -1
  384. package/src/platform-server.js +86 -9
  385. package/tests/abandon_task.mjs +59 -3
  386. package/tests/api_cli_flags.mjs +53 -0
  387. package/tests/auth_page_gate.mjs +13 -0
  388. package/tests/backfill_sessions.mjs +127 -1
  389. package/tests/backup_cli.mjs +54 -0
  390. package/tests/bongos_box_connect.mjs +77 -0
  391. package/tests/box_access.mjs +130 -1
  392. package/tests/box_credential.mjs +125 -0
  393. package/tests/box_host_keys.mjs +24 -0
  394. package/tests/box_infra_resolve.mjs +149 -0
  395. package/tests/box_scope_session.mjs +6 -2
  396. package/tests/box_sync.mjs +55 -0
  397. package/tests/box_task_scope.mjs +99 -0
  398. package/tests/branding.mjs +41 -23
  399. package/tests/cf_ruleset_preflight.mjs +142 -0
  400. package/tests/cf_tunnel.mjs +37 -0
  401. package/tests/claim_gate_rebase.mjs +98 -0
  402. package/tests/clawback_confirmed_backlog.mjs +103 -0
  403. package/tests/cli_lib_formatters.mjs +20 -0
  404. package/tests/confirm_attribution.mjs +30 -46
  405. package/tests/credit_grant.mjs +198 -10
  406. package/tests/criterion_authoring_gate.mjs +272 -0
  407. package/tests/criterion_progress.mjs +33 -1
  408. package/tests/dev_lib.mjs +253 -0
  409. package/tests/devbox_artifact_gate.mjs +75 -0
  410. package/tests/devbox_dmg_backdrop.mjs +137 -0
  411. package/tests/devbox_icons.mjs +304 -0
  412. package/tests/devbox_installer_brand.mjs +232 -0
  413. package/tests/devbox_key_register.mjs +234 -0
  414. package/tests/docs_openapi_route.mjs +110 -0
  415. package/tests/doctor_hooks.mjs +141 -0
  416. package/tests/extract_json.mjs +140 -0
  417. package/tests/fitness.mjs +89 -0
  418. package/tests/gen_freshness.mjs +96 -0
  419. package/tests/github_repos_helpers.mjs +91 -0
  420. package/tests/github_token_store.mjs +121 -0
  421. package/tests/goal_advisory.mjs +251 -0
  422. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  423. package/tests/goal_routes.mjs +59 -4
  424. package/tests/goal_tier.mjs +12 -3
  425. package/tests/governance_catalog.mjs +129 -0
  426. package/tests/governance_claim_eligibility.mjs +262 -0
  427. package/tests/governance_config.mjs +187 -0
  428. package/tests/governance_ownership_scope.mjs +410 -0
  429. package/tests/governance_page_gates.mjs +324 -0
  430. package/tests/governance_parity.mjs +336 -0
  431. package/tests/governance_principals.mjs +232 -0
  432. package/tests/governance_protected_surfaces.mjs +208 -0
  433. package/tests/governance_require_permission.mjs +223 -0
  434. package/tests/governance_resolver.mjs +84 -0
  435. package/tests/governance_role_sync.mjs +231 -0
  436. package/tests/governance_seed.mjs +127 -0
  437. package/tests/governance_session_scope.mjs +434 -0
  438. package/tests/governance_vanilla_boot.mjs +203 -0
  439. package/tests/grade_attribution.mjs +7 -7
  440. package/tests/hall_audit.mjs +223 -0
  441. package/tests/hall_nav.mjs +191 -0
  442. package/tests/hall_palette.mjs +206 -0
  443. package/tests/hall_signout.mjs +124 -0
  444. package/tests/hook_user_agents.mjs +10 -0
  445. package/tests/idea_triage.mjs +162 -0
  446. package/tests/idp_device_exchange.mjs +198 -0
  447. package/tests/idp_federation.mjs +100 -0
  448. package/tests/init.mjs +51 -0
  449. package/tests/instance_config.mjs +65 -0
  450. package/tests/instance_mismatch_guard.mjs +23 -6
  451. package/tests/instance_release_config.mjs +104 -0
  452. package/tests/linkify_refs.mjs +15 -2
  453. package/tests/migrations_forward_safe.mjs +86 -0
  454. package/tests/module_api.mjs +1 -1
  455. package/tests/module_contributions.mjs +55 -0
  456. package/tests/module_loader.mjs +10 -5
  457. package/tests/module_scope_active_claims.mjs +94 -0
  458. package/tests/needs_rebase.mjs +92 -0
  459. package/tests/one_active_claim_per_session.mjs +76 -0
  460. package/tests/override_attribution.mjs +10 -8
  461. package/tests/override_request_ownership.mjs +8 -4
  462. package/tests/package_core.mjs +246 -1
  463. package/tests/parse_cookie_decode.mjs +42 -0
  464. package/tests/pay_on_land.mjs +129 -0
  465. package/tests/platform_boot.mjs +100 -1
  466. package/tests/post_login_landing.mjs +42 -0
  467. package/tests/preflight_checks.mjs +72 -0
  468. package/tests/provision.mjs +289 -7
  469. package/tests/pruned_lockfile_integrity.mjs +79 -0
  470. package/tests/publish_branch_route.mjs +53 -0
  471. package/tests/publish_reconciler.mjs +187 -2
  472. package/tests/repo_info_binding.mjs +248 -0
  473. package/tests/reward_gate.mjs +11 -2
  474. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  475. package/tests/reward_mode_surfacing.mjs +168 -0
  476. package/tests/route_permission_check.mjs +301 -0
  477. package/tests/route_rank_check.mjs +254 -12
  478. package/tests/route_validation.mjs +30 -0
  479. package/tests/sequence.mjs +267 -0
  480. package/tests/session_digest.mjs +44 -0
  481. package/tests/session_index.mjs +18 -6
  482. package/tests/session_records.mjs +39 -1
  483. package/tests/session_reward_on_land.mjs +381 -0
  484. package/tests/session_reward_reconcile.mjs +229 -0
  485. package/tests/ship_api_client_pathspec.mjs +100 -0
  486. package/tests/ship_base_flag.mjs +93 -0
  487. package/tests/ship_ci_deploy.mjs +140 -3
  488. package/tests/ship_upstream_deletion.mjs +57 -0
  489. package/tests/smoke_target.mjs +233 -0
  490. package/tests/start_env_guard.mjs +87 -0
  491. package/tests/start_rebase_warning.mjs +103 -0
  492. package/tests/status_mirror_sync.mjs +122 -0
  493. package/tests/stop_refcheck.mjs +19 -1
  494. package/tests/task_goal_link.mjs +15 -6
  495. package/tests/upgrade.mjs +393 -5
  496. package/tests/web_admission_status.mjs +162 -0
  497. package/tests/write_validation_gaps.mjs +110 -0
  498. package/.gitignore +0 -91
  499. package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +0 -94
  500. package/docs/adr/0140-cloudbongos-standalone-reprovision.md +0 -43
  501. package/scripts/hall-preview/fixtures/access-requests.json +0 -20
  502. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  503. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  504. package/scripts/hall-preview/fixtures/audit-log.json +0 -68
  505. package/scripts/hall-preview/fixtures/blockers__detail.json +0 -12
  506. package/scripts/hall-preview/fixtures/box__me.json +0 -5
  507. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -69
  508. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  509. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  510. package/scripts/hall-preview/fixtures/builders__roster.json +0 -48
  511. package/scripts/hall-preview/fixtures/goals.json +0 -502
  512. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  513. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  514. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  515. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  516. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  517. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  518. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  519. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  520. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -32
  521. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  522. package/scripts/hall-preview/fixtures/inbox__detail.json +0 -15
  523. package/scripts/hall-preview/fixtures/instance.json +0 -124
  524. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  525. package/scripts/hall-preview/fixtures/me.json +0 -476
  526. package/scripts/hall-preview/fixtures/me__art-key__own.json +0 -6
  527. package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +0 -209
  528. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  529. package/scripts/hall-preview/fixtures/me__render.json +0 -5
  530. package/scripts/hall-preview/fixtures/me__skill-prefs.json +0 -143
  531. package/scripts/hall-preview/fixtures/me__sound-prefs.json +0 -67
  532. package/scripts/hall-preview/fixtures/me__wandering.json +0 -43
  533. package/scripts/hall-preview/fixtures/override-requests.json +0 -15
  534. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  535. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  536. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  537. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  538. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  539. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  540. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  541. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  542. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  543. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  544. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  545. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  546. package/scripts/hall-preview/fixtures/security__docs.json +0 -10
  547. package/scripts/hall-preview/fixtures/security__reports.json +0 -31
  548. package/scripts/hall-preview/fixtures/sessions__search.json +0 -9
  549. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  550. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  551. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  552. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  553. package/scripts/hall-preview/fixtures/versions.json +0 -89
@@ -133,11 +133,31 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
133
133
  .conflict__sev--medium { background: var(--warn-weak); color: var(--warn); }
134
134
 
135
135
  .crit-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
136
- .crit { display: grid; grid-template-columns: 22px minmax(0,1fr); gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; }
136
+ /* task 1002164 — a third trailing column holds the per-criterion Confirm action;
137
+ it collapses to zero width on the rows that have none. */
138
+ .crit { display: grid; grid-template-columns: 22px minmax(0,1fr) auto; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; }
137
139
  .crit:last-child { border-bottom: none; }
138
140
  .crit__mark { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--border-strong); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--ink-faint); }
139
141
  .crit--done .crit__mark { background: var(--ok); border-color: var(--ok); color: #fff; }
140
142
  .crit--done .crit__text { color: var(--ink-soft); }
143
+
144
+ /* task 1002164 — "met, awaiting confirmation": every linked task shipped but the
145
+ criterion is not yet confirmed. Distinct from both done (solid ✓) and open
146
+ (empty circle) so the three states read apart at a glance. */
147
+ .crit--pending .crit__mark { border-color: var(--warn); color: var(--warn); font-weight: 700; }
148
+ .crit__act { display: flex; align-items: center; }
149
+ .crit-list--full .crit__act { align-self: start; padding-top: 1px; }
150
+ .crit__confirm {
151
+ cursor: pointer; white-space: nowrap; padding: 3px 10px; border-radius: 999px;
152
+ border: 1px solid var(--ok); background: transparent; color: var(--ok);
153
+ font: inherit; font-size: 11.5px; font-weight: 600;
154
+ }
155
+ .crit__confirm:hover:not(:disabled) { background: var(--ok); color: #fff; }
156
+ .crit__confirm:disabled { opacity: .6; cursor: default; }
157
+ .crit__flag {
158
+ white-space: nowrap; padding: 2px 8px; border-radius: 999px;
159
+ background: var(--warn-weak); color: var(--warn); font-size: 10.5px; font-weight: 600;
160
+ }
141
161
  /* BV1.R79: per-criterion expand in the capped band — short label, full text on
142
162
  click (matches the Roadmap page's .vbar__crit-d pattern). */
143
163
  .crit-d { min-width: 0; }
@@ -181,3 +201,61 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
181
201
 
182
202
  /* Filtered-count line under the kit filter bar (list view). */
183
203
  .goals-count-line { margin: -4px 0 12px; font-size: 12.5px; color: var(--ink-faint); }
204
+
205
+ /* ============================================================
206
+ task 1002439 — Goals "what's next" rollup (grouped list view).
207
+ Replaces the paginated card grid: a task-readiness summary, then
208
+ goals grouped Active / Blocked / Achieved. Each row rolls its
209
+ tasks up into ready/in-progress/blocked; the task→task dependency
210
+ graph itself lives on the Tasks page. Uses the shared style.css tokens.
211
+ ============================================================ */
212
+ /* The list container used to be an auto-fill CARD grid; the rollup renders
213
+ grouped full-width blocks into it, so flip it to normal block flow. */
214
+ #goal-grid.goal-grid { display: block; gap: 0; }
215
+ .gr-summary { display: flex; flex-wrap: wrap; gap: 22px; margin: 6px 0 20px; }
216
+ .gr-sm { display: flex; align-items: baseline; gap: 8px; font-size: 13px; color: var(--ink-soft); }
217
+ .gr-sm b { font-size: 20px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); font-variant-numeric: tabular-nums; }
218
+ .gr-sm__dot { width: 8px; height: 8px; border-radius: 50%; align-self: center; }
219
+
220
+ .gr-sec { display: flex; align-items: center; gap: 9px; margin: 26px 0 8px; }
221
+ .gr-sec b { font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-faint); }
222
+ .gr-sec__n { font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
223
+
224
+ .gr-list { border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-card); overflow: hidden; }
225
+ .gr-row { display: grid; grid-template-columns: auto 1fr auto; gap: 16px; align-items: center; padding: 15px 17px; border-bottom: 1px solid var(--rule-soft); }
226
+ .gr-row:last-child { border-bottom: 0; }
227
+ .gr-row:hover { background: color-mix(in srgb, var(--ink) 2.5%, var(--bg-card)); }
228
+ .gr-ringcol { flex: none; }
229
+ .gr-crit-none { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--rule); color: var(--ink-faint); font-size: 13px; }
230
+ .gr-main { min-width: 0; }
231
+ .gr-title { display: inline-block; font-size: 15px; font-weight: 650; letter-spacing: -.01em; color: var(--ink); line-height: 1.3; }
232
+ .gr-title:hover { color: var(--accent-text); }
233
+ .gr-meta { font-size: 12px; color: var(--ink-faint); margin-top: 3px; font-variant-numeric: tabular-nums; }
234
+ .gr-roll { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 8px; }
235
+ .gr-d { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
236
+ .gr-d i { width: 7px; height: 7px; border-radius: 50%; }
237
+ .gr-d b { color: var(--ink); font-weight: 600; }
238
+ .gr-right { text-align: right; min-width: 150px; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
239
+ .gr-next { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; max-width: 230px; }
240
+ .gr-next__t { font-size: 12.5px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 230px; }
241
+ .gr-claim { background: var(--accent); color: #fff; border-radius: 8px; padding: 6px 14px; font-size: 12.5px; font-weight: 650; white-space: nowrap; }
242
+ .gr-claim:hover { background: var(--accent-deep); }
243
+ .gr-drill { font-size: 12.5px; color: var(--ink-faint); display: inline-flex; align-items: center; gap: 5px; }
244
+ .gr-drill:hover { color: var(--accent-text); }
245
+ .gr-met { font-size: 12.5px; font-weight: 600; color: var(--ok); }
246
+ .gr-quiet { font-size: 12.5px; color: var(--ink-faint); }
247
+
248
+ .gr-pills { display: flex; flex-wrap: wrap; gap: 8px; }
249
+ .gr-pill { display: inline-flex; align-items: center; gap: 8px; background: var(--bg-card); border: 1px solid var(--rule); border-radius: 20px; padding: 6px 13px 6px 8px; color: var(--ink-soft); font-size: 12.5px; }
250
+ .gr-pill:hover { border-color: var(--border-strong); }
251
+ .gr-pill b { color: var(--ink); font-weight: 600; }
252
+ .gr-pill__ok { width: 17px; height: 17px; border-radius: 50%; background: var(--ok-weak); color: var(--ok); display: grid; place-items: center; font-size: 10px; font-weight: 800; }
253
+ .gr-pill__id { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
254
+ .gr-pills--muted { opacity: .6; }
255
+
256
+ @media (max-width: 640px) {
257
+ .gr-row { grid-template-columns: auto 1fr; row-gap: 11px; }
258
+ .gr-right { grid-column: 1 / -1; align-items: flex-start; text-align: left; }
259
+ .gr-next { align-items: flex-start; }
260
+ .gr-next__t { max-width: 100%; }
261
+ }
@@ -14,6 +14,14 @@
14
14
  block per the hall placement rules; shared pager/filter/tab/count-pill
15
15
  styles now live in style.css's hall-kit section. -->
16
16
  <link rel="stylesheet" href="/builders/goals.css">
17
+ <!-- task 1002425 — the goal-detail "Tasks" pane mirrors the Tasks board's
18
+ claimable cards + bulk toolbar, so it needs the board's page-local card /
19
+ .task__claim / .bulk-toolbar styling. That styling lives in work.css (the
20
+ shared base .task grid is already in style.css above); linking it here is
21
+ the no-duplication way to give both surfaces identical cards. (Follow-up:
22
+ promote the shared card/toolbar rules into style.css so work.css can go
23
+ back to being board-only — idea captured at ship.) -->
24
+ <link rel="stylesheet" href="/builders/work.css">
17
25
  </head>
18
26
  <body data-page="goals" data-page-title="Goals">
19
27
 
@@ -89,23 +97,25 @@
89
97
 
90
98
  <div class="scroll" style="margin-top:20px">
91
99
  <div class="goal-work__head">
92
- <h2 class="scroll__h">Work</h2>
100
+ <h2 class="scroll__h">Tasks</h2>
93
101
  <!-- task 2171: the To do / Completed toggle is built by
94
102
  OTBKit.makeTabs (hash:false — the #/goal/N sub-route
95
103
  namespace stays untouched; tabs key off in-page state). -->
96
104
  <div class="goal-work__tabs" id="goal-work-tabs" aria-label="Goal tasks"></div>
97
105
  </div>
98
106
  <div id="goal-todo-pane" role="tabpanel" aria-labelledby="tab-todo">
99
- <!-- task 1828 — Kind / Status / Credits headers sort the list (click
100
- cycles desc → asc → natural); a ready row carries an inline Claim. -->
101
- <table class="ledger" id="goal-todo"><thead><tr>
102
- <th>№</th><th>Task</th>
103
- <th class="ledger__sortable" id="goal-todo-sort-kind" role="button" tabindex="0" aria-sort="none">Kind</th>
104
- <th class="ledger__sortable" id="goal-todo-sort-status" role="button" tabindex="0" aria-sort="none">Status</th>
105
- <th class="ledger__sortable" id="goal-todo-sort-credits" role="button" tabindex="0" aria-sort="none" data-currency-tmpl="{Label} Est." title="Estimated reward — the actual payout is set when the task ships">Credits Est.</th>
106
- <th aria-label="Actions"></th>
107
- </tr></thead>
108
- <tbody><tr><td colspan="6" class="ledger__empty">…</td></tr></tbody></table>
107
+ <!-- task 1002425 — the To-do pane mirrors the Tasks board's Ready
108
+ queue so a goal's tasks have the same functionality as the board:
109
+ a shared filter bar → rich claimable cards → multi-select with
110
+ bulk claim → per-card copy-prompt, all opening the same task
111
+ overlay. Scoped to this goal, so no Version/Goal filters (they'd
112
+ be redundant). Sorting moved from the old column headers onto the
113
+ filter bar's Sort control (matching the board). -->
114
+ <div id="goal-work-filters"></div>
115
+ <p class="claim-count-line" id="goal-todo-count" aria-live="polite"></p>
116
+ <div class="task-list" id="goal-todo-list">
117
+ <div class="profile__placeholder">…</div>
118
+ </div>
109
119
  <div id="goal-todo-pager-mount"></div>
110
120
  </div>
111
121
  <div id="goal-done-pane" role="tabpanel" aria-labelledby="tab-done" hidden>
@@ -119,6 +129,21 @@
119
129
  <div id="goal-done-pager-mount"></div>
120
130
  </div>
121
131
  </div>
132
+
133
+ <!-- task 1002425 — bulk-action toolbar for the goal's task cards,
134
+ mirroring the Tasks board's toolbar. Hidden until 1+ ready cards are
135
+ selected. position:fixed (via .bulk-toolbar in work.css) so its DOM
136
+ location here is immaterial; it lives inside the detail view so it's
137
+ scoped to this route and cleared on route change. Bulk claim is the
138
+ headline action; bulk release + copy parallel/sequential prompts
139
+ stay board-only for now (noted follow-up). -->
140
+ <div id="goal-bulk-toolbar" class="bulk-toolbar" hidden role="region" aria-label="Bulk actions">
141
+ <span class="bulk-toolbar__count" id="goal-bulk-count"></span>
142
+ <div class="bulk-toolbar__actions">
143
+ <button type="button" class="bulk-toolbar__btn" id="goal-bulk-claim-btn">Bulk claim</button>
144
+ </div>
145
+ <button type="button" class="bulk-toolbar__clear" id="goal-bulk-clear-btn">Clear</button>
146
+ </div>
122
147
  </section>
123
148
 
124
149
  <!-- CONFLICTS full view (hash-routed: #/goal/N/conflicts) — the whole
@@ -164,6 +189,8 @@
164
189
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
165
190
 
166
191
  <script src="/builders/shell.js?v=2026-07-03-goals1"></script>
192
+ <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
193
+ <script src="/builders/palette.js" defer></script>
167
194
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
168
195
  <!-- shared component kit (window.OTBKit) — pager, filter bar, tabs, empty/skeleton (task 2166). -->
169
196
  <script src="/builders/hall-kit.js"></script>
@@ -3,13 +3,21 @@
3
3
  // Every widget — core here, module-contributed from a module's own client script —
4
4
  // registers into the window.OTB hall-widget registry (dom-utils.js), and builders.js
5
5
  // mounts the registered set into the shell's view containers (task 1723 redesign):
6
- // view: 'home' | 'standing' | 'achievements' | 'leaderboard' (default 'home')
7
- // zone: a finer mount target inside the Home view
8
- // ('home-banner' | 'home-stats' | 'home-band' | 'home-main')
9
- // Both fields ride the registry entry untouched; builders.js resolves them to the
10
- // #zone-* containers in index.html and falls back to <main> when absent, so a
6
+ // view: 'home' | 'standing' | 'leaderboard' (default 'home')
7
+ // zone: a finer mount target inside the Home view
8
+ // ('home-banner' | 'home-stats' | 'home-band' | 'home-main')
9
+ // group: a finer mount target inside Standing — which rail section this card
10
+ // belongs to ('work' | 'karma' | 'progress' | 'achievements', task 2174).
11
+ // All three ride the registry entry untouched; builders.js resolves them to the
12
+ // #zone-*/#standing-* containers and falls back to <main> when absent, so a
11
13
  // module widget written before the redesign still lands (on Home).
12
14
  //
15
+ // task 2174 — Standing is "one identity band, then rail-navigated sections grouped
16
+ // by question": the Profile card is the band, and every other Standing widget
17
+ // declares the `group` that answers its question. Achievements folded in from the
18
+ // retired #achievements hash view; the security-bounty rate card moved off Standing
19
+ // to /drachmae (a reward schedule is reference material, not personal standing).
20
+ //
13
21
  // Each widget owns its skeleton markup. mount(host) stamps that skeleton into the
14
22
  // registry-made <section>; builders.js then wires data to the same element ids it
15
23
  // always has (#profile-body, #recent-ships, …) — the data-rendering code is
@@ -27,9 +35,13 @@
27
35
  // setHtml — stamp a widget's skeleton into its host <section>. The host element
28
36
  // already carries the section's stable id + class (builders.js creates it from the
29
37
  // registry entry), so the skeleton is just the inner content.
38
+ // task 2177: `core: true` marks these as the hall's OWN cards, which exempts a
39
+ // home-main one from the summary/collapsed rule contributeHallWidget applies to
40
+ // everything else. It is a statement about provenance, not a privilege to grow —
41
+ // the zone budgets in builders.js still bind, and CI asserts them.
30
42
  const w = (id, label, order, html, opts) =>
31
43
  reg(Object.assign({
32
- id, label, order,
44
+ id, label, order, core: true,
33
45
  mount(host) { host.innerHTML = html; },
34
46
  }, opts || {}));
35
47
 
@@ -100,12 +112,15 @@
100
112
 
101
113
  /* ---------------- Standing ---------------- */
102
114
 
103
- // 1. Profile — the identity band at the top of Standing (#726).
115
+ // 1. Profile — the identity band at the top of Standing (#726). No `group`:
116
+ // the band sits above the rail sections and is never a rail entry.
104
117
  w('profile-scroll', 'Profile', 20,
105
118
  '<h2 id="profile-h" class="sr-only">Profile</h2>' +
106
119
  '<div class="profile" id="profile-body"><div class="profile__placeholder">…</div></div>',
107
120
  { view: 'standing', sectionClass: 'scroll scroll--profile', labelledby: 'profile-h' });
108
121
 
122
+ /* -- Work — "what have I shipped, and how was it judged" -- */
123
+
109
124
  // 2. WORKS — recent ships.
110
125
  w('ships-scroll', 'Your work', 30,
111
126
  '<h2 id="ships-h" class="scroll__h">Your work</h2>' +
@@ -124,66 +139,64 @@
124
139
  '</div>' +
125
140
  '<table class="ledger" id="recent-ships"><thead><tr><th>№</th><th>Work</th><th data-currency-label="caps">Credits</th><th>Shipped</th></tr></thead>' +
126
141
  '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>' +
127
- '<div class="pager" id="ships-pager" hidden>' +
128
- '<button class="btn-ghost" id="ships-prev" disabled>← earlier</button>' +
129
- '<span id="ships-range" class="pager__range">1–10</span>' +
130
- '<button class="btn-ghost" id="ships-next">later →</button>' +
131
- '</div>',
132
- { view: 'standing', labelledby: 'ships-h' });
142
+ // task 2174: the hand-rolled prev/next bar gives way to the OTBKit pager
143
+ // (per-page select, page indicator, clamping) — same #ships-* id prefix.
144
+ window.OTBKit.pagerBarHtml('ships', { label: 'shipped work' }),
145
+ { view: 'standing', group: 'work', labelledby: 'ships-h' });
133
146
 
134
- // 3. CURVE — the builder's development curve (V3.R72 #291, C5).
135
- w('analytics-scroll', 'Progress', 40,
136
- '<h2 id="curve-h" class="scroll__h">Progress</h2>' +
137
- '<p class="scroll__lede">How your output has changed over time — work shipped, cost and time per work, and how reviews held up. <span id="curve-scope-note"></span></p>' +
138
- '<div class="curve" id="curve-body">' +
139
- '<div class="profile__placeholder" id="curve-empty" style="display:none;">Not enough shipped work yet to chart.</div>' +
140
- '<div class="curve__headline" id="curve-headline"></div>' +
141
- '<div class="curve__grid" id="curve-grid"></div>' +
142
- '<div class="curve__kinds" id="curve-kinds"></div>' +
143
- '</div>',
144
- { view: 'standing', labelledby: 'curve-h', hiddenByDefault: true });
145
-
146
- // 4. MARKS — review quality of recent output.
147
- w('grades-scroll', 'Reviews', 50,
147
+ // 3. MARKS — review quality of recent output.
148
+ w('grades-scroll', 'Reviews', 32,
148
149
  '<h2 id="marks-h" class="scroll__h">Reviews</h2>' +
149
150
  '<div class="profile__placeholder" id="marks-empty" style="display:none;">No work reviewed yet.</div>' +
150
151
  '<table class="ledger" id="recent-grades"><thead><tr><th>№</th><th>Work</th><th>Score</th><th>Verdict</th><th>Reviewed</th></tr></thead>' +
151
152
  '<tbody><tr><td colspan="5" class="ledger__empty">…</td></tr></tbody></table>' +
152
153
  '<p class="ledger__note" id="grades-rolling-note" hidden></p>',
153
- { view: 'standing', labelledby: 'marks-h' });
154
+ { view: 'standing', group: 'work', labelledby: 'marks-h' });
155
+
156
+ /* -- Karma — peer standing; one currency, one section -- */
154
157
 
155
- // 5. KARMA feed — V3.R26 (#246). Hidden until /me returns karma data.
156
- w('karma-scroll', 'Karma', 60,
158
+ // 4. KARMA feed — V3.R26 (#246). Hidden until /me returns karma data.
159
+ w('karma-scroll', 'Karma', 40,
157
160
  '<h2 id="karma-h" class="scroll__h">Karma</h2>' +
158
161
  '<p class="scroll__lede">Karma rewards good citizenship — ratified ideas, peer recognition, approvals. Distinct from ' + curLabel() + ', which counts work shipped.</p>' +
159
162
  '<table class="ledger" id="karma-feed"><thead><tr><th>When</th><th>Delta</th><th>Reason</th><th>Granted by</th></tr></thead>' +
160
163
  '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>',
161
- { view: 'standing', labelledby: 'karma-h', hiddenByDefault: true });
164
+ { view: 'standing', group: 'karma', labelledby: 'karma-h', hiddenByDefault: true });
162
165
 
163
- // 5b. Peer acclaim — V3.R25 (#245). Hidden until data.
164
- w('acclaim-scroll', 'Peer recognition', 70,
166
+ // 4b. Peer acclaim — V3.R25 (#245). Hidden until data.
167
+ w('acclaim-scroll', 'Peer recognition', 42,
165
168
  '<h2 id="acclaim-h" class="scroll__h">Peer recognition</h2>' +
166
169
  '<p class="scroll__lede">Recognize your peers’ finished work. A vote up (+) or down (−) shapes their karma after a one-week cooling period. You can’t vote on your own work.</p>' +
167
170
  '<table class="ledger" id="acclaim-feed"><thead><tr><th>Work</th><th>By</th><th>Votes</th><th>Your vote</th></tr></thead>' +
168
- '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>',
169
- { view: 'standing', labelledby: 'acclaim-h', hiddenByDefault: true });
171
+ '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>' +
172
+ // task 1002446: the last unpaged list in the hall. The feed is already
173
+ // client-side, so the kit's pager fits without touching the endpoint.
174
+ window.OTBKit.pagerBarHtml('acclaim', { label: 'entries' }),
175
+ { view: 'standing', group: 'karma', labelledby: 'acclaim-h', hiddenByDefault: true });
176
+
177
+ /* -- Progress — how the output has changed over time -- */
170
178
 
171
- // 6. BOUNTY — red-team rewards payout table (V3.R65 #284).
172
- w('bounty-scroll', 'Security bounties', 80,
173
- '<h2 id="bounty-h" class="scroll__h">Security bounties</h2>' +
174
- '<p class="scroll__lede">Find a flaw in the system’s own walls and report it — rewards are paid in ' + curLabel() + ' by severity. The numbers below are the live reward schedule. <a href="/diagrams">See how it fits the whole.</a></p>' +
175
- '<table class="ledger" id="bounty-table"><thead><tr><th>Severity</th><th data-currency-label="caps">Credits</th><th>What counts</th></tr></thead>' +
176
- '<tbody><tr><td colspan="3" class="ledger__empty">…</td></tr></tbody></table>',
177
- { view: 'standing', labelledby: 'bounty-h' });
179
+ // 5. CURVE — the builder's development curve (V3.R72 #291, C5).
180
+ w('analytics-scroll', 'Progress', 50,
181
+ '<h2 id="curve-h" class="scroll__h">Progress</h2>' +
182
+ '<p class="scroll__lede">How your output has changed over time — work shipped, cost and time per work, and how reviews held up. <span id="curve-scope-note"></span></p>' +
183
+ '<div class="curve" id="curve-body">' +
184
+ '<div class="profile__placeholder" id="curve-empty" style="display:none;">Not enough shipped work yet to chart.</div>' +
185
+ '<div class="curve__headline" id="curve-headline"></div>' +
186
+ '<div class="curve__grid" id="curve-grid"></div>' +
187
+ '<div class="curve__kinds" id="curve-kinds"></div>' +
188
+ '</div>',
189
+ { view: 'standing', group: 'progress', labelledby: 'curve-h', hiddenByDefault: true });
178
190
 
179
- /* ---------------- Achievements ---------------- */
191
+ /* -- Achievements — long-term progression (folded in from the retired
192
+ #achievements hash view, task 2174) -- */
180
193
 
181
- // 7. Achievements — long-term progression (#726).
182
- w('honours-scroll', 'Achievements', 85,
183
- '<h2 id="ach-h" class="sr-only">Achievements</h2>' +
194
+ // 6. Achievements (#726).
195
+ w('honours-scroll', 'Achievements', 60,
196
+ '<h2 id="ach-h" class="scroll__h">Achievements</h2>' +
184
197
  '<p class="scroll__lede">Eight achievements recognize sustained contribution. Earned ones are highlighted; the rest show what’s left to do.</p>' +
185
198
  '<div class="ach-grid" id="ach-grid"><div class="profile__placeholder">…</div></div>',
186
- { view: 'achievements', sectionClass: 'scroll scroll--bare', labelledby: 'ach-h' });
199
+ { view: 'standing', group: 'achievements', labelledby: 'ach-h' });
187
200
 
188
201
  /* ---------------- Leaderboard ---------------- */
189
202
 
@@ -197,10 +210,7 @@
197
210
  '<th class="ledger__sortable" id="lb-sort-karma" aria-sort="none" title="Sort by karma (peer recognition + approvals)">Karma</th>' +
198
211
  '<th class="ledger__sortable" id="lb-sort-tokens" aria-sort="none" title="Sort by tokens used across recorded sessions — efficiency is tokens ÷ credits (hover a row for tokens-per-drachma)">Tokens</th>' +
199
212
  '</tr></thead><tbody><tr><td colspan="6" class="ledger__empty">…</td></tr></tbody></table>' +
200
- '<div class="pager">' +
201
- '<button class="btn-ghost" id="lb-prev" disabled>← earlier</button>' +
202
- '<span id="lb-range" class="pager__range">1–10</span>' +
203
- '<button class="btn-ghost" id="lb-next">later →</button>' +
204
- '</div>',
213
+ // task 2174: OTBKit pager — same #lb-* id prefix as the bar it replaces.
214
+ window.OTBKit.pagerBarHtml('lb', { label: 'builders' }),
205
215
  { view: 'leaderboard', labelledby: 'lb-h' });
206
216
  })();
@@ -0,0 +1,123 @@
1
+ /* harbor.css — Page-local styles for the Harbor 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 harbor — built on the shared design system's
7
+ derived tokens only (no page-local colour values). Each builder's dev
8
+ box renders as a card whose top strip + pill carry its lifecycle state. */
9
+ .harbor-summary {
10
+ display: grid;
11
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
12
+ gap: 14px;
13
+ margin: 6px 0 22px;
14
+ }
15
+ .harbor-stat {
16
+ border: 1px solid var(--border);
17
+ border-radius: var(--radius);
18
+ background: var(--surface);
19
+ padding: 12px 14px;
20
+ }
21
+ .harbor-stat__label {
22
+ font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
23
+ font-weight: 600; color: var(--ink-faint);
24
+ }
25
+ .harbor-stat__value {
26
+ font-size: 22px; font-weight: 650; color: var(--ink);
27
+ font-variant-numeric: tabular-nums; margin-top: 2px;
28
+ }
29
+
30
+ /* The dock — the strip the box cards sit on. */
31
+ .harbor-dock {
32
+ display: grid;
33
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
34
+ gap: 16px;
35
+ padding: 18px;
36
+ border-radius: var(--radius);
37
+ border: 1px solid var(--border);
38
+ background: var(--surface-2);
39
+ }
40
+
41
+ .harbor-container {
42
+ border: 1px solid var(--border);
43
+ border-radius: var(--radius);
44
+ background: var(--surface);
45
+ overflow: hidden;
46
+ display: flex; flex-direction: column;
47
+ }
48
+ /* The state strip along the card's top, coloured by lifecycle state. */
49
+ .harbor-container__roof {
50
+ height: 4px;
51
+ background-color: var(--ok);
52
+ }
53
+ .harbor-container--parked .harbor-container__roof { background-color: var(--ink-faint); }
54
+ .harbor-container--pending .harbor-container__roof { background-color: var(--warn); }
55
+ .harbor-container--gone .harbor-container__roof { background-color: var(--border-strong); }
56
+ .harbor-container--error .harbor-container__roof { background-color: var(--danger); }
57
+ .harbor-container--blocked .harbor-container__roof { background-color: var(--danger); }
58
+
59
+ .harbor-container__body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
60
+ .harbor-container__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
61
+ .harbor-container__who { color: var(--ink); font-weight: 600; font-size: 14.5px; }
62
+ .harbor-container__rank { color: var(--ink-faint); font-size: 12px; margin-left: 6px; font-weight: 400; }
63
+
64
+ .harbor-pill {
65
+ font-size: 11px; font-weight: 600;
66
+ letter-spacing: 0.04em; text-transform: uppercase;
67
+ padding: 2px 9px; border-radius: 999px; white-space: nowrap;
68
+ border: 1px solid var(--border); color: var(--ink-soft); background: var(--surface-2);
69
+ }
70
+ .harbor-pill--active { background: var(--ok-weak); border-color: color-mix(in srgb, var(--ok) 30%, transparent); color: var(--ok); }
71
+ .harbor-pill--pending { background: var(--warn-weak); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn); }
72
+ .harbor-pill--blocked { background: var(--danger-weak); border-color: color-mix(in srgb, var(--danger) 30%, transparent); color: var(--danger); }
73
+
74
+ .harbor-rows { list-style: none; padding: 0; margin: 2px 0 0; }
75
+ .harbor-rows li {
76
+ display: flex; justify-content: space-between; gap: 12px;
77
+ padding: 4px 0; border-bottom: 1px solid var(--border);
78
+ font-size: 13px;
79
+ }
80
+ .harbor-rows li:last-child { border-bottom: none; }
81
+ .harbor-rows li .k { color: var(--ink-soft); }
82
+ .harbor-rows li .v { color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }
83
+
84
+ .harbor-blocked-note {
85
+ font-size: 12.5px; color: var(--danger);
86
+ border-left: 2px solid var(--danger); padding-left: 8px; margin: 2px 0 0;
87
+ }
88
+
89
+ .harbor-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 8px; }
90
+ .harbor-btn {
91
+ font: inherit; font-size: 12.5px; font-weight: 500;
92
+ padding: 5px 12px; border: 1px solid var(--border-strong);
93
+ background: var(--surface); color: var(--ink-soft);
94
+ border-radius: var(--radius-sm); cursor: pointer; flex: 1;
95
+ }
96
+ .harbor-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
97
+ .harbor-btn:disabled { opacity: 0.45; cursor: default; }
98
+ .harbor-btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
99
+
100
+ .harbor-empty, .harbor-sealed { color: var(--ink-soft); padding: 16px 0; }
101
+
102
+ /* Lightweight modal for confirm / block dialogs. Viewport-fixed overlay;
103
+ z-index sits above the shell's sidebar/drawer layers. */
104
+ .harbor-modal-bg {
105
+ position: fixed; inset: 0; background: color-mix(in srgb, var(--ink) 45%, transparent);
106
+ display: flex; align-items: center; justify-content: center; z-index: 200; padding: 20px;
107
+ }
108
+ .harbor-modal {
109
+ background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
110
+ max-width: 460px; width: 100%; padding: 20px 22px;
111
+ box-shadow: var(--shadow-pop);
112
+ }
113
+ .harbor-modal h2 { color: var(--ink); margin: 0 0 8px; font-size: 16px; font-weight: 650; }
114
+ .harbor-modal p { color: var(--ink); font-size: 13.5px; margin: 0 0 12px; }
115
+ .harbor-modal label { display: block; font-size: 13px; color: var(--ink-soft); margin: 10px 0 4px; }
116
+ .harbor-modal input[type=text], .harbor-modal textarea {
117
+ width: 100%; box-sizing: border-box; font: inherit; font-size: 13.5px;
118
+ padding: 7px 9px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
119
+ background: var(--surface); color: var(--ink);
120
+ }
121
+ .harbor-modal__check { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 0; font-size: 13px; color: var(--ink); }
122
+ .harbor-modal__check input { margin-top: 3px; }
123
+ .harbor-modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
@@ -10,126 +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 harbor — built on the shared design system's
15
- derived tokens only (no page-local colour values). Each builder's dev
16
- box renders as a card whose top strip + pill carry its lifecycle state. */
17
- .harbor-summary {
18
- display: grid;
19
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
20
- gap: 14px;
21
- margin: 6px 0 22px;
22
- }
23
- .harbor-stat {
24
- border: 1px solid var(--border);
25
- border-radius: var(--radius);
26
- background: var(--surface);
27
- padding: 12px 14px;
28
- }
29
- .harbor-stat__label {
30
- font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
31
- font-weight: 600; color: var(--ink-faint);
32
- }
33
- .harbor-stat__value {
34
- font-size: 22px; font-weight: 650; color: var(--ink);
35
- font-variant-numeric: tabular-nums; margin-top: 2px;
36
- }
37
-
38
- /* The dock — the strip the box cards sit on. */
39
- .harbor-dock {
40
- display: grid;
41
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
42
- gap: 16px;
43
- padding: 18px;
44
- border-radius: var(--radius);
45
- border: 1px solid var(--border);
46
- background: var(--surface-2);
47
- }
48
-
49
- .harbor-container {
50
- border: 1px solid var(--border);
51
- border-radius: var(--radius);
52
- background: var(--surface);
53
- overflow: hidden;
54
- display: flex; flex-direction: column;
55
- }
56
- /* The state strip along the card's top, coloured by lifecycle state. */
57
- .harbor-container__roof {
58
- height: 4px;
59
- background-color: var(--ok);
60
- }
61
- .harbor-container--parked .harbor-container__roof { background-color: var(--ink-faint); }
62
- .harbor-container--pending .harbor-container__roof { background-color: var(--warn); }
63
- .harbor-container--gone .harbor-container__roof { background-color: var(--border-strong); }
64
- .harbor-container--error .harbor-container__roof { background-color: var(--danger); }
65
- .harbor-container--blocked .harbor-container__roof { background-color: var(--danger); }
66
-
67
- .harbor-container__body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
68
- .harbor-container__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
69
- .harbor-container__who { color: var(--ink); font-weight: 600; font-size: 14.5px; }
70
- .harbor-container__rank { color: var(--ink-faint); font-size: 12px; margin-left: 6px; font-weight: 400; }
71
-
72
- .harbor-pill {
73
- font-size: 11px; font-weight: 600;
74
- letter-spacing: 0.04em; text-transform: uppercase;
75
- padding: 2px 9px; border-radius: 999px; white-space: nowrap;
76
- border: 1px solid var(--border); color: var(--ink-soft); background: var(--surface-2);
77
- }
78
- .harbor-pill--active { background: var(--ok-weak); border-color: color-mix(in srgb, var(--ok) 30%, transparent); color: var(--ok); }
79
- .harbor-pill--pending { background: var(--warn-weak); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn); }
80
- .harbor-pill--blocked { background: var(--danger-weak); border-color: color-mix(in srgb, var(--danger) 30%, transparent); color: var(--danger); }
81
-
82
- .harbor-rows { list-style: none; padding: 0; margin: 2px 0 0; }
83
- .harbor-rows li {
84
- display: flex; justify-content: space-between; gap: 12px;
85
- padding: 4px 0; border-bottom: 1px solid var(--border);
86
- font-size: 13px;
87
- }
88
- .harbor-rows li:last-child { border-bottom: none; }
89
- .harbor-rows li .k { color: var(--ink-soft); }
90
- .harbor-rows li .v { color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }
91
-
92
- .harbor-blocked-note {
93
- font-size: 12.5px; color: var(--danger);
94
- border-left: 2px solid var(--danger); padding-left: 8px; margin: 2px 0 0;
95
- }
96
-
97
- .harbor-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 8px; }
98
- .harbor-btn {
99
- font: inherit; font-size: 12.5px; font-weight: 500;
100
- padding: 5px 12px; border: 1px solid var(--border-strong);
101
- background: var(--surface); color: var(--ink-soft);
102
- border-radius: var(--radius-sm); cursor: pointer; flex: 1;
103
- }
104
- .harbor-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
105
- .harbor-btn:disabled { opacity: 0.45; cursor: default; }
106
- .harbor-btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
107
-
108
- .harbor-empty, .harbor-sealed { color: var(--ink-soft); padding: 16px 0; }
109
-
110
- /* Lightweight modal for confirm / block dialogs. Viewport-fixed overlay;
111
- z-index sits above the shell's sidebar/drawer layers. */
112
- .harbor-modal-bg {
113
- position: fixed; inset: 0; background: color-mix(in srgb, var(--ink) 45%, transparent);
114
- display: flex; align-items: center; justify-content: center; z-index: 200; padding: 20px;
115
- }
116
- .harbor-modal {
117
- background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
118
- max-width: 460px; width: 100%; padding: 20px 22px;
119
- box-shadow: var(--shadow-pop);
120
- }
121
- .harbor-modal h2 { color: var(--ink); margin: 0 0 8px; font-size: 16px; font-weight: 650; }
122
- .harbor-modal p { color: var(--ink); font-size: 13.5px; margin: 0 0 12px; }
123
- .harbor-modal label { display: block; font-size: 13px; color: var(--ink-soft); margin: 10px 0 4px; }
124
- .harbor-modal input[type=text], .harbor-modal textarea {
125
- width: 100%; box-sizing: border-box; font: inherit; font-size: 13.5px;
126
- padding: 7px 9px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
127
- background: var(--surface); color: var(--ink);
128
- }
129
- .harbor-modal__check { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 0; font-size: 13px; color: var(--ink); }
130
- .harbor-modal__check input { margin-top: 3px; }
131
- .harbor-modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
132
- </style>
13
+ <link rel="stylesheet" href="/builders/harbor.css">
133
14
  </head>
134
15
  <body data-page="harbor" data-page-title="Harbor">
135
16
 
@@ -161,6 +42,8 @@
161
42
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
162
43
 
163
44
  <script src="/builders/shell.js?v=2026-07-02-shell1"></script>
45
+ <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
46
+ <script src="/builders/palette.js" defer></script>
164
47
  <script src="/builders/dom-utils.js?v=2026-06-16-harbor"></script>
165
48
  <script src="/builders/harbor.js?v=2026-06-16-harbor"></script>
166
49
  </body>