@bongos/core 1.19.467 → 1.19.469
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.
- package/.bongos-core.json +86 -36
- package/docs/adr/0225-privacy-suppresses-cross-project-surfaces-only.md +84 -0
- package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +169 -0
- package/docs/adr/README.md +2 -0
- package/docs/copy-inventory.md +5 -10
- package/docs/copy-registry.json +15 -92
- package/docs/file-map.md +5 -1
- package/docs/module-api-changelog.md +4 -0
- package/docs/research/task-network-map/a-every-task-p2.png +0 -0
- package/docs/research/task-network-map/a-every-task-p40.png +0 -0
- package/docs/research/task-network-map/b-dependency-forest-p2.png +0 -0
- package/docs/research/task-network-map/b-dependency-forest-p40.png +0 -0
- package/docs/research/task-network-map/c-goals-p2.png +0 -0
- package/docs/research/task-network-map/c-goals-p40.png +0 -0
- package/docs/research/task-network-map/d-joined-by-goal.png +0 -0
- package/docs/research/task-network-map-readability.md +191 -0
- package/modules/hall-ui/public/people.css +3 -2
- package/modules/hall-ui/public/people.html +2 -2
- package/modules/hall-ui/public/people.js +5 -4
- package/modules/hall-ui/public/people.states.json +1 -1
- package/modules/hall-ui/public/settings.js +1 -1
- package/modules/hall-ui/public/style.css +4 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/spike-task-map.js +730 -0
- package/src/bongos/serve-internal.js +20 -8
- package/src/module-api.js +1 -1
- package/tests/hall_page_gate_map.mjs +4 -2
- package/tests/hall_reading_world.mjs +2 -2
- package/tests/hall_roster_world.mjs +40 -12
- package/tests/spike_task_map.mjs +0 -0
- package/modules/hall-ui/public/scouting.html +0 -69
- package/modules/hall-ui/public/scouting.states.json +0 -59
package/docs/copy-registry.json
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
6
|
+
"strings": 1586,
|
|
7
7
|
"unique_ids": 1376,
|
|
8
|
-
"certain":
|
|
8
|
+
"certain": 1586,
|
|
9
9
|
"heuristic": 0,
|
|
10
|
-
"duplicate_ids":
|
|
10
|
+
"duplicate_ids": 151
|
|
11
11
|
},
|
|
12
12
|
"surfaces": {
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
|
-
"files":
|
|
16
|
-
"strings":
|
|
15
|
+
"files": 72,
|
|
16
|
+
"strings": 1143
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -168,18 +168,6 @@
|
|
|
168
168
|
"modules/public-landing/public/projects.html:1042"
|
|
169
169
|
]
|
|
170
170
|
},
|
|
171
|
-
{
|
|
172
|
-
"id": "b95918d421ae",
|
|
173
|
-
"surface": "builders-hall",
|
|
174
|
-
"text": "People — {{worldName}}",
|
|
175
|
-
"occurrences": 4,
|
|
176
|
-
"at": [
|
|
177
|
-
"modules/hall-ui/public/people.html:6",
|
|
178
|
-
"modules/hall-ui/public/people.html:6",
|
|
179
|
-
"modules/hall-ui/public/scouting.html:6",
|
|
180
|
-
"modules/hall-ui/public/scouting.html:6"
|
|
181
|
-
]
|
|
182
|
-
},
|
|
183
171
|
{
|
|
184
172
|
"id": "3eb67b892dea",
|
|
185
173
|
"surface": "landing",
|
|
@@ -499,16 +487,6 @@
|
|
|
499
487
|
"modules/hall-ui/public/watch.js:315"
|
|
500
488
|
]
|
|
501
489
|
},
|
|
502
|
-
{
|
|
503
|
-
"id": "29bd516ad17e",
|
|
504
|
-
"surface": "builders-hall",
|
|
505
|
-
"text": "Builder directory",
|
|
506
|
-
"occurrences": 2,
|
|
507
|
-
"at": [
|
|
508
|
-
"modules/hall-ui/public/people.html:37",
|
|
509
|
-
"modules/hall-ui/public/scouting.html:42"
|
|
510
|
-
]
|
|
511
|
-
},
|
|
512
490
|
{
|
|
513
491
|
"id": "563d29ed86d8",
|
|
514
492
|
"surface": "builders-hall",
|
|
@@ -709,16 +687,6 @@
|
|
|
709
687
|
"modules/hall-ui/public/drachmae.html:6"
|
|
710
688
|
]
|
|
711
689
|
},
|
|
712
|
-
{
|
|
713
|
-
"id": "ddebbccd4b37",
|
|
714
|
-
"surface": "builders-hall",
|
|
715
|
-
"text": "Everyone building across hosted projects, ranked by track record. Descriptive only — cross-project numbers never carry authority here.",
|
|
716
|
-
"occurrences": 2,
|
|
717
|
-
"at": [
|
|
718
|
-
"modules/hall-ui/public/people.html:29",
|
|
719
|
-
"modules/hall-ui/public/scouting.html:34"
|
|
720
|
-
]
|
|
721
|
-
},
|
|
722
690
|
{
|
|
723
691
|
"id": "f70f217504ce",
|
|
724
692
|
"surface": "status-dashboard",
|
|
@@ -879,16 +847,6 @@
|
|
|
879
847
|
"modules/status-ui/public/index.html:312"
|
|
880
848
|
]
|
|
881
849
|
},
|
|
882
|
-
{
|
|
883
|
-
"id": "2bde9c630fd2",
|
|
884
|
-
"surface": "builders-hall",
|
|
885
|
-
"text": "Loading the directory…",
|
|
886
|
-
"occurrences": 2,
|
|
887
|
-
"at": [
|
|
888
|
-
"modules/hall-ui/public/people.html:40",
|
|
889
|
-
"modules/hall-ui/public/scouting.html:45"
|
|
890
|
-
]
|
|
891
|
-
},
|
|
892
850
|
{
|
|
893
851
|
"id": "ceec2218efe3",
|
|
894
852
|
"surface": "builders-hall",
|
|
@@ -1049,6 +1007,16 @@
|
|
|
1049
1007
|
"modules/hall-ui/public/goals.html:187"
|
|
1050
1008
|
]
|
|
1051
1009
|
},
|
|
1010
|
+
{
|
|
1011
|
+
"id": "b95918d421ae",
|
|
1012
|
+
"surface": "builders-hall",
|
|
1013
|
+
"text": "People — {{worldName}}",
|
|
1014
|
+
"occurrences": 2,
|
|
1015
|
+
"at": [
|
|
1016
|
+
"modules/hall-ui/public/people.html:6",
|
|
1017
|
+
"modules/hall-ui/public/people.html:6"
|
|
1018
|
+
]
|
|
1019
|
+
},
|
|
1052
1020
|
{
|
|
1053
1021
|
"id": "ed8edd684547",
|
|
1054
1022
|
"surface": "builders-hall",
|
|
@@ -2478,15 +2446,6 @@
|
|
|
2478
2446
|
"origin": "html-text",
|
|
2479
2447
|
"confidence": "certain"
|
|
2480
2448
|
},
|
|
2481
|
-
{
|
|
2482
|
-
"id": "29bd516ad17e",
|
|
2483
|
-
"surface": "builders-hall",
|
|
2484
|
-
"text": "Builder directory",
|
|
2485
|
-
"file": "modules/hall-ui/public/scouting.html",
|
|
2486
|
-
"line": 42,
|
|
2487
|
-
"origin": "html-text",
|
|
2488
|
-
"confidence": "certain"
|
|
2489
|
-
},
|
|
2490
2449
|
{
|
|
2491
2450
|
"id": "08bfcc9198ba",
|
|
2492
2451
|
"surface": "builders-hall",
|
|
@@ -4431,15 +4390,6 @@
|
|
|
4431
4390
|
"origin": "html-text",
|
|
4432
4391
|
"confidence": "certain"
|
|
4433
4392
|
},
|
|
4434
|
-
{
|
|
4435
|
-
"id": "ddebbccd4b37",
|
|
4436
|
-
"surface": "builders-hall",
|
|
4437
|
-
"text": "Everyone building across hosted projects, ranked by track record. Descriptive only — cross-project numbers never carry authority here.",
|
|
4438
|
-
"file": "modules/hall-ui/public/scouting.html",
|
|
4439
|
-
"line": 34,
|
|
4440
|
-
"origin": "html-text",
|
|
4441
|
-
"confidence": "certain"
|
|
4442
|
-
},
|
|
4443
4393
|
{
|
|
4444
4394
|
"id": "4750e12477e7",
|
|
4445
4395
|
"surface": "builders-hall",
|
|
@@ -5583,15 +5533,6 @@
|
|
|
5583
5533
|
"origin": "html-text",
|
|
5584
5534
|
"confidence": "certain"
|
|
5585
5535
|
},
|
|
5586
|
-
{
|
|
5587
|
-
"id": "2bde9c630fd2",
|
|
5588
|
-
"surface": "builders-hall",
|
|
5589
|
-
"text": "Loading the directory…",
|
|
5590
|
-
"file": "modules/hall-ui/public/scouting.html",
|
|
5591
|
-
"line": 45,
|
|
5592
|
-
"origin": "html-text",
|
|
5593
|
-
"confidence": "certain"
|
|
5594
|
-
},
|
|
5595
5536
|
{
|
|
5596
5537
|
"id": "fcd755e8dd30",
|
|
5597
5538
|
"surface": "builders-hall",
|
|
@@ -6789,24 +6730,6 @@
|
|
|
6789
6730
|
"origin": "html-title",
|
|
6790
6731
|
"confidence": "certain"
|
|
6791
6732
|
},
|
|
6792
|
-
{
|
|
6793
|
-
"id": "b95918d421ae",
|
|
6794
|
-
"surface": "builders-hall",
|
|
6795
|
-
"text": "People — {{worldName}}",
|
|
6796
|
-
"file": "modules/hall-ui/public/scouting.html",
|
|
6797
|
-
"line": 6,
|
|
6798
|
-
"origin": "html-text",
|
|
6799
|
-
"confidence": "certain"
|
|
6800
|
-
},
|
|
6801
|
-
{
|
|
6802
|
-
"id": "b95918d421ae",
|
|
6803
|
-
"surface": "builders-hall",
|
|
6804
|
-
"text": "People — {{worldName}}",
|
|
6805
|
-
"file": "modules/hall-ui/public/scouting.html",
|
|
6806
|
-
"line": 6,
|
|
6807
|
-
"origin": "html-title",
|
|
6808
|
-
"confidence": "certain"
|
|
6809
|
-
},
|
|
6810
6733
|
{
|
|
6811
6734
|
"id": "4a46b478edaf",
|
|
6812
6735
|
"surface": "builders-hall",
|
package/docs/file-map.md
CHANGED
|
@@ -68,6 +68,9 @@
|
|
|
68
68
|
│ │ ├── overnight-builder.md ← (#358) operator runbook for the autonomous overnight session-runner
|
|
69
69
|
│ │ ├── builder-box-lifecycle.md ← (#598/ADR 0031) operator runbook: provision/park/wake/deprovision dev boxes, the two sweeps, config env, going-live steps
|
|
70
70
|
│ │ └── managed-settings-remote-control.md ← (#599/ADR 0031 §1, #760/ADR 0038) operator+builder guide: distribute the locked Claude Desktop SSH config; the browser web-terminal (ttyd + Cloudflare Tunnel) on-ramp
|
|
71
|
+
│ ├── research/ ← investigations that answer a question rather than record a decision (an ADR) or a procedure (a recipe)
|
|
72
|
+
│ │ ├── task-network-map-readability.md ← (task 1003282, goal 1000072) the spike verdict: a node-link map of ~1,357 tasks is unreadable at every dependency density — 59–97% isolated dots, and the dense fix overplots 84% of them into the 40-node goal graph. Build the goal graph + a per-goal dependency forest; measure the real density with `--from` first
|
|
73
|
+
│ │ └── task-network-map/ ← the figures that verdict argues from, rendered by scripts/gds/spike-task-map.js — regenerate, never hand-edit
|
|
71
74
|
│ ├── reviews/ ← temporary audit/review docs (e.g. claude-md-audit-V3.R86.md)
|
|
72
75
|
│ ├── session-logs/ ← one file per session, named YYYY-MM-DD-<slug>.md (CLAUDE.md §13 indexes them)
|
|
73
76
|
│ └── session-log-archive.md ← compressed older session-log prose
|
|
@@ -127,7 +130,7 @@
|
|
|
127
130
|
│ ├── sessions/ ← CORE-DOMAIN carve (BV1.R82, default-on): the session_records corpus + data plane (upload, cross-builder search/deep-dive), the BFG read-the-room scorer, session-pulse/stale-claim helpers. Registers no port — reached via HTTP POST to its own /sessions route; resolves the economy `reward` port for the cost-plus token reward. CLAUDE.md, module.json, routes/sessions.js, bfg.js, pulse.js.
|
|
128
131
|
│ ├── autonomy/ ← CORE-DOMAIN carve (BV1.R83, default-on): the MAS autonomy surfaces — the $0 deterministic autonomy gate (System 3, inert until armed), the conductor/architect CLIs, and the in-process routine timers (incl. the weekly peer-vote-tally poller). Registers no port; resolves the lifecycle `tallyPeerVotes` doorway. CLAUDE.md, module.json, routes/autonomy.js, autonomy.js.
|
|
129
132
|
│ ├── status-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R84, default-on): the public status dashboard at status.<apex>, moved from public-status/. NO routes/db/port — declares contributes.webSurfaces:[{host:"status.",dir:"public"}], served by the loader web-surface seam (moduleWebSurfaces → serve-internal). CLAUDE.md, module.json, public/{index.html,status.js,style.css,cursors/,snapshots/}.
|
|
130
|
-
│ ├── hall-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R85, default-on): the authenticated builders' hall at builders.<apex>, moved from public-builders/ (~13k LOC, the largest). NO routes/db/port — declares contributes.webSurfaces:[{host:"builders.",dir:"public"}] for discovery, but UNLIKE status-ui keeps its DEDICATED serving block in serve-internal (the /builders shim + canonical redirects + citizen/Archon page gates + asset-stamping + hall-widget injection), partitioned out of the generic web-surface loop and served from BUILDERS_DIR. CLAUDE.md, module.json, public/{index.html,builders.js,style.css,work,watch,harbor,gate,pair,settings,ranks,sessions,primer,diagrams,atlas,...}.{html,js},cursors/,chime.wav. Three ARCHETYPE sheets sit beside the per-page ones: `record.css` (the task + idea records, task 1003305), `room.css` (the READING ROOMS — the primer + the diagrams index, task 1003306: the reading measure and rhythm, the table of contents, the progress hairline and the framed figure diagram-viewer.js upgrades on both pages) and `oversight.css` (the OVERSIGHT family — government, watch, harbor, gate, task 1003469: the row, the figure band inside a panel, the group head, the inline form, the grant toggle and the shared confirm modal; named oversight because the vocabulary wall bans "governance" on the government surface). A page sheet then holds only what one page has and the others do not — `primer.css` the acknowledge gate, `diagrams.css` the legend strip, `gate.css` the hold reasons and file chips, `watch.css` the severities, the report reader and the grade trend, `people.css` the directory's identity cell (task 1003470
|
|
133
|
+
│ ├── hall-ui/ ← CORE-DOMAIN WEB-SURFACE carve (BV1.R85, default-on): the authenticated builders' hall at builders.<apex>, moved from public-builders/ (~13k LOC, the largest). NO routes/db/port — declares contributes.webSurfaces:[{host:"builders.",dir:"public"}] for discovery, but UNLIKE status-ui keeps its DEDICATED serving block in serve-internal (the /builders shim + canonical redirects + citizen/Archon page gates + asset-stamping + hall-widget injection), partitioned out of the generic web-surface loop and served from BUILDERS_DIR. CLAUDE.md, module.json, public/{index.html,builders.js,style.css,work,watch,harbor,gate,pair,settings,ranks,sessions,primer,diagrams,atlas,...}.{html,js},cursors/,chime.wav. Three ARCHETYPE sheets sit beside the per-page ones: `record.css` (the task + idea records, task 1003305), `room.css` (the READING ROOMS — the primer + the diagrams index, task 1003306: the reading measure and rhythm, the table of contents, the progress hairline and the framed figure diagram-viewer.js upgrades on both pages) and `oversight.css` (the OVERSIGHT family — government, watch, harbor, gate, task 1003469: the row, the figure band inside a panel, the group head, the inline form, the grant toggle and the shared confirm modal; named oversight because the vocabulary wall bans "governance" on the government surface). A page sheet then holds only what one page has and the others do not — `primer.css` the acknowledge gate, `diagrams.css` the legend strip, `gate.css` the hold reasons and file chips, `watch.css` the severities, the report reader and the grade trend, `people.css` the directory's identity cell (task 1003470 made the legacy door `/scouting` ship the same body and script as `/people`; task 1003440 then deleted the door — `scouting.html` and `scouting.states.json` are gone and the URL 301s to `/people`).
|
|
131
134
|
│ ├── lifecycle/ ← CORE-DOMAIN carve (BV1.R86, default-on): the build state machine — tasks · claims · versions · done-when · goals · dependencies · claim→ship→grade→credit · github-push + merge-lock + conflict-resolve + publish-reconciler. The LAST, most-coupled carve; registers the `lifecycle` kernel port (createTask, classifyTaskKind, tallyPeerVotes, work-tracking reads). CLAUDE.md, module.json, routes/{tasks,claims,versions,done-when,goals,dependencies,gate-approvals,analytics}.js, lifecycle.js, github-push.js, merge-lock.js, conflict-resolve.js, publish-reconciler.js, task-visuals.js + task-visual-db.js + routes/visuals.js (the optional ship-time visual, task 1003109 — the route file is NOT named task-*.js on purpose; see the module CLAUDE.md).
|
|
132
135
|
│ ├── copy-desk/ ← CORE-DOMAIN module (task 1003113 / R02 of goal 1000074, default-on): the COPY half of the design contract — ADR 0081 gave design TOKENS a repo-owned source of truth, text had none. Owns the FLAG (anyone in any role marks a string or a whole surface as needing an artist's attention, with a reason required in BOTH the route and a CHECK constraint) and the QUEUE an artist reads it from. READS R01's committed registry (docs/copy-registry.json, generated by scripts/gds/copy-inventory.js) and never writes it. NO LIVE CMS is the hard non-goal: no column here could hold replacement text, and copy_no_cms.mjs pins that. Key is `copy-desk`, not `copy` — the branding contract already owns a `copy` block, so the bare word reds the "core carries no module code" fitness check. CLAUDE.md, module.json, registry.js, flags.js, routes/copy-desk.js, migrations/copy_desk_001_flags.sql, tests/{copy_flags,copy_queue,copy_no_cms}.mjs. Its hall surface lives with hall-ui (public/copy-desk.{html,js,css}), per the one-key-per-web-surface precedent.
|
|
133
136
|
│ ├── ui-design/ ← CORE-DOMAIN module (task 1003324 / ADR 0197, default-on): the design capability every builder on every instance gets — ships METHOD, never a world. Absorbs ADR 0081's layer: adapters/{claude-design,figma}/index.js (moved from src/ui/adapters/), scripts/{design-sync,figma-design-sync,validate-design}.js (moved from scripts/gds/, which keeps thin shims), docs/design-contract.md (moved from docs/). Declaration-only: contributes.skills design (the /design playbook, new) + design-sync + figma-design-sync; no routes/port/migrations, so disabling it touches no served surface. CLAUDE.md separates the platform FLOORS (the Fifteen Rule, the dark twins, no page :root, the 24px floor, AA in both modes, the kill switch) from the instance's WORLD (its packs + DESIGN.md). kit/ (task 1003320) is the look-before-you-ship kit: lib.js (the floors, the states/probes contracts, the action + expectation vocabularies, the WCAG maths, the stub spawner), serve.js (any surface through the doorway's real transforms + fixtures/), render.js (states × 1440/390/320 × dark/light, audited), probe.js (PASS/FAIL contracts), check-mock.js (platform rules + the instance's DESIGN.md taste bans, then the detector), tells.js (task 1003329 / ADR 0223: the anti-pattern detector as two tiers — floors FAIL, craft tells WARN, kit-ignore waivers per file; the rendered twins live in lib.js factsInPage), contrast.js + png.js; a page's <page>.states.json / <page>.probes.json sit BESIDE the surface (modules/public-landing/public/, modules/hall-ui/public/). Recipe: docs/recipes/ui-look-before-you-ship.md. skills/ (task 1003321 / ADR 0198) is the vendoring policy: policy.json (licence allowlist, verdicts that may land, sidecar fields, preamble markers), PREAMBLE.md (the platform preamble every vendored SKILL.md opens with), README.md (the roster — both origins scanned dangerous on 2026-08-28, landed as rebuild specs; nothing vendored — and the landing recipe); a landable copy goes under skills/vendor/<name>/ with PROVENANCE.md + LICENSE and is materialised into an instance's .claude/skills/ by claude-materialize.js step 1b. skills/<name>/ (task 1003325 / ADR 0220) are the in-house rebuilds from the specs, first-party and counted: design-taste-frontend (the default taste skill), design-taste-frontend-v1 (the earlier generation, kept distinct), high-end-visual-design (the polish pass), redesign-existing-projects (the in-place upgrade); each opens with the same preamble and carries a "Rebuilt from" section instead of a sidecar. impeccable/ (task 1003326 / ADR 0221) is the design-craft method as ONE skill with sub-commands: SKILL.md (the router, the menu, the craft floor, the bounded finish) + reference/<sub-command>.md (eighteen playbooks, one loaded per request); no hooks, no bypass agent, no telemetry, no live server. image-to-code/, imagegen-frontend-web/, imagegen-frontend-mobile/, brandkit/ (task 1003328 / ADR 0222) are the image family under the hero-only rule: plates and hero objects only, the pair (JPEG dark plate + WebP alpha cutout) with a <file>.json sidecar beside each, through the instance's art pipeline key; the grove specimen's styles/grove/assets/ is the worked example. styles/ (task 1003323 / ADR 0219) is the style library: <name>/pack.json (the theme.ui overlay, exactly the fifteen) + DESIGN.md (the look's derived recipes, thirteen in lockstep with the pack) + mock.html (the specimen); chrome-world (pinned to the neutral pack), expedition, grove; STYLE=<name> on the kit lays a look over the instance's pack through GDS_BRANDING_FILE; tests/ui_design_styles.mjs runs the world/cosmos/hall token suites once per alternate (UI_DESIGN_PACK). config/design-tokens.* + design-sources.json STAY in config/ as the host boundary; public-landing keeps its own key (first customer, not owner).
|
|
@@ -159,6 +162,7 @@
|
|
|
159
162
|
│ ├── next-number.js ← deterministic next-free ADR + migration number from origin/main ∪ local working tree; supersedes the drift-prone claim-time DB counter (V4.R26, [#964](https://example.com/builders#/task/964)). `node scripts/gds/next-number.js [--json]`
|
|
160
163
|
│ ├── gen-repo-map.js ← Path B (ADR 0063, [#1224](https://example.com/builders#/task/1224)): zero-dep, deterministic symbol-skeleton generator → docs/repo-map.md + the generated factual block in each nested CLAUDE.md; ranks exported symbols by reference frequency. `--check` = CI gate; regenerated on deploy by ship.js regenerateRepoMap()
|
|
161
164
|
│ ├── gen-file-map.js ← ADR 0066 ([#1276](https://example.com/builders#/task/1276)): generates the `.claude/skills/` + `.claude/scheduled-tasks/` sections of docs/file-map.md from disk; per-entry notes come from docs/file-map.notes.json; `--check` fails on drift OR a skill/routine with no note (CI gate via fitness.js); regenerated on deploy by ship.js regenerateFileMap()
|
|
165
|
+
│ ├── spike-task-map.js ← (task 1003282, goal 1000072) the task-network-map spike harness: builds a ~1,357-task graph across a swept dependency density, lays it out for real (<redacted> + Barnes-Hut), counts what decides readability (isolated nodes, components, distinguishable marks / overplot, crossings, ink budget, payload) and renders PNGs with a hand-rolled encoder. Zero deps, no DB. `--from <tasks.json>` measures the REAL corpus instead of the model. Verdict: docs/research/task-network-map-readability.md
|
|
162
166
|
│ ├── fitness.js ← Path C (ADR 0062 §9, [#1225](https://example.com/builders#/task/1225)): architecture fitness functions — core↔host import boundary (zero grandfathered exceptions as of R52/#1191), CLAUDE.md budget + nested-doc presence (ADR 0061), no route bypasses rank checks (reuses route-rank-check), repo-map freshness. Enforced in CI via tests/fitness.mjs (the `unit` gate). `node scripts/gds/fitness.js`
|
|
163
167
|
│ ├── ship.js ← resolve claim as shipped, award credits (`/builder-ship`); also uploads a secret-scrubbed session digest to the corpus (6D.1, ADR 0027); on a dev box runs the sandbox-first review gate before resolving (#927, ADR 0046)
|
|
164
168
|
│ ├── ship-visual.js ← the OPTIONAL `--visual <image> [--visual-alt "…"]` leg of a ship (task 1003109): screens the file BEFORE the claim resolves (bad input costs no claim), uploads it AFTER (a failed picture never fails a ship)
|
|
@@ -1371,5 +1371,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1371
1371
|
landed since 1.19.465 with no explicit bump. run 33583122775. (task 1002620)
|
|
1372
1372
|
1.19.467 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1373
1373
|
landed since 1.19.466 with no explicit bump. run 33638703282. (task 1002620)
|
|
1374
|
+
1.19.468 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1375
|
+
landed since 1.19.467 with no explicit bump. run 33640370009. (task 1002620)
|
|
1376
|
+
1.19.469 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1377
|
+
landed since 1.19.468 with no explicit bump. run 33643388774. (task 1002620)
|
|
1374
1378
|
---------------------------------------------------------------------------
|
|
1375
1379
|
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Can a network map of ~1,357 tasks be read? — the spike
|
|
2
|
+
|
|
3
|
+
- **Task:** [1003282](https://cloudbongos.com/builders#/task/1003282) · goal 1000072 (Human legibility)
|
|
4
|
+
- **Date:** 2026-08-28
|
|
5
|
+
- **Harness:** [`scripts/gds/spike-task-map.js`](../../scripts/gds/spike-task-map.js) — no dependencies, no network, no DB. Re-run with `node scripts/gds/spike-task-map.js`.
|
|
6
|
+
- **Figures:** [`docs/research/task-network-map/`](task-network-map/) — rendered by the harness, not drawn by hand.
|
|
7
|
+
|
|
8
|
+
## The answer
|
|
9
|
+
|
|
10
|
+
**No — not as a map of tasks, at any dependency density, and the obvious fix makes it
|
|
11
|
+
worse.** What *is* readable is the forty-node **goal** graph as the entry point, with a
|
|
12
|
+
per-goal **dependency forest** as the drill-down. That second view is 3–40% of the
|
|
13
|
+
corpus, never 100%, and that is the finding rather than a compromise: the tasks it
|
|
14
|
+
leaves out are the ones with nothing to connect them to.
|
|
15
|
+
|
|
16
|
+
The map worth building is therefore **not** "the task graph, zoomed out". It is the
|
|
17
|
+
goal graph, drawn once, with a task-level view that opens *inside* a goal.
|
|
18
|
+
|
|
19
|
+
## How it was measured
|
|
20
|
+
|
|
21
|
+
The house rule for questions of this shape was set by this goal's own shipped criterion
|
|
22
|
+
`legibility-sort-and-staleness`: *"~1,357 tasks on BONGOS-V1 alone. A view that does not
|
|
23
|
+
survive that number is not a solution"* — answered in `tests/goal_sort_staleness.mjs` by
|
|
24
|
+
**executing** the board pipeline over a corpus that size. A network map is the same
|
|
25
|
+
question one dimension harder, so it got the same treatment: build the graph, lay it out
|
|
26
|
+
with a real Fruchterman–Reingold pass (Barnes–Hut quadtree, θ=0.8 — the approximation
|
|
27
|
+
d3-force uses), draw it to a real raster, and count.
|
|
28
|
+
|
|
29
|
+
**The dependency density is swept, not guessed.** How many tasks actually declare a
|
|
30
|
+
`task_dependencies` row is a fact of the live DB, which this environment cannot reach.
|
|
31
|
+
Rather than assume one number, the harness sweeps p ∈ {2, 5, 10, 20, 40}% — the share of
|
|
32
|
+
tasks declaring at least one dependency — and reports where each conclusion would flip.
|
|
33
|
+
Every conclusion below holds across the whole range, which is why the missing fact does
|
|
34
|
+
not change the verdict. Point the harness at a real dump to replace every number here
|
|
35
|
+
with a measured one:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
node scripts/gds/spike-task-map.js --from tasks.json # a GET /tasks?include=deps dump
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Four views of the same corpus, all at 1280×720 (a laptop viewport with the hall's chrome
|
|
42
|
+
removed — quoting a 4K desktop would flatter the result for a screen most readers do not
|
|
43
|
+
have):
|
|
44
|
+
|
|
45
|
+
| | view | what it is |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| **A** | every task | the literal reading of "a network map of 1,300 tasks" |
|
|
48
|
+
| **B** | tasks with a dependency | A with the unconnected nodes swept off |
|
|
49
|
+
| **C** | goals | one node per goal, cross-goal dependencies aggregated |
|
|
50
|
+
| **D** | tasks joined by goal | the obvious second attempt, once A turns out to be sparse |
|
|
51
|
+
|
|
52
|
+
## The numbers
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
density view nodes edges isol% comps marks lost% cross pitch label? ms KB
|
|
56
|
+
------------------------------------------------------------------------------------------------------------------------
|
|
57
|
+
p=2% every task 1357 21 97.2 1336 1355 0.1 0 26.1px NO 861 6
|
|
58
|
+
p=2% tasks with a dependency 38 21 0 17 38 0 0 155.7px yes 34 0
|
|
59
|
+
p=2% goals 40 5 80 35 40 0 0 151.8px yes 54 0
|
|
60
|
+
any tasks joined by goal 1357 22341 0 40 222 83.6 1492927~ 26.1px NO 1003 232
|
|
61
|
+
p=5% every task 1357 44 94.1 1313 1352 0.4 1 26.1px NO 855 6
|
|
62
|
+
p=5% tasks with a dependency 80 44 0 36 80 0 1 107.3px yes 24 1
|
|
63
|
+
p=5% goals 40 7 72.5 33 40 0 2 151.8px yes 8 0
|
|
64
|
+
p=10% every task 1357 81 89.7 1277 1351 0.4 2 26.1px NO 818 6
|
|
65
|
+
p=10% tasks with a dependency 140 81 0 60 140 0 2 81.1px yes 54 1
|
|
66
|
+
p=10% goals 40 13 52.5 27 40 0 2 151.8px yes 9 0
|
|
67
|
+
p=20% every task 1357 168 79.2 1189 1336 1.5 5 26.1px NO 884 7
|
|
68
|
+
p=20% tasks with a dependency 282 168 0 114 282 0 8 57.2px yes 143 3
|
|
69
|
+
p=20% goals 40 31 22.5 12 40 0 12 151.8px yes 9 0
|
|
70
|
+
p=40% every task 1357 351 59.5 1006 1320 2.7 33 26.1px NO 897 9
|
|
71
|
+
p=40% tasks with a dependency 549 351 0 198 549 0 30 41px NO 325 6
|
|
72
|
+
p=40% goals 40 50 2.5 2 40 0 44 151.8px yes 10 0
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`marks` = distinct 7px cells any node lands in — what a reader can actually tell apart.
|
|
76
|
+
`lost%` = share of nodes overplotting a mark another node already owns.
|
|
77
|
+
`pitch` = √(canvas area ÷ nodes), the square each node owns. `label?` asks whether that
|
|
78
|
+
square is as wide as a six-character label (48px).
|
|
79
|
+
|
|
80
|
+
## What each row says
|
|
81
|
+
|
|
82
|
+
### A — "every task" is confetti, not a hairball
|
|
83
|
+
|
|
84
|
+
This is the surprise, and it is the whole result. A 1,357-node graph is *expected* to
|
|
85
|
+
fail as a tangle: too many edges, too many crossings, one illegible ball of yarn. It
|
|
86
|
+
fails the other way. **59.5% to 97.2% of tasks have no dependency at all**, so the
|
|
87
|
+
picture is 1,006–1,336 separate components — overwhelmingly single dots — and **33
|
|
88
|
+
crossings at the densest end**, which is nothing.
|
|
89
|
+
|
|
90
|
+

|
|
91
|
+
|
|
92
|
+
That disc of 1,320 distinguishable dots with a few three-node chains in the middle is
|
|
93
|
+
the *best* case in the sweep. Two things follow, and neither is fixable by drawing
|
|
94
|
+
better:
|
|
95
|
+
|
|
96
|
+
- **A force layout is arranging nothing.** It has no opinion about where a thousand
|
|
97
|
+
unconnected islands go, so their positions carry no information. Every dot's location
|
|
98
|
+
is an accident of the seed. A reader who infers anything from proximity here is being
|
|
99
|
+
misled by the renderer.
|
|
100
|
+
- **Labels never fit.** 26.1px of pitch against the 48px a six-character label needs —
|
|
101
|
+
and that is the *average*, before clustering. So the map cannot say which task any dot
|
|
102
|
+
is, which means the only way to read it is to hover 1,357 times.
|
|
103
|
+
|
|
104
|
+
Sparse-and-disconnected is a *different failure* from dense-and-tangled, and it needs a
|
|
105
|
+
different answer. You cannot declutter your way out of it; there is no clutter.
|
|
106
|
+
|
|
107
|
+
### D — making it dense draws the goal graph, badly
|
|
108
|
+
|
|
109
|
+
The natural next move once A turns out sparse: connect tasks by something that actually
|
|
110
|
+
relates them. Shared goal is the obvious candidate, and it is the one a "task network"
|
|
111
|
+
would reach for.
|
|
112
|
+
|
|
113
|
+

|
|
114
|
+
|
|
115
|
+
Forty dots. **22,341 edges, ~1.49 million crossings, 232 KB of graph, a full second of
|
|
116
|
+
layout — and 83.6% of the nodes overplot, leaving 222 marks that read as forty.** Each
|
|
117
|
+
goal is a clique, so each clique contracts to a blob smaller than the dot used to draw
|
|
118
|
+
it, and every edge inside it is sub-pixel.
|
|
119
|
+
|
|
120
|
+
The dense view spends three orders of magnitude more edges to draw, illegibly, the
|
|
121
|
+
picture that view C draws legibly with fifty. That is not a tuning problem. It is the
|
|
122
|
+
data saying that at this scale the only structure the eye can extract from 1,357 tasks
|
|
123
|
+
**is** the forty goals.
|
|
124
|
+
|
|
125
|
+
### C — the goal graph is readable, everywhere in the sweep
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
Forty nodes, 5–50 edges, zero overplot, 151.8px of pitch — three times what a label
|
|
130
|
+
needs — and it stays readable at every density measured. It is also the view the system
|
|
131
|
+
already computes: `modules/lifecycle/goal-rollup.js` produces one row per goal in
|
|
132
|
+
Postgres precisely because the browser could not hold the task corpus (5,229,455 bytes
|
|
133
|
+
for ~1,400 tasks, measured 2026-08-25). **The readable map is the one whose data layer
|
|
134
|
+
already exists.**
|
|
135
|
+
|
|
136
|
+
At low density it has its own honest weakness — 80% of goals are isolated at p=2%,
|
|
137
|
+
because cross-goal dependencies are what draw its edges. A goal graph with no edges is a
|
|
138
|
+
legend, not a map. Which side of that line the live corpus falls on is the one number
|
|
139
|
+
worth measuring before building.
|
|
140
|
+
|
|
141
|
+
### B — the dependency forest is the drill-down
|
|
142
|
+
|
|
143
|
+

|
|
144
|
+
|
|
145
|
+
Sweeping the isolated nodes off A leaves 38–549 nodes and zero overplot, readable with
|
|
146
|
+
labels up to p=20% and as unlabelled dots beyond. This is the task-level view that
|
|
147
|
+
works, and it works *because* it does not try to show every task.
|
|
148
|
+
|
|
149
|
+
Note what it costs: at p=40% it still fails the label test (41px pitch), so even the
|
|
150
|
+
forest wants scoping. Per goal it is 1–14 nodes — comfortably readable, and the natural
|
|
151
|
+
thing to open when someone clicks a goal in C.
|
|
152
|
+
|
|
153
|
+
## What to build, if anything
|
|
154
|
+
|
|
155
|
+
1. **The goal graph (C) as the map.** Forty nodes, edges = cross-goal dependencies,
|
|
156
|
+
weight = task count, colour = the ADR 0192 category the goals already carry. Its data
|
|
157
|
+
is one `goalRollups` query plus a cross-goal dependency count; the payload is bytes,
|
|
158
|
+
not megabytes.
|
|
159
|
+
2. **The dependency forest (B), scoped to one goal, as the drill-down.** Not a zoom of a
|
|
160
|
+
global map — a separate, small query answered when a goal is opened.
|
|
161
|
+
3. **Never view A, and never view D.** Not as a default, not as an "advanced" toggle.
|
|
162
|
+
A shows a thousand dots whose positions are noise; D shows forty dots and calls it a
|
|
163
|
+
thousand. Both invite a reader to believe they are seeing structure that is not there,
|
|
164
|
+
which is a worse outcome than no map — this goal is about legibility, and a confident
|
|
165
|
+
picture of nothing is the opposite of it.
|
|
166
|
+
|
|
167
|
+
**Before any of it is built, measure the real density**, with `--from`. Two numbers
|
|
168
|
+
decide the shape: the share of tasks carrying a dependency (does B have anything in it?)
|
|
169
|
+
and the share of dependencies that cross a goal boundary (does C have any edges?). If
|
|
170
|
+
cross-goal dependencies are near zero, C is forty disconnected dots and the honest
|
|
171
|
+
deliverable is a grid of goal cards, not a graph — which the hall's Goals page already
|
|
172
|
+
is. **That is a real possible outcome of this spike, and it would mean the right amount
|
|
173
|
+
of new map to build is none.**
|
|
174
|
+
|
|
175
|
+
## Caveats, stated plainly
|
|
176
|
+
|
|
177
|
+
- **The corpus is synthetic.** The live DB is unreachable from the environment this ran
|
|
178
|
+
in, so the harness sweeps a plausible range instead of measuring one truth. The sweep
|
|
179
|
+
is what makes the verdict robust — every conclusion above holds from p=2% to p=40% —
|
|
180
|
+
but the *specific* numbers are model output, not observation. Re-run with `--from`.
|
|
181
|
+
- **The goal count (40) and the 85% within-goal edge preference are modelled**, from the
|
|
182
|
+
repo's own record of ~38 open goals on BONGOS-V1 (`scripts/gds/goal-names.js`) and from
|
|
183
|
+
how dependencies are declared in practice. A very different real distribution would
|
|
184
|
+
change C's edge count — not A's isolation, which is bounded by p by construction.
|
|
185
|
+
- **`marks` is a proxy for legibility, not legibility.** It counts what is
|
|
186
|
+
*distinguishable*, not what is *understandable*; a map can clear it and still say
|
|
187
|
+
nothing. It is used here only to make overplotting a number, which is the one thing
|
|
188
|
+
looking at a picture reliably fails to do.
|
|
189
|
+
- **The layout is one algorithm.** A hierarchical or Sugiyama-style layout would draw
|
|
190
|
+
view B's chains better than a force pass does. It would not change A (there is nothing
|
|
191
|
+
to lay out) or D (the overplotting is arithmetic, not layout).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* people.css — page-local styles for the cross-project builder directory
|
|
2
|
-
(task 1003470, goal 1000081), served at /people
|
|
3
|
-
|
|
2
|
+
(task 1003470, goal 1000081), served at /people — its legacy door /scouting
|
|
3
|
+
was deleted in task 1003440 and now 301s here. Only the identity cell lives
|
|
4
|
+
here: the
|
|
4
5
|
ledger, the filter bar, the pager, the chips and the empty state are the
|
|
5
6
|
shell's and the kit's. Tokens are the world's real names — no compat alias. */
|
|
6
7
|
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
32
|
<main id="hall-main">
|
|
33
|
-
<!-- task 1003470: ONE directory.
|
|
34
|
-
|
|
33
|
+
<!-- task 1003470: ONE directory. Its legacy door /scouting rendered this
|
|
34
|
+
same page from the same script, and task 1003440 deleted it — the same
|
|
35
35
|
/api/gds/scouting rollup used to be drawn three different ways. -->
|
|
36
36
|
<section class="scroll" id="people-scroll" aria-labelledby="people-h">
|
|
37
37
|
<h2 id="people-h" class="scroll__h">Builder directory<span class="count-pill" id="people-count" hidden></span></h2>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// people.js — the People page: the cross-project builder directory (task
|
|
2
|
-
// 1002577; ADR 0141 §4 is the data's design of record), served at /people
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// 1002577; ADR 0141 §4 is the data's design of record), served at /people —
|
|
3
|
+
// task 1003470 first made its legacy door /scouting render this same script,
|
|
4
|
+
// and task 1003440 deleted that door (the URL 301s here), because the
|
|
5
|
+
// same /api/gds/scouting rollup was being drawn three
|
|
5
6
|
// different ways (a kit ledger here, a hand-built table there, and the same
|
|
6
7
|
// columns in a different order). The endpoint is gated server-side on
|
|
7
|
-
// 'project.curate' OR being a project owner (R14, ADR 0210);
|
|
8
|
+
// 'project.curate' OR being a project owner (R14, ADR 0210); this page is
|
|
8
9
|
// gated in serve-internal.js on that same pair, so a visitor who is neither
|
|
9
10
|
// never sees this shell.
|
|
10
11
|
//
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_": "People — the cross-project directory behind requireProjectCuratePage (metic+ via project.curate, or a project owner). Descriptive only; it grants no authority, and the page says so above the fold. Written with the re-skin (task 1003307); the redesign (task 1003470) added the identity cell, the sort and craft lenses, and the `search` state.
|
|
2
|
+
"_": "People — the cross-project directory behind requireProjectCuratePage (metic+ via project.curate, or a project owner). Descriptive only; it grants no authority, and the page says so above the fold. Written with the re-skin (task 1003307); the redesign (task 1003470) added the identity cell, the sort and craft lenses, and the `search` state. Its legacy door /scouting was deleted in task 1003440; the URL 301s here. Populated look: the hall-preview harness (scripts/hall-preview/fixtures/scouting.json carries five builders, three with avatars).",
|
|
3
3
|
"page": "/builders/people",
|
|
4
4
|
"surface": "hall-ui",
|
|
5
5
|
"stub": {
|
|
@@ -555,7 +555,7 @@
|
|
|
555
555
|
// GET/PATCH /api/bongos/me/cross-project (platform-identity module — hub only).
|
|
556
556
|
// One on/off toggle: "show my cross-project record on my public profile".
|
|
557
557
|
// Enforcement is server-side in the module's read functions, so flipping it
|
|
558
|
-
// takes effect immediately on the profile
|
|
558
|
+
// takes effect immediately on the profile and /people. The section
|
|
559
559
|
// reveals ONLY when the module's endpoint answers (404 on a vanilla instance →
|
|
560
560
|
// stays hidden, no error state). P04 later re-homes this in the Profile rail
|
|
561
561
|
// group; storage is account-global on the hub (not behavior_prefs).
|
|
@@ -2859,9 +2859,10 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
2859
2859
|
does not exist, so "Someone helped" rendered full-size on every row. */
|
|
2860
2860
|
.btn--sm { min-height: 26px; padding: 0 11px; font-size: 12.5px; }
|
|
2861
2861
|
|
|
2862
|
-
/* people.js:45 — the builder's name cell. The only definition
|
|
2863
|
-
in scouting.html's inline <style>, so the same data read bold on
|
|
2864
|
-
plain on People.
|
|
2862
|
+
/* people.js:45 — the builder's name cell. The hall's only definition used to
|
|
2863
|
+
live in scouting.html's inline <style>, so the same data read bold on
|
|
2864
|
+
Scouting and plain on People. It lives here now, and scouting.html itself
|
|
2865
|
+
went with task 1003440. */
|
|
2865
2866
|
.who { font-weight: 600; }
|
|
2866
2867
|
|
|
2867
2868
|
/* people.js:105 — notice() sets body.className='note'. .note lives in
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.469",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.469",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.469",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|