Merge ci-token-value 312eb7e8 into master (gate: green on 168a2cf0, recorded by tools/ci/pre-push.sh; landed on the box mirror under the exception declared by main: main's ruling, 7 Oct 2026 19:5x UK: the GitHub account is suspended, lanes land on the box mirror's master, the box gate stamp is the verdict; GitHub gets the fast-forward when it answers)
This commit is contained in:
commit
079afdeadd
15 changed files with 2104 additions and 5 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Igneum 2.0 test harness map
|
||||
|
||||
Generated from tools/ci/test-map.json by tools/ci/test-map-doc.mjs; edit the JSON, never this page. Registry: docs/plans/igneum-2.0-test-registry.json (190 cases).
|
||||
Generated from tools/ci/test-map.json by tools/ci/test-map-doc.mjs; edit the JSON, never this page. Registry: docs/plans/igneum-2.0-test-registry.json (262 cases).
|
||||
|
||||
Rule: a case maps to a cell only where the cell's tests visibly answer it; coverage names what the cell proves and what remains; a mapped cell's green writes RUNNING, PASS only when coverage is full and the evidence file exists; an automated case with no cell reads NOT RUN with its reason, never PASS by inference.
|
||||
|
||||
|
|
@ -573,7 +573,39 @@ Rule: a case maps to a cell only where the cell's tests visibly answer it; cover
|
|||
- R2-F14-R01 Public build has no default arbitrary remote execution and a documented least-privilege boundary.: R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map
|
||||
- R2-F14-R02 Automatic updates off remains off for urgent manifests until explicit action.: R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map
|
||||
- R2-F14-R03 A compromised fleet/update signing key cannot silently acquire wallet access or activate a consensus change.: R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map
|
||||
- TV-01 Resolve and freeze the monetary contract: TV-01 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + independent panel); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-02 Reproduce complete supply accounting: TV-02 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-03 Fair launch and early distribution: TV-03 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Release + ecosystem); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-04 Security budget without price rescue: TV-04 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + protocol); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-05 Strongest surviving specialist: TV-05 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Hardware reviewer + economics); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-06 Every fee and payment reconciles: TV-06 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + application); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-07 Ownership-critical engineering closure: TV-07 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + independent security); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-08 Custody and recovery usability: TV-08 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Wallet + independent users); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-09 Independently verifiable settlement: TV-09 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Wallet + consensus); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-10 Minimum-node and sponsored-use limits: TV-10 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + application); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-11 Pooled payments without authority loss: TV-11 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Pool + independent operators); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-12 Reproducible and consented software: TV-12 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Release + independent security); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-13 Committed maintenance coverage: TV-13 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Maintainers + independent finance); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-14 Founder-absent operating exercise: TV-14 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Independent operations panel); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-15 Governance and authority boundaries: TV-15 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + governance); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-16 Two functional independent access routes: TV-16 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Ecosystem + independent reviewer); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-17 Supply-price-liquidity measurement: TV-17 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Measurement steward); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-18 Real versus incentivised demand: TV-18 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-19 Independent developer adoption: TV-19 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Ecosystem + external developers); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-20 Programmable payment acceptance: TV-20 (token value gate, scope PAYMENT CAPABILITY): no gate executed; the harness is the owner role's (Application + wallet); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-21 Useful paid proof demand: TV-21 (token value gate, scope PAID WORK CAPABILITY): no gate executed; the harness is the owner role's (Proving + independent customers); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-22 Replaceable work-market gateway: TV-22 (token value gate, scope WORK MARKET CAPABILITY): no gate executed; the harness is the owner role's (Application + independent operators); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-23 Obligation-based deposits: TV-23 (token value gate, scope SERVICE BONDS IF ENABLED): no gate executed; the harness is the owner role's (Economics + security); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-24 AI earns a separate commercial case: TV-24 (token value gate, scope AI IF ENABLED): no gate executed; the harness is the owner role's (Compute + independent reviewer); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-25 Bounded machine purchasing: TV-25 (token value gate, scope AGENTS IF ENABLED): no gate executed; the harness is the owner role's (Application + security); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-26 Cryptographic migration readiness: TV-26 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Cryptography + protocol); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-27 Private data and oracle assurance: TV-27 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Security + product); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-28 Stable assets and bridge isolation: TV-28 (token value gate, scope STABLE/BRIDGE IF ENABLED): no gate executed; the harness is the owner role's (Application + security + counsel); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-29 Growth without inaccessible verification: TV-29 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + operations); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-30 Energy and claims discipline: TV-30 (token value gate, scope CORE): no gate executed; the harness is the owner role's (GPU + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-31 Public-claim and activity review: TV-31 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Qualified counsel); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
- TV-32 Observed leadership, not a roadmap certificate: TV-32 (token value gate, scope LEADERSHIP CLAIM): no gate executed; the harness is the owner role's (Independent acceptance panel); a supplemental layer, never counted as independent evidence; not yet named in the map
|
||||
|
||||
## Count
|
||||
|
||||
171 automated cases: 88 mapped to a cell, 141 NOT RUN with a reason.
|
||||
203 automated cases: 88 mapped to a cell, 173 NOT RUN with a reason.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -173,6 +173,10 @@ merge_with_batches() { # <tip> <sha> <msg> [branch]: in a worktree at <tip> me
|
|||
node tools/ci/int-suite.mjs --traceability docs/plans/igneum-2.0-master/traceability.json --write >/dev/null || { echo "merge-to-master: the INT suite does not regenerate on the merged tree" >&2; git merge --abort 2>/dev/null; return 1; }
|
||||
echo "merge-to-master: regenerated the INT suite on master's registry"
|
||||
fi
|
||||
if [ -f tools/ci/token-value-suite.mjs ] && [ -f docs/plans/igneum-2.0-master/token-value/rules-and-gates.json ]; then
|
||||
node tools/ci/token-value-suite.mjs --write >/dev/null || { echo "merge-to-master: the VR and TV suites do not regenerate on the merged tree" >&2; git merge --abort 2>/dev/null; return 1; }
|
||||
echo "merge-to-master: regenerated the VR and TV suites on master's registry"
|
||||
fi
|
||||
for f in $BATCHES; do
|
||||
[ "$f" = . ] && continue
|
||||
git checkout -q "$( [ "$mode" = branch ] && echo "$tip" || echo "$sha" )" -- "$f"
|
||||
|
|
@ -377,7 +381,7 @@ bash tools/ci/rule24-crate-gate.sh "$BASE" "$SHA" || { echo "merge-to-master: RE
|
|||
REGISTRY_PATH="${REGISTRY_PATH:-docs/plans/igneum-2.0-test-registry.json}"
|
||||
BATCHES=$(git diff --name-only --diff-filter=AM "$BASE" "$SHA" -- tools/ci/batches/ | grep -E '\.json$' || true)
|
||||
NOTES=$(git diff --name-only --diff-filter=AM "$BASE" "$SHA" -- tools/ci/notes/ | grep -E '\.json$' || true) # {suite, text}, replayed through test-record.mjs --note-file
|
||||
REVGEN=0; git diff --quiet "$BASE" "$SHA" -- tools/ci/review-suite.mjs tools/ci/int-suite.mjs docs/analysis/review-2026-10-08-b/findings.json docs/analysis/review-2026-10-08-b/dispatch.md docs/plans/igneum-2.0-master/traceability.json 2>/dev/null || REVGEN=1 # the REV and INT suites regenerate on the merged tree
|
||||
REVGEN=0; git diff --quiet "$BASE" "$SHA" -- tools/ci/review-suite.mjs tools/ci/int-suite.mjs tools/ci/token-value-suite.mjs docs/analysis/review-2026-10-08-b/findings.json docs/analysis/review-2026-10-08-b/dispatch.md docs/plans/igneum-2.0-master/traceability.json docs/plans/igneum-2.0-master/token-value/rules-and-gates.json 2>/dev/null || REVGEN=1 # the REV and INT suites regenerate on the merged tree
|
||||
[ -n "$NOTES" ] || [ "$REVGEN" = 1 ] && BATCHES="${BATCHES:-.}" # the registry is rebuilt from master's copy whenever any transform rides
|
||||
RULE26_SKIP_PATHS=""; [ -n "$BATCHES" ] && RULE26_SKIP_PATHS="$REGISTRY_PATH"
|
||||
# the harness map page is generated from tools/ci/test-map.json (test-map-doc.mjs); a branch that changed the map regenerated the
|
||||
|
|
|
|||
8
tools/ci/notes/decision-d01-20261009.json
Normal file
8
tools/ci/notes/decision-d01-20261009.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"decision": "D01",
|
||||
"status": "RATIFIED",
|
||||
"word": "capped issuance, no tail escape clause, no forecast-triggered minting, no ordinary parameter vote that expands the cap; subject to the pre-launch security-funding gate TV-04 (a fail means delay or an open reconsideration, never an undisclosed rescue)",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)",
|
||||
"condition": "subject to TV-04"
|
||||
}
|
||||
8
tools/ci/notes/decision-d02-20261009.json
Normal file
8
tools/ci/notes/decision-d02-20261009.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"decision": "D02",
|
||||
"status": "RATIFIED WITH PARAMETER PENDING",
|
||||
"word": "the same-cap emission comparison is approved (current pacing vs a longer distribution; code-generated figures for years 1, 2, 5, 10, 20 with rounding and terminal behaviour; no founder reserve); the final schedule stays PENDING EVIDENCE, neither alternative frozen",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)",
|
||||
"condition": "the final schedule PENDING EVIDENCE"
|
||||
}
|
||||
7
tools/ci/notes/decision-d03-20261009.json
Normal file
7
tools/ci/notes/decision-d03-20261009.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"decision": "D03",
|
||||
"status": "RATIFIED",
|
||||
"word": "separate accountable budgets for hashing, internal proving, external work and maintenance, every payment counted once; external prover revenue never counted as miner security, maintenance and Labs profit at once",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)"
|
||||
}
|
||||
8
tools/ci/notes/decision-d04-20261009.json
Normal file
8
tools/ci/notes/decision-d04-20261009.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"decision": "D04",
|
||||
"status": "RATIFIED WITH PARAMETER PENDING",
|
||||
"word": "explicit auditable routing with no hidden company allocation; the 80/20 split is emission allocation only; the external-job fee or burn rate is NOT ratified, comparative pricing tests decide",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)",
|
||||
"condition": "the external-job fee or burn rate not ratified; comparative pricing tests decide"
|
||||
}
|
||||
7
tools/ci/notes/decision-d05-20261009.json
Normal file
7
tools/ci/notes/decision-d05-20261009.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"decision": "D05",
|
||||
"status": "RATIFIED",
|
||||
"word": "a recovery certificate is never ordinary finality on any wallet, receipt, API or bridge; labels do not repair an unsafe recovery rule, which still needs its tests",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)"
|
||||
}
|
||||
7
tools/ci/notes/decision-d06-20261009.json
Normal file
7
tools/ci/notes/decision-d06-20261009.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"decision": "D06",
|
||||
"status": "RATIFIED",
|
||||
"word": "separate claims; public wording \"Designed to compete for leadership among GPU-first networks.\"; after testing, the demonstrated advantage is named, never a blanket number one",
|
||||
"by": "founder",
|
||||
"recorded_against": "its specification, release and acceptance tests before activation (the coordinator's relay of the founder's ratification, 9 October 2026, 09:2x UK)"
|
||||
}
|
||||
4
tools/ci/notes/tv-counting-20261009.json
Normal file
4
tools/ci/notes/tv-counting-20261009.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"suite": "TV",
|
||||
"text": "Counting note (main's order, 9 October 2026, by 11:00 UK): the VR rules (40) and TV gates (32) are a supplemental layer over the master's 128 cases, the 18 integration gates and the 44 review regressions, never added to them as independent evidence; no TV gate has executed; every VR rule is PROPOSED and requires ratification by the founder and its owner role; the decisions D01 to D06 are UNAPPROVED, the founder's."
|
||||
}
|
||||
4
tools/ci/notes/tv-counting-registry-20261009.json
Normal file
4
tools/ci/notes/tv-counting-registry-20261009.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"suite": "registry",
|
||||
"text": "Counting note (9 October 2026): the registry carries 128 master cases, 18 integration gates (INT), 44 review regressions (REV), and the token value layer (VR 40 rules, TV 32 gates) as a supplement that is never counted as independent evidence; the decisions block D01 to D06 is UNAPPROVED."
|
||||
}
|
||||
|
|
@ -4,3 +4,4 @@ set -euo pipefail
|
|||
node tools/ci/review-suite.mjs --self-test | grep -v '^self-test passed' || true
|
||||
node tools/ci/review-suite.mjs --findings docs/analysis/review-2026-10-08-b/findings.json --dispatch docs/analysis/review-2026-10-08-b/dispatch.md --prefix REV --check
|
||||
if [ -f docs/plans/igneum-2.0-master/traceability.json ]; then node tools/ci/int-suite.mjs --self-test | grep -v '^self-test passed' || true; node tools/ci/int-suite.mjs --traceability docs/plans/igneum-2.0-master/traceability.json --check; fi
|
||||
if [ -f docs/plans/igneum-2.0-master/token-value/rules-and-gates.json ]; then node tools/ci/token-value-suite.mjs --self-test | grep -v '^self-test passed' || true; node tools/ci/token-value-suite.mjs --check; fi
|
||||
|
|
|
|||
|
|
@ -882,6 +882,38 @@
|
|||
"R2-F13-R03": "R2-F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map",
|
||||
"R2-F14-R01": "R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map",
|
||||
"R2-F14-R02": "R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map",
|
||||
"R2-F14-R03": "R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map"
|
||||
"R2-F14-R03": "R2-F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map",
|
||||
"TV-01": "TV-01 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + independent panel); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-02": "TV-02 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-03": "TV-03 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Release + ecosystem); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-04": "TV-04 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + protocol); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-05": "TV-05 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Hardware reviewer + economics); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-06": "TV-06 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + application); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-07": "TV-07 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + independent security); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-08": "TV-08 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Wallet + independent users); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-09": "TV-09 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Wallet + consensus); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-10": "TV-10 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + application); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-11": "TV-11 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Pool + independent operators); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-12": "TV-12 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Release + independent security); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-13": "TV-13 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Maintainers + independent finance); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-14": "TV-14 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Independent operations panel); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-15": "TV-15 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + governance); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-16": "TV-16 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Ecosystem + independent reviewer); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-17": "TV-17 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Measurement steward); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-18": "TV-18 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Economics + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-19": "TV-19 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Ecosystem + external developers); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-20": "TV-20 (token value gate, scope PAYMENT CAPABILITY): no gate executed; the harness is the owner role's (Application + wallet); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-21": "TV-21 (token value gate, scope PAID WORK CAPABILITY): no gate executed; the harness is the owner role's (Proving + independent customers); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-22": "TV-22 (token value gate, scope WORK MARKET CAPABILITY): no gate executed; the harness is the owner role's (Application + independent operators); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-23": "TV-23 (token value gate, scope SERVICE BONDS IF ENABLED): no gate executed; the harness is the owner role's (Economics + security); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-24": "TV-24 (token value gate, scope AI IF ENABLED): no gate executed; the harness is the owner role's (Compute + independent reviewer); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-25": "TV-25 (token value gate, scope AGENTS IF ENABLED): no gate executed; the harness is the owner role's (Application + security); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-26": "TV-26 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Cryptography + protocol); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-27": "TV-27 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Security + product); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-28": "TV-28 (token value gate, scope STABLE/BRIDGE IF ENABLED): no gate executed; the harness is the owner role's (Application + security + counsel); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-29": "TV-29 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Protocol + operations); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-30": "TV-30 (token value gate, scope CORE): no gate executed; the harness is the owner role's (GPU + measurement); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-31": "TV-31 (token value gate, scope CORE): no gate executed; the harness is the owner role's (Qualified counsel); a supplemental layer, never counted as independent evidence; not yet named in the map",
|
||||
"TV-32": "TV-32 (token value gate, scope LEADERSHIP CLAIM): no gate executed; the harness is the owner role's (Independent acceptance panel); a supplemental layer, never counted as independent evidence; not yet named in the map"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,6 +207,14 @@ if (args.includes('--self-test')) {
|
|||
if (reg.cases[2].run_status) { console.log('self-test failed: a manual case was given a run status'); fails = 1; }
|
||||
const regS = { suites: [{ code: 'X', tests: [{ id: 'X-1', method: 'Automated', accept: 'a' }] }] }; if (casesOf(regS).length !== 1) { console.log('self-test failed: the suites/tests registry shape was not read'); fails = 1; }
|
||||
const regN = { suites: [{ code: 'FIN', tests: [{ id: 'F-1', method: 'Automated', accept: 'keep' }] }] }; fs.writeFileSync(`${d}/regn.json`, JSON.stringify(regN));
|
||||
const regD = { suites: [], decisions: [{ id: 'D01', title: 't', required_resolution: 'r', status: 'UNAPPROVED', owner: 'founder' }] }; fs.writeFileSync(`${d}/regd.json`, JSON.stringify(regD));
|
||||
fs.writeFileSync(`${d}/dn.json`, JSON.stringify({ decision: 'D01', status: 'RATIFIED', word: 'capped issuance', by: 'founder', recorded_against: 'spec' }));
|
||||
const dr = child_process.spawnSync(process.execPath, [new URL(import.meta.url).pathname, '--note-file', `${d}/dn.json`], { env: { ...process.env, TEST_REGISTRY: `${d}/regd.json`, TEST_MAP: `${d}/map.json` }, encoding: 'utf8' });
|
||||
const regD2 = JSON.parse(fs.readFileSync(`${d}/regd.json`, 'utf8'));
|
||||
if (!(dr.status === 0 && regD2.decisions[0].status === 'RATIFIED' && regD2.decisions[0].word === 'capped issuance' && regD2.decisions[0].ratified_by === 'founder' && regD2.decisions[0].ratified_at)) { console.log(`self-test failed: a decision note file did not ratify D01: ${dr.stdout} ${dr.stderr}`); fails = 1; }
|
||||
fs.writeFileSync(`${d}/dnb.json`, JSON.stringify({ decision: 'D01', status: 'APPROVED-ISH', word: 'x', by: 'founder' }));
|
||||
const drb = child_process.spawnSync(process.execPath, [new URL(import.meta.url).pathname, '--note-file', `${d}/dnb.json`], { env: { ...process.env, TEST_REGISTRY: `${d}/regd.json`, TEST_MAP: `${d}/map.json` }, encoding: 'utf8' });
|
||||
if (drb.status === 0) { console.log('self-test failed: a decision status outside the vocabulary was accepted'); fails = 1; }
|
||||
const nr = child_process.spawnSync(process.execPath, [new URL(import.meta.url).pathname, '--note', 'FIN', 'the ruling'], { env: { ...process.env, TEST_REGISTRY: `${d}/regn.json`, TEST_MAP: `${d}/map.json` }, encoding: 'utf8' });
|
||||
const regN2 = JSON.parse(fs.readFileSync(`${d}/regn.json`, 'utf8'));
|
||||
if (!(nr.status === 0 && regN2.suites[0].notes?.length === 1 && regN2.suites[0].notes[0].text === 'the ruling' && regN2.suites[0].tests[0].accept === 'keep')) { console.log(`self-test failed: --note did not append a dated note to the suite and keep the accept text: ${nr.stdout} ${nr.stderr}`); fails = 1; }
|
||||
|
|
@ -243,7 +251,19 @@ if (args.includes('--check')) { const r = check(reg, map); for (const l of r.lin
|
|||
if (args.includes('--label-islands')) { const n = labelIslands(reg); fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); console.log(`test-record: ${n} record(s) measured on the 2.0 devnet since ${ISLAND_SINCE} labelled "${ISLAND_LABEL}"`); process.exit(0); }
|
||||
if (args.includes('--normalize')) { const n = normalize(reg); fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); console.log(`test-record: normalized ${n} rows to the decision vocabulary and the record schema`); process.exit(0); }
|
||||
if (arg('--cases')) { console.log(((map.cells || {})[arg('--cases')]?.cases || []).join(',')); process.exit(0); }
|
||||
if (arg('--note-file')) { const n = load(arg('--note-file')); args.push('--note', n.suite, n.text); }
|
||||
if (arg('--note-file')) { const n = load(arg('--note-file'));
|
||||
if (n.decision) { // the decision form (9 October 2026, 09:3x UK): the founder's ratification of a decision in the registry's decisions block, replayed at the merge like any note
|
||||
const STATUSES = new Set(['UNAPPROVED', 'RATIFIED', 'RATIFIED WITH PARAMETER PENDING', 'PENDING EVIDENCE', 'REJECTED']);
|
||||
if (!STATUSES.has(String(n.status))) { console.error(`test-record: decision ${n.decision}: status ${n.status} is not one of ${[...STATUSES].join(' | ')}`); process.exit(2); }
|
||||
if (!n.word || !n.by) { console.error(`test-record: decision ${n.decision}: a ratification carries the founder's word verbatim (word) and who said it (by)`); process.exit(2); }
|
||||
reg.decisions = reg.decisions || []; const dec = reg.decisions.find((x) => x.id === n.decision);
|
||||
if (!dec) { console.error(`test-record: decision ${n.decision} is not in the registry's decisions block (the VR and TV suites bring D01 to D06)`); process.exit(2); }
|
||||
const before = acceptSnapshot(reg);
|
||||
dec.status = n.status; dec.word = n.word; dec.ratified_by = n.by; dec.ratified_at = n.at || new Date().toISOString(); if (n.recorded_against) dec.recorded_against = n.recorded_against; if (n.condition) dec.condition = n.condition;
|
||||
if (acceptSnapshot(reg) !== before) { console.error('test-record: REFUSED: a decision changed an accept text'); process.exit(1); }
|
||||
fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); console.log(`test-record: decision ${n.decision} ${n.status} (${n.by})`); process.exit(0);
|
||||
}
|
||||
args.push('--note', n.suite, n.text); }
|
||||
if (arg('--note')) {
|
||||
const code = arg('--note'); const text = args[args.indexOf('--note') + 2];
|
||||
if (code === 'registry' && text) { const before = acceptSnapshot(reg); reg.notes = reg.notes || []; reg.notes.push({ at: new Date().toISOString(), text }); if (acceptSnapshot(reg) !== before) { console.error('test-record: REFUSED'); process.exit(1); } fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); console.log(`test-record: registry note ${reg.notes.length}: ${text.slice(0, 80)}`); process.exit(0); }
|
||||
|
|
|
|||
98
tools/ci/token-value-suite.mjs
Normal file
98
tools/ci/token-value-suite.mjs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env node
|
||||
// The VR and TV suites of the acceptance registry (main's order through the coordinator, 9 October 2026, by 11:00 UK): generated from
|
||||
// docs/plans/igneum-2.0-master/token-value/rules-and-gates.json, never by hand; --check refuses drift.
|
||||
// VR: the 40 normative rules, each a row whose rule_status is the file's (PROPOSED - REQUIRES RATIFICATION), run_status NOT RUN with the
|
||||
// reason "requires ratification", method "Ratification" (not Automated: no harness exists for a rule; ratification is the founder's
|
||||
// and the owner role's), the owner role, the requirement verbatim as title and accept, the file's evidence line as evidence.
|
||||
// TV: the 32 gates, each a row NOT RUN, method "Automated + independent review", the scope as the file gives it (CORE, CAPABILITY IF
|
||||
// ENABLED, LEADERSHIP CLAIM), inherited_links kept as cross-references to the master's suites and profiles, the pass criterion
|
||||
// verbatim as accept, setup and procedure carried, the threshold_status carried.
|
||||
// decisions: D01 to D06 as the registry's top-level `decisions` block, every one UNAPPROVED, the founder's.
|
||||
// The counting note stays: these are a supplemental layer, never added to the 128 + 18 + 44 as independent evidence (tools/ci/notes).
|
||||
// node tools/ci/token-value-suite.mjs --file <rules-and-gates.json> [--write | --check] node tools/ci/token-value-suite.mjs --self-test
|
||||
import fs from 'node:fs'; import path from 'node:path';
|
||||
const args = process.argv.slice(2); const arg = (n) => { const i = args.indexOf(n); return i >= 0 ? args[i + 1] : undefined; };
|
||||
const ROOT = process.env.TEST_RECORD_ROOT || path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
|
||||
const REG = process.env.TEST_REGISTRY || path.join(ROOT, 'docs/plans/igneum-2.0-test-registry.json');
|
||||
const MAP = process.env.TEST_MAP || path.join(ROOT, 'tools/ci/test-map.json');
|
||||
const SRC = 'docs/plans/igneum-2.0-master/token-value/rules-and-gates.json';
|
||||
|
||||
export function suites(d) {
|
||||
const vr = { code: 'VR', title: 'VR: the token value and network leadership rules (normative, proposed, requiring ratification)', source: `${SRC} rules`,
|
||||
gate: 'Ratification by the founder and each rule\'s owner role', owner: 'founder (ratification); the owner role per rule', fixtures: ['F0'],
|
||||
summary: `${(d.rules || []).length} normative rules from ${d.document} ${d.version} (snapshot ${d.snapshot}); ${d.scope}`,
|
||||
tests: (d.rules || []).map((r) => ({ id: r.id, title: r.title, requirement: r.requirement, accept: r.requirement, evidence: r.evidence || '',
|
||||
priority: 'P0', profile: 'P00', cadence: 'Once, at ratification; again on any change of the rule', method: 'Ratification', source: ['TV'],
|
||||
gate: 'Ratified', owner: r.owner_role || 'unassigned', owner_role: r.owner_role || 'unassigned', manual_page: null,
|
||||
rule_status: r.status || 'PROPOSED - REQUIRES RATIFICATION', run_status: 'NOT RUN' })) };
|
||||
const tv = { code: 'TV', title: 'TV: the token value and network leadership gates (proposed; no gate executed)', source: `${SRC} gates`,
|
||||
gate: 'Token value gates closed', owner: 'the owner role per gate', fixtures: ['F0'],
|
||||
summary: `${(d.gates || []).length} gates from ${d.document} ${d.version} (snapshot ${d.snapshot}); scope CORE, CAPABILITY IF ENABLED or LEADERSHIP CLAIM as the file gives it; ${d.scope}`,
|
||||
tests: (d.gates || []).map((g) => ({ id: g.id, title: g.title, setup: g.setup || '', procedure: g.procedure || '', accept: g.pass_criterion || '', evidence: g.evidence || '',
|
||||
priority: g.scope === 'CORE' ? 'P0' : 'P1', profile: 'P00', cadence: 'Every release candidate', method: 'Automated + independent review', source: ['TV'],
|
||||
gate: 'Token value gates closed', owner: g.owner_role || 'unassigned', owner_role: g.owner_role || 'unassigned', manual_page: null,
|
||||
scope: g.scope || '', inherited_links: Array.isArray(g.inherited_links) ? g.inherited_links.slice() : [], threshold_status: g.threshold_status || '',
|
||||
run_status: 'NOT RUN', master_status: g.status || 'NOT RUN' })) };
|
||||
const decisions = (d.decisions || []).map((x) => ({ id: x.id, title: x.title, required_resolution: x.required_resolution, status: 'UNAPPROVED', owner: 'founder' }));
|
||||
return { vr, tv, decisions };
|
||||
}
|
||||
const LIVE = ['run_status', 'run_id', 'evidence_path', 'updated', 'evidence_record', 'evidence_records', 'blocked_on', 'method_recorded', 'in_progress_since', 'deferral_note', 'approvals', 'ratified_at', 'ratified_by'];
|
||||
export function merge(reg, s) {
|
||||
const old = (reg.suites || []).find((x) => x.code === s.code); const live = new Map((old?.tests || []).map((t) => [t.id, t]));
|
||||
for (const t of s.tests) { const o = live.get(t.id); if (o) for (const k of LIVE) if (k in o) t[k] = o[k]; }
|
||||
if (old?.notes) s.notes = old.notes;
|
||||
reg.suites = [...(reg.suites || []).filter((x) => x.code !== s.code), s]; return reg;
|
||||
}
|
||||
export function mergeDecisions(reg, decisions) {
|
||||
const old = new Map((reg.decisions || []).map((x) => [x.id, x]));
|
||||
const KEEP = ['status', 'word', 'ratified_at', 'ratified_by', 'recorded_against', 'condition', 'approved_at', 'approved_by'];
|
||||
reg.decisions = decisions.map((x) => { const o = old.get(x.id); if (!(o && o.status && o.status !== 'UNAPPROVED')) return x; const k = { ...x }; for (const f of KEEP) if (f in o) k[f] = o[f]; return k; });
|
||||
return reg;
|
||||
}
|
||||
const canon = (o) => JSON.stringify(o, (k, v) => (v && typeof v === 'object' && !Array.isArray(v)) ? Object.fromEntries(Object.keys(v).sort().map((x) => [x, v[x]])) : v);
|
||||
export function mapReasons(map, tv) { // a TV gate with no cell reads NOT RUN with its reason (the check's rule for Automated cases)
|
||||
const mapped = new Set(Object.values(map.cells || {}).flatMap((c) => c.cases || [])); map.not_run = map.not_run || {}; let n = 0;
|
||||
for (const t of tv.tests) { if (mapped.has(t.id)) { delete map.not_run[t.id]; continue; } map.not_run[t.id] = `${t.id} (token value gate, scope ${t.scope}): no gate executed; the harness is the owner role's (${t.owner_role}); a supplemental layer, never counted as independent evidence; not yet named in the map`; n++; }
|
||||
return n;
|
||||
}
|
||||
function stripLive(s) { return { ...s, notes: undefined, tests: s.tests.map((t) => { const c = { ...t }; for (const k of LIVE) delete c[k]; return c; }) }; }
|
||||
|
||||
if (args.includes('--self-test')) {
|
||||
let fails = 0;
|
||||
const d = { document: 'doc', version: '1.0-proposed', snapshot: '2026-10-08', scope: 'a supplement', status: 'PROPOSED',
|
||||
rules: [{ id: 'VR-01', title: 'one', requirement: 'ratify one contract', evidence: 'e', owner_role: 'Protocol + governance', status: 'PROPOSED - REQUIRES RATIFICATION' }],
|
||||
gates: [{ id: 'TV-01', title: 'freeze', setup: 's', procedure: 'p', pass_criterion: 'no conflict', evidence: 'e', owner_role: 'Protocol + independent panel', inherited_links: ['GOV', 'VR-01'], scope: 'CORE', status: 'NOT RUN', threshold_status: 'PROPOSED' },
|
||||
{ id: 'TV-02', title: 'cap', setup: 's', procedure: 'p', pass_criterion: 'c', evidence: 'e', owner_role: 'x', inherited_links: [], scope: 'CAPABILITY IF ENABLED', status: 'NOT RUN', threshold_status: '' }],
|
||||
decisions: [{ id: 'D01', title: 'cap', required_resolution: 'choose', status: 'UNAPPROVED' }] };
|
||||
const { vr, tv, decisions } = suites(d);
|
||||
if (!(vr.code === 'VR' && vr.tests.length === 1 && vr.tests[0].method === 'Ratification' && vr.tests[0].run_status === 'NOT RUN' && vr.tests[0].rule_status === 'PROPOSED - REQUIRES RATIFICATION' && vr.tests[0].accept === 'ratify one contract' && vr.tests[0].owner_role === 'Protocol + governance')) { console.log('self-test failed: the VR row is not the rule verbatim, NOT RUN, Ratification, with its owner role and rule_status'); fails = 1; }
|
||||
if (!(tv.code === 'TV' && tv.tests.length === 2 && tv.tests[0].scope === 'CORE' && tv.tests[0].priority === 'P0' && tv.tests[1].priority === 'P1' && tv.tests[0].inherited_links.join() === 'GOV,VR-01' && tv.tests[0].accept === 'no conflict' && tv.tests[0].run_status === 'NOT RUN')) { console.log('self-test failed: the TV row does not carry the scope, the links, the criterion and NOT RUN'); fails = 1; }
|
||||
if (!(decisions.length === 1 && decisions[0].status === 'UNAPPROVED' && decisions[0].owner === 'founder')) { console.log('self-test failed: the decisions block is not UNAPPROVED and the founder\'s'); fails = 1; }
|
||||
const reg = { suites: [{ code: 'TV', notes: [{ text: 'n' }], tests: [{ id: 'TV-01', run_status: 'NOT RUN', in_progress_since: 't', evidence_records: { 'c:x': { decision: 'PASS' } }, run_id: 'r' }] }], decisions: [{ id: 'D01', status: 'RATIFIED', word: 'w', ratified_by: 'founder', ratified_at: 't' }] };
|
||||
merge(reg, tv); mergeDecisions(reg, decisions); const t = reg.suites[0];
|
||||
if (!(t.tests[0].in_progress_since === 't' && t.tests[0].evidence_records?.['c:x']?.decision === 'PASS' && t.tests[1].run_status === 'NOT RUN' && t.notes?.length === 1 && reg.decisions[0].status === 'RATIFIED' && reg.decisions[0].word === 'w' && reg.decisions[0].ratified_at === 't')) { console.log('self-test failed: regenerating lost live fields, notes or an approved decision'); fails = 1; }
|
||||
const map = { cells: { c: { cases: ['TV-01'] } }, not_run: {} }; if (!(mapReasons(map, tv) === 1 && !map.not_run['TV-01'] && /CAPABILITY IF ENABLED/.test(map.not_run['TV-02']))) { console.log('self-test failed: the map reasons for unmapped gates'); fails = 1; }
|
||||
const s2 = suites(d); if (canon(stripLive(s2.tv)) !== canon(stripLive(tv))) { console.log('self-test failed: the generator is not deterministic'); fails = 1; }
|
||||
if (!fails) console.log('self-test passed: one VR row per rule (the requirement verbatim, Ratification, NOT RUN, the rule_status and owner role), one TV row per gate (the scope, the links, the criterion, NOT RUN), the decisions block UNAPPROVED and the founder\'s; regenerating keeps live fields, notes and an approved decision; unmapped gates get their map reasons; the output is deterministic');
|
||||
process.exit(fails);
|
||||
}
|
||||
const file = arg('--file') ? path.resolve(arg('--file')) : path.join(ROOT, SRC);
|
||||
if (!fs.existsSync(file)) { console.error(`token-value-suite: no ${file}`); process.exit(2); }
|
||||
const d = JSON.parse(fs.readFileSync(file, 'utf8')); const { vr, tv, decisions } = suites(d);
|
||||
const reg = JSON.parse(fs.readFileSync(REG, 'utf8')); const map = fs.existsSync(MAP) ? JSON.parse(fs.readFileSync(MAP, 'utf8')) : { cells: {}, not_run: {} };
|
||||
if (args.includes('--check')) {
|
||||
let bad = 0;
|
||||
for (const s of [vr, tv]) { const cur = (reg.suites || []).find((x) => x.code === s.code); if (!cur) { console.error(`token-value-suite: the registry has no ${s.code} suite; run --write`); bad++; continue; }
|
||||
if (canon(stripLive(cur)) !== canon(stripLive(s))) { console.error(`token-value-suite: the registry's ${s.code} suite differs from the generator's output; run --write and commit`); bad++; } }
|
||||
const curD = (reg.decisions || []).map((x) => ({ id: x.id, title: x.title, required_resolution: x.required_resolution })); const wantD = decisions.map((x) => ({ id: x.id, title: x.title, required_resolution: x.required_resolution }));
|
||||
if (canon(curD) !== canon(wantD)) { console.error('token-value-suite: the registry\'s decisions block differs from the file\'s D01 to D06; run --write'); bad++; }
|
||||
if (!bad) console.log(`token-value-suite: the VR (${vr.tests.length}) and TV (${tv.tests.length}) suites and the decisions block (${decisions.length}) match ${SRC}`);
|
||||
process.exit(bad ? 1 : 0);
|
||||
}
|
||||
if (args.includes('--write')) {
|
||||
merge(reg, vr); merge(reg, tv); mergeDecisions(reg, decisions); const n = mapReasons(map, tv);
|
||||
fs.writeFileSync(REG, JSON.stringify(reg, null, 2) + '\n'); fs.writeFileSync(MAP, JSON.stringify(map, null, 2) + '\n');
|
||||
console.log(`token-value-suite: VR written (${vr.tests.length} rules), TV written (${tv.tests.length} gates), decisions ${decisions.length} (UNAPPROVED); ${n} NOT RUN reasons in the map`);
|
||||
process.exit(0);
|
||||
}
|
||||
console.error('usage: token-value-suite.mjs --file <rules-and-gates.json> [--write | --check] | --self-test'); process.exit(2);
|
||||
Loading…
Reference in a new issue