@bongos/core 1.19.725 → 1.19.727

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 (229) hide show
  1. package/.bongos-core.json +179 -494
  2. package/.devcontainer/Dockerfile +1 -1
  3. package/.devcontainer/devcontainer.json +2 -2
  4. package/.devcontainer/healthcheck.sh +1 -1
  5. package/.devcontainer/init-firewall.sh +1 -1
  6. package/.devcontainer/post-create.sh +2 -2
  7. package/.env.local.example +1 -1
  8. package/Dockerfile +1 -1
  9. package/docs/copy-inventory.md +1 -1
  10. package/docs/copy-registry.json +9 -9
  11. package/docs/module-api-changelog.md +4 -0
  12. package/docs/recipes/devbox-app-release.md +4 -4
  13. package/modules/dev-box/app/scripts/dmgbuild-settings.py +5 -5
  14. package/modules/dev-box/app/scripts/gen-brand.js +1 -1
  15. package/modules/dev-box/app/src/brand.js +1 -1
  16. package/modules/dev-box/app/test/unit.mjs +16 -16
  17. package/modules/dev-box/box-access.js +1 -1
  18. package/modules/dev-box/routes/box.js +1 -1
  19. package/modules/discord/discord-approvals.js +1 -1
  20. package/modules/grading/grader-model.js +1 -1
  21. package/modules/grading/grader-prompt.js +1 -1
  22. package/modules/grading/grader-workers/quality.js +1 -1
  23. package/modules/hall-ui/module.json +1 -1
  24. package/modules/hall-ui/public/brand-apply.js +1 -1
  25. package/modules/hall-ui/public/shell.js +1 -1
  26. package/modules/hall-ui/public/work.js +1 -1
  27. package/modules/lifecycle/conflict-resolve.js +1 -1
  28. package/modules/lifecycle/db-analytics.js +1 -1
  29. package/modules/lifecycle/routes/analytics.js +1 -1
  30. package/modules/onboarding/approval-broadcast.js +1 -1
  31. package/modules/onboarding/onboarding.js +1 -1
  32. package/modules/provisioning/tests/liveness.mjs +1 -1
  33. package/modules/public-landing/public/index.html +1 -1
  34. package/modules/public-landing/public/projects-floor.states.json +2 -2
  35. package/modules/public-landing/public/projects.probes.json +4 -4
  36. package/modules/public-landing/public/projects.states.json +2 -2
  37. package/modules/status-ui/module.json +1 -1
  38. package/modules/status-ui/public/status.js +4 -4
  39. package/modules/status-ui/public/style.css +1 -1
  40. package/modules/ui-design/kit/fixtures/cost-summary.json +1 -1
  41. package/modules/ui-design/kit/fixtures/featured-hub.json +1 -1
  42. package/modules/ui-design/kit/fixtures/featured.json +1 -1
  43. package/modules/ui-design/kit/fixtures/leaderboard.json +1 -1
  44. package/modules/ui-design/kit/fixtures/my-projects.json +1 -1
  45. package/modules/ui-design/kit/fixtures/progress.json +1 -1
  46. package/modules/ui-design/kit/fixtures/recent-shipped.json +1 -1
  47. package/package-lock.json +2 -2
  48. package/package.json +1 -1
  49. package/scripts/cron/style_guide_audit.sh +1 -1
  50. package/scripts/discord/lib.js +1 -1
  51. package/scripts/discord/post.js +1 -1
  52. package/scripts/gds/audit-authorship.sh +1 -1
  53. package/scripts/gds/audit-replay.sh +29 -2
  54. package/scripts/gds/audit-ships.js +1 -1
  55. package/scripts/gds/backfill-sessions.js +2 -2
  56. package/scripts/gds/cf-tunnel.js +4 -4
  57. package/scripts/gds/claude-materialize.js +2 -2
  58. package/scripts/gds/cli-lib.js +6 -6
  59. package/scripts/gds/cutover-codemod.js +1 -1
  60. package/scripts/gds/dev-lib.js +2 -2
  61. package/scripts/gds/diagnose-achievements.js +2 -2
  62. package/scripts/gds/fitness-checks-identity.js +6 -4
  63. package/scripts/gds/gate-review.js +14 -6
  64. package/scripts/gds/gen-diagrams.js +1 -1
  65. package/scripts/gds/leak-scan-allowlist.js +293 -0
  66. package/scripts/gds/learning-capture.js +1 -1
  67. package/scripts/gds/linkify-refs.js +2 -2
  68. package/scripts/gds/local-preview-lib.js +1 -1
  69. package/scripts/gds/mirror-lineage-check.js +1 -1
  70. package/scripts/gds/mirror-redact.js +17 -2
  71. package/scripts/gds/newcomer-floor.templates.json +1 -1
  72. package/scripts/gds/package-core.js +18 -1
  73. package/scripts/gds/paste-token.js +1 -1
  74. package/scripts/gds/provision-units.js +2 -2
  75. package/scripts/gds/publish-manifest.js +15 -0
  76. package/scripts/gds/repo-metrics.js +1 -1
  77. package/scripts/gds/sandbox-stage.js +1 -1
  78. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +1 -1
  79. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +1 -1
  80. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +1 -1
  81. package/scripts/gds/seed-bongos-tasks.js +2 -2
  82. package/scripts/gds/seed-gds-v4-tasks.js +1 -1
  83. package/scripts/gds/seed-medusa-tasks.js +10 -10
  84. package/scripts/gds/seed-module-upstreaming.js +1 -1
  85. package/scripts/gds/seed-productization-tasks.js +6 -6
  86. package/scripts/gds/seed-provisioning-tasks.js +2 -2
  87. package/scripts/gds/seed-staging.sh +19 -6
  88. package/scripts/gds/ship-deploy-target.js +1 -1
  89. package/scripts/gds/ship-flow.js +1 -1
  90. package/scripts/gds/smoke-gds.js +1 -1
  91. package/scripts/status-probe.mjs +2 -2
  92. package/src/bongos/auth-discord.js +2 -2
  93. package/src/bongos/live-channel.js +1 -1
  94. package/src/bongos/permission-path-check.js +80 -3
  95. package/src/bongos/pool.js +1 -1
  96. package/src/bongos/routes/auth.js +11 -11
  97. package/src/bongos/routes/security.js +1 -1
  98. package/src/bongos/routes.js +1 -1
  99. package/src/branding.js +1 -1
  100. package/src/devbox-downloads.js +1 -1
  101. package/src/instance-config.js +2 -2
  102. package/src/module-api.js +1 -1
  103. package/src/module-loader/provenance.js +2 -2
  104. package/tests/art_stage.mjs +2 -2
  105. package/tests/auth_anthropic_identity.mjs +1 -1
  106. package/tests/auth_duplicate_cookie.mjs +1 -1
  107. package/tests/auth_error_brand.mjs +1 -1
  108. package/tests/auth_inactive_builder.mjs +1 -1
  109. package/tests/backup_cli.mjs +4 -4
  110. package/tests/bongos_box_connect.mjs +2 -2
  111. package/tests/bongos_downloads.mjs +2 -2
  112. package/tests/bongos_login.mjs +5 -5
  113. package/tests/box_connect_e2e.mjs +2 -2
  114. package/tests/box_dns_repoint.mjs +10 -10
  115. package/tests/box_host_keys.mjs +1 -1
  116. package/tests/box_onboard.mjs +9 -9
  117. package/tests/box_scope_session.mjs +1 -1
  118. package/tests/box_terminal_ssrf.mjs +7 -7
  119. package/tests/boxes.mjs +9 -9
  120. package/tests/branding.mjs +2 -2
  121. package/tests/bump_version.mjs +2 -2
  122. package/tests/cf_tunnel.mjs +40 -40
  123. package/tests/cli_token_reissue.mjs +7 -7
  124. package/tests/cloud_bongos_pack.mjs +1 -1
  125. package/tests/currency_label.mjs +8 -8
  126. package/tests/dev_lib.mjs +4 -4
  127. package/tests/devbox_dmg_backdrop.mjs +1 -1
  128. package/tests/devbox_downloads.mjs +2 -2
  129. package/tests/devbox_icons.mjs +1 -1
  130. package/tests/discord_approvals.mjs +1 -1
  131. package/tests/discord_oauth.mjs +2 -2
  132. package/tests/executed_closure.mjs +6 -1
  133. package/tests/first_admin_bootstrap.mjs +1 -1
  134. package/tests/gate_approvals.mjs +5 -5
  135. package/tests/government_protected_surfaces.mjs +137 -0
  136. package/tests/grade_aggregates_unavailable.mjs +1 -1
  137. package/tests/hook_user_agents.mjs +2 -2
  138. package/tests/init.mjs +6 -6
  139. package/tests/instance_config.mjs +1 -1
  140. package/tests/instance_manifest.mjs +5 -5
  141. package/tests/instance_mismatch_guard.mjs +13 -13
  142. package/tests/leak_scan_allowlist.mjs +94 -0
  143. package/tests/migrate_root_resolution.mjs +4 -4
  144. package/tests/mirror_redact.mjs +28 -4
  145. package/tests/module_catalog.mjs +5 -5
  146. package/tests/module_submissions.mjs +3 -3
  147. package/tests/package_core.mjs +1 -1
  148. package/tests/parallel-load.mjs +6 -6
  149. package/tests/projects_hub.mjs +2 -2
  150. package/tests/provision.mjs +50 -50
  151. package/tests/provisioning_github_app_routes.mjs +1 -1
  152. package/tests/provisioning_onboard_mode.mjs +2 -2
  153. package/tests/publish_reconciler.mjs +4 -4
  154. package/tests/sandbox_stage.mjs +1 -1
  155. package/tests/scrubber_corpus.mjs +3 -3
  156. package/tests/search_isolation.mjs +1 -1
  157. package/tests/session_records.mjs +1 -1
  158. package/tests/ship_card.mjs +6 -6
  159. package/tests/ship_ci_deploy.mjs +1 -1
  160. package/tests/single_host_hall.mjs +9 -9
  161. package/tests/smoke_preflight.mjs +1 -1
  162. package/tests/smoke_target.mjs +1 -1
  163. package/tests/status-probe.mjs +1 -1
  164. package/tests/status_mirror_sync.mjs +1 -1
  165. package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +0 -45
  166. package/docs/design/mocks/_schemes.css +0 -604
  167. package/docs/design/mocks/component-sheet.html +0 -428
  168. package/docs/design/mocks/hall/_tokens.css +0 -370
  169. package/docs/design/mocks/hall/board/v1.html +0 -846
  170. package/docs/design/mocks/hall/board/v2.html +0 -858
  171. package/docs/design/mocks/hall/board/v3.html +0 -884
  172. package/docs/design/mocks/hall/goals/v1.html +0 -1212
  173. package/docs/design/mocks/hall/goals/v2.html +0 -1192
  174. package/docs/design/mocks/hall/goals/v3.html +0 -1205
  175. package/docs/design/mocks/hall/hall-sheet.html +0 -244
  176. package/docs/design/mocks/hall/reading/v1.html +0 -1125
  177. package/docs/design/mocks/hall/reading/v2.html +0 -1177
  178. package/docs/design/mocks/hall/reading/v3.html +0 -1150
  179. package/docs/design/mocks/hall/settings/v1.html +0 -1238
  180. package/docs/design/mocks/hall/settings/v2.html +0 -1235
  181. package/docs/design/mocks/hall/settings/v3.html +0 -1299
  182. package/docs/design/mocks/hall/task/v1.html +0 -633
  183. package/docs/design/mocks/hall/task/v2.html +0 -646
  184. package/docs/design/mocks/hall/task/v3.html +0 -647
  185. package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg +0 -0
  186. package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg.json +0 -13
  187. package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg +0 -0
  188. package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg.json +0 -13
  189. package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg +0 -0
  190. package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg.json +0 -13
  191. package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg +0 -0
  192. package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg.json +0 -13
  193. package/docs/design/mocks/hub/hub-sheet.html +0 -192
  194. package/docs/design/mocks/hub/mine.html +0 -465
  195. package/docs/design/mocks/hub/picker.html +0 -421
  196. package/docs/design/mocks/hub/planets.html +0 -356
  197. package/docs/design/mocks/hub/v1.html +0 -1209
  198. package/docs/design/mocks/hub/v2.html +0 -1257
  199. package/docs/design/mocks/hub/v3.html +0 -1496
  200. package/docs/design/mocks/hub/wizard.html +0 -421
  201. package/docs/design/mocks/landing/landing-sheet.html +0 -131
  202. package/docs/design/mocks/landing/v1.html +0 -956
  203. package/docs/design/mocks/landing/v2.html +0 -708
  204. package/docs/design/mocks/landing/v3.html +0 -911
  205. package/docs/design/mocks/landing-page-mock.html +0 -687
  206. package/docs/design/mocks/landing-palettes.html +0 -103
  207. package/docs/design/mocks/projects-hub-mock.html +0 -991
  208. package/docs/design/mocks/projects-hub-variants.html +0 -146
  209. package/docs/design/mocks/projects-page-mock.html +0 -167
  210. package/docs/design/mocks/world/blue-hud/_tokens.css +0 -246
  211. package/docs/design/mocks/world/blue-hud/hall.html +0 -595
  212. package/docs/design/mocks/world/blue-hud/landing.html +0 -424
  213. package/docs/design/mocks/world/blue-hud/status.html +0 -410
  214. package/docs/design/mocks/world/chrome-blobs/_tokens.css +0 -479
  215. package/docs/design/mocks/world/chrome-blobs/hall.html +0 -553
  216. package/docs/design/mocks/world/chrome-blobs/landing-b.html +0 -581
  217. package/docs/design/mocks/world/chrome-blobs/landing.html +0 -328
  218. package/docs/design/mocks/world/chrome-blobs/status.html +0 -416
  219. package/docs/design/mocks/world/natgeo-editorial/_tokens.css +0 -377
  220. package/docs/design/mocks/world/natgeo-editorial/hall.html +0 -649
  221. package/docs/design/mocks/world/natgeo-editorial/landing-b.html +0 -743
  222. package/docs/design/mocks/world/natgeo-editorial/landing.html +0 -475
  223. package/docs/design/mocks/world/natgeo-editorial/status.html +0 -437
  224. package/docs/design/mocks/world/organic-cards/_tokens.css +0 -462
  225. package/docs/design/mocks/world/organic-cards/hall.html +0 -625
  226. package/docs/design/mocks/world/organic-cards/landing-b.html +0 -736
  227. package/docs/design/mocks/world/organic-cards/landing.html +0 -420
  228. package/docs/design/mocks/world/organic-cards/status.html +0 -458
  229. package/docs/design/mocks/world/world-sheet.html +0 -156
@@ -1,1150 +0,0 @@
1
- <!doctype html>
2
- <html lang="en" data-mode="dark" data-theme="dark">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <title>Reading room, the hall in the world: v3 "the glass hall" (task 1003302)</title>
7
- <link rel="icon" href="data:,">
8
- <link rel="preconnect" href="https://fonts.googleapis.com">
9
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
11
- <link rel="stylesheet" href="../_tokens.css">
12
- <style>
13
- /* ---------------------------------------------------------------------------
14
- READING ROOM, v3 "the glass hall". In dark the hall's own rendered plate sits
15
- behind the whole shell under --plate-veil; the sidebar and the topbar are
16
- glass over it; the article is a --bg-card card at --radius so ink never lands
17
- on the plate. The sidebar is the 64px rail at every width and expands on
18
- hover or focus-within. In light there is no plate: light is the same room on
19
- paper, never a black panel, so --plate and --plate-veil resolve to none and
20
- the ground is simply the page.
21
-
22
- THE PLATE IS A TOKEN, NOT A FILE. --plate is `none` in ../_tokens.css until
23
- the hall's own plate is shot, and this composition is complete without it:
24
- the ground then reads as the flat void, which is the honest fallback and what
25
- light shows anyway. Nothing here needs the image to arrive.
26
- --------------------------------------------------------------------------- */
27
-
28
- *, *::before, *::after { box-sizing: border-box; }
29
- html { -webkit-text-size-adjust: 100%; }
30
-
31
- body {
32
- /* ---- the composition tokens for v3 ---- */
33
- --gutter: clamp(22px, 3.2vw, 52px);
34
- --shell-pad: 24px; /* 24 puts a 16px icon dead centre in the 64px rail */
35
- --rail-open: 268px;
36
- --toc-w: 246px;
37
- --col-gap: 34px;
38
- --card-pad: clamp(24px, 3.4vw, 58px);
39
- /* the measure is set in ch, but a `ch` is Manrope's ZERO, which is much wider
40
- than its average lowercase: 58ch measured 72 rendered characters. These are
41
- tuned against the rendered count, which is what the world's 56 to 62 means. */
42
- --measure: 49ch; /* the prose column: 60 rendered characters */
43
- --body-size: 17.5px;
44
- --body-lead: 1.78; /* the light face needs the extra leading over a ground */
45
- --h1-size: clamp(36px, 4.6vw, 58px);
46
- --h2-size: clamp(26px, 2.8vw, 36px);
47
- --h3-size: 20px;
48
-
49
- margin: 0;
50
- min-height: 100dvh;
51
- display: grid;
52
- grid-template-columns: var(--sidebar-w-rail) minmax(0, 1fr);
53
- grid-template-rows: auto minmax(0, 1fr);
54
- background: var(--bg);
55
- color: var(--ink);
56
- font-family: var(--font-body);
57
- font-size: var(--body-size);
58
- line-height: var(--body-lead);
59
- -webkit-font-smoothing: antialiased;
60
- }
61
-
62
- /* ---------- the ground: one rendered plate behind the whole shell ----------
63
- dark composites the black plate with lighten over the black ground and lays
64
- --plate-veil over it. Light has neither token, so this layer paints the page
65
- ground and disappears. */
66
-
67
- .app-plate {
68
- position: fixed; inset: 0; z-index: 0; pointer-events: none;
69
- background-color: var(--bg);
70
- background-image: var(--plate);
71
- background-size: cover;
72
- background-position: center;
73
- background-blend-mode: var(--plate-blend);
74
- }
75
- .app-plate::after {
76
- content: ""; position: absolute; inset: 0;
77
- background: var(--plate-veil);
78
- }
79
-
80
- /* ---------- shared atoms ---------- */
81
-
82
- .u-sr {
83
- position: absolute; width: 1px; height: 1px; margin: -1px;
84
- padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
85
- }
86
- .num { font-variant-numeric: tabular-nums; }
87
- .label {
88
- font: 400 var(--label-size)/1.25 var(--label-face);
89
- letter-spacing: var(--label-space);
90
- text-transform: var(--label-case);
91
- color: var(--ink-faint);
92
- }
93
- .nav-icon, .topbar-icon, .foot-icon {
94
- width: 16px; height: 16px; flex: none;
95
- fill: none; stroke: currentColor; stroke-width: 1.4;
96
- stroke-linecap: round; stroke-linejoin: round;
97
- }
98
-
99
- .skip {
100
- position: absolute; left: var(--sp-sm); top: -60px; z-index: 200;
101
- display: inline-flex; align-items: center; min-height: 34px;
102
- padding: 6px 18px; border-radius: var(--radius-pill);
103
- background: var(--bg-card); color: var(--ink);
104
- border: var(--line) solid var(--rule); text-decoration: none; font-size: 14px;
105
- transition: top 200ms cubic-bezier(.2, .7, .3, 1);
106
- }
107
- .skip:focus { top: var(--sp-xs); }
108
-
109
- /* ---------- the focus treatment ---------- */
110
-
111
- :focus-visible,
112
- body[data-state="focus"] .is-focus {
113
- outline: 2px solid var(--focus);
114
- outline-offset: 3px;
115
- box-shadow: 0 0 0 8px var(--bg);
116
- border-radius: 4px;
117
- }
118
-
119
- /* ---------- the sidebar: glass, and the 64px rail at every width ---------- */
120
-
121
- .app-sidebar {
122
- position: fixed; top: 0; left: 0; bottom: 0;
123
- width: var(--sidebar-w-rail);
124
- display: flex; flex-direction: column; min-height: 0;
125
- overflow: hidden; /* the sidebar never scrolls: its nav does */
126
- background: var(--glass);
127
- -webkit-backdrop-filter: blur(var(--glass-blur));
128
- backdrop-filter: blur(var(--glass-blur));
129
- border-right: var(--line) solid var(--glass-edge);
130
- z-index: var(--z-sidebar);
131
- transition: width 300ms cubic-bezier(.2, .7, .3, 1);
132
- }
133
- .app-sidebar:hover, .app-sidebar:focus-within { width: var(--rail-open); }
134
- /* ?state=rail pins the rail shut, so a reviewer can read the closed state */
135
- body[data-state="rail"] .app-sidebar:hover,
136
- body[data-state="rail"] .app-sidebar:focus-within { width: var(--sidebar-w-rail); }
137
-
138
- .app-sidebar__brand {
139
- flex: none; height: var(--topbar-h);
140
- display: flex; align-items: center;
141
- padding: 0 var(--shell-pad);
142
- border-bottom: var(--line) solid var(--glass-edge);
143
- }
144
- .brand-mark {
145
- display: flex; align-items: center; gap: 11px;
146
- min-height: 30px; padding: 3px 0;
147
- color: var(--ink); text-decoration: none;
148
- font-weight: 500; font-size: 15.5px; letter-spacing: -.015em;
149
- }
150
- .brand-mark__dot {
151
- width: 12px; height: 12px; flex: none; margin-left: 2px;
152
- border: 2px solid var(--ink); border-radius: var(--radius-pill);
153
- }
154
-
155
- .app-sidebar__nav {
156
- flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
157
- padding: var(--sp-sm) 0 var(--sp-md);
158
- }
159
- .nav-group { padding-bottom: var(--sp-xs); }
160
- .nav-group + .nav-group {
161
- margin-top: var(--sp-xs); padding-top: var(--sp-xs);
162
- border-top: var(--line) solid var(--glass-edge);
163
- }
164
- .nav-group__head {
165
- display: flex; align-items: center; justify-content: space-between; gap: 8px;
166
- width: 100%; min-height: 26px; padding: 4px var(--shell-pad) 6px; margin: 0;
167
- background: none; border: 0; cursor: pointer;
168
- font: 400 var(--label-size)/1.25 var(--label-face);
169
- letter-spacing: var(--label-space); text-transform: var(--label-case);
170
- color: var(--ink-faint);
171
- }
172
- .nav-group__chevron {
173
- width: 10px; height: 6px; flex: none;
174
- fill: none; stroke: currentColor; stroke-width: 1.4;
175
- stroke-linecap: round; stroke-linejoin: round;
176
- }
177
- .nav-item {
178
- text-transform: lowercase;
179
- display: flex; align-items: center; gap: 11px;
180
- min-height: 38px; padding: 6px var(--shell-pad);
181
- border-left: 2px solid transparent;
182
- color: var(--ink-soft); text-decoration: none; font-size: 14.5px;
183
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
184
- }
185
- .nav-item:hover { color: var(--ink); }
186
- .nav-item--active { color: var(--ink); border-left-color: var(--accent); }
187
- /* the rail hides the words rather than removing them, so the expansion is a
188
- reveal and never a relayout */
189
- .nav-item__label, .nav-group__head-label, .nav-group__chevron, .brand-mark__name,
190
- .shell-user__meta {
191
- white-space: nowrap; opacity: 0;
192
- transition: opacity 200ms cubic-bezier(.2, .7, .3, 1);
193
- }
194
- .app-sidebar:hover .nav-item__label,
195
- .app-sidebar:hover .nav-group__head-label,
196
- .app-sidebar:hover .nav-group__chevron,
197
- .app-sidebar:hover .brand-mark__name,
198
- .app-sidebar:hover .shell-user__meta,
199
- .app-sidebar:focus-within .nav-item__label,
200
- .app-sidebar:focus-within .nav-group__head-label,
201
- .app-sidebar:focus-within .nav-group__chevron,
202
- .app-sidebar:focus-within .brand-mark__name,
203
- .app-sidebar:focus-within .shell-user__meta { opacity: 1; }
204
- body[data-state="rail"] .app-sidebar:hover .nav-item__label,
205
- body[data-state="rail"] .app-sidebar:hover .nav-group__head-label,
206
- body[data-state="rail"] .app-sidebar:hover .nav-group__chevron,
207
- body[data-state="rail"] .app-sidebar:hover .brand-mark__name,
208
- body[data-state="rail"] .app-sidebar:hover .shell-user__meta { opacity: 0; }
209
-
210
- .app-sidebar__foot {
211
- flex: none; display: flex; flex-direction: column; align-items: center; gap: 6px;
212
- padding: var(--sp-xs) 16px;
213
- border-top: var(--line) solid var(--glass-edge);
214
- }
215
- /* the closed rail is 32px of room inside its padding, which a row of three
216
- controls cannot hold, so the foot stacks until the rail opens */
217
- .app-sidebar:hover .app-sidebar__foot,
218
- .app-sidebar:focus-within .app-sidebar__foot { flex-direction: row; }
219
- body[data-state="rail"] .app-sidebar:hover .app-sidebar__foot { flex-direction: column; }
220
- .shell-user {
221
- /* max-width keeps the chip inside the closed rail: without it the flex box
222
- is its open width and the avatar centres itself off the left edge */
223
- flex: 1 1 auto; min-width: 0; max-width: 100%; overflow: hidden;
224
- display: flex; align-items: center; gap: 10px;
225
- min-height: 40px; padding: 2px 0;
226
- color: var(--ink); text-decoration: none;
227
- }
228
- .shell-user__avatar {
229
- width: 32px; height: 32px; flex: none; border-radius: var(--radius-pill);
230
- background: var(--glass-strong);
231
- border: var(--line) solid var(--glass-edge);
232
- }
233
- .shell-user__meta { display: flex; flex-direction: column; min-width: 0; }
234
- .shell-user__name {
235
- font-size: 13.5px; font-weight: 500;
236
- white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
237
- }
238
- .shell-user__rank {
239
- font: 400 var(--label-size)/1.35 var(--label-face);
240
- letter-spacing: var(--label-space); text-transform: var(--label-case);
241
- color: var(--ink-faint);
242
- }
243
- .shell-home, .shell-signout {
244
- flex: none; width: 30px; height: 30px;
245
- display: inline-flex; align-items: center; justify-content: center;
246
- color: var(--ink-faint); text-decoration: none;
247
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
248
- }
249
- .shell-home:hover, .shell-signout:hover { color: var(--ink); }
250
-
251
- .app-scrim { display: none; }
252
-
253
- /* ---------- the topbar: glass over the plate ---------- */
254
-
255
- .app-topbar {
256
- grid-column: 2; grid-row: 1;
257
- position: sticky; top: 0; z-index: var(--z-topbar);
258
- height: var(--topbar-h);
259
- display: flex; align-items: center; gap: var(--sp-sm);
260
- padding: 0 var(--gutter);
261
- background: var(--glass);
262
- -webkit-backdrop-filter: blur(var(--glass-blur));
263
- backdrop-filter: blur(var(--glass-blur));
264
- border-bottom: var(--line) solid var(--glass-edge);
265
- }
266
- .topbar-menu {
267
- display: none; width: 32px; height: 32px; margin-left: -6px;
268
- align-items: center; justify-content: center;
269
- background: none; border: 0; color: var(--ink-soft); cursor: pointer;
270
- }
271
- .topbar-title {
272
- margin: 0;
273
- font-family: var(--font-display); font-weight: 300;
274
- font-size: 21px; letter-spacing: -.03em; color: var(--ink);
275
- }
276
- .topbar-side { margin-left: auto; display: flex; align-items: center; gap: var(--sp-xs); }
277
- .topbar-note {
278
- font: 400 var(--label-size)/1.25 var(--label-face);
279
- letter-spacing: var(--label-space); text-transform: var(--label-case);
280
- color: var(--ink-faint); white-space: nowrap;
281
- }
282
- .topbar-jump {
283
- display: inline-flex; align-items: center; gap: 9px;
284
- min-height: 32px; padding: 0 13px;
285
- background: var(--glass-strong); border: var(--line) solid var(--glass-edge);
286
- border-radius: var(--radius-pill);
287
- color: var(--ink-soft); font-family: var(--font-body); font-size: 13px;
288
- cursor: pointer;
289
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
290
- }
291
- .topbar-jump:hover { color: var(--ink); }
292
- .topbar-jump__kbd { font: 400 11px var(--font-mono); color: var(--ink-faint); }
293
- .zoom-toggle, .theme-toggle {
294
- width: 32px; height: 32px;
295
- display: inline-flex; align-items: center; justify-content: center;
296
- background: none; border: 0; color: var(--ink-soft); cursor: pointer;
297
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
298
- }
299
- .zoom-toggle:hover, .theme-toggle:hover { color: var(--ink); }
300
-
301
- /* ---------- the content column ---------- */
302
-
303
- .app-content {
304
- grid-column: 2; grid-row: 2;
305
- position: relative; z-index: 1; /* over the plate layer, under the topbar */
306
- min-width: 0; padding: 0 var(--gutter) var(--sp-xl);
307
- }
308
- .app-content:focus { outline: none; }
309
-
310
- /* ---------- 1. the reading progress bar ---------- */
311
-
312
- .primer-progress {
313
- position: sticky; top: var(--topbar-h); z-index: 25;
314
- height: 3px; margin: 0 calc(var(--gutter) * -1);
315
- background: color-mix(in srgb, var(--accent) 14%, transparent);
316
- }
317
- .primer-progress__bar {
318
- height: 100%; width: 46%;
319
- background: var(--accent);
320
- transition: width 200ms cubic-bezier(.2, .7, .3, 1);
321
- }
322
- body[data-state="loading"] .primer-progress__bar,
323
- body[data-state="empty"] .primer-progress__bar,
324
- body[data-state="error"] .primer-progress__bar { width: 0; }
325
-
326
- /* ---------- the page head, written on the ground ---------- */
327
-
328
- .page-head { padding: var(--sp-xl) 0 var(--sp-lg); max-width: 1010px; }
329
- .page-head__eyebrow { margin: 0 0 14px; }
330
- .page-head__h {
331
- margin: 0;
332
- font-family: var(--font-display); font-weight: 300;
333
- font-size: var(--h1-size); line-height: 1.02; letter-spacing: -.042em;
334
- text-transform: lowercase; color: var(--ink);
335
- text-shadow: var(--type-halo); /* black in dark, none in light */
336
- }
337
- .page-head__sub {
338
- margin: var(--sp-md) 0 0; max-width: var(--measure);
339
- color: var(--ink-soft); font-size: 16px;
340
- }
341
-
342
- /* ---------- 2. the table of contents, as glass ---------- */
343
-
344
- /* the loosest version still needs a ceiling: past about 1010px the card is more
345
- empty ground than page, and a reading card that wide reads as a void */
346
- .primer-layout {
347
- display: grid;
348
- grid-template-columns: var(--toc-w) minmax(0, 1fr);
349
- gap: var(--col-gap);
350
- align-items: start;
351
- max-width: 1010px;
352
- }
353
- .primer-toc {
354
- position: sticky; top: calc(var(--topbar-h) + var(--sp-md));
355
- align-self: start;
356
- }
357
- .primer-toc__toggle {
358
- display: none; width: 100%;
359
- align-items: center; justify-content: space-between;
360
- min-height: 44px; padding: 8px 16px;
361
- background: var(--glass); border: var(--line) solid var(--glass-edge);
362
- -webkit-backdrop-filter: blur(var(--glass-blur));
363
- backdrop-filter: blur(var(--glass-blur));
364
- border-radius: var(--radius);
365
- color: var(--ink); font-family: var(--font-body); font-size: 14.5px;
366
- cursor: pointer;
367
- }
368
- .primer-toc__chevron {
369
- width: 10px; height: 6px; flex: none;
370
- fill: none; stroke: currentColor; stroke-width: 1.4;
371
- stroke-linecap: round; stroke-linejoin: round;
372
- transition: transform 200ms cubic-bezier(.2, .7, .3, 1);
373
- }
374
- .primer-toc__toggle[aria-expanded="true"] .primer-toc__chevron { transform: rotate(180deg); }
375
- .primer-toc__inner {
376
- background: var(--glass);
377
- border: var(--line) solid var(--glass-edge);
378
- -webkit-backdrop-filter: blur(var(--glass-blur));
379
- backdrop-filter: blur(var(--glass-blur));
380
- border-radius: var(--radius);
381
- padding: var(--sp-md) var(--sp-sm) var(--sp-sm);
382
- }
383
- .primer-toc__heading { margin: 0 0 var(--sp-sm); padding: 0 var(--sp-xs); }
384
- .primer-toc__list { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
385
- .primer-toc__list a {
386
- display: flex; align-items: baseline; gap: 11px;
387
- min-height: 34px; padding: 8px var(--sp-xs);
388
- border-radius: var(--radius-sm);
389
- border-left: 2px solid transparent;
390
- color: var(--ink-soft); text-decoration: none;
391
- font-size: 14px; line-height: 1.4;
392
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
393
- }
394
- .primer-toc__list a::before {
395
- counter-increment: toc;
396
- content: counter(toc, decimal-leading-zero);
397
- flex: none;
398
- font: 400 11px/1 var(--font-mono); font-variant-numeric: tabular-nums;
399
- color: var(--ink-faint);
400
- }
401
- .primer-toc__list a:hover { color: var(--ink); }
402
- /* the scrollspy's lit row */
403
- .primer-toc__list a.is-active {
404
- color: var(--ink);
405
- background: var(--glass-strong);
406
- border-left-color: var(--accent);
407
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
408
- }
409
- .primer-toc__placeholder {
410
- padding: 8px var(--sp-xs); color: var(--ink-faint); font-size: 14px;
411
- }
412
-
413
- /* ---------- 3. the article, a card over the plate ---------- */
414
-
415
- .primer-article {
416
- padding: var(--card-pad);
417
- background: var(--bg-card);
418
- border: var(--line) solid var(--rule-soft);
419
- border-radius: var(--radius);
420
- counter-reset: sec;
421
- color: var(--ink);
422
- }
423
- /* prose is measured on the card; a table, a figure and a code block may take
424
- the whole card, which is the only reason the card is wider than the measure */
425
- .primer-article > p,
426
- .primer-article > ul,
427
- .primer-article > ol,
428
- .primer-article > blockquote,
429
- .primer-article > h2,
430
- .primer-article > h3 { max-width: var(--measure); }
431
-
432
- .primer-article h2 {
433
- margin: calc(var(--sp-xl) * 1.4) 0 var(--sp-md);
434
- scroll-margin-top: calc(var(--topbar-h) + 28px);
435
- font-family: var(--font-display); font-weight: 300;
436
- font-size: var(--h2-size); line-height: 1.06; letter-spacing: -.035em;
437
- color: var(--ink);
438
- }
439
- /* the section number sits in the card's own margin, so the headline reads as
440
- one uninterrupted shape */
441
- .primer-article h2::before {
442
- counter-increment: sec;
443
- content: counter(sec, decimal-leading-zero);
444
- display: block; margin-bottom: 14px;
445
- font: 400 var(--label-size)/1.25 var(--label-face);
446
- letter-spacing: var(--label-space); font-variant-numeric: tabular-nums;
447
- color: var(--ink-faint);
448
- }
449
- .primer-article > h2:first-child { margin-top: 0; }
450
- .primer-article h3 {
451
- margin: var(--sp-lg) 0 var(--sp-xs);
452
- font-family: var(--font-display); font-weight: 400;
453
- font-size: var(--h3-size); letter-spacing: -.02em; color: var(--ink);
454
- }
455
- .primer-article p { margin: 0 0 var(--sp-md); }
456
- .primer-article ul, .primer-article ol { margin: 0 0 var(--sp-lg); padding-left: 1.4em; }
457
- .primer-article li { margin-bottom: 12px; }
458
- .primer-article li::marker { color: var(--ink-faint); }
459
- .primer-article a {
460
- color: var(--accent-ink);
461
- /* 1px of vertical padding takes the inline hit area past the 24px floor */
462
- padding: 1px 0;
463
- text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px;
464
- }
465
- .primer-article strong { font-weight: 600; color: var(--ink); }
466
- .primer-article em { font-style: italic; }
467
- .primer-article code {
468
- font: 400 .85em/1.4 var(--font-mono);
469
- background: var(--glass);
470
- padding: 2px 6px; border-radius: 4px;
471
- }
472
- .primer-article pre {
473
- margin: 0 0 var(--sp-lg);
474
- padding: var(--sp-md) var(--sp-lg);
475
- overflow-x: auto;
476
- background: var(--glass);
477
- border: var(--line) solid var(--glass-edge);
478
- border-radius: var(--radius);
479
- }
480
- .primer-article pre code {
481
- background: none; padding: 0; border-radius: 0;
482
- font-size: 13.5px; line-height: 1.8; color: var(--ink-soft);
483
- }
484
- .primer-article blockquote {
485
- margin: var(--sp-lg) 0; padding: var(--sp-md) var(--sp-lg);
486
- background: var(--glass);
487
- border: var(--line) solid var(--glass-edge);
488
- border-left: 2px solid var(--rule);
489
- border-radius: 0 var(--radius) var(--radius) 0;
490
- color: var(--ink-soft);
491
- }
492
- .primer-article blockquote p { margin: 0; max-width: var(--measure); }
493
- .primer-article table {
494
- width: 100%;
495
- border-collapse: collapse; margin: 0 0 var(--sp-lg);
496
- font-size: 14.5px; font-variant-numeric: tabular-nums;
497
- }
498
- .primer-article th, .primer-article td {
499
- text-align: left; vertical-align: top;
500
- padding: 13px 16px 13px 0;
501
- border-bottom: var(--line) solid var(--rule-soft);
502
- }
503
- .primer-article th {
504
- font: 400 var(--label-size)/1.25 var(--label-face);
505
- letter-spacing: var(--label-space); text-transform: var(--label-case);
506
- color: var(--ink-faint);
507
- padding-bottom: 13px;
508
- }
509
- .primer-article td.t-id { font: 400 13px var(--font-mono); color: var(--ink-faint); }
510
- .primer-article td.t-n, .primer-article th.t-n { text-align: right; padding-right: 0; }
511
- .primer-article tr:last-child td { border-bottom: 0; }
512
-
513
- /* ---------- 4. the inline diagram ---------- */
514
-
515
- .primer-figure { margin: var(--sp-xl) 0; }
516
- .primer-figure__frame {
517
- position: relative;
518
- padding: var(--sp-lg) var(--sp-md);
519
- background: var(--glass);
520
- border: var(--line) solid var(--glass-edge);
521
- border-radius: var(--radius);
522
- }
523
- .primer-figure__art { display: block; width: 100%; height: auto; }
524
- .primer-figure__zoom {
525
- position: absolute; top: 12px; right: 12px;
526
- display: inline-flex; align-items: center; gap: 8px;
527
- min-height: 32px; padding: 0 14px;
528
- background: var(--bg-card); border: var(--line) solid var(--glass-edge);
529
- border-radius: var(--radius-pill);
530
- color: var(--ink-soft); font-family: var(--font-body); font-size: 12.5px;
531
- cursor: pointer;
532
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
533
- }
534
- .primer-figure__zoom:hover { color: var(--ink); }
535
- .primer-figure figcaption {
536
- margin-top: 14px; max-width: var(--measure);
537
- font-size: 13.5px; line-height: 1.55; color: var(--ink-faint);
538
- }
539
- .dgm-rule { stroke: var(--rule); stroke-width: 1; }
540
- .dgm-dot { fill: none; stroke: var(--ink-faint); stroke-width: 1.4; }
541
- .dgm-dot--lit { fill: var(--accent); stroke: var(--accent); }
542
- .dgm-step {
543
- font: 400 11px var(--label-face); letter-spacing: var(--label-space);
544
- fill: var(--ink-faint);
545
- }
546
- .dgm-step--lit { fill: var(--ink); }
547
- .dgm-clause { font: 400 11.5px var(--font-body); fill: var(--ink-faint); }
548
-
549
- /* ---------- the loading skeleton, in the shape of the article ---------- */
550
-
551
- .sk {
552
- display: block; height: 10px; border-radius: 4px;
553
- background: color-mix(in srgb, var(--ink) 9%, transparent);
554
- }
555
- .primer-toc__list--sk li { padding: 11px var(--sp-xs); }
556
- .primer-skeleton {
557
- padding: var(--card-pad);
558
- background: var(--bg-card);
559
- border: var(--line) solid var(--rule-soft);
560
- border-radius: var(--radius);
561
- }
562
- .primer-skeleton__h { height: 28px; width: 58%; margin-bottom: var(--sp-lg); }
563
- .primer-skeleton__p { margin-bottom: var(--sp-lg); max-width: var(--measure); }
564
- .primer-skeleton__p .sk { margin-bottom: 15px; }
565
- .primer-skeleton__rule { height: var(--line); margin: var(--sp-xl) 0 var(--sp-lg); background: var(--rule-soft); }
566
- .sk-w1 { width: 100%; } .sk-w2 { width: 96%; } .sk-w3 { width: 99%; }
567
- .sk-w4 { width: 91%; } .sk-w5 { width: 74%; } .sk-w6 { width: 46%; }
568
- .sk-w7 { width: 84%; } .sk-w8 { width: 63%; }
569
-
570
- /* ---------- the empty and error notes, each on the card ---------- */
571
-
572
- .primer-note {
573
- padding: var(--card-pad);
574
- background: var(--bg-card);
575
- border: var(--line) solid var(--rule-soft);
576
- border-radius: var(--radius);
577
- }
578
- .primer-note__label { margin: 0 0 14px; }
579
- .primer-note--error .primer-note__label { color: var(--danger); }
580
- .primer-note__body { margin: 0 0 var(--sp-lg); max-width: var(--measure); color: var(--ink-soft); }
581
- .primer-note__acts { display: flex; flex-wrap: wrap; gap: var(--sp-xs); margin: 0; }
582
- .primer-note__act {
583
- display: inline-flex; align-items: center; min-height: 38px; padding: 0 20px;
584
- border: var(--line) solid var(--rule); border-radius: var(--radius-pill);
585
- background: none; color: var(--ink); text-decoration: none;
586
- font-family: var(--font-body); font-size: 14px; cursor: pointer;
587
- }
588
- .primer-note__act:hover { border-color: var(--ink-faint); }
589
-
590
- /* ---------- 5. the acknowledge gate, its own card under the article ---------- */
591
-
592
- .primer-ack {
593
- margin-top: var(--sp-sm);
594
- padding: var(--card-pad);
595
- background: var(--bg-card);
596
- border: var(--line) solid var(--rule-soft);
597
- border-radius: var(--radius);
598
- }
599
- .primer-ack__h {
600
- margin: 0 0 14px;
601
- font-family: var(--font-display); font-weight: 300;
602
- font-size: 28px; letter-spacing: -.03em; color: var(--ink);
603
- }
604
- .primer-ack__lede { margin: 0 0 var(--sp-md); max-width: var(--measure); color: var(--ink-soft); }
605
- .primer-ack__meter { margin: 0 0 var(--sp-lg); }
606
- .primer-ack__meter .num { color: var(--ink); }
607
- .primer-ack__btn {
608
- display: inline-flex; align-items: center;
609
- min-height: 48px; padding: 0 30px;
610
- background: var(--glass); border: var(--line) solid var(--glass-edge);
611
- border-radius: var(--radius-pill);
612
- color: var(--ink-faint); font-family: var(--font-body); font-size: 15px;
613
- cursor: not-allowed;
614
- transition: color 200ms cubic-bezier(.2, .7, .3, 1);
615
- }
616
- .primer-ack__btn[aria-disabled="false"] {
617
- background: var(--accent); border-color: var(--accent);
618
- color: var(--accent-on); cursor: pointer;
619
- }
620
- .primer-ack__note { margin: var(--sp-sm) 0 0; font-size: 13.5px; color: var(--ink-faint); }
621
-
622
- /* ---------- the state contract: real markup, shown and hidden by CSS ---------- */
623
-
624
- .p-populated, .p-loading, .p-empty, .p-error { display: none; }
625
- body[data-state="populated"] .p-populated,
626
- body[data-state="rail"] .p-populated,
627
- body[data-state="drawer"] .p-populated,
628
- body[data-state="focus"] .p-populated { display: block; }
629
- body[data-state="loading"] .p-loading { display: block; }
630
- body[data-state="empty"] .p-empty { display: block; }
631
- body[data-state="error"] .p-error { display: block; }
632
-
633
- body[data-state="focus"] .primer-toc__toggle { display: flex; margin-bottom: var(--sp-sm); }
634
- /* the rail expands on focus-within, so ?state=focus opens it to show the ring
635
- on the current nav item where a keyboard reader would actually meet it */
636
- body[data-state="focus"] .app-sidebar { width: var(--rail-open); }
637
- body[data-state="focus"] .nav-item__label,
638
- body[data-state="focus"] .nav-group__head-label,
639
- body[data-state="focus"] .nav-group__chevron,
640
- body[data-state="focus"] .brand-mark__name,
641
- body[data-state="focus"] .shell-user__meta { opacity: 1; }
642
- body[data-state="focus"] .app-sidebar__foot,
643
- body[data-state="drawer"] .app-sidebar__foot { flex-direction: row; }
644
-
645
- /* the bar's note folds away before the row can outrun a narrow viewport */
646
- @media (max-width: 1024px) {
647
- .topbar-note { display: none; }
648
- }
649
-
650
- /* ---------- the drawer ---------- */
651
-
652
- body[data-state="drawer"] { grid-template-columns: minmax(0, 1fr); }
653
- body[data-state="drawer"] .app-topbar,
654
- body[data-state="drawer"] .app-content { grid-column: 1; }
655
- body[data-state="drawer"] .topbar-menu { display: inline-flex; }
656
- body[data-state="drawer"] .app-sidebar {
657
- width: 276px; z-index: var(--z-drawer);
658
- background: var(--glass-strong);
659
- }
660
- body[data-state="drawer"] .nav-item__label,
661
- body[data-state="drawer"] .nav-group__head-label,
662
- body[data-state="drawer"] .nav-group__chevron,
663
- body[data-state="drawer"] .brand-mark__name,
664
- body[data-state="drawer"] .shell-user__meta { opacity: 1; }
665
- body[data-state="drawer"] .app-scrim {
666
- display: block; position: fixed; inset: 0; z-index: var(--z-scrim);
667
- background: rgba(0, 0, 0, .55);
668
- }
669
-
670
- /* ---------- 760px: the page's one breakpoint ----------
671
- the same one primer.js's matchMedia mirrors and tests/hall_audit.mjs pins. */
672
-
673
- @media (max-width: 760px) {
674
- body {
675
- --gutter: 16px;
676
- --col-gap: 0px;
677
- --card-pad: 20px;
678
- --body-size: 16.5px;
679
- --body-lead: 1.7;
680
- --measure: 100%;
681
- grid-template-columns: minmax(0, 1fr);
682
- }
683
- .app-topbar, .app-content { grid-column: 1; }
684
- .topbar-menu { display: inline-flex; }
685
- .app-sidebar { width: 276px; transform: translateX(-100%); z-index: var(--z-drawer); }
686
- body[data-state="drawer"] .app-sidebar { transform: none; }
687
- .page-head { padding-top: var(--sp-lg); }
688
- .primer-layout { grid-template-columns: minmax(0, 1fr); }
689
- .primer-toc { position: static; margin-bottom: var(--sp-sm); }
690
- .primer-toc__toggle { display: flex; }
691
- .primer-toc__inner { display: none; margin-top: 8px; }
692
- .primer-toc__toggle[aria-expanded="true"] + .primer-toc__inner { display: block; }
693
- .primer-article h2 { font-size: 24px; }
694
- .page-head__h { font-size: 36px; }
695
- /* a markdown table's column count is fixed by its source, so its min-content
696
- width outruns a phone. Give the table its own scrollport rather than let it
697
- drag the page sideways. This is primer.css's shipped rule, unchanged. */
698
- .primer-article table {
699
- display: block; width: max-content; max-width: 100%; overflow-x: auto;
700
- }
701
- .primer-figure__zoom { position: static; margin-top: var(--sp-xs); }
702
- }
703
- </style>
704
- <script>
705
- (function(){try{var q=new URLSearchParams(location.search||location.hash.slice(1)||'').get('mode');
706
- var m=(q==='light'||q==='dark')?q:'dark';
707
- document.documentElement.setAttribute('data-mode',m);
708
- document.documentElement.setAttribute('data-theme',m);}catch(e){}})();
709
- </script>
710
- </head>
711
- <body class="mock" data-state="populated">
712
- <!--
713
- Reading room in the chrome world, v3 "the glass hall" (task 1003302, goal 1000081).
714
- THESIS Atmosphere is never drawn, it is a rendered plate, so the hall gets a ground and the
715
- reading surface answers it by becoming a card the plate can never reach the ink on.
716
- COMPOSITION First viewport at 1440: the hall's plate under --plate-veil behind everything, a 64px
717
- glass rail that expands to 268px on hover or focus, a glass topbar, the progress
718
- hairline, then the lowercase h1 alone over the ground carrying the black type halo,
719
- and below it a glass table of contents beside a --bg-card article card at 16px radius,
720
- prose measured to 60ch at 17.5px on 1.78 leading, the loosest of the three.
721
- LIGHT No plate at all: light is the same room on paper, never a black panel, so the glass
722
- flattens to a 5 percent ink tint with zero blur, the type halo goes to none, and the
723
- only thing left of the version is its density and its radius.
724
- RISK A photographic ground under a twenty page document is the most expensive choice here:
725
- the rail costs a newcomer the names of the rooms until they hover, the card floats
726
- rather than sits so a long scroll never touches an edge, and every hall page after
727
- this one pays for the plate again.
728
- ?state=populated the page with real data
729
- ?state=loading skeletons in the SHAPE of the final content
730
- ?state=empty nothing to show yet
731
- ?state=error the feed failed
732
- ?state=rail the sidebar collapsed to its 64px rail
733
- ?state=drawer the mobile drawer open
734
- ?state=focus keyboard focus rings on the page's real controls
735
- -->
736
-
737
- <a class="skip" href="#main">Skip to content</a>
738
-
739
- <div class="app-plate" aria-hidden="true"></div>
740
-
741
- <div class="app-sidebar" id="app-sidebar">
742
- <div class="app-sidebar__brand">
743
- <a class="brand-mark" href="/" id="brand-mark">
744
- <span class="brand-mark__dot"></span><span class="brand-mark__name">Cloud Bongos</span></a>
745
- </div>
746
- <nav class="app-sidebar__nav" aria-label="Primary">
747
- <div class="nav-group">
748
- <a class="nav-item" id="nav-home" href="/" data-gate="always">
749
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 7.2 8 2.5l5.5 4.7V13a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5z"/></svg>
750
- <span class="nav-item__label">Home</span></a>
751
- <a class="nav-item" id="nav-roadmap" href="/roadmap" data-gate="always">
752
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 4h11M2.5 8h7.5M2.5 12h4.5"/></svg>
753
- <span class="nav-item__label">Roadmap</span></a>
754
- <a class="nav-item" id="nav-goals" href="/goals" data-gate="always">
755
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="5.5"/><circle cx="8" cy="8" r="1.6"/></svg>
756
- <span class="nav-item__label">Goals</span></a>
757
- <a class="nav-item" id="nav-work" href="/work" data-gate="always">
758
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 4.5h11v9h-11zM2.5 7.5h11M6 7.5v6"/></svg>
759
- <span class="nav-item__label">Tasks</span></a>
760
- <a class="nav-item" id="nav-ideas" href="/ideas" data-gate="always">
761
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 2.5a3.6 3.6 0 0 0-2.2 6.4v1.3h4.4V8.9A3.6 3.6 0 0 0 8 2.5zM6.4 12.6h3.2"/></svg>
762
- <span class="nav-item__label">Ideas</span></a>
763
- <a class="nav-item" id="nav-copy-desk" href="/copy-desk" data-gate="always">
764
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M4 2.5h5l3 3v8H4zM9 2.5v3h3"/></svg>
765
- <span class="nav-item__label">Copy desk</span></a>
766
- </div>
767
- <div class="nav-group nav-group--collapsible" id="nav-items-you" data-group="you">
768
- <button class="nav-group__head" data-gate="signed" data-group="you" aria-controls="nav-items-you" aria-expanded="true">
769
- <span class="nav-group__head-label">You</span>
770
- <svg class="nav-group__chevron" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1.2 5 4.8 9 1.2"/></svg></button>
771
- <a class="nav-item" id="nav-standing" href="/#standing" data-gate="signed">
772
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 13.5V9M8 13.5V4.5M13 13.5v-3"/></svg>
773
- <span class="nav-item__label">Standing</span></a>
774
- <a class="nav-item" id="nav-profile" href="/profile" data-gate="signed">
775
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="5.6" r="2.6"/><path d="M3.2 13.5a4.8 4.8 0 0 1 9.6 0"/></svg>
776
- <span class="nav-item__label">Profile</span></a>
777
- </div>
778
- <div class="nav-group nav-group--collapsible" id="nav-items-community" data-group="community">
779
- <button class="nav-group__head" data-gate="signed" data-group="community" aria-controls="nav-items-community" aria-expanded="true">
780
- <span class="nav-group__head-label">Community</span>
781
- <svg class="nav-group__chevron" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1.2 5 4.8 9 1.2"/></svg></button>
782
- <a class="nav-item" id="nav-collab" href="/collab" data-gate="signed">
783
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="5.6" cy="5.6" r="2.1"/><circle cx="10.6" cy="10.4" r="2.1"/><path d="M7.2 7.2 9 8.9"/></svg>
784
- <span class="nav-item__label">Collab</span></a>
785
- <a class="nav-item" id="nav-leaderboard" href="/#leaderboard" data-gate="signed">
786
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 13.5h11M5 13.5V8.2h2.2v5.3M8.8 13.5V4.5H11v9"/></svg>
787
- <span class="nav-item__label">Leaderboard</span></a>
788
- <a class="nav-item" id="nav-people" href="/people" data-gate="signed">
789
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="6" cy="5.6" r="2.2"/><path d="M2.2 13.2a3.9 3.9 0 0 1 7.6 0M10.6 4.1a2.2 2.2 0 0 1 0 4.3M11.6 9.7a3.9 3.9 0 0 1 2.2 3.5"/></svg>
790
- <span class="nav-item__label">People</span></a>
791
- </div>
792
- <div class="nav-group nav-group--collapsible" id="nav-items-docs" data-group="docs">
793
- <button class="nav-group__head" data-gate="always" data-group="docs" aria-controls="nav-items-docs" aria-expanded="true">
794
- <span class="nav-group__head-label">Docs</span>
795
- <svg class="nav-group__chevron" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1.2 5 4.8 9 1.2"/></svg></button>
796
- <a class="nav-item nav-item--active is-focus" id="nav-primer" href="/primer" data-gate="always" aria-current="page">
797
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 4.4v9M8 4.4A3.4 3.4 0 0 0 5 2.9H2.6v8.6H5a3.4 3.4 0 0 1 3 1.9M8 4.4A3.4 3.4 0 0 1 11 2.9h2.4v8.6H11a3.4 3.4 0 0 0-3 1.9"/></svg>
798
- <span class="nav-item__label">Primer</span></a>
799
- <a class="nav-item" id="nav-ranks" href="/ranks" data-gate="always">
800
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 11.5l5-4 5 4M3 7.5l5-4 5 4"/></svg>
801
- <span class="nav-item__label">Ranks</span></a>
802
- <a class="nav-item" id="nav-economy" href="/drachmae" data-gate="always">
803
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="5.5"/><path d="M6 6.4h4M6 9.6h4M8 4.6v6.8"/></svg>
804
- <span class="nav-item__label">Economy</span></a>
805
- <a class="nav-item" id="nav-diagrams" href="/diagrams" data-gate="always">
806
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 2.8h4.2v3.4H2.5zM9.3 9.8h4.2v3.4H9.3zM4.6 6.2v3.6h6.8"/></svg>
807
- <span class="nav-item__label">Diagrams</span></a>
808
- <a class="nav-item" id="nav-atlas" href="/atlas" data-gate="always">
809
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 12.8V4.2h4l1.2 1.6h5.8v7z"/></svg>
810
- <span class="nav-item__label">Repo Atlas</span></a>
811
- <a class="nav-item" id="nav-modules" href="/modules" data-gate="always">
812
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.8 2.8h4.2v4.2H2.8zM9 2.8h4.2v4.2H9zM2.8 9h4.2v4.2H2.8zM9 9h4.2v4.2H9z"/></svg>
813
- <span class="nav-item__label">Modules</span></a>
814
- <a class="nav-item" id="nav-apidocs" href="/docs" data-gate="always">
815
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M6 3.6 2.6 8 6 12.4M10 3.6 13.4 8 10 12.4"/></svg>
816
- <span class="nav-item__label">API docs</span></a>
817
- </div>
818
- <div class="nav-group nav-group--collapsible" id="nav-items-government" data-group="government">
819
- <button class="nav-group__head" data-gate="signed" data-group="government" aria-controls="nav-items-government" aria-expanded="true">
820
- <span class="nav-group__head-label">Government</span>
821
- <svg class="nav-group__chevron" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1.2 5 4.8 9 1.2"/></svg></button>
822
- <a class="nav-item" id="nav-watch" href="/watch" data-gate="signed">
823
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M1.6 8s2.4-4.2 6.4-4.2S14.4 8 14.4 8s-2.4 4.2-6.4 4.2S1.6 8 1.6 8z"/><circle cx="8" cy="8" r="1.8"/></svg>
824
- <span class="nav-item__label">Watch</span></a>
825
- <a class="nav-item" id="nav-harbor" href="/harbor" data-gate="signed">
826
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="3.4" r="1.4"/><path d="M8 4.9v8.6M4.6 7.1h6.8M2.9 9.4a5.1 5.1 0 0 0 10.2 0"/></svg>
827
- <span class="nav-item__label">Harbor</span></a>
828
- <a class="nav-item" id="nav-gate" href="/gate" data-gate="signed">
829
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.8 13.5V6L8 2.8 13.2 6v7.5M6.2 13.5V9h3.6v4.5"/></svg>
830
- <span class="nav-item__label">Gate</span></a>
831
- <a class="nav-item" id="nav-sessions" href="/sessions" data-gate="signed">
832
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="5.5"/><path d="M8 4.8V8l2.4 1.4"/></svg>
833
- <span class="nav-item__label">Sessions</span></a>
834
- <a class="nav-item" id="nav-government" href="/government" data-gate="signed">
835
- <svg class="nav-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 2.4l4.8 1.8v4c0 3-2.1 4.6-4.8 5.4-2.7-.8-4.8-2.4-4.8-5.4v-4z"/></svg>
836
- <span class="nav-item__label">Permissions</span></a>
837
- </div>
838
- </nav>
839
- <div class="app-sidebar__foot">
840
- <a class="shell-user" id="shell-user" href="/settings" title="Settings">
841
- <span class="shell-user__avatar"></span>
842
- <span class="shell-user__meta">
843
- <span class="shell-user__name">Percy Jackson</span>
844
- <span class="shell-user__rank">Owner</span></span></a>
845
- <a class="shell-home" href="/" title="Back to Cloud Bongos">
846
- <svg class="foot-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 7.2 8 2.5l5.5 4.7V13a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5z"/></svg>
847
- <span class="u-sr">Back to Cloud Bongos</span></a>
848
- <a class="shell-signout" href="/api/bongos/auth/logout" title="Sign out">
849
- <svg class="foot-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M6.4 2.8H3.2v10.4h3.2M9.4 5.4 12 8l-2.6 2.6M12 8H6.2"/></svg>
850
- <span class="u-sr">Sign out</span></a>
851
- </div>
852
- </div>
853
- <div class="app-scrim" id="app-scrim" aria-hidden="true"></div>
854
-
855
- <header class="app-topbar" id="app-topbar">
856
- <button class="topbar-menu" id="topbar-menu" aria-label="Open navigation" aria-expanded="false">
857
- <svg class="topbar-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 4.5h11M2.5 8h11M2.5 11.5h11"/></svg></button>
858
- <h2 class="topbar-title">Primer</h2>
859
- <div class="topbar-side">
860
- <span class="topbar-note">Docs, a ten minute read</span>
861
- <button class="topbar-jump" id="topbar-jump" aria-label="Jump to a page or record">
862
- <span class="topbar-jump__label">Jump to</span><kbd class="topbar-jump__kbd">Ctrl K</kbd></button>
863
- <button class="zoom-toggle" aria-label="Text size">
864
- <svg class="topbar-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M1.8 12.4 5 4.6l3.2 7.8M2.9 10.2h4.2M9.6 12.4 12 7l2.4 5.4M10.4 10.6h3.2"/></svg></button>
865
- <button class="theme-toggle" aria-label="Switch theme">
866
- <svg class="topbar-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M13.2 9.4A5.6 5.6 0 0 1 6.6 2.8a5.6 5.6 0 1 0 6.6 6.6z"/></svg></button>
867
- </div>
868
- </header>
869
-
870
- <main class="app-content" id="main" tabindex="-1">
871
-
872
- <!-- 1. the reading progress bar -->
873
- <div class="primer-progress" aria-hidden="true"><div class="primer-progress__bar"></div></div>
874
-
875
- <div class="page-head">
876
- <p class="page-head__eyebrow label">Docs</p>
877
- <h1 class="page-head__h">the primer</h1>
878
- <p class="page-head__sub">Everything a new builder needs before claiming a first task: what this
879
- platform is, how work moves from claim to credit, and what each rank opens.</p>
880
- </div>
881
-
882
- <div class="primer-layout">
883
-
884
- <!-- 2. the sticky table of contents, as glass. Under 760px it collapses
885
- behind the Sections disclosure, the page's one breakpoint. -->
886
- <aside class="primer-toc" id="primer-toc" aria-label="Sections in this primer">
887
- <button type="button" class="primer-toc__toggle is-focus" id="primer-toc-toggle"
888
- aria-expanded="false" aria-controls="primer-toc-list">
889
- <span class="primer-toc__toggle-label">Sections</span>
890
- <svg class="primer-toc__chevron" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1.2 5 4.8 9 1.2"/></svg></button>
891
- <nav class="primer-toc__inner">
892
- <p class="primer-toc__heading label" id="primer-toc-heading">In this primer</p>
893
- <ol class="primer-toc__list p-populated" id="primer-toc-list" aria-labelledby="primer-toc-heading">
894
- <li><a href="#s-what">What Cloud Bongos is</a></li>
895
- <li><a class="is-active is-focus" href="#s-lifecycle" aria-current="location">The claim to ship lifecycle</a></li>
896
- <li><a href="#s-board">Reading the board</a></li>
897
- <li><a href="#s-ranks">Ranks, and what each one opens</a></li>
898
- <li><a href="#s-credits">Credits, and what they are worth</a></li>
899
- <li><a href="#s-first">Your first task</a></li>
900
- </ol>
901
- <ol class="primer-toc__list primer-toc__list--sk p-loading" aria-hidden="true">
902
- <li><span class="sk sk-w2"></span></li>
903
- <li><span class="sk sk-w5"></span></li>
904
- <li><span class="sk sk-w7"></span></li>
905
- <li><span class="sk sk-w4"></span></li>
906
- <li><span class="sk sk-w8"></span></li>
907
- <li><span class="sk sk-w6"></span></li>
908
- </ol>
909
- <ul class="primer-toc__list p-empty">
910
- <li class="primer-toc__placeholder">No sections yet</li>
911
- </ul>
912
- <ul class="primer-toc__list p-error">
913
- <li class="primer-toc__placeholder">Sections unavailable</li>
914
- </ul>
915
- </nav>
916
- </aside>
917
-
918
- <div class="primer-col">
919
-
920
- <!-- 3. the article, a card over the plate. Flat markdown output: h2, h3,
921
- p, ul, ol, table, pre, blockquote and inline marks. -->
922
- <article class="primer-article p-populated" id="primer-article">
923
-
924
- <h2 id="s-what">What Cloud Bongos is</h2>
925
- <p>Cloud Bongos is an <strong>AI first build platform</strong>. A human owner sets the scope and
926
- the hard gates; agents claim the work and write the code. Everything that happens to this
927
- project becomes a row in one ledger: a task is created, claimed, built, graded, shipped and
928
- paid. If a change is not in the ledger, the ledger lies, so there is no tiny fix that skips it
929
- and no setup step that counts as free.</p>
930
- <p>Two versions are open as you read this. <strong>BONGOS-V1</strong>, the platform itself, has
931
- shipped <span class="num">1,176</span> of <span class="num">1,612</span> tasks against
932
- <span class="num">190</span> criteria, <span class="num">75</span> percent complete.
933
- <strong>CB-V1</strong>, the Customer-0 dogfood, has shipped <span class="num">58</span> of
934
- <span class="num">155</span>. You may claim from either, on whichever suits the time you have.</p>
935
-
936
- <h3>The five rooms you will use in week one</h3>
937
- <p>The hall is where the work is done. Five of its rooms carry almost everything:</p>
938
- <ul>
939
- <li>The <a href="/work">board</a>, where every ready task is listed with its credits and its estimate.</li>
940
- <li><a href="/goals">Goals</a>, which gather tasks into one module scoped piece of work with a done condition.</li>
941
- <li>Your <a href="/#standing">standing</a>: your rank, your credits, and everything you have shipped.</li>
942
- <li>The docs, this page among them, which are the only place the method is written down.</li>
943
- <li>The <a href="/watch">watch</a>, where a grade, a merge or a deploy that went wrong surfaces first.</li>
944
- </ul>
945
-
946
- <h2 id="s-lifecycle">The claim to ship lifecycle</h2>
947
- <p>Work moves through five beats, always in this order. The rail below is the same one the task
948
- page draws, and the beat you are on is the lit one.</p>
949
-
950
- <!-- 4. the inline diagram, injected after a named h2, with an affordance
951
- to open it fullscreen. -->
952
- <figure class="primer-figure" id="fig-lifecycle">
953
- <div class="primer-figure__frame">
954
- <svg class="primer-figure__art" viewBox="0 0 660 132" role="img"
955
- aria-label="The five beats of the lifecycle, left to right: claim, build, grade, ship, credit. Build is the lit step.">
956
- <path class="dgm-rule" d="M24 20h108M150 20h108M276 20h108M402 20h108M528 20h108"/>
957
- <circle class="dgm-dot" cx="30" cy="44" r="5"/>
958
- <circle class="dgm-dot dgm-dot--lit" cx="156" cy="44" r="5"/>
959
- <circle class="dgm-dot" cx="282" cy="44" r="5"/>
960
- <circle class="dgm-dot" cx="408" cy="44" r="5"/>
961
- <circle class="dgm-dot" cx="534" cy="44" r="5"/>
962
- <text class="dgm-step" x="24" y="74">CLAIM</text>
963
- <text class="dgm-step dgm-step--lit" x="150" y="74">BUILD</text>
964
- <text class="dgm-step" x="276" y="74">GRADE</text>
965
- <text class="dgm-step" x="402" y="74">SHIP</text>
966
- <text class="dgm-step" x="528" y="74">CREDIT</text>
967
- <text class="dgm-clause" x="24" y="98">lock the task<tspan x="24" dy="16">to your session</tspan></text>
968
- <text class="dgm-clause" x="150" y="98">write it in your<tspan x="150" dy="16">own worktree</tspan></text>
969
- <text class="dgm-clause" x="276" y="98">a panel reads<tspan x="276" dy="16">the real diff</tspan></text>
970
- <text class="dgm-clause" x="402" y="98">merged, then<tspan x="402" dy="16">deployed</tspan></text>
971
- <text class="dgm-clause" x="528" y="98">paid on land,<tspan x="528" dy="16">not on claim</tspan></text>
972
- </svg>
973
- <button type="button" class="primer-figure__zoom" aria-label="Open the lifecycle diagram fullscreen">
974
- <svg class="topbar-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M6 2.5H2.5V6M10 2.5h3.5V6M10 13.5h3.5V10M6 13.5H2.5V10"/></svg>
975
- <span>Fullscreen</span></button>
976
- </div>
977
- <figcaption>The claim to ship lifecycle. Exactly one step is lit at a time, and credits land
978
- at ship, never at claim.</figcaption>
979
- </figure>
980
-
981
- <ol>
982
- <li><strong>Claim.</strong> A claim locks one task to one session, so two builders can work the
983
- same version without colliding. A claim is refused if the task is already held, is not ready,
984
- or has a dependency that has not shipped.</li>
985
- <li><strong>Build.</strong> Work from a worktree of your own, never the main checkout. Write the
986
- code, the doc comment and the tests together: a change with no test is a change nobody can
987
- defend at grade.</li>
988
- <li><strong>Grade.</strong> A panel of reviewers reads the real committed diff, not your summary
989
- of it. A grade that fails is a description of what is missing, not a verdict on you.</li>
990
- <li><strong>Ship.</strong> The task moves to confirmed when the checks are green, then to shipped
991
- when the branch is merged and deployed. The server lands most merges on its own.</li>
992
- <li><strong>Credit.</strong> Credits are written when the work lands, which is why an abandoned
993
- branch pays nothing and a merged one pays in full.</li>
994
- </ol>
995
-
996
- <blockquote>
997
- <p>A task you have not claimed is a task another builder can claim out from under you. Claim
998
- first, then open the editor.</p>
999
- </blockquote>
1000
-
1001
- <h3>The three commands</h3>
1002
- <p>All five beats run from three commands. Run them from your own worktree:
1003
- <code>claim.js</code> refuses in the main checkout on purpose, because branching there strands
1004
- the ship at <em>confirmed</em> and somebody has to go and rescue it.</p>
1005
- <pre><code>node scripts/gds/claim.js 1002529
1006
- # build on the task branch, commit as you go
1007
- node scripts/gds/ship.js --summary "Provisioned instances now read config/branding.json"</code></pre>
1008
- <p><em>If a claim is refused, read the reason before you retry it.</em> The three refusals mean
1009
- three different things, and only one of them is worth waiting out.</p>
1010
-
1011
- <h2 id="s-board">Reading the board</h2>
1012
- <p>The board lists what is ready right now. Every row carries the version it belongs to, the kind
1013
- of work, the credits it pays and the estimate it was written with. Sort by nothing: read the
1014
- five at the top, and take the one you can finish today.</p>
1015
-
1016
- <table>
1017
- <thead>
1018
- <tr>
1019
- <th scope="col">Task</th>
1020
- <th scope="col">Version</th>
1021
- <th scope="col">Kind</th>
1022
- <th scope="col" class="t-n">Credits</th>
1023
- <th scope="col" class="t-n">Estimate</th>
1024
- </tr>
1025
- </thead>
1026
- <tbody>
1027
- <tr><td class="t-id">1001479</td><td>BONGOS-V1</td><td>infra</td><td class="t-n">10</td><td class="t-n">20m</td></tr>
1028
- <tr><td class="t-id">1002529</td><td>BONGOS-V1</td><td>bug</td><td class="t-n">50</td><td class="t-n">60m</td></tr>
1029
- <tr><td class="t-id">1002572</td><td>BONGOS-V1</td><td>bug</td><td class="t-n">60</td><td class="t-n">60m</td></tr>
1030
- <tr><td class="t-id">1003226</td><td>BONGOS-V1</td><td>bug</td><td class="t-n">25</td><td class="t-n">45m</td></tr>
1031
- <tr><td class="t-id">1003366</td><td>CB-V1</td><td>infra</td><td class="t-n">60</td><td class="t-n">240m</td></tr>
1032
- </tbody>
1033
- </table>
1034
-
1035
- <p>Task <span class="num">1002529</span>, "Provisioned instances ignore config/branding.json", is
1036
- the honest first claim on that list: one wrong lookup, a test that proves it, and a fix small
1037
- enough to read in one sitting. Task <span class="num">1003366</span> is not, because it edits
1038
- the protected surfaces file, and that needs a rank you do not have yet.</p>
1039
-
1040
- <h2 id="s-ranks">Ranks, and what each one opens</h2>
1041
- <p>There are four ranks. Rank is held in the database and checked on every request, so no local
1042
- file, this page included, can grant you anything. What rises with rank is not privilege for its
1043
- own sake: it is how much of the pipeline you are trusted to change.</p>
1044
- <ul>
1045
- <li><strong>Newcomer.</strong> Read everything, claim sandboxed work, ship it. The permission
1046
- and pipeline surfaces are closed, and the tooling will say so rather than let you push.</li>
1047
- <li><strong>Contributor.</strong> The ordinary building rank: claim across both versions, open
1048
- goals, file blockers, write ADRs.</li>
1049
- <li><strong>Trusted.</strong> Adds the daily cadence work, the triage of ideas and blockers, and
1050
- planning sessions that set a version's scope.</li>
1051
- <li><strong>Owner.</strong> Sets scope and the hard gates. One human owner per instance, plus the
1052
- agents the owner has raised to it.</li>
1053
- </ul>
1054
- <p>Rising is not a request you file. It is what the ledger says about the work you have already
1055
- shipped, read at review.</p>
1056
-
1057
- <h2 id="s-credits">Credits, and what they are worth</h2>
1058
- <p>Credits are the platform's currency, and one credit is one dollar of value returned. The
1059
- instance has spent <span class="num">$49,708.47</span> to date, almost all of it on model
1060
- calls, and the work that spend bought is carried at <span class="num">71,040</span> credits.
1061
- That ratio is the whole argument for the method, so it is on the wall rather than in a report.</p>
1062
- <p>A shipped task pays what it was written to pay. Task <span class="num">1003322</span>, which
1063
- carved the front door into its own module, paid <span class="num">60</span> credits: estimated
1064
- at <span class="num">240</span> minutes, shipped in <span class="num">37</span>. The estimate
1065
- is not a target and beating it earns nothing extra, which is deliberate.</p>
1066
- <p>The standing board reads, at the time of writing: lars589 on
1067
- <span class="num">44,562</span> credits, Percy Jackson on <span class="num">14,441</span>,
1068
- IAMMASTERQUA on <span class="num">3,316</span>, scootermack on <span class="num">2,646</span>.
1069
- A credit figure is data, not a live thing, so it is set in ink and never in the accent.</p>
1070
-
1071
- <h2 id="s-first">Your first task</h2>
1072
- <p>Do these in order. The whole loop, claim to credit, should take one sitting.</p>
1073
- <ol>
1074
- <li>Acknowledge this primer at the foot of the page.</li>
1075
- <li>Open the <a href="/work">board</a> and read the five ready tasks end to end before choosing.</li>
1076
- <li>Claim one, in a worktree of its own.</li>
1077
- <li>Write the failing test first, then the change that passes it.</li>
1078
- <li>Ship with a summary a non engineer could read, because that summary is what gets broadcast.</li>
1079
- </ol>
1080
- <p>If something in here turned out to be wrong, that is a task too: file it, claim it, and fix the
1081
- page. The <a href="/ranks">rank ladder</a> and the <a href="/drachmae">economy</a> pages go
1082
- deeper on the two subjects this one only sketches.</p>
1083
- </article>
1084
-
1085
- <!-- the loading state: a skeleton in the SHAPE of the article -->
1086
- <div class="primer-skeleton p-loading" aria-hidden="true">
1087
- <span class="sk primer-skeleton__h sk-w5"></span>
1088
- <div class="primer-skeleton__p">
1089
- <span class="sk sk-w1"></span><span class="sk sk-w3"></span>
1090
- <span class="sk sk-w2"></span><span class="sk sk-w5"></span>
1091
- </div>
1092
- <div class="primer-skeleton__p">
1093
- <span class="sk sk-w2"></span><span class="sk sk-w1"></span>
1094
- <span class="sk sk-w4"></span><span class="sk sk-w6"></span>
1095
- </div>
1096
- <div class="primer-skeleton__rule"></div>
1097
- <span class="sk primer-skeleton__h sk-w8"></span>
1098
- <div class="primer-skeleton__p">
1099
- <span class="sk sk-w3"></span><span class="sk sk-w1"></span>
1100
- <span class="sk sk-w7"></span><span class="sk sk-w5"></span>
1101
- </div>
1102
- </div>
1103
-
1104
- <!-- the empty state: the document loaded, and has no sections -->
1105
- <div class="primer-note p-empty">
1106
- <p class="primer-note__label label">No sections yet</p>
1107
- <p class="primer-note__body">The primer document exists but carries no headings, so there is
1108
- nothing to build a table of contents from and nothing to acknowledge. An owner writes the first
1109
- section in <code>docs/onboarding/primer.md</code>; this page renders it on the next load.</p>
1110
- <p class="primer-note__acts"><a class="primer-note__act" href="/work">Go to the board</a></p>
1111
- </div>
1112
-
1113
- <!-- the error state: the markdown failed to load -->
1114
- <div class="primer-note primer-note--error p-error">
1115
- <p class="primer-note__label label">The primer did not load</p>
1116
- <p class="primer-note__body">The markdown behind this page could not be fetched: the request to
1117
- <code>/builders/docs/primer.md</code> returned 502. Nothing you did caused it, and nothing you
1118
- have already read is lost.</p>
1119
- <p class="primer-note__acts">
1120
- <button type="button" class="primer-note__act">Try again</button>
1121
- <a class="primer-note__act" href="/watch">See the watch</a></p>
1122
- </div>
1123
-
1124
- <!-- 5. the acknowledge gate -->
1125
- <section class="primer-ack p-populated" id="primer-ack" aria-labelledby="primer-ack-h">
1126
- <h2 class="primer-ack__h" id="primer-ack-h">Acknowledge the primer</h2>
1127
- <p class="primer-ack__lede">Read to the end and the button below unlocks. It is an honour system
1128
- signal rather than a test: it records that you have seen the rules you are about to work under.</p>
1129
- <p class="primer-ack__meter label">Read <span class="num">46%</span> of the 90% needed</p>
1130
- <button type="button" class="primer-ack__btn is-focus" id="primer-ack-btn"
1131
- aria-disabled="true" aria-describedby="primer-ack-note">I have read it</button>
1132
- <p class="primer-ack__note" id="primer-ack-note">Locked until you reach 90 percent. The control
1133
- stays reachable by keyboard so it can say why.</p>
1134
- </section>
1135
-
1136
- </div>
1137
- </div>
1138
- </main>
1139
-
1140
- <script>
1141
- /* the mock's state contract: read ?state= once and apply it. Nothing is built here, and no motion. */
1142
- (function () {
1143
- var ok = ['populated', 'loading', 'empty', 'error', 'rail', 'drawer', 'focus'];
1144
- var s = new URLSearchParams(location.search || location.hash.slice(1) || '').get('state') || 'populated';
1145
- if (ok.indexOf(s) === -1) s = 'populated';
1146
- document.body.setAttribute('data-state', s);
1147
- })();
1148
- </script>
1149
- </body>
1150
- </html>