@bongos/core 1.19.190 → 1.19.191
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 +15 -10
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/seed-board-room-tasks.js +196 -0
- package/src/module-api.js +3 -1
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.191",
|
|
6
|
+
"core_contract": "1.19.191",
|
|
7
|
+
"source_commit": "0a30e8955f1b4904fc8eca19d56228a7dff4b32e",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-17T01:01:06.099Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 309,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1283,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1613,
|
|
20
|
+
"tree_sha256": "234f75ccb67ec7927d6010bbcbd597c9f256e10615cce8d0cbda596850bc0e34",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -4262,12 +4262,12 @@
|
|
|
4262
4262
|
{
|
|
4263
4263
|
"path": "package-lock.json",
|
|
4264
4264
|
"mode": "0000644",
|
|
4265
|
-
"sha256": "
|
|
4265
|
+
"sha256": "ecea40048b1e131835510177f7e19c5cff45b3449c8115b1f1303bde7961a1a4"
|
|
4266
4266
|
},
|
|
4267
4267
|
{
|
|
4268
4268
|
"path": "package.json",
|
|
4269
4269
|
"mode": "0000644",
|
|
4270
|
-
"sha256": "
|
|
4270
|
+
"sha256": "7f2cdbd17679eff46f8f1d19f593e2f75e909c25e536094b650fe47529547ba7"
|
|
4271
4271
|
},
|
|
4272
4272
|
{
|
|
4273
4273
|
"path": "public-docs/index.html",
|
|
@@ -5284,6 +5284,11 @@
|
|
|
5284
5284
|
"mode": "0000644",
|
|
5285
5285
|
"sha256": "15d4d176f561e408c6116208b295fe5f03fc5e06ca8bb713f023fb1950d1a89a"
|
|
5286
5286
|
},
|
|
5287
|
+
{
|
|
5288
|
+
"path": "scripts/gds/seed-board-room-tasks.js",
|
|
5289
|
+
"mode": "0000644",
|
|
5290
|
+
"sha256": "a079b2422e842deed0bbcd7ad5ae3ab7e1ec4576a26689a80f67e9a56a2411ba"
|
|
5291
|
+
},
|
|
5287
5292
|
{
|
|
5288
5293
|
"path": "scripts/gds/seed-bongos-app-tasks.js",
|
|
5289
5294
|
"mode": "0000644",
|
|
@@ -5872,7 +5877,7 @@
|
|
|
5872
5877
|
{
|
|
5873
5878
|
"path": "src/module-api.js",
|
|
5874
5879
|
"mode": "0000644",
|
|
5875
|
-
"sha256": "
|
|
5880
|
+
"sha256": "1ecbb2895d1ef012f455fe9827f59dade9bfee689b9a86230122a0334c4bff9d"
|
|
5876
5881
|
},
|
|
5877
5882
|
{
|
|
5878
5883
|
"path": "src/module-loader/catalog.js",
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.191",
|
|
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.191",
|
|
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.191",
|
|
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",
|
|
@@ -0,0 +1,196 @@
|
|
|
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/gds/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/gds${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 0162 (verdicts advisory), 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); });
|
package/src/module-api.js
CHANGED
|
@@ -807,8 +807,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
807
807
|
// landed since 1.19.188 with no explicit bump. run 31983108640. (task 1002620)
|
|
808
808
|
// 1.19.190 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
809
809
|
// landed since 1.19.189 with no explicit bump. run 31983360426. (task 1002620)
|
|
810
|
+
// 1.19.191 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
811
|
+
// landed since 1.19.190 with no explicit bump. run 31983663234. (task 1002620)
|
|
810
812
|
// ---------------------------------------------------------------------------
|
|
811
|
-
const CORE_VERSION = '1.19.
|
|
813
|
+
const CORE_VERSION = '1.19.191'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
812
814
|
|
|
813
815
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
814
816
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|