import assert from "node:assert/strict"; import test from "node:test"; import { NATIVE_CLI_CONTRACTS } from "../lib/native-review-cli.ts"; // Organic RDD parity: the four organic-parity capability columns exist on every // shipped NATIVE_CLI_CONTRACTS row. Every row through the pinned "2.1.11" // reports them false. "2.2.0" is the first capability-true row and it lights // only what was demonstrated to reach a negotiated consumer, per Design // Decision #1 ("Future row policy"). // // A row describes what the NATIVE CLI puts on the wire, never what Pi manages // to show. `riskEvidence` and `hint` stay false on 2.2.0 even though a Pi // operator now sees both, because Pi derives them from `risk_reasons` and // `changed_files` rather than receiving them: the closed `start/v2` schema // omits the fields. Lighting the row would tell a future reader the envelope // carries something it does not. const ORGANIC_PARITY_CAPABILITIES = ["mode", "riskEvidence", "hint", "delivery"] as const; const DARK_VERSIONS = ["2.1.4", "2.1.5", "2.1.6", "2.1.7", "2.1.8", "2.1.9", "2.1.10", "2.1.11"] as const; test("every row through the pinned 2.1.11 reports the organic-parity capability columns false", () => { for (const version of DARK_VERSIONS) { const contract = NATIVE_CLI_CONTRACTS[version] as Record; for (const capability of ORGANIC_PARITY_CAPABILITIES) { assert.equal( Object.hasOwn(contract, capability) ? contract[capability] : false, false, `${version}.${capability} must be false or absent`, ); } } }); test("the 2.1.11 row explicitly reports all four organic-parity capabilities false", () => { const contract = NATIVE_CLI_CONTRACTS["2.1.11"] as Record; assert.equal(contract.mode, false); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); assert.equal(contract.delivery, false); }); test("2.2.0 lights only the two capabilities its negotiated envelope demonstrably carries", () => { // Ground-truthed against the released v2.2.0 binary: the kill switch and // delivery disposition reach the negotiated path, while `risk_evidence` and // `hint` appear only in the plain envelope. See // tests/native-risk-evidence-parity.test.ts for the captured evidence. const contract = NATIVE_CLI_CONTRACTS["2.2.0"] as Record; assert.equal(contract.mode, true); assert.equal(contract.delivery, true); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); }); test("2.2.1 repeats 2.2.0 because the lane Pi speaks did not move", () => { // Ground-truthed against the released v2.2.1 binary. On // review-integration/v1 it advertises capabilities/v1.5 (protocol minor 5), // but the negotiated start envelope is still the closed `start/v2`, so // `risk_evidence` and `hint` still cannot arrive. v2.2.1 does publish a // second contract, review-integration/v2, whose `start/v3` carries frozen // base/candidate trees -- but Pi does not negotiate it yet, and a row // describes the lane in use, not the lane available. const contract = NATIVE_CLI_CONTRACTS["2.2.1"] as Record; assert.equal(contract.mode, true); assert.equal(contract.delivery, true); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); assert.deepEqual(contract, NATIVE_CLI_CONTRACTS["2.2.0"] as Record); }); test("2.2.2 repeats 2.2.1 because the lane Pi speaks still did not move", () => { // Ground-truthed against the released v2.2.2 binary: on // review-integration/v1 it advertises capabilities/v1.5 and the negotiated // start envelope is still the closed `start/v2`, so risk_evidence and hint // still cannot arrive on the lane Pi negotiates. const contract = NATIVE_CLI_CONTRACTS["2.2.2"] as Record; assert.equal(contract.mode, true); assert.equal(contract.delivery, true); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); assert.deepEqual(contract, NATIVE_CLI_CONTRACTS["2.2.1"] as Record); }); test("2.2.3 repeats 2.2.2 because Pi's consumed capability columns did not move", () => { // Ground-truthed against the released v2.2.3 binary: the v2 lane reports // protocol 2.0, the same eight negotiated operations, and the same START // fields represented by this table. const contract = NATIVE_CLI_CONTRACTS["2.2.3"] as Record; assert.equal(contract.mode, true); assert.equal(contract.delivery, true); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); assert.deepEqual(contract, NATIVE_CLI_CONTRACTS["2.2.2"] as Record); }); test("2.4.0 repeats 2.2.3 because the START envelope Pi consumes still omits risk_evidence and hint", () => { // Ground-truthed against the published v2.4.0 linux_amd64 release binary // (sha256:0be4467... , captured 2026-08-17), not against a main build: // // mode `gentle-ai review mode status --json` still answers // `gentle-ai.rdd-mode-status/v1`. The RESOLVED value moved -- // an unconfigured install now reports effective "off" with // source "default" instead of "on" -- but that is a decision // the envelope carries, not a capability it lost. // delivery `review validate --gate pre-commit` still answers // `gentle-ai.review-gate-result/v1` with // `delivery: "disabled/unmanaged"` at exit 0. Under opt-in RDD // this is now the DEFAULT delivery answer for an install that // never enabled review, so the column matters more, not less. // // riskEvidence and hint stay dark for exactly the reason the 2.2.0 comment // gives, re-proven rather than inherited: the negotiated // `gentle-ai.review-integration.start/v3` envelope captured from this // binary carries `risk_reasons: [{ code: "non_executable_only" }]` and no // `risk_evidence` and no `hint`. `risk_evidence` does appear in v2.4.0, but // only on the `gentle-ai.review-integration.consent/v3` blocking envelope, // which is a different envelope on a different branch of START and is not // what these columns describe. const contract = NATIVE_CLI_CONTRACTS["2.4.0"] as Record; assert.equal(contract.mode, true); assert.equal(contract.delivery, true); assert.equal(contract.riskEvidence, false); assert.equal(contract.hint, false); assert.deepEqual(contract, NATIVE_CLI_CONTRACTS["2.2.3"] as Record); }); test("no shipped version key was added beyond the pin bump", () => { // Rows are promises to consumers, so a new key only ever appears in a // dedicated commit alongside a pin bump, never as a side effect. v2.2.4 and // v2.3.0 shipped upstream while Pi stayed on 2.2.3 and were never pinned, // so they get no row: a row asserts ground truth measured against a binary // Pi actually ran, and the table only has to be ascending, not gapless. assert.deepEqual(Object.keys(NATIVE_CLI_CONTRACTS), [...DARK_VERSIONS, "2.2.0", "2.2.1", "2.2.2", "2.2.3", "2.4.0"]); });