@bongos/core 1.21.176 → 1.21.178

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 (214) hide show
  1. package/.bongos-core.json +186 -496
  2. package/.claude/skills/planning-session/SKILL.md +2 -2
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +0 -6
  5. package/clients/bongos-client/index.cjs +0 -6
  6. package/clients/bongos-client/index.d.ts +0 -6
  7. package/clients/bongos-client/index.mjs +0 -6
  8. package/config/scheduled-routines.json +3 -8
  9. package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +3 -2
  10. package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +1 -1
  11. package/docs/adr/0093-tranche-2-core-carve-sequence.md +1 -1
  12. package/docs/api/openapi.json +1 -87
  13. package/docs/api-reference.md +1 -8
  14. package/docs/canonical-permissions.md +4 -4
  15. package/docs/copy-inventory.md +25 -39
  16. package/docs/copy-registry.json +73 -200
  17. package/docs/file-map.md +6 -11
  18. package/docs/handoff-template.md +1 -1
  19. package/docs/module-api-changelog.md +4 -0
  20. package/docs/modules-contract.md +2 -2
  21. package/docs/onboarding/diagrams/README.md +3 -7
  22. package/docs/onboarding/diagrams/assertions.json +3 -3
  23. package/docs/page-inventory.json +4 -7
  24. package/docs/page-readings.json +1520 -1569
  25. package/docs/recipes/ops-gotchas.md +3 -1
  26. package/modules/autonomy/db.js +9 -0
  27. package/modules/autonomy/module.json +2 -2
  28. package/modules/autonomy/pollers/daily-checks.js +262 -0
  29. package/modules/autonomy/pollers/routine-timers.js +7 -5
  30. package/modules/autonomy/rank-roles.js +64 -0
  31. package/modules/autonomy/server-schedule.js +37 -0
  32. package/modules/government/catalog.js +10 -7
  33. package/modules/government/decision-board.js +0 -1
  34. package/modules/government/decision-rules.js +0 -1
  35. package/modules/government/docket.js +0 -1
  36. package/modules/government/protected-surfaces.js +1 -1
  37. package/modules/government/protected-surfaces.json +2 -3
  38. package/modules/hall-ui/public/atlas.html +1 -1
  39. package/modules/hall-ui/public/blockers.html +1 -1
  40. package/modules/hall-ui/public/board-room.html +1 -1
  41. package/modules/hall-ui/public/city.html +1 -1
  42. package/modules/hall-ui/public/collab.html +1 -1
  43. package/modules/hall-ui/public/commands.html +1 -1
  44. package/modules/hall-ui/public/copy-desk.html +1 -1
  45. package/modules/hall-ui/public/deploy.html +1 -1
  46. package/modules/hall-ui/public/diagrams.html +1 -1
  47. package/modules/hall-ui/public/drachmae.html +1 -1
  48. package/modules/hall-ui/public/fleet.html +1 -1
  49. package/modules/hall-ui/public/gate.css +4 -26
  50. package/modules/hall-ui/public/gate.html +12 -27
  51. package/modules/hall-ui/public/gate.js +26 -176
  52. package/modules/hall-ui/public/gate.states.json +4 -22
  53. package/modules/hall-ui/public/goal-map.html +1 -1
  54. package/modules/hall-ui/public/goals.html +1 -1
  55. package/modules/hall-ui/public/government.html +1 -1
  56. package/modules/hall-ui/public/idea.html +1 -1
  57. package/modules/hall-ui/public/ideas.html +1 -1
  58. package/modules/hall-ui/public/index.html +1 -1
  59. package/modules/hall-ui/public/modules.html +1 -1
  60. package/modules/hall-ui/public/my-agents.html +1 -1
  61. package/modules/hall-ui/public/primer.html +1 -1
  62. package/modules/hall-ui/public/profile.html +1 -1
  63. package/modules/hall-ui/public/project-settings.html +1 -1
  64. package/modules/hall-ui/public/ranks.html +1 -1
  65. package/modules/hall-ui/public/roadmap.html +1 -1
  66. package/modules/hall-ui/public/roster.html +1 -1
  67. package/modules/hall-ui/public/sessions.html +1 -1
  68. package/modules/hall-ui/public/settings.html +1 -1
  69. package/modules/hall-ui/public/shell.js +1 -1
  70. package/modules/hall-ui/public/street-card.js +5 -9
  71. package/modules/hall-ui/public/street-desk.js +2 -2
  72. package/modules/hall-ui/public/street-inside.js +1 -1
  73. package/modules/hall-ui/public/street.html +1 -1
  74. package/modules/hall-ui/public/studio.html +1 -1
  75. package/modules/hall-ui/public/task.html +1 -1
  76. package/modules/hall-ui/public/thinking.html +1 -1
  77. package/modules/hall-ui/public/tweak-editor.html +1 -1
  78. package/modules/hall-ui/public/watch.html +1 -1
  79. package/modules/hall-ui/public/work.html +1 -1
  80. package/modules/lifecycle/matter-acts.js +0 -6
  81. package/modules/lifecycle/module.json +0 -1
  82. package/package-lock.json +2 -2
  83. package/package.json +1 -1
  84. package/release-notes.json +36 -0
  85. package/scripts/bongos/adopt-preflight.js +3 -3
  86. package/scripts/bongos/api-alias-caller-scan.js +2 -2
  87. package/scripts/bongos/audit-authorship.sh +1 -8
  88. package/scripts/bongos/audit-rank-roles.js +15 -56
  89. package/scripts/bongos/bump-version.js +46 -9
  90. package/scripts/bongos/codemod-rename-scripts-gds.js +0 -1
  91. package/scripts/bongos/diagram-facts.js +1 -1
  92. package/scripts/bongos/do-api.js +1 -1
  93. package/scripts/bongos/doc-cli-guard.js +2 -0
  94. package/scripts/bongos/doc-control-claims.js +2 -2
  95. package/scripts/bongos/fitness-checks-identity.js +4 -15
  96. package/scripts/bongos/gen-diagrams.js +3 -3
  97. package/scripts/bongos/government-walk.js +3 -9
  98. package/scripts/bongos/hard-floor.js +52 -0
  99. package/scripts/bongos/publish-manifest.js +3 -3
  100. package/scripts/bongos/pulse.js +5 -3
  101. package/scripts/bongos/routine-schedule.js +38 -3
  102. package/scripts/bongos/run-unit-tests.js +17 -5
  103. package/scripts/bongos/ship-regen.js +2 -3
  104. package/scripts/gds/{goal-names.js → hard-floor.js} +3 -4
  105. package/scripts/security/dep-audit.js +50 -124
  106. package/src/bongos/module-scope-map.js +2 -2
  107. package/src/bongos/permission-path-check.js +1 -1
  108. package/src/bongos/route-rank-check.js +1 -8
  109. package/src/bongos/routes.js +1 -2
  110. package/src/module-api.js +1 -1
  111. package/src/modules.js +1 -1
  112. package/tests/acclaim_feed_evidence_db.mjs +42 -23
  113. package/tests/adr_0089_scope.mjs +7 -5
  114. package/tests/autonomy_daily_checks.mjs +201 -0
  115. package/tests/bump_version.mjs +52 -18
  116. package/tests/claude_materialize.mjs +12 -12
  117. package/tests/copy_desk_flags_db.mjs +22 -14
  118. package/tests/effective_visibility_predicate.mjs +0 -18
  119. package/tests/gating_review_retired.mjs +1 -1
  120. package/tests/government_act_alone_buildings.mjs +1 -3
  121. package/tests/government_board_membership_db.mjs +35 -22
  122. package/tests/government_protected_surfaces.mjs +29 -13
  123. package/tests/governor_docket.mjs +0 -2
  124. package/tests/governor_matter_acts.mjs +6 -8
  125. package/tests/hall_city.mjs +1 -1
  126. package/tests/hall_matter_card.mjs +2 -2
  127. package/tests/hall_oversight_world.mjs +16 -12
  128. package/tests/hall_street_desk.mjs +4 -3
  129. package/tests/hall_street_inside.mjs +1 -1
  130. package/tests/helpers.mjs +34 -0
  131. package/tests/howto_state.mjs +33 -56
  132. package/tests/howto_state_db.mjs +68 -0
  133. package/tests/idea_credit_streams_db.mjs +11 -3
  134. package/tests/integration_parked_ratchet.mjs +7 -1
  135. package/tests/nav_permission_atoms.mjs +1 -1
  136. package/tests/page_notes_db.mjs +12 -8
  137. package/tests/page_tweak_no_rearm.mjs +50 -0
  138. package/tests/publish_manifest.mjs +64 -0
  139. package/tests/routine_capture_kind.mjs +18 -7
  140. package/tests/routine_schedule.mjs +42 -0
  141. package/tests/search_isolation.mjs +5 -103
  142. package/tests/search_isolation_db.mjs +140 -0
  143. package/tests/session_earnings_mirror_db.mjs +2 -0
  144. package/tests/workflow_exec_paths.mjs +9 -11
  145. package/modules/lifecycle/routes/gate-approvals.js +0 -299
  146. package/scripts/bongos/artifact-staleness.js +0 -267
  147. package/scripts/bongos/ci-grade.js +0 -82
  148. package/scripts/bongos/classify-discipline.js +0 -153
  149. package/scripts/bongos/codemod-rename-src-gds.js +0 -145
  150. package/scripts/bongos/coreB-carve-proof.sh +0 -725
  151. package/scripts/bongos/gate-review.js +0 -330
  152. package/scripts/bongos/goal-names.js +0 -102
  153. package/scripts/bongos/rename-goals.js +0 -109
  154. package/scripts/bongos/seed-adopt-tasks.js +0 -75
  155. package/scripts/bongos/seed-api-contract-goal-tasks.js +0 -141
  156. package/scripts/bongos/seed-board-room-tasks.js +0 -196
  157. package/scripts/bongos/seed-bongos-app-tasks.js +0 -294
  158. package/scripts/bongos/seed-bongos-coreB-tranche1-tasks.js +0 -81
  159. package/scripts/bongos/seed-bongos-coreB-tranche2-tasks.js +0 -100
  160. package/scripts/bongos/seed-bongos-goal-hierarchy-tasks.js +0 -307
  161. package/scripts/bongos/seed-bongos-module-system-tasks.js +0 -346
  162. package/scripts/bongos/seed-bongos-tasks.js +0 -214
  163. package/scripts/bongos/seed-bongos-v1-seo-tasks.js +0 -104
  164. package/scripts/bongos/seed-bv1-community-tasks.js +0 -131
  165. package/scripts/bongos/seed-bv1-privacy-invites-tasks.js +0 -133
  166. package/scripts/bongos/seed-bv1-profile-page-tasks.js +0 -161
  167. package/scripts/bongos/seed-bv1-r01-delta-tasks.js +0 -154
  168. package/scripts/bongos/seed-bv2-tweak-mode-tasks.js +0 -277
  169. package/scripts/bongos/seed-gds-v4-tasks.js +0 -624
  170. package/scripts/bongos/seed-governance-tasks.js +0 -340
  171. package/scripts/bongos/seed-medusa-tasks.js +0 -440
  172. package/scripts/bongos/seed-module-upstreaming.js +0 -219
  173. package/scripts/bongos/seed-productization-tasks.js +0 -235
  174. package/scripts/bongos/seed-project-admin-console-tasks.js +0 -88
  175. package/scripts/bongos/seed-provisioning-tasks.js +0 -83
  176. package/scripts/bongos/seed-strict-versioning-tasks.js +0 -275
  177. package/scripts/bongos/seed-v2-world-tasks.js +0 -283
  178. package/scripts/gds/artifact-staleness.js +0 -7
  179. package/scripts/gds/ci-grade.js +0 -7
  180. package/scripts/gds/classify-discipline.js +0 -7
  181. package/scripts/gds/codemod-rename-src-gds.js +0 -7
  182. package/scripts/gds/coreB-carve-proof.sh +0 -8
  183. package/scripts/gds/gate-review.js +0 -7
  184. package/scripts/gds/rename-goals.js +0 -7
  185. package/scripts/gds/seed-adopt-tasks.js +0 -7
  186. package/scripts/gds/seed-api-contract-goal-tasks.js +0 -7
  187. package/scripts/gds/seed-board-room-tasks.js +0 -6
  188. package/scripts/gds/seed-bongos-app-tasks.js +0 -7
  189. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +0 -7
  190. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +0 -7
  191. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +0 -7
  192. package/scripts/gds/seed-bongos-module-system-tasks.js +0 -7
  193. package/scripts/gds/seed-bongos-tasks.js +0 -7
  194. package/scripts/gds/seed-bongos-v1-seo-tasks.js +0 -6
  195. package/scripts/gds/seed-bv1-community-tasks.js +0 -6
  196. package/scripts/gds/seed-bv1-privacy-invites-tasks.js +0 -6
  197. package/scripts/gds/seed-bv1-profile-page-tasks.js +0 -6
  198. package/scripts/gds/seed-bv1-r01-delta-tasks.js +0 -6
  199. package/scripts/gds/seed-bv2-tweak-mode-tasks.js +0 -6
  200. package/scripts/gds/seed-gds-v4-tasks.js +0 -7
  201. package/scripts/gds/seed-governance-tasks.js +0 -7
  202. package/scripts/gds/seed-medusa-tasks.js +0 -7
  203. package/scripts/gds/seed-module-upstreaming.js +0 -7
  204. package/scripts/gds/seed-productization-tasks.js +0 -7
  205. package/scripts/gds/seed-project-admin-console-tasks.js +0 -6
  206. package/scripts/gds/seed-provisioning-tasks.js +0 -7
  207. package/scripts/gds/seed-strict-versioning-tasks.js +0 -7
  208. package/scripts/gds/seed-v2-world-tasks.js +0 -7
  209. package/scripts/migrate_cost_ledger.sh +0 -178
  210. package/tests/artifact_staleness.mjs +0 -207
  211. package/tests/gate_approvals.mjs +0 -611
  212. package/tests/gate_review.mjs +0 -152
  213. package/tests/goal_names.mjs +0 -120
  214. package/tests/newcomer_generator.mjs +0 -48
@@ -1,141 +0,0 @@
1
- #!/usr/bin/env node
2
- // seed-api-contract-goal-tasks.js
3
- // Seeds BONGOS-V1 goal 36 — "Robust, versioned, easy-to-call public API" — from
4
- // the 2026-07-04 Archon planning session (task 1987). Five done-when criteria
5
- // (slugs api-error-envelope · api-versioning · api-client-sdk · api-validation ·
6
- // api-pagination) were created via POST /versions/BONGOS-V1/done-when before this
7
- // runs; this seeds the 14 tasks (refs R01-R14) + their criterion links + the
8
- // dependency edges. Entry point is CONTRACT-FIRST, so only the zero-dep,
9
- // non-spike Phase-A tasks (R01 envelope contract, R05 versioning policy) plus the
10
- // independent R13 pagination decision are promoted to `ready`; R07 (the
11
- // source-of-truth spike) stays backlog by convention and is opened manually when
12
- // Phase B starts; everything else auto-promotes as its predecessor ships.
13
- //
14
- // Idempotent: task create on source_ref, criterion links on (task_id,
15
- // criterion_id), dependency edges on (task_id, depends_on_task_id). Safe to re-run.
16
- // Run: node scripts/bongos/seed-api-contract-goal-tasks.js
17
- const { cliClient } = require('./cli-lib.js');
18
-
19
- const GOAL_ID = 36;
20
- const C = {
21
- envelope: 'api-error-envelope',
22
- versioning: 'api-versioning',
23
- sdk: 'api-client-sdk',
24
- validation: 'api-validation',
25
- pagination: 'api-pagination',
26
- };
27
-
28
- // ref → task spec. `deps` are local R## refs, resolved to ids after create.
29
- const TASKS = [
30
- // ---- Criterion 1: error envelope (Phase A) ----
31
- { ref: 'R01', kind: 'decision', priority: 5, est: 90, crit: [C.envelope],
32
- title: 'API error envelope + code taxonomy (contract + ADR)',
33
- description: 'Define the single error response envelope `{error:{code,message,details}}` and the taxonomy that collapses today\'s ~339 ad-hoc error strings into a documented registry. Deliverable: an ADR + a shared registry module of canonical codes. No behaviour change — this is the contract R02 implements. Serves C1 (api-error-envelope). deps: none.',
34
- deps: [] },
35
- { ref: 'R02', kind: 'infra', priority: 5, est: 120, crit: [C.envelope],
36
- title: 'Central error-handling middleware + envelope helper',
37
- description: 'Add a central Express error-handling middleware + an `ApiError`/`res.fail(code,status,details)` helper (kernel route layer) emitting the R01 envelope; wire the handler last so any thrown/unhandled error returns the envelope. Backward-compatible — existing ad-hoc responses keep working until the R04 sweep. Serves C1. deps: R01.',
38
- deps: ['R01'] },
39
- { ref: 'R03', kind: 'infra', priority: 4, est: 90, crit: [C.envelope],
40
- title: 'Build check: fail on a route emitting a non-envelope error',
41
- description: 'Add a fitness/lint check (into fitness.js / the unit gate) that fails the build when a route hand-rolls a flat `res.status(NNN).json({error:\'...\'})` instead of the R02 helper. Holds the line as the sweep progresses. Serves C1. deps: R02.',
42
- deps: ['R02'] },
43
- { ref: 'R04', kind: 'refactor', priority: 4, est: 240, crit: [C.envelope],
44
- title: 'Sweep existing routes onto the error envelope',
45
- description: 'Convert the ~219 handlers across core + modules from ad-hoc flat errors to the R02 envelope (the audit found 168 open-coded 500s + 615 flat-error sites). Mechanical but wide — touches every module\'s routes. Serves C1. deps: R02.',
46
- deps: ['R02'] },
47
- // ---- Criterion 2: versioning (Phase A) ----
48
- { ref: 'R05', kind: 'decision', priority: 5, est: 90, crit: [C.versioning],
49
- title: 'API versioning + deprecation policy (ADR)',
50
- description: 'ADR defining the versioning scheme (a `/v1/` path marker), what counts as a breaking change, the deprecation window, and how the currently-un-updatable consumers (shipped Dev Box binaries, live boxes, status dashboard) are handled. Serves C2 (api-versioning). deps: none.',
51
- deps: [] },
52
- { ref: 'R06', kind: 'infra', priority: 5, est: 150, crit: [C.versioning],
53
- title: 'Serve the API under /v1/ with legacy aliasing',
54
- description: 'Mount the current surface under `/v1/` and alias today\'s unversioned paths (`/api/bongos`, `/api/gds`) into it so no consumer breaks on day one. Stamp the version into the OpenAPI spec + `/docs`. Serves C2. deps: R05.',
55
- deps: ['R05'] },
56
- // ---- Criterion 3: client SDK (Phase B) ----
57
- { ref: 'R07', kind: 'spike', priority: 4, est: 120, crit: [C.sdk],
58
- title: 'Spike: pick the API contract source-of-truth (schema-first vs code-first)',
59
- description: 'Decide whether the OpenAPI spec becomes the SOURCE (schema-first: define request/response schemas -> generate spec + validation + client) or stays GENERATED from code with codegen layered on. This one decision shapes the SDK (C3) and validation (C4). Output: an ADR + a sub-task list refining R08-R12. kind=spike (stays backlog; opened manually when Phase B starts). Serves C3, informs C4. deps: none (do after Phase A).',
60
- deps: [] },
61
- { ref: 'R08', kind: 'feature', priority: 3, est: 180, crit: [C.sdk],
62
- title: 'Generate + publish the typed API client',
63
- description: 'Per the R07 decision, generate a typed client from the OpenAPI spec and publish it for install (internal package first). Serves C3. deps: R07.',
64
- deps: ['R07'] },
65
- { ref: 'R09', kind: 'refactor', priority: 3, est: 240, crit: [C.sdk],
66
- title: 'Migrate internal callers onto the client; delete duplicates',
67
- description: 'Move the CLI (cli-lib apiCall), the devbox Electron app (its own gds-client), and the web UIs (per-page fetch helpers) onto the generated client; delete the 3 duplicate implementations. Cuts per-call boilerplate from ~15 lines to 1. Touches hall-ui/status-ui/dev-box. Serves C3. deps: R08.',
68
- deps: ['R08'] },
69
- { ref: 'R10', kind: 'feature', priority: 3, est: 120, crit: [C.sdk],
70
- title: 'External-consumer on-ramp + hello-world (proof)',
71
- description: 'Document how an outside program authenticates (token acquisition beyond the interactive Device Flow) and makes its first call, with a runnable hello-world using the published client. The PROOF an external self-hoster can actually use the API. Serves C3. deps: R08.',
72
- deps: ['R08'] },
73
- // ---- Criterion 4: validation (Phase C) ----
74
- { ref: 'R11', kind: 'feature', priority: 3, est: 240, crit: [C.validation],
75
- title: 'Spec-driven request validation: 100% writes + query params',
76
- description: 'Per the R07 decision, drive validation from the spec so every write route AND its query parameters are validated, and unknown/typo\'d fields are rejected with the R02 envelope (today ~55% coverage, extras silently dropped). Serves C4 (api-validation). deps: R07.',
77
- deps: ['R07'] },
78
- { ref: 'R12', kind: 'infra', priority: 3, est: 90, crit: [C.validation],
79
- title: 'Build check: fail on an unvalidated write route',
80
- description: 'Add a fitness check that fails the build when a write route (POST/PUT/PATCH/DELETE) has no spec-bound validation. Locks in C4\'s 100% coverage. Serves C4. deps: R11.',
81
- deps: ['R11'] },
82
- // ---- Criterion 5: pagination (Phase C) ----
83
- { ref: 'R13', kind: 'decision', priority: 2, est: 90, crit: [C.pagination],
84
- title: 'Pagination contract + shared helper (decision)',
85
- description: 'Decide one pagination convention (cursor vs limit/offset) and build the shared helper. Today three styles coexist (limit-only, limit+offset, none) with per-endpoint clamps. Serves C5 (api-pagination). deps: none (independent).',
86
- deps: [] },
87
- { ref: 'R14', kind: 'refactor', priority: 2, est: 180, crit: [C.pagination],
88
- title: 'Adopt the pagination contract across list endpoints; cap unbounded lists',
89
- description: 'Apply the R13 helper across all list endpoints and cap the currently-unbounded public lists (leaderboard, blockers, versions). Serves C5. deps: R13.',
90
- deps: ['R13'] },
91
- ];
92
-
93
- (async () => {
94
- const api = await cliClient();
95
- const idByRef = {};
96
- // Phase 1: create tasks (idempotent on source_ref) + link criteria explicitly
97
- // (criterion_ids at create is not honored on this build; /criteria is idempotent).
98
- for (const t of TASKS) {
99
- const create = await api.tasks.postTasks({ body: {
100
- version_id: 'BONGOS-V1',
101
- goal_id: GOAL_ID,
102
- title: t.title,
103
- description: t.description,
104
- kind: t.kind,
105
- discipline: 'engineer',
106
- priority: t.priority,
107
- est_minutes: t.est,
108
- source: 'planning',
109
- source_ref: `BONGOS-V1-api-contract-${t.ref}`,
110
- } });
111
- const task = create.data && (create.data.task || create.data);
112
- const id = task && task.id;
113
- if (!id) { console.log(` ${t.ref}: CREATE FAILED — ${create.status} ${JSON.stringify(create.data).slice(0, 160)}`); continue; }
114
- idByRef[t.ref] = id;
115
- const link = await api.tasks.postTasksIdCriteria({ id, body: { criterion_ids: t.crit } });
116
- console.log(` ${t.ref} -> task ${id} (${t.kind}, P${t.priority}, goal ${task.goal_id}) · criteria ${link.status === 200 ? 'ok' : (JSON.stringify(link.data).slice(0, 120))}`);
117
- }
118
- // Phase 2: dependency edges (idempotent on (task_id, depends_on_task_id)).
119
- console.log('--- dependencies ---');
120
- for (const t of TASKS) {
121
- const id = idByRef[t.ref];
122
- if (!id || !t.deps.length) continue;
123
- for (const dep of t.deps) {
124
- const depId = idByRef[dep];
125
- if (!depId) { console.log(` ${t.ref}: dep ${dep} not created — skip`); continue; }
126
- const r = await api.tasks.postTasksIdDependencies({ id, body: { depends_on_task_id: depId } });
127
- console.log(` ${t.ref}(${id}) -> ${dep}(${depId}) ${r.status === 200 || r.status === 201 ? 'ok' : (JSON.stringify(r.data).slice(0, 120))}`);
128
- }
129
- }
130
- // Phase 3: promote the zero-dep, non-spike tasks to `ready` (contract-first:
131
- // R01 + R05 open Phase A now; R13 is independent). R07 (spike) stays backlog.
132
- console.log('--- promote (zero-dep, non-spike) ---');
133
- for (const t of TASKS) {
134
- if (t.deps.length || t.kind === 'spike') continue;
135
- const id = idByRef[t.ref];
136
- if (!id) continue;
137
- const p = await api.tasks.postTasksIdPromote({ id, body: {} });
138
- console.log(` ${t.ref}(${id}) promote -> ${p.status} ${p.ok ? 'ready' : JSON.stringify(p.data).slice(0, 120)}`);
139
- }
140
- console.log('refs:', JSON.stringify(idByRef));
141
- })().catch((e) => console.log('ERR ' + (e && e.message)));
@@ -1,196 +0,0 @@
1
- // Seed the tasks for goal 1000069 "Governance & voting — the Board Room" (BONGOS-V1).
2
- // Source of truth: docs/specs/bongos-v1-board-room.md (status: final).
3
- // Idempotent on (source, source_ref). Re-running resolves to the existing rows.
4
- //
5
- // Run: node scripts/bongos/seed-board-room-tasks.js
6
- const os = require('os');
7
- const sess = require(os.homedir() + '/.config/cloudbongos/gds-session.json');
8
- const BASE = sess.api_base.replace(/\/$/, '');
9
- const TOKEN = sess.token;
10
- const VER = 'BONGOS-V1';
11
- const GOAL = 1000069;
12
- const SRC = 'planning-session';
13
- const H = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' };
14
-
15
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
16
- async function api(method, path, body, _tries = 0) {
17
- await sleep(500); // base throttle to stay under the per-IP rate limit
18
- const res = await fetch(`${BASE}/api/bongos${path}`, {
19
- method, headers: H, body: body ? JSON.stringify(body) : undefined,
20
- });
21
- const text = await res.text();
22
- let json; try { json = JSON.parse(text); } catch { json = { _raw: text.slice(0, 300) }; }
23
- if (res.status === 429 && _tries < 8) {
24
- const wait = ((json.error && json.error.details && json.error.details.retry_after_seconds) || 30) + 1;
25
- console.log(` …rate-limited, waiting ${wait}s`);
26
- await sleep(wait * 1000);
27
- return api(method, path, body, _tries + 1);
28
- }
29
- return { status: res.status, ok: res.ok, json };
30
- }
31
-
32
- // Criterion slugs (position-independent — see the spec's Criteria table).
33
- const C1 = 'board-full-idea-ratification';
34
- const C2 = 'rejection-returns-with-reason';
35
- const C3 = 'who-governs-is-config';
36
- const C4 = 'timed-sitting-absence-never-blocks';
37
- const C5 = 'board-room-and-charter-library';
38
- const C6 = 'discord-notification-mirror';
39
-
40
- const SPEC = 'See docs/specs/bongos-v1-board-room.md (status: final).';
41
-
42
- const TASKS = [
43
- // ---- Phase A — decide + foundation (P5) ----
44
- { ref:'R01', kind:'decision', disc:'engineer', prio:5, est:150, crit:[C1,C3,C4], deps:[],
45
- title:'R01 · ADR: the Board Room government model',
46
- desc:`Record the government model as one decision so the schema has something to encode.\n\nMUST STATE: the board's TWO subjects (a Full Idea, and a change to the constitution itself) and why nothing else is votable; membership as a configured predicate resolved per request and uncached; the timed SITTING (absent votes are nulled, not blocking) and why that replaces quorum — the clock IS the deadlock exit; CONSENT rather than majority, with silence as consent and one reasoned objection returning the idea; a zero-vote close PASSING; the OPEN ballot; Discord as an outbound notification mirror that casts nothing; and the amendment rule — a constitutional change is decided under whatever rule the CURRENT constitution names, so flipping out of monarchy is a legal monarchy act.\n\nAlso record the two owner decisions taken against recommendation with their trade-offs intact: vote-karma (yes-clicking bias, accepted because item volume is too low to farm) and automatic window-open on grade pass (author loses timing control; concurrent windows become normal).\n\nGrounding: idea 1000738, idea 1000754, the Six Variables of Governance synthesis, ADR 0151 (permissions-as-atoms), ADR 0157, ADR 0158 §2 (verdicts advisory), ADR 0162 (no human approval in the land path), ADR 0174 (government/ranks/roles). ${SPEC}` },
47
-
48
- { ref:'R02', kind:'decision', disc:'engineer', prio:5, est:90, crit:[C1], deps:['R01'],
49
- title:'R02 · The pass-event contract the ideator credit lane consumes',
50
- desc:`Agree the pass-event shape with goal 1000067 (IC5, task 1002999) BEFORE the emitter is built, so no parallel vote is invented — ADR 0172 (per-craft compensation) is explicit that stream 3 "consumes the Board Room's pass event; invents no parallel vote".\n\nDone-when: payload fields, the idempotency key, and once-per-idea semantics are written down and referenced by both goals. Stream 3 pays max(30, round(completeness% x 100)) once per idea, reason 'idea.credit.governance_pass'. economy stays OUT of this goal's scope — we emit, 1000067 pays. Deps R01. ${SPEC}` },
51
-
52
- { ref:'R03', kind:'feature', disc:'engineer', prio:5, est:210, crit:[C1,C2,C4], deps:['R01'],
53
- title:'R03 · Schema: board items, votes, and rejections',
54
- desc:`Module-owned migration under modules/government/. NOTE the fitness rule derives a module migration's legal table namespace from the DIRECTORY NAME (this is what forced tasks 1003004+1003005 to land together), so tables are government_*.\n\nMUST include subject_type ('full_idea' | 'constitutional_amendment') FROM DAY ONE — cheap now, expensive to bolt on. A vote row carries voter, direction, timestamp, and for an objection the free-text reason plus exactly one of the five Full Idea section keys. UNIQUE(item, voter) on the peer_votes precedent (migration 058). Item carries opened_at, closes_at, closed_at, outcome.\n\nRe-read modules/ideas/templates.js for the five section keys — they are the owner's own wording and must not be re-invented. Deps R01. ${SPEC}` },
55
-
56
- { ref:'R04', kind:'feature', disc:'engineer', prio:5, est:150, crit:[C1,C3], deps:['R03'],
57
- title:'R04 · Permission catalog + grant migration for the board keys',
58
- desc:`Add board.item.open, board.vote.cast, board.config.manage following modules/government/catalog.js's five-step recipe EXACTLY. All three are operational (system:false) — creating or casting confers no authority on anyone; compare the version.create comment which argues this against a symmetry reading.\n\nThe grant migration is LOAD-BEARING not bookkeeping: an already-migrated DB never learns a key added only in code, and the new route then 403s everyone. Copy governance_006_version_create.sql's shape verbatim — one INSERT...SELECT '<rank>', unnest(ARRAY[...]) block PER RANK, because the drift guard tests/governance_seed.mjs scans for that literal form and a combined unnest parses as zero grants.\n\nPin every write route in src/bongos/route-rank-check.js. WATCH THE DEPLOY BOUNDARY: the grant rows and the code constant must land in the SAME deploy (ADR 0174 §Consequences) or the check fails closed. Deps R03. ${SPEC}` },
59
-
60
- // ---- Phase B — the rule engine (P5 spine, P4 tail) ----
61
- { ref:'R05', kind:'feature', disc:'engineer', prio:5, est:180, crit:[C3], deps:['R04'],
62
- title:'R05 · The constitution: membership, pass rule, and window as config',
63
- desc:`config/government.json + config/government.neutral.json gain a board block: membership predicate, pass_rule, window_minutes, close_early_on_full_turnout. Platform default and this instance's day-one value are MONARCHY — membership 'rank:archon', pass_rule 'first_ratifier', no clock — expressed as configuration on the real machinery, never as a separate code path.\n\nThe recommended starting point documented alongside it is: all Archons, one vote each, consent, 90-minute window. Deps R04. ${SPEC}` },
64
-
65
- { ref:'R06', kind:'feature', disc:'engineer', prio:5, est:150, crit:[C3], deps:['R05'],
66
- title:'R06 · Board membership resolver — per request, uncached',
67
- desc:`Resolve the configured predicate to a live member list on every request with NO caching, preserving ADR 0016's instant-demotion property the permission resolver already guarantees.\n\nMembership derives from RANK, never from role: PATCH /me/disciplines is deliberately ungated ("a builder owns their own profile", src/bongos/routes/me.js:311), so a role-derived franchise would be one-request privilege escalation. The spec records why the role-chamber model was rejected. Deps R05. ${SPEC}` },
68
-
69
- { ref:'R07', kind:'feature', disc:'engineer', prio:5, est:150, crit:[C1,C4], deps:['R06'],
70
- title:'R07 · A window opens automatically when a Full Idea passes the grade',
71
- desc:`The completeness grade is the FLOOR, the vote is the MERIT. A Full Idea crossing the pass bar (60, ADR 0172 per-craft) automatically opens a voting window; a sub-bar idea never reaches the board and instead returns to its author via R13.\n\nConcurrent windows are normal and expected — a direct consequence of automatic opening at a 90-minute default. Reuse modules/ideas/completeness.js; do not re-implement scoring. Deps R06. ${SPEC}` },
72
-
73
- { ref:'R08', kind:'feature', disc:'engineer', prio:5, est:210, crit:[C1,C4], deps:['R06'],
74
- title:'R08 · Cast a vote: open ballot, anti-self, live re-check, karma',
75
- desc:`POST a vote gated on board.vote.cast. HARD RULES: an author may NOT vote on their own item (server-side, the peer_votes anti-self precedent) — this is the bright line that keeps ratification from being ceremonial; membership is re-checked LIVE on every write; the write is idempotent on (item, voter).\n\nOpen ballot: member, direction and timestamp are visible to all members, which is what makes the vote-karma auditable. Award the voter karma for a vote cast IN-WINDOW (proposed +1 — surface the constant for confirmation). The Full Idea's author earns karma on ratification, mirroring KARMA_RATIFY_DELTA (+3, tuned down from +5 in V3.R28 — do NOT copy the stale +5 still printed in planning-session/SKILL.md and openapi.json). Deps R06. ${SPEC}` },
76
-
77
- { ref:'R09', kind:'feature', disc:'engineer', prio:5, est:120, crit:[C2], deps:['R03'],
78
- title:'R09 · Rejection payload: a reason plus one of the five sections',
79
- desc:`An objection carries free-text plus EXACTLY ONE of the five Full Idea section keys as the cause. This is the mechanism that makes the hall the only possible voting surface — a Discord reaction cannot express it, so reaction-voting would make every rejection feedback-free.\n\nA sub-bar completeness grade flags its weakest section automatically, using the per-field scores completeness.js already computes. Section keys come from modules/ideas/templates.js. Deps R03. ${SPEC}` },
80
-
81
- { ref:'R10', kind:'feature', disc:'engineer', prio:5, est:210, crit:[C4], deps:['R08','R09'],
82
- title:'R10 · Close + tally: consent, nulled absences, zero-vote pass',
83
- desc:`Closing rules, all declared rather than emergent: absent members are NULLED — dropped from the denominator, never counted as a no, so absence can never block; silence is consent; ONE reasoned objection returns the idea under C2; a window closing with ZERO votes PASSES (the idea already cleared the grade gate, and absence never blocks); and the window closes EARLY the moment every member has voted, so latency is min(full turnout, window).\n\nThe monarchy pass_rule 'first_ratifier' resolves through this same path. Deps R08,R09. ${SPEC}` },
84
-
85
- { ref:'R12', kind:'feature', disc:'engineer', prio:5, est:120, crit:[C1], deps:['R10'],
86
- title:'R12 · Emit the pass event exactly once per ratified idea',
87
- desc:`Fire R02's agreed contract on a passing close. Idempotent — a replay, a re-close, or a resubmission that passes again must never double-fire. This is the event goal 1000067 (IC5, task 1002999) is BLOCKED on; shipping it unblocks stream 3. Deps R10. ${SPEC}` },
88
-
89
- { ref:'R11', kind:'feature', disc:'engineer', prio:4, est:150, crit:[C4], deps:['R10'],
90
- title:'R11 · The window expiry poller',
91
- desc:`A window closes on time with nobody touching it. Nothing in-tree expires a vote today; the nearest precedents are the 7-day lagged peer-vote tally and the ~5-minute publish reconciler — follow the reconciler's per-sweep disposition-logging habit so a stuck window is visible rather than silent. Must handle concurrent windows. Deps R10. ${SPEC}` },
92
-
93
- { ref:'R13', kind:'feature', disc:'engineer', prio:4, est:180, crit:[C2], deps:['R09','R10'],
94
- title:'R13 · Return-to-originator, and resubmission',
95
- desc:`A vote fail OR a sub-bar grade sends the idea back to its ORIGINATOR carrying its feedback — it never dies and never stalls. The author revises and resubmits, which re-opens a window.\n\nBecause completeness.js scores the five fields per-field, a resubmission can be checked against the flagged section — surface whether the flagged section actually changed. Resubmission is unbounded in v1 (the grade gate already bounds spam) and every past rejection stays visible on the item history. Deps R09,R10. ${SPEC}` },
96
-
97
- { ref:'R14', kind:'feature', disc:'engineer', prio:4, est:180, crit:[C3], deps:['R10'],
98
- title:'R14 · Constitutional amendments as the board\'s second subject',
99
- desc:`Propose a change to the constitution, then ratify it under whatever rule the CURRENT constitution names. Under monarchy that resolves to "the Archon ratifies", so flipping OUT of monarchy is a legal monarchy act; every change after that belongs to the consent board. This is how a constitution's own amendment procedure normally works, and it is why no bootstrap special case is needed.\n\nThis is the owner's answer to the loophole that motivated the whole feature — the rule that constrains the owner can no longer be weakened by the owner alone. Deps R10. ${SPEC}` },
100
-
101
- // ---- Phase C — the hall (P4) ----
102
- { ref:'R15', kind:'feature', disc:'engineer', prio:4, est:150, crit:[C5], deps:['R05'],
103
- title:'R15 · Government page IA: Constitution / Board Room / Ranks & Permissions',
104
- desc:`Government becomes the page that answers "how is this project governed", in three sections: Constitution (what we run + the charter library), Board Room (open items, your vote, the clock), and Ranks & Permissions (today's administration surface, unchanged).\n\nThe tab was renamed from Governance under task 1003007 — build on that, do not re-litigate the naming. Deps R05. ${SPEC}` },
105
-
106
- { ref:'R16', kind:'feature', disc:'engineer', prio:4, est:240, crit:[C1,C4,C5], deps:['R08','R15'],
107
- title:'R16 · The Board Room: open items, the clock, the tally',
108
- desc:`Open items with their remaining time, your own vote state, a LIVE open-ballot tally (who voted which way and when), and the closed history with outcomes. Must read sensibly with several concurrent windows, which are normal at a 90-minute default with automatic opening. Deps R08,R15. ${SPEC}` },
109
-
110
- { ref:'R17', kind:'feature', disc:'engineer', prio:4, est:180, crit:[C2,C5], deps:['R09','R16'],
111
- title:'R17 · The vote UI: cast, reason box, five-section picker',
112
- desc:`Cast a vote, and for an objection write the reason and pick exactly one of the five Full Idea sections. The full idea and its five sections must be in front of the voter while they decide — that context is the entire reason voting happens in the hall rather than on a Discord reaction. Deps R09,R16. ${SPEC}` },
113
-
114
- { ref:'R18', kind:'feature', disc:'engineer', prio:4, est:150, crit:[C3,C5], deps:['R14','R15'],
115
- title:'R18 · The Constitution section: what we run, and how it changed',
116
- desc:`Show the active constitution in plain language — who may vote, how an item passes, how long a window runs — plus the full change history, so a switch can never be flipped quietly. Deps R14,R15. ${SPEC}` },
117
-
118
- { ref:'R19', kind:'feature', disc:'engineer', prio:4, est:210, crit:[C5], deps:['R15'],
119
- title:'R19 · The charter library: seven constitutions and the ladder',
120
- desc:`Present all seven government structures (Monarchy/BDFL, Timocratic Republic, Direct Democracy, Presidential, Cooperative, Federation, Foundation), the three trajectories (Locked, Laddered, Scheduled), and the developmental ladder's thresholds (~9 named executive, ~25, ~50 written charter + council, ~150 adjudication separates / federate beyond).\n\nMark which are SELECTABLE TODAY versus documented-for-later, so nobody is misled. Name which is recommended at this project's CURRENT builder count. This is the half of the surface that earns its keep at two builders — the owner's stated purpose is getting a team up to speed before deciding when to flip the switch.\n\nSource: the Six Variables of Governance synthesis (Parts III and IV). Deps R15. ${SPEC}` },
121
-
122
- // ---- Phase D — the mirror (P3) ----
123
- { ref:'R20', kind:'feature', disc:'engineer', prio:3, est:90, crit:[C6], deps:['R01'],
124
- title:'R20 · The board channel, with per-rank view access',
125
- desc:`Add the board channel to docs/discord/channels.json with per-rank view access (ADR 0037 — the bot creates/edits channels, topics and access from that config file). Independent of the whole rule engine, so this is good early parallel work for a second builder. Deps R01. ${SPEC}` },
126
-
127
- { ref:'R21', kind:'feature', disc:'engineer', prio:3, est:180, crit:[C6], deps:['R07','R20'],
128
- title:'R21 · Announce a window: mention the members, deep-link the hall',
129
- desc:`On window open, post to the board channel mentioning the members whose vote is wanted, carrying a deep link straight to that item in the hall. The mention IS the "vote within X" notice, and Discord's own mobile app IS the mobile push — no new surface is needed and the bot has no DM capability today (verified).\n\nFollow modules/discord/approval-broadcast + discord-approvals.js for the BROADCAST shape only. Discord is outbound-only here: it reads nothing inbound and casts no vote. Deps R07,R20. ${SPEC}` },
130
-
131
- { ref:'R22', kind:'feature', disc:'engineer', prio:3, est:120, crit:[C6], deps:['R10','R21'],
132
- title:'R22 · Mirror state: closed, and the outcome',
133
- desc:`Edit the announcement in place as the item closes and resolves, so the channel never shows a stale open window. The item's state lives in the DATABASE — Discord is a mirror of it, never a source. Deps R10,R21. ${SPEC}` },
134
-
135
- // ---- Phase E — proofs (P3) ----
136
- { ref:'R23', kind:'verify', disc:'engineer', prio:3, est:150, crit:[C1,C3], deps:['R12','R17','R22'],
137
- title:'R23 · PROOF: day-one monarchy, end to end',
138
- desc:`On the live configuration: a Full Idea passes the completeness grade, a window opens automatically, the Archon ratifies in the hall, and the pass event fires exactly once with the payload IC5 expects. Proves C1 and the day-one half of C3 — and proves the board path really is the code path monarchy runs through. Deps R12,R17,R22. ${SPEC}` },
139
-
140
- { ref:'R24', kind:'verify', disc:'engineer', prio:3, est:120, crit:[C2], deps:['R13','R17'],
141
- title:'R24 · PROOF: a rejection round-trip',
142
- desc:`Reject a Full Idea with a reason and a flagged section, confirm the author sees both, revise that section, resubmit, and pass. Also confirm the sub-bar-grade path flags the weakest section automatically. Proves C2 end to end. Deps R13,R17. ${SPEC}` },
143
-
144
- { ref:'R25', kind:'verify', disc:'engineer', prio:3, est:180, crit:[C3,C4], deps:['R11','R14','R18'],
145
- title:'R25 · PROOF: flip the switch, then run a real sitting',
146
- desc:`Change the constitution from monarchy to the consent board BY RATIFICATION under the monarchy rule, then run a timed sitting through to expiry — verifying an absent member's vote is nulled rather than blocking, that a zero-vote close passes, and that a window closes early on full turnout. The single most important proof in the goal: it is the only thing that shows the switch actually works before you need it. Deps R11,R14,R18. ${SPEC}` },
147
-
148
- { ref:'R26', kind:'verify', disc:'engineer', prio:3, est:90, crit:[C5], deps:['R19'],
149
- title:'R26 · PROOF: the charter library reads right at this headcount',
150
- desc:`Confirm the library's recommendation matches this project's actual builder count, that selectable-today is honestly marked, and that a newcomer can answer "what are we running, and what could we run" from the page alone. Deps R19. ${SPEC}` },
151
- ];
152
-
153
- async function main() {
154
- const idByRef = {};
155
- console.log(`Seeding ${TASKS.length} tasks → ${VER} / goal ${GOAL}\n`);
156
-
157
- for (const t of TASKS) {
158
- const source_ref = `board-room-${t.ref}`;
159
- const body = {
160
- version_id: VER, goal_id: GOAL, source: SRC, source_ref,
161
- title: t.title, description: t.desc,
162
- kind: t.kind, discipline: t.disc, status: 'backlog',
163
- priority: t.prio, est_minutes: t.est,
164
- criterion_ids: t.crit,
165
- };
166
- const r = await api('POST', '/tasks', body);
167
- if (r.ok && r.json.task) {
168
- idByRef[t.ref] = r.json.task.id;
169
- console.log(` ${t.ref} → ${r.json.task.id} ${t.title.slice(0, 62)}`);
170
- } else if (r.status === 409 && r.json.task) {
171
- idByRef[t.ref] = r.json.task.id;
172
- console.log(` ${t.ref} → ${r.json.task.id} (already seeded)`);
173
- } else {
174
- console.error(` ${t.ref} FAILED ${r.status}`, JSON.stringify(r.json).slice(0, 400));
175
- }
176
- }
177
-
178
- console.log('\nWiring dependencies…');
179
- let edges = 0;
180
- for (const t of TASKS) {
181
- const id = idByRef[t.ref];
182
- if (!id || !t.deps.length) continue;
183
- for (const ref of t.deps) {
184
- const dep = idByRef[ref];
185
- if (!dep) { console.error(` ${t.ref} dep ${ref} unresolved`); continue; }
186
- const r = await api('POST', `/tasks/${id}/dependencies`, { depends_on_task_id: dep });
187
- if (r.ok || r.status === 409) { edges++; console.log(` ${t.ref} ← ${ref}`); }
188
- else console.error(` ${t.ref} ← ${ref} FAILED ${r.status}`, JSON.stringify(r.json).slice(0, 300));
189
- }
190
- }
191
-
192
- console.log(`\nDone. ${Object.keys(idByRef).length}/${TASKS.length} tasks, ${edges} dependency edges.`);
193
- console.log('Zero-dep layer (promote to ready): R01');
194
- }
195
-
196
- main().catch((e) => { console.error(e); process.exit(1); });