@bongos/core 1.19.234 → 1.19.235
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 +20 -15
- package/modules/government/board.js +24 -2
- package/modules/government/db.js +12 -0
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/government.js +59 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +3 -1
- package/tests/government_charter_library.mjs +77 -0
- package/tests/government_constitution_view.mjs +2 -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.235",
|
|
6
|
+
"core_contract": "1.19.235",
|
|
7
|
+
"source_commit": "b91cbff1532b00e3cdd2204e713b35cf093c9b02",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-18T16:
|
|
9
|
+
"built_at": "2026-08-18T16:46:17.722Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 311,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1319,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1651,
|
|
20
|
+
"tree_sha256": "d20a6edcee7ad8a7e81eefec0b07689a820b194634cdb5350c8c4263127990ea",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -2902,7 +2902,7 @@
|
|
|
2902
2902
|
{
|
|
2903
2903
|
"path": "modules/government/board.js",
|
|
2904
2904
|
"mode": "0000644",
|
|
2905
|
-
"sha256": "
|
|
2905
|
+
"sha256": "9d3d9414ca1c1bafc901a7343cdccafc7261b0dba492134a9a1064e6b3d82b61"
|
|
2906
2906
|
},
|
|
2907
2907
|
{
|
|
2908
2908
|
"path": "modules/government/catalog.js",
|
|
@@ -2917,7 +2917,7 @@
|
|
|
2917
2917
|
{
|
|
2918
2918
|
"path": "modules/government/db.js",
|
|
2919
2919
|
"mode": "0000644",
|
|
2920
|
-
"sha256": "
|
|
2920
|
+
"sha256": "ab75e3e0fd2b7eee747e525403f8a2ea863dbf1f4332cb3c6ec1b413ed7af7e3"
|
|
2921
2921
|
},
|
|
2922
2922
|
{
|
|
2923
2923
|
"path": "modules/government/migrations/governance_001_tables.sql",
|
|
@@ -3272,12 +3272,12 @@
|
|
|
3272
3272
|
{
|
|
3273
3273
|
"path": "modules/hall-ui/public/government.html",
|
|
3274
3274
|
"mode": "0000644",
|
|
3275
|
-
"sha256": "
|
|
3275
|
+
"sha256": "87ec2d8c002edf0a440e658cb29e567a07544bc36bb535d4cb0fd5130629a92e"
|
|
3276
3276
|
},
|
|
3277
3277
|
{
|
|
3278
3278
|
"path": "modules/hall-ui/public/government.js",
|
|
3279
3279
|
"mode": "0000644",
|
|
3280
|
-
"sha256": "
|
|
3280
|
+
"sha256": "505003cd76eb3760459ed53555b5c0803e1efaffb2e17ee15c7ed032a1607289"
|
|
3281
3281
|
},
|
|
3282
3282
|
{
|
|
3283
3283
|
"path": "modules/hall-ui/public/hall-kit.js",
|
|
@@ -4322,12 +4322,12 @@
|
|
|
4322
4322
|
{
|
|
4323
4323
|
"path": "package-lock.json",
|
|
4324
4324
|
"mode": "0000644",
|
|
4325
|
-
"sha256": "
|
|
4325
|
+
"sha256": "7731f20b3114fe6a083c06fe6b92d0048e4d5d136ba4fcc49f9a10f66c9577e5"
|
|
4326
4326
|
},
|
|
4327
4327
|
{
|
|
4328
4328
|
"path": "package.json",
|
|
4329
4329
|
"mode": "0000644",
|
|
4330
|
-
"sha256": "
|
|
4330
|
+
"sha256": "844c9c21b09d3d41cd8663a37d651ec717a5ba25d5fb24fda5e57930ca278cb2"
|
|
4331
4331
|
},
|
|
4332
4332
|
{
|
|
4333
4333
|
"path": "public-docs/index.html",
|
|
@@ -5942,7 +5942,7 @@
|
|
|
5942
5942
|
{
|
|
5943
5943
|
"path": "src/module-api.js",
|
|
5944
5944
|
"mode": "0000644",
|
|
5945
|
-
"sha256": "
|
|
5945
|
+
"sha256": "c3a588bdcb0781e8f71dd492f26b09a2212ababebf52e511dccb9018ad84f89b"
|
|
5946
5946
|
},
|
|
5947
5947
|
{
|
|
5948
5948
|
"path": "src/module-loader/catalog.js",
|
|
@@ -6904,6 +6904,11 @@
|
|
|
6904
6904
|
"mode": "0000644",
|
|
6905
6905
|
"sha256": "74cfbd482b689df40348af3bdaf050f056e216ff18fdd6add4136d4589b7cd92"
|
|
6906
6906
|
},
|
|
6907
|
+
{
|
|
6908
|
+
"path": "tests/government_charter_library.mjs",
|
|
6909
|
+
"mode": "0000644",
|
|
6910
|
+
"sha256": "9a52ac8fbbc9e7b0fc4b45841b9dbf831615e5d64eb1e3f0d9c446fc70552629"
|
|
6911
|
+
},
|
|
6907
6912
|
{
|
|
6908
6913
|
"path": "tests/government_claim_eligibility.mjs",
|
|
6909
6914
|
"mode": "0000644",
|
|
@@ -6917,7 +6922,7 @@
|
|
|
6917
6922
|
{
|
|
6918
6923
|
"path": "tests/government_constitution_view.mjs",
|
|
6919
6924
|
"mode": "0000644",
|
|
6920
|
-
"sha256": "
|
|
6925
|
+
"sha256": "64fc8006d5b3a562b01a38bfd0ad00a1357969b0ac52ce270e77d4d93eddca80"
|
|
6921
6926
|
},
|
|
6922
6927
|
{
|
|
6923
6928
|
"path": "tests/government_fold.mjs",
|
|
@@ -530,9 +530,30 @@ async function boardRoomView({ closedLimit = 20 } = {}) {
|
|
|
530
530
|
// row carries the rule it was DECIDED UNDER (the item's snapshot), so the
|
|
531
531
|
// reader can verify every change was made legally by the constitution of its
|
|
532
532
|
// day — the §7 chain, auditable end to end.
|
|
533
|
+
// ── the charter ladder's recommendation (BV1.R19, criterion C5) ─────────────
|
|
534
|
+
//
|
|
535
|
+
// The developmental ladder from the Six Variables synthesis (Part III), as the
|
|
536
|
+
// spec's task text records it: formality is adopted only where informal
|
|
537
|
+
// coordination breaks. PURE and server-side so R26's proof can hold the
|
|
538
|
+
// recommendation against the real headcount — the library's one live datum.
|
|
539
|
+
// The bands deliberately track only the thresholds the synthesis NAMES
|
|
540
|
+
// (~9 name an executive, ~50 written charter + council, ~150 adjudication
|
|
541
|
+
// separates / federate beyond); everything else is reference prose, not code.
|
|
542
|
+
function recommendedCharter(headcount) {
|
|
543
|
+
const n = Number(headcount) || 0;
|
|
544
|
+
if (n <= 2) return { key: 'monarchy', rung: 'solo/pair', why: 'informal coordination has nothing to break yet — the founding monarchy is the honest shape' };
|
|
545
|
+
if (n <= 8) return { key: 'direct-democracy', rung: 'circle (3–8)', why: 'a consent circle of all trusted members — the rung this ladder was written on' };
|
|
546
|
+
if (n <= 49) return { key: 'presidential', rung: '~9: name an executive', why: 'past ~9, naming an executive beats everyone coordinating with everyone' };
|
|
547
|
+
if (n <= 149) return { key: 'foundation', rung: '~50: written charter + council', why: 'past ~50, the charter must be written down and a council carries it' };
|
|
548
|
+
return { key: 'federation', rung: '~150: adjudication separates — federate beyond', why: 'past ~150, one body cannot both govern and adjudicate; federate' };
|
|
549
|
+
}
|
|
550
|
+
|
|
533
551
|
async function constitutionView({ historyLimit = 50 } = {}) {
|
|
534
552
|
const { board: live } = loadGovernmentConfig();
|
|
535
|
-
const rows = await
|
|
553
|
+
const [rows, headcount] = await Promise.all([
|
|
554
|
+
db.listAmendmentHistory(historyLimit),
|
|
555
|
+
db.countActiveBuilders(),
|
|
556
|
+
]);
|
|
536
557
|
const history = rows.map((r) => ({
|
|
537
558
|
item_id: String(r.item_id),
|
|
538
559
|
amendment_id: String(r.amendment_id),
|
|
@@ -546,7 +567,7 @@ async function constitutionView({ historyLimit = 50 } = {}) {
|
|
|
546
567
|
outcome: r.outcome,
|
|
547
568
|
decided_under: r.decided_under || null,
|
|
548
569
|
}));
|
|
549
|
-
return { board: live, history };
|
|
570
|
+
return { board: live, history, headcount, recommended: recommendedCharter(headcount) };
|
|
550
571
|
}
|
|
551
572
|
|
|
552
573
|
// ── R13's read: the feedback a returned idea carries back to its author ─────
|
|
@@ -591,4 +612,5 @@ module.exports = {
|
|
|
591
612
|
proposeAmendment,
|
|
592
613
|
boardRoomView,
|
|
593
614
|
constitutionView,
|
|
615
|
+
recommendedCharter,
|
|
594
616
|
};
|
package/modules/government/db.js
CHANGED
|
@@ -509,6 +509,17 @@ async function getAmendmentSubjects(amendmentIds) {
|
|
|
509
509
|
return rows;
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
+
// The live headcount (R19): active humans, the same two filters as board
|
|
513
|
+
// membership — a machine principal is not a team member, and neither is a
|
|
514
|
+
// departed builder. Feeds the charter library's "recommended at YOUR headcount"
|
|
515
|
+
// line, which R26's proof holds against this exact number.
|
|
516
|
+
async function countActiveBuilders() {
|
|
517
|
+
const { rows } = await pool.query(
|
|
518
|
+
`SELECT count(*)::int AS n FROM builders WHERE status = 'active' AND system_role IS NULL`,
|
|
519
|
+
);
|
|
520
|
+
return rows[0] ? rows[0].n : 0;
|
|
521
|
+
}
|
|
522
|
+
|
|
512
523
|
// The constitution's change HISTORY (R18): every CLOSED amendment sitting —
|
|
513
524
|
// passed AND returned — joined to what was proposed, newest first. Returned
|
|
514
525
|
// proposals are deliberately part of the record: "a switch can never be flipped
|
|
@@ -653,4 +664,5 @@ module.exports = {
|
|
|
653
664
|
getIdeaSubjects,
|
|
654
665
|
getAmendmentSubjects,
|
|
655
666
|
listAmendmentHistory,
|
|
667
|
+
countActiveBuilders,
|
|
656
668
|
};
|
|
@@ -99,6 +99,6 @@
|
|
|
99
99
|
<script src="/builders/palette.js" defer></script>
|
|
100
100
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
101
101
|
<script src="/builders/hall-kit.js"></script>
|
|
102
|
-
<script src="/builders/government.js?v=2026-08-18-
|
|
102
|
+
<script src="/builders/government.js?v=2026-08-18-charter-library"></script>
|
|
103
103
|
</body>
|
|
104
104
|
</html>
|
|
@@ -470,6 +470,64 @@
|
|
|
470
470
|
</div>`;
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
+
// ---- the charter library (R19) ---------------------------------------------
|
|
474
|
+
|
|
475
|
+
// The REFERENCE half of the Charter Builder — the seven structures, the three
|
|
476
|
+
// trajectories, the ladder — and deliberately not the configuration machinery
|
|
477
|
+
// (the scale argument in ADR 0175: formality is adopted only where informal
|
|
478
|
+
// coordination breaks). `selectable` means EXPRESSIBLE TODAY through the real
|
|
479
|
+
// config — a rank-predicate membership plus first_ratifier|consent — so nobody
|
|
480
|
+
// is misled about what a settings change can and cannot reach. Source: the
|
|
481
|
+
// Six-Variables synthesis (Verro Labs, Aug 2026), Parts III–IV, via the spec.
|
|
482
|
+
const CHARTERS = [
|
|
483
|
+
{ key: 'monarchy', name: 'Monarchy / BDFL', selectable: true,
|
|
484
|
+
how: "membership rank:archon · first ratifier · no clock — the shipped default",
|
|
485
|
+
blurb: 'One trusted executive decides. Fast, legible, and honest at founding scale; the shape every project actually starts in.' },
|
|
486
|
+
{ key: 'timocratic-republic', name: 'Timocratic Republic', selectable: true,
|
|
487
|
+
how: 'membership by a trusted rank (e.g. rank:metic) · consent · a timed sitting',
|
|
488
|
+
blurb: 'Standing accrues to those actively building: the franchise follows earned rank, not headcount.' },
|
|
489
|
+
{ key: 'direct-democracy', name: 'Direct Democracy', selectable: true,
|
|
490
|
+
how: 'membership rank:xenos (everyone) · consent · a timed sitting',
|
|
491
|
+
blurb: 'Every builder sits on the board. Consent keeps it unblockable: silence passes, one reasoned objection returns.' },
|
|
492
|
+
{ key: 'presidential', name: 'Presidential', selectable: false,
|
|
493
|
+
blurb: 'An ELECTED executive with a fixed term. Needs election machinery this system does not have yet — documented for later.' },
|
|
494
|
+
{ key: 'cooperative', name: 'Cooperative', selectable: false,
|
|
495
|
+
blurb: 'Formal one-member-one-vote with membership shares and exit rules. Needs the membership-share machinery — documented for later.' },
|
|
496
|
+
{ key: 'federation', name: 'Federation', selectable: false,
|
|
497
|
+
blurb: 'Multiple chambers or sub-projects, each self-governing, coordinating through a compact. The >150 shape — documented for later.' },
|
|
498
|
+
{ key: 'foundation', name: 'Foundation', selectable: true,
|
|
499
|
+
how: 'a CUSTOM rank as the trustee body (the Ranks tab creates it) · consent · a timed sitting',
|
|
500
|
+
blurb: 'A written charter carried by a small appointed council. Expressible today by governing through a custom rank.' },
|
|
501
|
+
];
|
|
502
|
+
const TRAJECTORIES = [
|
|
503
|
+
{ name: 'Locked', blurb: 'The constitution stays as founded until deliberately amended — no automatic movement.' },
|
|
504
|
+
{ name: 'Laddered', blurb: 'Steps up the developmental ladder as the team crosses each headcount threshold.' },
|
|
505
|
+
{ name: 'Scheduled', blurb: 'Pre-commits the dates or milestones at which each step happens, decided in advance.' },
|
|
506
|
+
];
|
|
507
|
+
const LADDER = 'solo/pair → circle (3–8) → ~9 name an executive → ~25 → ~50 written charter + council → ~150 adjudication separates → beyond: federate';
|
|
508
|
+
|
|
509
|
+
function charterCard(c, recommendedKey) {
|
|
510
|
+
const pill = c.selectable
|
|
511
|
+
? '<span class="gov-pill gov-pill--seeded">selectable today</span>'
|
|
512
|
+
: '<span class="gov-pill gov-pill--locked">documented for later</span>';
|
|
513
|
+
const rec = c.key === recommendedKey ? ' <span class="gov-pill gov-pill--custom">recommended at your headcount</span>' : '';
|
|
514
|
+
const how = c.how ? `<div class="gov-perm__guards">as configuration: ${escapeHtml(c.how)}</div>` : '';
|
|
515
|
+
return `<div class="gov-assign-row"><span class="gov-assign-row__who"><strong>${escapeHtml(c.name)}</strong> — ${escapeHtml(c.blurb)}${how}</span>${pill}${rec}</div>`;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function charterLibraryHtml(data) {
|
|
519
|
+
const rec = data.recommended || {};
|
|
520
|
+
return `
|
|
521
|
+
<h2 class="gov-h">Charter library</h2>
|
|
522
|
+
<p class="gov-grid-note">The seven government structures, for getting a team up to speed before deciding when to flip a switch. <strong>Selectable today</strong> means expressible through the real configuration — a rank-based membership plus a pass rule — with no new code. This project has <strong>${escapeHtml(String(data.headcount ?? '?'))}</strong> active builder${data.headcount === 1 ? '' : 's'}: ${escapeHtml(rec.why || '')} <em>(${escapeHtml(rec.rung || '')})</em>.</p>
|
|
523
|
+
<div class="gov-section">${CHARTERS.map((c) => charterCard(c, rec.key)).join('')}</div>
|
|
524
|
+
<h2 class="gov-h">Trajectories</h2>
|
|
525
|
+
<p class="gov-grid-note">How a project moves between structures over time — summarized from the synthesis:</p>
|
|
526
|
+
<div class="gov-section">${TRAJECTORIES.map((t) => `<div class="gov-assign-row"><span class="gov-assign-row__who"><strong>${escapeHtml(t.name)}</strong> — ${escapeHtml(t.blurb)}</span></div>`).join('')}</div>
|
|
527
|
+
<p class="gov-grid-note muted">The developmental ladder: ${escapeHtml(LADDER)}. Formality is adopted only where informal coordination breaks.</p>
|
|
528
|
+
`;
|
|
529
|
+
}
|
|
530
|
+
|
|
473
531
|
async function loadConstitution() {
|
|
474
532
|
const box = document.getElementById('gov-constitution');
|
|
475
533
|
let data;
|
|
@@ -494,6 +552,7 @@
|
|
|
494
552
|
${history.length
|
|
495
553
|
? `<div class="gov-section">${history.map(historyRow).join('')}</div>`
|
|
496
554
|
: `<p class="gov-empty">Never amended — this project still runs its founding constitution.</p>`}
|
|
555
|
+
${charterLibraryHtml(data)}
|
|
497
556
|
`;
|
|
498
557
|
}
|
|
499
558
|
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.235",
|
|
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.235",
|
|
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.235",
|
|
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",
|
package/src/module-api.js
CHANGED
|
@@ -895,8 +895,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
895
895
|
// landed since 1.19.232 with no explicit bump. run 32160823445. (task 1002620)
|
|
896
896
|
// 1.19.234 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
897
897
|
// landed since 1.19.233 with no explicit bump. run 32161368847. (task 1002620)
|
|
898
|
+
// 1.19.235 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
899
|
+
// landed since 1.19.234 with no explicit bump. run 32161981393. (task 1002620)
|
|
898
900
|
// ---------------------------------------------------------------------------
|
|
899
|
-
const CORE_VERSION = '1.19.
|
|
901
|
+
const CORE_VERSION = '1.19.235'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
900
902
|
|
|
901
903
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
902
904
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// tests/government_charter_library.mjs — the charter library (BV1.R19 of goal
|
|
2
|
+
// 1000069, criterion C5): seven constitutions, three trajectories, the ladder —
|
|
3
|
+
// and ONE live datum, the recommendation at this project's actual headcount.
|
|
4
|
+
//
|
|
5
|
+
// The recommendation is SERVER-SIDE and pure precisely so R26's proof can hold
|
|
6
|
+
// it against the real number; the library prose is client reference content.
|
|
7
|
+
import assert from 'node:assert/strict';
|
|
8
|
+
import { test } from 'node:test';
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
16
|
+
const GOV = path.join(ROOT, 'modules', 'government');
|
|
17
|
+
const board = require(path.join(GOV, 'board.js'));
|
|
18
|
+
const db = require(path.join(GOV, 'db.js'));
|
|
19
|
+
|
|
20
|
+
const { recommendedCharter } = board;
|
|
21
|
+
|
|
22
|
+
test('the ladder bands track exactly the thresholds the synthesis names', () => {
|
|
23
|
+
assert.equal(recommendedCharter(1).key, 'monarchy');
|
|
24
|
+
assert.equal(recommendedCharter(2).key, 'monarchy', 'this project today: two builders → the founding monarchy');
|
|
25
|
+
assert.equal(recommendedCharter(3).key, 'direct-democracy', 'the circle rung starts at 3');
|
|
26
|
+
assert.equal(recommendedCharter(8).key, 'direct-democracy');
|
|
27
|
+
assert.equal(recommendedCharter(9).key, 'presidential', '~9: name an executive');
|
|
28
|
+
assert.equal(recommendedCharter(49).key, 'presidential');
|
|
29
|
+
assert.equal(recommendedCharter(50).key, 'foundation', '~50: written charter + council');
|
|
30
|
+
assert.equal(recommendedCharter(149).key, 'foundation');
|
|
31
|
+
assert.equal(recommendedCharter(150).key, 'federation', '~150: adjudication separates — federate');
|
|
32
|
+
assert.equal(recommendedCharter(0).key, 'monarchy', 'a zero/unknown headcount fails to the founding shape');
|
|
33
|
+
assert.equal(recommendedCharter('nonsense').key, 'monarchy');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('constitutionView carries the live headcount and its recommendation', async () => {
|
|
37
|
+
const originals = { listAmendmentHistory: db.listAmendmentHistory, countActiveBuilders: db.countActiveBuilders };
|
|
38
|
+
db.listAmendmentHistory = async () => [];
|
|
39
|
+
db.countActiveBuilders = async () => 7;
|
|
40
|
+
try {
|
|
41
|
+
const view = await board.constitutionView();
|
|
42
|
+
assert.equal(view.headcount, 7);
|
|
43
|
+
assert.equal(view.recommended.key, 'direct-democracy');
|
|
44
|
+
assert.ok(view.recommended.rung.includes('circle'));
|
|
45
|
+
} finally { Object.assign(db, originals); }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('the headcount counts the same population membership does (SQL pin)', () => {
|
|
49
|
+
const src = fs.readFileSync(path.join(GOV, 'db.js'), 'utf8');
|
|
50
|
+
const block = src.slice(src.indexOf('async function countActiveBuilders'), src.indexOf("// The constitution's change HISTORY"));
|
|
51
|
+
assert.match(block, /status = 'active'/);
|
|
52
|
+
assert.match(block, /system_role IS NULL/, 'a machine principal is not a team member');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('the library presents all seven structures with honest selectable marks (client source pins)', () => {
|
|
56
|
+
const client = fs.readFileSync(path.join(ROOT, 'modules', 'hall-ui', 'public', 'government.js'), 'utf8');
|
|
57
|
+
const lib = client.slice(client.indexOf('const CHARTERS'), client.indexOf('function charterCard'));
|
|
58
|
+
for (const name of ['Monarchy / BDFL', 'Timocratic Republic', 'Direct Democracy', 'Presidential', 'Cooperative', 'Federation', 'Foundation']) {
|
|
59
|
+
assert.ok(lib.includes(`name: '${name}'`), `the library must present ${name}`);
|
|
60
|
+
}
|
|
61
|
+
// Selectable ⇔ expressible through the REAL config (a rank predicate + a
|
|
62
|
+
// shipped pass rule). Every selectable entry must SAY HOW; every
|
|
63
|
+
// documented-for-later entry must not pretend.
|
|
64
|
+
const selectableTrue = (lib.match(/selectable: true/g) || []).length;
|
|
65
|
+
const selectableFalse = (lib.match(/selectable: false/g) || []).length;
|
|
66
|
+
assert.equal(selectableTrue + selectableFalse, 7, 'every structure is marked, none left ambiguous');
|
|
67
|
+
assert.equal(selectableTrue, 4, 'monarchy, timocratic republic, direct democracy, foundation — the config-expressible four');
|
|
68
|
+
const trueBlocks = lib.split('selectable: true').slice(1);
|
|
69
|
+
for (const b of trueBlocks) {
|
|
70
|
+
assert.ok(b.slice(0, 200).includes('how:'), 'a selectable structure names its configuration');
|
|
71
|
+
}
|
|
72
|
+
assert.match(client, /recommended at your headcount/, 'the one live datum is rendered');
|
|
73
|
+
assert.match(client, /c\.key === recommendedKey/, "the pill is driven by the SERVER's recommendation, never re-derived client-side");
|
|
74
|
+
for (const t of ['Locked', 'Laddered', 'Scheduled']) {
|
|
75
|
+
assert.ok(client.includes(`name: '${t}'`), `trajectory ${t} present`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
@@ -33,7 +33,7 @@ async function withDb(stubs, fn) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
test('the live board block is RESOLVED per request — this vanilla checkout reads monarchy', async () => {
|
|
36
|
-
const view = await withDb({ listAmendmentHistory: async () => [] }, () => board.constitutionView());
|
|
36
|
+
const view = await withDb({ listAmendmentHistory: async () => [], countActiveBuilders: async () => 2 }, () => board.constitutionView());
|
|
37
37
|
assert.deepEqual(view.board, BOARD_DEFAULTS,
|
|
38
38
|
'no instance pack here, so the resolved value IS the neutral monarchy — never a hardcoded copy');
|
|
39
39
|
assert.deepEqual(view.history, []);
|
|
@@ -42,6 +42,7 @@ test('the live board block is RESOLVED per request — this vanilla checkout rea
|
|
|
42
42
|
test('the history projects passed AND returned, with proposer identity and the decided-under snapshot', async () => {
|
|
43
43
|
const MONARCHY = { membership: 'rank:archon', pass_rule: 'first_ratifier', window_minutes: null, close_early_on_full_turnout: true };
|
|
44
44
|
const view = await withDb({
|
|
45
|
+
countActiveBuilders: async () => 2,
|
|
45
46
|
listAmendmentHistory: async (limit) => {
|
|
46
47
|
assert.equal(limit, 50);
|
|
47
48
|
return [
|