@bongos/core 1.19.454 → 1.19.456

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 (58) hide show
  1. package/.bongos-core.json +116 -51
  2. package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +1 -0
  3. package/docs/copy-inventory.md +231 -228
  4. package/docs/copy-registry.json +352 -312
  5. package/docs/module-api-changelog.md +4 -0
  6. package/modules/discord/db.js +0 -3
  7. package/modules/discord/discord-bot.js +8 -1
  8. package/modules/discord/discord-bugs.js +133 -74
  9. package/modules/discord/module.json +1 -1
  10. package/modules/hall-ui/public/atlas.css +41 -32
  11. package/modules/hall-ui/public/atlas.html +8 -0
  12. package/modules/hall-ui/public/atlas.states.json +60 -0
  13. package/modules/hall-ui/public/collab.css +2 -2
  14. package/modules/hall-ui/public/collab.html +7 -1
  15. package/modules/hall-ui/public/collab.states.json +60 -0
  16. package/modules/hall-ui/public/copy-desk.css +21 -16
  17. package/modules/hall-ui/public/copy-desk.html +9 -1
  18. package/modules/hall-ui/public/copy-desk.states.json +59 -0
  19. package/modules/hall-ui/public/drachmae.html +38 -5
  20. package/modules/hall-ui/public/drachmae.js +20 -2
  21. package/modules/hall-ui/public/drachmae.states.json +64 -0
  22. package/modules/hall-ui/public/gate.css +20 -25
  23. package/modules/hall-ui/public/gate.html +9 -1
  24. package/modules/hall-ui/public/gate.states.json +60 -0
  25. package/modules/hall-ui/public/goals-lib.js +22 -5
  26. package/modules/hall-ui/public/goals-render.js +27 -5
  27. package/modules/hall-ui/public/goals.css +141 -60
  28. package/modules/hall-ui/public/goals.html +8 -1
  29. package/modules/hall-ui/public/goals.states.json +74 -0
  30. package/modules/hall-ui/public/government.css +35 -36
  31. package/modules/hall-ui/public/government.html +9 -1
  32. package/modules/hall-ui/public/government.states.json +59 -0
  33. package/modules/hall-ui/public/harbor.css +23 -26
  34. package/modules/hall-ui/public/harbor.html +9 -1
  35. package/modules/hall-ui/public/harbor.states.json +59 -0
  36. package/modules/hall-ui/public/modules.css +22 -21
  37. package/modules/hall-ui/public/modules.html +9 -1
  38. package/modules/hall-ui/public/modules.states.json +73 -0
  39. package/modules/hall-ui/public/people.html +7 -1
  40. package/modules/hall-ui/public/people.states.json +59 -0
  41. package/modules/hall-ui/public/scouting.html +7 -1
  42. package/modules/hall-ui/public/scouting.states.json +54 -0
  43. package/modules/hall-ui/public/sessions.css +1 -1
  44. package/modules/hall-ui/public/sessions.html +9 -1
  45. package/modules/hall-ui/public/sessions.states.json +58 -0
  46. package/modules/hall-ui/public/style.css +125 -5
  47. package/modules/hall-ui/public/watch.css +36 -39
  48. package/modules/hall-ui/public/watch.html +9 -1
  49. package/modules/hall-ui/public/watch.states.json +60 -0
  50. package/modules/lifecycle/goal-suggest.js +70 -2
  51. package/modules/lifecycle/lifecycle.js +7 -0
  52. package/package-lock.json +2 -2
  53. package/package.json +1 -1
  54. package/src/module-api.js +1 -1
  55. package/tests/discord_bugs.mjs +110 -31
  56. package/tests/filing_abuse_matrix.mjs +59 -20
  57. package/tests/goal_subtitle.mjs +14 -8
  58. package/tests/goal_suggest.mjs +107 -1
@@ -0,0 +1,59 @@
1
+ {
2
+ "_": "People — the cross-project directory behind requireProjectCuratePage (metic+ via project.curate). Descriptive only; it grants no authority, and the page says so above the fold. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
+ "page": "/builders/people",
4
+ "surface": "hall-ui",
5
+ "stub": {
6
+ "prefix": "/builders/"
7
+ },
8
+ "modeQuery": false,
9
+ "_feeds": "The kit's own stub carries no feed for this page, so against it the page renders its EMPTY and SKELETON states — which is the point: those are states the floors must hold in. Against the hall-preview harness the same states render populated. Every declared 404 below is a fixture the harness does not carry, named rather than hidden.",
10
+ "ignoreRequests": [
11
+ "/api/(gds|bongos)/me$",
12
+ "/api/(gds|bongos)/me/",
13
+ "/api/(gds|bongos)/goals",
14
+ "/api/(gds|bongos)/inbox/",
15
+ "/api/(gds|bongos)/versions",
16
+ "/api/(gds|bongos)/builders",
17
+ "/api/(gds|bongos)/public/"
18
+ ],
19
+ "ignoreConsole": [
20
+ "/api/(gds|bongos)/",
21
+ "\\b401\\b",
22
+ "\\b403\\b",
23
+ "\\b404\\b",
24
+ "\\b501\\b",
25
+ "Unauthorized",
26
+ "Forbidden",
27
+ "Not Found",
28
+ "Not Implemented",
29
+ "load failed"
30
+ ],
31
+ "states": {
32
+ "directory": {
33
+ "auth": true,
34
+ "actions": [
35
+ [
36
+ "wait",
37
+ 700
38
+ ]
39
+ ],
40
+ "expect": {
41
+ "visible": [
42
+ "#people-scroll"
43
+ ]
44
+ }
45
+ },
46
+ "out": {
47
+ "auth": false
48
+ }
49
+ },
50
+ "reducedMotion": {
51
+ "auth": true,
52
+ "actions": [
53
+ [
54
+ "wait",
55
+ 600
56
+ ]
57
+ ]
58
+ }
59
+ }
@@ -21,7 +21,13 @@
21
21
  <div class="app-body">
22
22
  <header class="app-topbar" id="app-topbar"></header>
23
23
  <div class="app-content">
24
- <div class="page-head">
24
+ <!-- task 1003307: the board page head. Scouting shipped with NO <h1> at all
25
+ (one-header-main-h1 measured 0 on every render), so the re-skin
26
+ carries the structural fix rather than porting the hole. The heading
27
+ is the LABEL voice, not a display line: on a working surface the
28
+ page's own name is the least interesting thing on it. -->
29
+ <div class="page-head page-head--board">
30
+ <h1 class="page-head__h">Scouting</h1>
25
31
  <p class="page-head__sub">Builders active across all hosted projects — an internal talent view. Descriptive only; it grants no authority anywhere.</p>
26
32
  </div>
27
33
 
@@ -0,0 +1,54 @@
1
+ {
2
+ "_": "Scouting — the internal talent view, same project.curate gate as People. Carries the hall's last three-line inline <style>, which is well inside hall_audit's budget and is left alone deliberately. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
+ "page": "/builders/scouting",
4
+ "surface": "hall-ui",
5
+ "stub": {
6
+ "prefix": "/builders/"
7
+ },
8
+ "modeQuery": false,
9
+ "_feeds": "The kit's own stub carries no feed for this page, so against it the page renders its EMPTY and SKELETON states — which is the point: those are states the floors must hold in. Against the hall-preview harness the same states render populated. Every declared 404 below is a fixture the harness does not carry, named rather than hidden.",
10
+ "ignoreRequests": [
11
+ "/api/(gds|bongos)/me$",
12
+ "/api/(gds|bongos)/me/",
13
+ "/api/(gds|bongos)/goals",
14
+ "/api/(gds|bongos)/inbox/",
15
+ "/api/(gds|bongos)/versions",
16
+ "/api/(gds|bongos)/scouting",
17
+ "/api/(gds|bongos)/builders"
18
+ ],
19
+ "ignoreConsole": [
20
+ "/api/(gds|bongos)/",
21
+ "\\b401\\b",
22
+ "\\b403\\b",
23
+ "\\b404\\b",
24
+ "\\b501\\b",
25
+ "Unauthorized",
26
+ "Forbidden",
27
+ "Not Found",
28
+ "Not Implemented",
29
+ "load failed"
30
+ ],
31
+ "states": {
32
+ "board": {
33
+ "auth": true,
34
+ "actions": [
35
+ [
36
+ "wait",
37
+ 700
38
+ ]
39
+ ]
40
+ },
41
+ "out": {
42
+ "auth": false
43
+ }
44
+ },
45
+ "reducedMotion": {
46
+ "auth": true,
47
+ "actions": [
48
+ [
49
+ "wait",
50
+ 600
51
+ ]
52
+ ]
53
+ }
54
+ }
@@ -9,7 +9,7 @@
9
9
  table.ledger th, table.ledger td { white-space: nowrap; }
10
10
  .ledger td.warn { color: var(--danger); font-weight: 600; }
11
11
  .ledger-sid {
12
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
12
+ font-family: var(--font-mono);
13
13
  font-size: 12.5px;
14
14
  color: var(--info);
15
15
  }
@@ -19,7 +19,15 @@
19
19
  <div class="app-body">
20
20
  <header class="app-topbar" id="app-topbar"></header>
21
21
  <div class="app-content">
22
- <div class="page-head"><p class="page-head__sub" id="ledger-sub">Loading sessions…</p></div>
22
+ <!-- task 1003307: the board page head. Sessions shipped with NO <h1> at all
23
+ (one-header-main-h1 measured 0 on every render), so the re-skin
24
+ carries the structural fix rather than porting the hole. The heading
25
+ is the LABEL voice, not a display line: on a working surface the
26
+ page's own name is the least interesting thing on it. -->
27
+ <div class="page-head page-head--board">
28
+ <h1 class="page-head__h">Sessions</h1>
29
+ <p class="page-head__sub" id="ledger-sub">Loading sessions…</p>
30
+ </div>
23
31
 
24
32
  <main id="hall-main">
25
33
  <!-- Access notice — shown by sessions.js when the viewer is not an Archon. -->
@@ -0,0 +1,58 @@
1
+ {
2
+ "_": "Sessions — the session ledger behind requireGovernmentPage. sessions.js pages SERVER-SIDE by offset and is the one sanctioned hand-rolled pager in the hall; this file measures it, it does not ask it to change. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
+ "page": "/builders/sessions",
4
+ "surface": "hall-ui",
5
+ "stub": {
6
+ "prefix": "/builders/"
7
+ },
8
+ "modeQuery": false,
9
+ "_feeds": "The kit's own stub carries no feed for this page, so against it the page renders its EMPTY and SKELETON states — which is the point: those are states the floors must hold in. Against the hall-preview harness the same states render populated. Every declared 404 below is a fixture the harness does not carry, named rather than hidden.",
10
+ "ignoreRequests": [
11
+ "/api/(gds|bongos)/me$",
12
+ "/api/(gds|bongos)/me/",
13
+ "/api/(gds|bongos)/goals",
14
+ "/api/(gds|bongos)/inbox/",
15
+ "/api/(gds|bongos)/versions",
16
+ "/api/(gds|bongos)/sessions"
17
+ ],
18
+ "ignoreConsole": [
19
+ "/api/(gds|bongos)/",
20
+ "\\b401\\b",
21
+ "\\b403\\b",
22
+ "\\b404\\b",
23
+ "\\b501\\b",
24
+ "Unauthorized",
25
+ "Forbidden",
26
+ "Not Found",
27
+ "Not Implemented",
28
+ "load failed"
29
+ ],
30
+ "states": {
31
+ "ledger": {
32
+ "auth": true,
33
+ "actions": [
34
+ [
35
+ "wait",
36
+ 700
37
+ ]
38
+ ],
39
+ "expect": {
40
+ "visible": [
41
+ "#stats-scroll"
42
+ ]
43
+ }
44
+ },
45
+ "out": {
46
+ "auth": false
47
+ }
48
+ },
49
+ "reducedMotion": {
50
+ "auth": true,
51
+ "actions": [
52
+ [
53
+ "wait",
54
+ 600
55
+ ]
56
+ ]
57
+ }
58
+ }
@@ -222,6 +222,11 @@
222
222
  --z-sidebar: 40;
223
223
  --z-scrim: 140;
224
224
  --z-drawer: 150;
225
+ /* A confirm dialog is the one thing that must sit above the drawer: it is
226
+ asking a question the drawer's content cannot answer. Added by task 1003307
227
+ because harbor and gate had each guessed a bare number for exactly this
228
+ (200 and 50), which is what a missing layer looks like. */
229
+ --z-modal: 160;
225
230
  --z-diagram-full: 9999;
226
231
 
227
232
  /* ---- the hall's own plate: the declared seam, deferred by the owner
@@ -1088,7 +1093,14 @@ main:focus { outline: none; }
1088
1093
  .next-up__foot a,
1089
1094
  .setup__steps a,
1090
1095
  .setup__hint a,
1091
- .setup__foot a {
1096
+ .setup__foot a,
1097
+ /* task 1003307 — the two empty-state voices. .empty-state is the kit's own and
1098
+ was simply missing from this list; .cb-empty is the same component under
1099
+ collab's older name (Collab's "set yours in Settings" link measured 51x18).
1100
+ Unifying the two names is worth doing, but renaming a class is not a
1101
+ re-skin's business. */
1102
+ .empty-state p a,
1103
+ .cb-empty a {
1092
1104
  display: inline-block;
1093
1105
  min-width: 24px;
1094
1106
  min-height: 24px;
@@ -1144,14 +1156,20 @@ main:focus { outline: none; }
1144
1156
  gap: 8px;
1145
1157
  }
1146
1158
  .stat-tile:first-child { border-left: 0; }
1147
- .stat-tile__label {
1159
+ .stat-tile__label,
1160
+ .gate-stat__label,
1161
+ .harbor-stat__label,
1162
+ .watch-stat__label {
1148
1163
  font-family: var(--label-face);
1149
1164
  font-size: var(--label-size);
1150
1165
  letter-spacing: var(--label-space);
1151
1166
  text-transform: var(--label-case);
1152
1167
  color: var(--ink-faint);
1153
1168
  }
1154
- .stat-tile__num {
1169
+ .stat-tile__num,
1170
+ .gate-stat__value,
1171
+ .harbor-stat__value,
1172
+ .watch-stat__num {
1155
1173
  font-family: var(--font-display);
1156
1174
  font-size: clamp(26px, 2.6vw, 34px);
1157
1175
  font-weight: 300;
@@ -1415,7 +1433,19 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1415
1433
  .ledger tbody tr:hover td { background: var(--glass); }
1416
1434
  /* task 1467: a builder name that links to their profile page reads as plain
1417
1435
  text in the dense leaderboard/roster, revealing itself as a link on hover. */
1418
- .lb-name { color: inherit; }
1436
+ .lb-name {
1437
+ color: inherit;
1438
+ /* A link is a control and owes the 24px floor on BOTH axes. This one is plain
1439
+ text in a dense ledger, so it had no box of its own and measured 83x18 on
1440
+ the Watch board (task 1003307). The vertical padding buys the height; the
1441
+ equal negative margin gives the space back so the row keeps its rhythm. */
1442
+ display: inline-block;
1443
+ min-height: 24px;
1444
+ min-width: 24px;
1445
+ padding: 3px 4px;
1446
+ margin: 0 -4px;
1447
+ line-height: 18px;
1448
+ }
1419
1449
  .lb-name:hover { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }
1420
1450
  .ledger__empty {
1421
1451
  color: var(--ink-faint);
@@ -2815,6 +2845,30 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
2815
2845
  .kit-tabs .setup__tab .count-pill { margin-left: 6px; }
2816
2846
 
2817
2847
  /* empty state — one short line + at most one action link */
2848
+ /* ── four classes that were referenced and defined nowhere (task 1003307) ────
2849
+ Each one rendered its text at the browser's default, which is why nobody
2850
+ noticed: an unstyled 16px serif-ish line next to a styled one reads as "a bit
2851
+ off", not as a bug. Found by auditing the pages against the archetype. */
2852
+
2853
+ /* collab.html:38,51 — the section note under a .scroll__h. The shell's name for
2854
+ this is .scroll__lede; both collab sections asked for .scroll__note. Rather
2855
+ than edit the markup, the name joins the lede it meant. */
2856
+ .scroll__note { margin: 0 0 14px; font-size: 13.5px; color: var(--ink-soft); max-width: var(--measure); }
2857
+
2858
+ /* collab.js:73-74 — the settle buttons asked for a small variant of .btn that
2859
+ does not exist, so "Someone helped" rendered full-size on every row. */
2860
+ .btn--sm { min-height: 26px; padding: 0 11px; font-size: 12.5px; }
2861
+
2862
+ /* people.js:45 — the builder's name cell. The only definition in the hall lives
2863
+ in scouting.html's inline <style>, so the same data read bold on Scouting and
2864
+ plain on People. One definition, both pages. */
2865
+ .who { font-weight: 600; }
2866
+
2867
+ /* people.js:105 — notice() sets body.className='note'. .note lives in
2868
+ my-projects.css, which People never loads, so every gated / empty / error
2869
+ message on that page rendered unstyled. */
2870
+ .note { margin: 0; font-size: 13.5px; color: var(--ink-soft); }
2871
+
2818
2872
  .empty-state { padding: 8px 0; }
2819
2873
  .empty-state p { margin: 0; font-size: 13.5px; color: var(--ink-soft); }
2820
2874
  .empty-state__action { display: inline-block; margin-top: 6px; font-size: 13px; }
@@ -2980,10 +3034,76 @@ html.palette-open { overflow: hidden; }
2980
3034
  /* The slot keeps its icon as an affordance; the label + hint would crowd the
2981
3035
  title on a phone. Ctrl/Cmd-K still opens it on a keyboard. */
2982
3036
  .topbar-jump__label, .topbar-jump__kbd { display: none; }
2983
- .topbar-jump { padding: 0 8px; }
3037
+ /* ...but the button carries min-width: 0 so it can shrink in the topbar's flex
3038
+ row, and with the label and the hint gone there is nothing left holding it
3039
+ open: it measured 18x32 at 320px, under the 24px floor on the horizontal
3040
+ axis. The icon-only button gets its width back explicitly (task 1003307). */
3041
+ .topbar-jump { padding: 0 8px; min-width: 32px; justify-content: center; }
2984
3042
  .palette__panel { margin-top: 6vh; }
2985
3043
  .palette__group { min-width: 56px; }
2986
3044
  }
3045
+ /* ── the fact vocabulary (task 1003307) ──────────────────────────────────────
3046
+ A row states facts about a record: its state, and the things it is scoped to.
3047
+ The archetype (docs/design/mocks/hall/goals/v3.html, .status + .chip) says a
3048
+ state is a HAIRLINE in its own colour with no fill, and a scope is a quiet
3049
+ mono chip. Neither is pressable, so neither takes the accent.
3050
+
3051
+ These live here because five pages had already invented them separately —
3052
+ .gov-pill, .harbor-pill, .gate-pill, .badge, .mod-chip — each re-spelling the
3053
+ label voice as literals. The shell had no neutral pill to take: .chip below is
3054
+ the accent-tinted FILTER chip, and it means "press me".
3055
+
3056
+ The state colours are the hall's fixed verification vocabulary, never the
3057
+ world's warm accent states (ADR 0196 §2): a status must not re-tint when an
3058
+ instance re-brands. */
3059
+ /* The five names below are the SAME pill, found by the task 1003307 audit:
3060
+ government, harbor, gate, watch and modules each invented one because the
3061
+ shell had none to take. They are aliased rather than renamed because renaming
3062
+ would mean editing five JS row builders, and a class name is not what was
3063
+ wrong — the duplicated, hand-rolled label voice was. Their own state
3064
+ modifiers stay in their own sheets. */
3065
+ .fact-pill,
3066
+ .gov-pill,
3067
+ .harbor-pill,
3068
+ .gate-pill,
3069
+ .badge,
3070
+ .mod-chip {
3071
+ display: inline-flex;
3072
+ align-items: center;
3073
+ min-height: 24px;
3074
+ padding: 0 11px;
3075
+ border: var(--line) solid currentColor;
3076
+ border-radius: var(--radius-pill);
3077
+ background: none;
3078
+ font-family: var(--label-face);
3079
+ font-size: 10.5px;
3080
+ letter-spacing: var(--label-space);
3081
+ text-transform: var(--label-case);
3082
+ color: var(--ink-faint);
3083
+ white-space: nowrap;
3084
+ }
3085
+ .fact-pill--open, .fact-pill--info { color: var(--info); }
3086
+ .fact-pill--blocked, .fact-pill--warn { color: var(--warn); }
3087
+ .fact-pill--achieved, .fact-pill--ok { color: var(--ok); }
3088
+ .fact-pill--danger { color: var(--danger); }
3089
+ .fact-pill--archived, .fact-pill--quiet { color: var(--ink-faint); }
3090
+
3091
+ /* A scope, not a state: what the record is filed under. Mono because it is a
3092
+ machine's word (a module key, a version id), --radius-sm because a pill would
3093
+ read as a second status. */
3094
+ .fact-chip {
3095
+ display: inline-flex;
3096
+ align-items: center;
3097
+ min-height: 24px;
3098
+ padding: 0 10px;
3099
+ border: var(--line) solid var(--rule-soft);
3100
+ border-radius: var(--radius-sm);
3101
+ font-family: var(--font-mono);
3102
+ font-size: 11px;
3103
+ color: var(--ink-faint);
3104
+ white-space: nowrap;
3105
+ }
3106
+
2987
3107
  /* task 1003276 — the human CATEGORY chip. Quiet by design: it sits beside the
2988
3108
  meta line, not above the title, because it is a label a person scans, never a
2989
3109
  status or a permission (ADR 0192). No hover/pointer affordance and no href —
@@ -20,8 +20,8 @@
20
20
  margin-top: 6px;
21
21
  }
22
22
  .watch-stat {
23
- background: var(--surface);
24
- border: 1px solid var(--border);
23
+ background: var(--bg-card);
24
+ border: var(--line) solid var(--rule-soft);
25
25
  border-radius: var(--radius-sm);
26
26
  padding: 12px 14px;
27
27
  text-align: center;
@@ -53,7 +53,7 @@ table.watch {
53
53
  table.watch th, table.watch td {
54
54
  padding: 6px 10px;
55
55
  text-align: left;
56
- border-bottom: 1px solid var(--border);
56
+ border-bottom: var(--line) solid var(--rule-soft);
57
57
  vertical-align: top;
58
58
  }
59
59
  table.watch th {
@@ -62,31 +62,37 @@ table.watch th {
62
62
  text-transform: uppercase;
63
63
  letter-spacing: 0.06em;
64
64
  color: var(--ink-faint);
65
- border-bottom: 1px solid var(--border-strong);
65
+ border-bottom: var(--line) solid var(--rule);
66
66
  white-space: nowrap;
67
67
  }
68
68
  table.watch td.num { text-align: right; font-variant-numeric: tabular-nums; }
69
69
  table.watch td.warn { color: var(--danger); font-weight: 600; }
70
- table.watch tr:hover td { background: var(--surface-2); }
70
+ table.watch tr:hover td { background: var(--glass); }
71
71
  /* the kit ledger (audit log) shares the same numeric-cell affordances */
72
72
  .ledger td.num { text-align: right; font-variant-numeric: tabular-nums; }
73
73
  .ledger td.num.warn { color: var(--danger); font-weight: 600; }
74
- .watch-mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.84rem; color: var(--info); }
74
+ .watch-mono { font-family: var(--font-mono); font-size: 0.84rem; color: var(--info); }
75
75
  .watch-empty { color: var(--ink-faint); font-size: 13px; padding: 10px 0; }
76
+ /* .watch-subh is .watch-sub-h without the second hyphen, and watch.js emits
77
+ both (:400/832/857 vs :638/640). The base rule below already groups them, so
78
+ the two spellings LOOK the same — the only real divergence was :first-of-type
79
+ below, which matched one spelling and not the other, so a section whose first
80
+ sub-heading happened to be spelled the other way carried 16px of top margin
81
+ instead of 8. Grouped there too (task 1003307). */
76
82
  .watch-note { color: var(--ink-faint); font-size: 12.5px; margin-top: 10px; }
77
83
  .watch-rank { font-size: 12px; color: var(--ink-faint); }
78
84
  .watch-doc {
79
85
  white-space: pre-wrap;
80
86
  word-break: break-word;
81
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
87
+ font-family: var(--font-mono);
82
88
  font-size: 0.8rem;
83
89
  line-height: 1.5;
84
90
  max-height: 60vh;
85
91
  overflow-y: auto;
86
92
  padding: 12px;
87
93
  margin-top: 8px;
88
- background: var(--surface-2);
89
- border: 1px solid var(--border);
94
+ background: var(--glass);
95
+ border: var(--line) solid var(--rule-soft);
90
96
  border-radius: var(--radius-sm);
91
97
  }
92
98
  .watch-sub-h, .watch-subh {
@@ -96,26 +102,17 @@ table.watch tr:hover td { background: var(--surface-2); }
96
102
  color: var(--ink);
97
103
  margin: 16px 0 4px;
98
104
  }
99
- .watch-sub-h:first-of-type { margin-top: 8px; }
105
+ .watch-sub-h:first-of-type, .watch-subh:first-of-type { margin-top: 8px; }
100
106
 
101
107
  /* Severity / status badges. */
102
- .badge {
103
- display: inline-block;
104
- font-size: 11px;
105
- font-weight: 600;
106
- letter-spacing: 0.04em;
107
- text-transform: uppercase;
108
- padding: 2px 8px;
109
- border-radius: 999px;
110
- border: 1px solid var(--border-strong);
111
- color: var(--ink-soft);
112
- white-space: nowrap;
113
- }
114
- .badge--sev-critical { background: var(--danger-weak); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
115
- .badge--sev-high { background: var(--warn-weak); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
116
- .badge--sev-medium { background: var(--info-weak); color: var(--info); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
117
- .badge--sev-low { background: var(--surface-2); color: var(--ink-soft); }
118
- .badge--status { background: var(--surface-2); color: var(--ink-soft); }
108
+ /* Base: the shell's .fact-pill (task 1003307). A severity is a state, so it is a
109
+ hairline in its own colour rather than a filled chip — four filled severities
110
+ stacked in one table row was the loudest thing on the Watch board. */
111
+ .badge--sev-critical { color: var(--danger); }
112
+ .badge--sev-high { color: var(--warn); }
113
+ .badge--sev-medium { color: var(--info); }
114
+ .badge--sev-low { color: var(--ink-faint); }
115
+ .badge--status { color: var(--ink-faint); }
119
116
 
120
117
  /* Row action buttons + selects. */
121
118
  .watch-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
@@ -124,27 +121,27 @@ table.watch tr:hover td { background: var(--surface-2); }
124
121
  font-size: 12.5px;
125
122
  font-weight: 500;
126
123
  padding: 4px 12px;
127
- border: 1px solid var(--border-strong);
128
- background: var(--surface);
124
+ border: var(--line) solid var(--rule);
125
+ background: var(--bg-card);
129
126
  color: var(--ink-soft);
130
127
  border-radius: var(--radius-sm);
131
128
  cursor: pointer;
132
129
  }
133
- .watch-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
130
+ .watch-btn:hover:not(:disabled) { background: var(--glass); color: var(--ink); }
134
131
  .watch-btn:disabled { opacity: 0.45; cursor: default; }
135
- .watch-btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border-strong)); }
132
+ .watch-btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--rule)); }
136
133
  .watch-select {
137
134
  font-family: var(--font-body);
138
135
  font-size: 13px;
139
136
  padding: 4px 6px;
140
- border: 1px solid var(--border-strong);
141
- background: var(--surface);
137
+ border: var(--line) solid var(--rule);
138
+ background: var(--bg-card);
142
139
  color: var(--ink);
143
140
  border-radius: var(--radius-sm);
144
141
  }
145
142
 
146
143
  .watch-req {
147
- border-bottom: 1px solid var(--border);
144
+ border-bottom: var(--line) solid var(--rule-soft);
148
145
  padding: 10px 0;
149
146
  display: flex; gap: 14px; flex-wrap: wrap;
150
147
  align-items: flex-start; justify-content: space-between;
@@ -162,8 +159,8 @@ table.watch tr:hover td { background: var(--surface-2); }
162
159
  font-size: 13px; color: var(--ink);
163
160
  }
164
161
  .watch-trend__bar-track {
165
- background: var(--surface-2); border-radius: 3px; height: 12px; overflow: hidden;
166
- border: 1px solid var(--border);
162
+ background: var(--glass); border-radius: 3px; height: 12px; overflow: hidden;
163
+ border: var(--line) solid var(--rule-soft);
167
164
  }
168
165
  .watch-trend__bar-fill { background: var(--accent); height: 100%; display: block; }
169
166
  .watch-trend__val { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
@@ -171,7 +168,7 @@ table.watch tr:hover td { background: var(--surface-2); }
171
168
  .watch-list { list-style: none; padding: 0; margin: 8px 0 0; }
172
169
  .watch-list li {
173
170
  display: flex; justify-content: space-between; gap: 12px;
174
- padding: 5px 0; border-bottom: 1px solid var(--border);
171
+ padding: 5px 0; border-bottom: var(--line) solid var(--rule-soft);
175
172
  font-size: 13px;
176
173
  }
177
174
  .watch-list li .k { color: var(--ink); }
@@ -180,12 +177,12 @@ table.watch tr:hover td { background: var(--surface-2); }
180
177
  .watch-foot-link {
181
178
  display: inline-block; margin-top: 12px;
182
179
  font-size: 13px; font-weight: 500;
183
- color: var(--accent-text);
180
+ color: var(--accent-ink);
184
181
  }
185
182
 
186
183
  /* Invite by GitHub username (task 1003044) — the Access requests section's own
187
184
  form: the way in on an invite-only project, a shortcut on an apply one. */
188
- .watch-invite { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--rule-soft); border-radius: 10px; }
185
+ .watch-invite { margin: 0 0 14px; padding: 12px 14px; border: var(--line) solid var(--rule-soft); border-radius: 10px; }
189
186
  .watch-invite__label { display: block; font-weight: 600; margin-bottom: 6px; }
190
187
  .watch-invite__row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
191
188
  .watch-invite__row input[type="text"] { flex: 1 1 200px; min-width: 0; }
@@ -22,7 +22,15 @@
22
22
  <div class="app-body">
23
23
  <header class="app-topbar" id="app-topbar"></header>
24
24
  <div class="app-content">
25
- <div class="page-head"><p class="page-head__sub" id="watch-sub">Loading…</p></div>
25
+ <!-- task 1003307: the board page head. Watch shipped with NO <h1> at all
26
+ (one-header-main-h1 measured 0 on every render), so the re-skin
27
+ carries the structural fix rather than porting the hole. The heading
28
+ is the LABEL voice, not a display line: on a working surface the
29
+ page's own name is the least interesting thing on it. -->
30
+ <div class="page-head page-head--board">
31
+ <h1 class="page-head__h">Watch</h1>
32
+ <p class="page-head__sub" id="watch-sub">Loading…</p>
33
+ </div>
26
34
 
27
35
  <main id="hall-main">
28
36
  <!-- Restricted notice — shown by watch.js when the viewer is not an Archon. -->
@@ -0,0 +1,60 @@
1
+ {
2
+ "_": "Watch — the attention board behind requireGovernmentPage. The SEALED state (a viewer below the gate) is a real render, not an error page, so it is a state here. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
+ "page": "/builders/watch",
4
+ "surface": "hall-ui",
5
+ "stub": {
6
+ "prefix": "/builders/"
7
+ },
8
+ "modeQuery": false,
9
+ "_feeds": "The kit's own stub carries no feed for this page, so against it the page renders its EMPTY and SKELETON states — which is the point: those are states the floors must hold in. Against the hall-preview harness the same states render populated. Every declared 404 below is a fixture the harness does not carry, named rather than hidden.",
10
+ "ignoreRequests": [
11
+ "/api/(gds|bongos)/me$",
12
+ "/api/(gds|bongos)/me/",
13
+ "/api/(gds|bongos)/goals",
14
+ "/api/(gds|bongos)/inbox/",
15
+ "/api/(gds|bongos)/versions",
16
+ "/api/(gds|bongos)/watch",
17
+ "/api/(gds|bongos)/analytics",
18
+ "/api/(gds|bongos)/tasks"
19
+ ],
20
+ "ignoreConsole": [
21
+ "/api/(gds|bongos)/",
22
+ "\\b401\\b",
23
+ "\\b403\\b",
24
+ "\\b404\\b",
25
+ "\\b501\\b",
26
+ "Unauthorized",
27
+ "Forbidden",
28
+ "Not Found",
29
+ "Not Implemented",
30
+ "load failed"
31
+ ],
32
+ "states": {
33
+ "board": {
34
+ "auth": true,
35
+ "actions": [
36
+ [
37
+ "wait",
38
+ 700
39
+ ]
40
+ ],
41
+ "expect": {
42
+ "visible": [
43
+ "#watch-attention"
44
+ ]
45
+ }
46
+ },
47
+ "out": {
48
+ "auth": false
49
+ }
50
+ },
51
+ "reducedMotion": {
52
+ "auth": true,
53
+ "actions": [
54
+ [
55
+ "wait",
56
+ 600
57
+ ]
58
+ ]
59
+ }
60
+ }