kijito-tools 0.2.0
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/LICENSE +201 -0
- package/NOTICE +6 -0
- package/README.md +220 -0
- package/bin/cli.js +34 -0
- package/install.sh +161 -0
- package/package.json +50 -0
- package/providers/_shared/wake-core.mjs +358 -0
- package/providers/claude/CLAUDE.md.snippet +31 -0
- package/providers/claude/install.sh +186 -0
- package/providers/claude/scripts/arm-session.sh +66 -0
- package/providers/claude/scripts/claude-armed.sh +101 -0
- package/providers/claude/scripts/heartbeat-watchdog.sh +209 -0
- package/providers/claude/scripts/inbox-selftest.sh +277 -0
- package/providers/claude/scripts/kijito-persona-lib.sh +94 -0
- package/providers/claude/scripts/kijito-qa-pass.sh +12 -0
- package/providers/claude/scripts/lifecycle-lib.sh +167 -0
- package/providers/claude/scripts/myctx.sh +46 -0
- package/providers/claude/scripts/self-clear.sh +134 -0
- package/providers/claude/scripts/session-autosend.sh +85 -0
- package/providers/claude/scripts/session-catchup-hint.sh +330 -0
- package/providers/claude/scripts/statusline-context.sh +67 -0
- package/providers/claude/skills/kijito-qa-memory/SKILL.md +110 -0
- package/providers/claude/skills/kijito-recall/SKILL.md +53 -0
- package/providers/claude/skills/kijito-start/SKILL.md +122 -0
- package/providers/claude/wiring/README.md +93 -0
- package/providers/claude/wiring/kijito-heartbeat@.service +21 -0
- package/providers/codex/README.md +75 -0
- package/providers/codex/codex-kijito-parity-plan.md +265 -0
- package/providers/codex/docs-codex-setup.md +64 -0
- package/providers/codex/install.mjs +184 -0
- package/providers/codex/n0-capability-probe-protocol.md +472 -0
- package/providers/codex/n0-harness/README.md +57 -0
- package/providers/codex/n0-harness/cli.mjs +58 -0
- package/providers/codex/n0-harness/evidence-manifest.mjs +77 -0
- package/providers/codex/n0-harness/fixture.mjs +279 -0
- package/providers/codex/n0-harness/lib.mjs +141 -0
- package/providers/codex/n0-harness/manifest.mjs +36 -0
- package/providers/codex/n0-harness/oracle.mjs +464 -0
- package/providers/codex/n0-harness/parser.mjs +200 -0
- package/providers/codex/n0-harness/prompt.mjs +43 -0
- package/providers/codex/n0-harness/snapshot.mjs +120 -0
- package/providers/codex/n0-harness/specimen.mjs +37 -0
- package/providers/codex/notify/kijito-notify-count.mjs +117 -0
- package/providers/codex/notify/kijito-notify-count.test.mjs +76 -0
- package/providers/codex/plans/gate4-battery-log.md +184 -0
- package/providers/codex/plans/gate4-battery-protocol.md +43 -0
- package/providers/codex/plans/hive-user-first-plan-QA.md +34 -0
- package/providers/codex/plans/hive-user-first-plan.md +247 -0
- package/providers/codex/release-manifest.json +53 -0
- package/providers/codex/same-chat-continuation-plan-gate.md +235 -0
- package/providers/codex/same-chat-continuation-plan.md +458 -0
- package/providers/codex/skills/kijito-qa-memory/SKILL.md +193 -0
- package/providers/codex/skills/kijito-qa-memory/agents/openai.yaml +4 -0
- package/providers/codex/skills/kijito-recall/SKILL.md +53 -0
- package/providers/codex/skills/kijito-start/SKILL.md +173 -0
- package/providers/codex/skills/kijito-start/agents/openai.yaml +4 -0
- package/providers/codex/test/n0-cli-refusal.test.mjs +31 -0
- package/providers/codex/test/n0-counterexample-matrix.test.mjs +118 -0
- package/providers/codex/test/n0-guard-census-core.mjs +1372 -0
- package/providers/codex/test/n0-guard-census.json +35479 -0
- package/providers/codex/test/n0-guard-census.mjs +31 -0
- package/providers/codex/test/n0-guard-census.test.mjs +374 -0
- package/providers/codex/test/n0-guard-counterexamples.mjs +1068 -0
- package/providers/codex/test/n0-guard-independent-projection.mjs +70 -0
- package/providers/codex/test/n0-guard-independent-projection.test.mjs +53 -0
- package/providers/codex/test/n0-guard-manifest-author.mjs +424 -0
- package/providers/codex/test/n0-guard-mutation-operators.test.mjs +244 -0
- package/providers/codex/test/n0-guard-mutation-runner.mjs +599 -0
- package/providers/codex/test/n0-guard-remainder-classes.test.mjs +314 -0
- package/providers/codex/test/n0-guard-sanitizer-pairs.test.mjs +68 -0
- package/providers/codex/test/n0-guard-shared-context-predicates.test.mjs +84 -0
- package/providers/codex/test/n0-harness.test.mjs +553 -0
- package/providers/codex/test/n0-notable-regressions.test.mjs +70 -0
- package/providers/codex/test/n0-subject-boundary.mjs +97 -0
- package/providers/codex/test/n0-subject-boundary.test.mjs +72 -0
- package/providers/codex/test/same-chat-plan-preflight.sh +167 -0
- package/providers/codex/tools/refresh-manifest.mjs +81 -0
- package/providers/codex/wake-helper/TRANSPORT-NOTES.md +25 -0
- package/providers/codex/wake-helper/integration.test.mjs +285 -0
- package/providers/codex/wake-helper/kijito-wake-helper.mjs +488 -0
- package/providers/codex/wake-helper/kijito-wake-helper.test.mjs +128 -0
- package/providers/codex/wake-helper/mock-daemon.mjs +64 -0
- package/providers/codex/wake-helper/status-probe.mjs +45 -0
- package/providers/codex/wake-helper/ws-uds.mjs +153 -0
- package/providers/monitor/.github/workflows/publish-npm.yml +38 -0
- package/providers/monitor/.github/workflows/publish-pypi.yml +30 -0
- package/providers/monitor/CHANGELOG.md +465 -0
- package/providers/monitor/IMPORT-PROVENANCE.md +68 -0
- package/providers/monitor/LICENSE +202 -0
- package/providers/monitor/NOTICE +7 -0
- package/providers/monitor/OPAQUE-OUTPUT-ENFORCEMENT.md +45 -0
- package/providers/monitor/README.md +571 -0
- package/providers/monitor/RELEASING.md +125 -0
- package/providers/monitor/arm-hive-monitor.sh +13 -0
- package/providers/monitor/bin/cli.js +43 -0
- package/providers/monitor/com.kijito.inbox-monitor.plist.template +59 -0
- package/providers/monitor/docs/DESIGN.md +984 -0
- package/providers/monitor/kijito-inbox-monitor@.service.template +95 -0
- package/providers/monitor/kijito_inbox_monitor.py +3666 -0
- package/providers/monitor/package.json +35 -0
- package/providers/monitor/pyproject.toml +42 -0
- package/providers/monitor/scripts/mutation-check.py +399 -0
- package/providers/monitor/scripts/prepublish-gate.sh +284 -0
- package/providers/monitor/test_kijito_monitor.py +5609 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { test } from "node:test";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { analyzeGuardGraph } from "./n0-guard-census-core.mjs";
|
|
9
|
+
|
|
10
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const ROOT = path.resolve(HERE, "../../..");
|
|
12
|
+
const SOURCE_ROOT = path.join(ROOT, "providers/codex/n0-harness");
|
|
13
|
+
const MANIFEST_PATH = path.join(HERE, "n0-guard-census.json");
|
|
14
|
+
|
|
15
|
+
const EXPECTED_SHADOWS = [
|
|
16
|
+
"oracle.mjs:81:17:rejecting-helper-call:74d6da1d9a547734",
|
|
17
|
+
"oracle.mjs:98:18:rejecting-helper-call:72e6f71373cc02a2",
|
|
18
|
+
"oracle.mjs:106:22:rejecting-helper-call:a09692553a3b4d79",
|
|
19
|
+
"oracle.mjs:177:17:rejecting-helper-call:4cfcd52300a3b9c3",
|
|
20
|
+
"oracle.mjs:189:19:rejecting-helper-call:d1a33bb56cfd0cb8",
|
|
21
|
+
"oracle.mjs:193:20:rejecting-helper-call:0378081cd7a677a4",
|
|
22
|
+
"oracle.mjs:215:18:rejecting-helper-call:395a93f673d3332a",
|
|
23
|
+
"oracle.mjs:223:3:rejecting-helper-call:8bbe25ad570a6758",
|
|
24
|
+
"oracle.mjs:242:23:rejecting-helper-call:421568a92598c2d1",
|
|
25
|
+
"oracle.mjs:292:3:rejecting-helper-call:2563493bf86065c7",
|
|
26
|
+
"oracle.mjs:430:3:rejecting-helper-call:0e82521959067f2f",
|
|
27
|
+
].sort();
|
|
28
|
+
|
|
29
|
+
const EXPECTED_SUCCESS_PATHS = [
|
|
30
|
+
"fixture.mjs:64:20:rejecting-helper-call:5ee8fe818d227757",
|
|
31
|
+
"fixture.mjs:116:18:rejecting-helper-call:e2f8125b417f7ed0",
|
|
32
|
+
"fixture.mjs:175:44:rejecting-helper-call:891243e1c000198e",
|
|
33
|
+
"fixture.mjs:220:54:rejecting-helper-call:891243e1c000198e",
|
|
34
|
+
"fixture.mjs:232:44:rejecting-helper-call:891243e1c000198e",
|
|
35
|
+
"fixture.mjs:252:17:rejecting-helper-call:107da86911fcb8d4",
|
|
36
|
+
"oracle.mjs:175:25:rejecting-helper-call:e2f8125b417f7ed0",
|
|
37
|
+
].sort();
|
|
38
|
+
|
|
39
|
+
const EXPECTED_DELEGATED = ["cli.mjs:28:18:rejecting-helper-call:2abc5cf6881921c3"];
|
|
40
|
+
|
|
41
|
+
const EXPECTED_DOWNSTREAM_DOMAIN_SHADOWS = new Map([
|
|
42
|
+
["oracle.mjs:230:7:predicate-atom:c501cea746d8b024", "oracle.canary.value-null"],
|
|
43
|
+
["oracle.mjs:230:17:predicate-atom:e052cf82d87a7ce7", "oracle.canary.value-primitive"],
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
function manifest() {
|
|
47
|
+
return JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf8"));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function allCases() {
|
|
51
|
+
const result = spawnSync(process.execPath, ["providers/codex/test/n0-guard-counterexamples.mjs", "--all"], {
|
|
52
|
+
cwd: ROOT,
|
|
53
|
+
encoding: "utf8",
|
|
54
|
+
timeout: 300_000,
|
|
55
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
56
|
+
});
|
|
57
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
58
|
+
return JSON.parse(result.stdout);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function fixture(source) {
|
|
62
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "n0-remainder-proof."));
|
|
63
|
+
fs.writeFileSync(path.join(root, "fixture.mjs"), source);
|
|
64
|
+
return root;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function independentlyOwned(entry) {
|
|
68
|
+
return [
|
|
69
|
+
"normal-ownership",
|
|
70
|
+
"reject-preserving-ownership",
|
|
71
|
+
"mixed-ownership",
|
|
72
|
+
"compound-member",
|
|
73
|
+
"same-code-shadow",
|
|
74
|
+
].includes(entry?.ownershipRecord?.kind)
|
|
75
|
+
|| entry?.disposition?.kind === "not-independently-discriminated";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
test("R4 membership is exact-11, adjacency-derived, and every member names an active pristine invalid-domain witness", () => {
|
|
79
|
+
const graph = analyzeGuardGraph(SOURCE_ROOT);
|
|
80
|
+
const frozen = manifest();
|
|
81
|
+
const pristine = allCases();
|
|
82
|
+
const derived = [];
|
|
83
|
+
for (const proof of graph.sameCodeShadows) {
|
|
84
|
+
const owner = frozen.entries.find((entry) => entry.id === proof.entryId);
|
|
85
|
+
const record = owner?.ownershipRecord;
|
|
86
|
+
if (record?.kind !== "same-code-shadow") continue;
|
|
87
|
+
assert.equal(record.downstreamEntryId, proof.downstreamEntryId, proof.entryId);
|
|
88
|
+
assert.equal(record.rejectCode, proof.rejectCode, proof.entryId);
|
|
89
|
+
assert.deepEqual(record.canonicalMutation, { operator: "suppress-thrown-rejection" }, proof.entryId);
|
|
90
|
+
assert.equal(typeof record.witnessId, "string", proof.entryId);
|
|
91
|
+
assert.deepEqual(
|
|
92
|
+
{ accepted: pristine[record.witnessId]?.accepted, code: pristine[record.witnessId]?.code },
|
|
93
|
+
{ accepted: false, code: proof.rejectCode },
|
|
94
|
+
`${proof.entryId}: A-R4 witness must actively reject the invalid domain with the shared code`,
|
|
95
|
+
);
|
|
96
|
+
assert.ok(independentlyOwned(frozen.entries.find((entry) => entry.id === proof.downstreamEntryId)), proof.downstreamEntryId);
|
|
97
|
+
derived.push(proof.entryId);
|
|
98
|
+
}
|
|
99
|
+
assert.deepEqual(derived.sort(), EXPECTED_SHADOWS);
|
|
100
|
+
assert.equal(frozen.floors.sameCodeShadowEntries, EXPECTED_SHADOWS.length);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("R4 proof fails closed on intervening operations and unequal rejection codes", () => {
|
|
104
|
+
const variants = [
|
|
105
|
+
["adjacent", "const value = requireObject(input, \"BAD\"); assertExactKeys(value, [], \"BAD\");", 1],
|
|
106
|
+
["intervening", "const value = requireObject(input, \"BAD\"); consume(value); assertExactKeys(value, [], \"BAD\");", 0],
|
|
107
|
+
["unequal", "const value = requireObject(input, \"BAD\"); assertExactKeys(value, [], \"OTHER\");", 0],
|
|
108
|
+
];
|
|
109
|
+
for (const [name, body, expected] of variants) {
|
|
110
|
+
const root = fixture(`
|
|
111
|
+
function fail(code){ throw new Error(code); }
|
|
112
|
+
function requireObject(value, code){ if(!value) fail(code); return value; }
|
|
113
|
+
function assertExactKeys(value, keys, code){ if(Object.keys(value).length !== keys.length) fail(code); }
|
|
114
|
+
function consume(){}
|
|
115
|
+
export function probe(input){ ${body} return {status:"N0_TEST_CAPABLE"}; }
|
|
116
|
+
`);
|
|
117
|
+
try {
|
|
118
|
+
assert.equal(analyzeGuardGraph(root).sameCodeShadows.length, expected, name);
|
|
119
|
+
} finally {
|
|
120
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("R7 downstream-domain shadows are exact-two, hash-bound, actively witnessed, and downstream-owned", () => {
|
|
126
|
+
const graph = analyzeGuardGraph(SOURCE_ROOT);
|
|
127
|
+
const frozen = manifest();
|
|
128
|
+
const pristine = allCases();
|
|
129
|
+
assert.deepEqual(
|
|
130
|
+
graph.downstreamDomainShadows.map((proof) => proof.entryId).sort(),
|
|
131
|
+
[...EXPECTED_DOWNSTREAM_DOMAIN_SHADOWS.keys()].sort(),
|
|
132
|
+
);
|
|
133
|
+
assert.equal(frozen.floors.downstreamDomainShadowEntries, 2);
|
|
134
|
+
for (const proof of graph.downstreamDomainShadows) {
|
|
135
|
+
const owner = frozen.entries.find((entry) => entry.id === proof.entryId)?.ownershipRecord;
|
|
136
|
+
assert.equal(owner?.kind, "downstream-domain-shadow", proof.entryId);
|
|
137
|
+
assert.equal(owner.downstreamEntryId, proof.downstreamEntryId, proof.entryId);
|
|
138
|
+
assert.deepEqual(owner.enforcingEntryIds, proof.enforcingEntryIds, proof.entryId);
|
|
139
|
+
assert.deepEqual(owner.canonicalMutation, { operator: "force-owned-condition", value: false }, proof.entryId);
|
|
140
|
+
assert.deepEqual(owner.catchReturn, proof.catchReturn, proof.entryId);
|
|
141
|
+
assert.equal(owner.pathHash, proof.pathHash, proof.entryId);
|
|
142
|
+
assert.equal(owner.witnessId, EXPECTED_DOWNSTREAM_DOMAIN_SHADOWS.get(proof.entryId), proof.entryId);
|
|
143
|
+
assert.deepEqual(
|
|
144
|
+
{ accepted: pristine[owner.witnessId]?.accepted, code: pristine[owner.witnessId]?.code },
|
|
145
|
+
{ accepted: false, code: "CANARY_MISSING" },
|
|
146
|
+
proof.entryId,
|
|
147
|
+
);
|
|
148
|
+
assert.ok(independentlyOwned(frozen.entries.find((entry) => entry.id === proof.downstreamEntryId)), proof.downstreamEntryId);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("R7 downstream-domain proof fails closed on changed catch, absent/outside/intervening/dynamic/optional helpers", () => {
|
|
153
|
+
const probe = (body) => `
|
|
154
|
+
function fail(){ throw new Error("BAD"); }
|
|
155
|
+
function assertExactKeys(value){ if(!value) fail(); }
|
|
156
|
+
function isCanary(value){ ${body} return true; }
|
|
157
|
+
export function probe(value){ if(!isCanary(value)) fail(); return {status:"N0_TEST_CAPABLE"}; }
|
|
158
|
+
`;
|
|
159
|
+
const variants = [
|
|
160
|
+
["closed", "if(!value || typeof value !== \"object\") return false; try { assertExactKeys(value); } catch { return false; }", 2],
|
|
161
|
+
["different-catch", "if(!value || typeof value !== \"object\") return false; try { assertExactKeys(value); } catch { return true; }", 0],
|
|
162
|
+
["no-helper", "if(!value || typeof value !== \"object\") return false; try { void value; } catch { return false; }", 0],
|
|
163
|
+
["outside-try", "if(!value || typeof value !== \"object\") return false; assertExactKeys(value); try {} catch { return false; }", 0],
|
|
164
|
+
["intervening", "if(!value || typeof value !== \"object\") return false; try { value = {}; assertExactKeys(value); } catch { return false; }", 0],
|
|
165
|
+
["dynamic", "if(!value || typeof value !== \"object\") return false; try { (0, assertExactKeys)(value); } catch { return false; }", 0],
|
|
166
|
+
["optional", "if(!value || typeof value !== \"object\") return false; try { assertExactKeys?.(value); } catch { return false; }", 0],
|
|
167
|
+
];
|
|
168
|
+
for (const [name, body, expected] of variants) {
|
|
169
|
+
const root = fixture(probe(body));
|
|
170
|
+
try {
|
|
171
|
+
assert.equal(analyzeGuardGraph(root).downstreamDomainShadows.length, expected, name);
|
|
172
|
+
} finally {
|
|
173
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("R7 direct witnesses retain their exact ordinary measured partitions", () => {
|
|
179
|
+
const frozen = manifest();
|
|
180
|
+
const expected = new Map([
|
|
181
|
+
["lib.mjs:82:92:predicate-atom:4542f69c79c1c3b7", {
|
|
182
|
+
kind: "normal-ownership",
|
|
183
|
+
witness: { partition: "acceptFlipSet", id: "lib.path.relative-absolute-injection", rejectCode: "X", acceptCode: "HELPER_ACCEPTED" },
|
|
184
|
+
}],
|
|
185
|
+
["oracle.mjs:237:44:predicate-atom:a9035cd3a7d97ea6", {
|
|
186
|
+
kind: "reject-preserving-ownership",
|
|
187
|
+
witness: { partition: "rejectDeltaSet", id: "oracle.canary.path-relative", beforeCode: "CANARY_MISSING", afterCode: "CANARY_PATH_CLASS" },
|
|
188
|
+
}],
|
|
189
|
+
["oracle.mjs:313:7:guard-atom:e3c481736ae16a55", {
|
|
190
|
+
kind: "reject-preserving-ownership",
|
|
191
|
+
witness: { partition: "rejectDeltaSet", id: "oracle.case.cases-null", beforeCode: "CASE_EVIDENCE_INVALID", afterCode: "ORACLE_EXCEPTION" },
|
|
192
|
+
}],
|
|
193
|
+
]);
|
|
194
|
+
for (const [id, proof] of expected) {
|
|
195
|
+
const entry = frozen.entries.find((candidate) => candidate.id === id);
|
|
196
|
+
assert.equal(entry?.ownershipRecord?.kind, proof.kind, id);
|
|
197
|
+
assert.deepEqual(entry?.witness, proof.witness, id);
|
|
198
|
+
assert.deepEqual(entry?.positiveRegressionSet, [], id);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("R3 compounds are seven closed units with exactly thirteen owned members", () => {
|
|
203
|
+
const frozen = manifest();
|
|
204
|
+
assert.equal(frozen.compounds.length, 7);
|
|
205
|
+
const members = frozen.compounds.flatMap((compound) => compound.memberIds);
|
|
206
|
+
assert.equal(members.length, 13);
|
|
207
|
+
assert.equal(new Set(members).size, 13);
|
|
208
|
+
assert.equal(frozen.floors.compoundDispositionUnits, 7);
|
|
209
|
+
assert.equal(frozen.floors.compoundDispositionMembers, 13);
|
|
210
|
+
for (const compound of frozen.compounds) {
|
|
211
|
+
assert.ok(compound.edits.length >= 2, compound.id);
|
|
212
|
+
assert.ok(compound.memberIds.every((id) => compound.edits.some((edit) => edit.entryId === id)), compound.id);
|
|
213
|
+
for (const memberId of compound.memberIds) {
|
|
214
|
+
const owner = frozen.entries.find((entry) => entry.id === memberId);
|
|
215
|
+
assert.deepEqual(owner?.ownershipRecord, { kind: "compound-member", compoundId: compound.id }, memberId);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("R5 membership is the exact analyzer-derived seven and the oracle guard proof names owned dischargers", () => {
|
|
221
|
+
const graph = analyzeGuardGraph(SOURCE_ROOT);
|
|
222
|
+
const frozen = manifest();
|
|
223
|
+
assert.deepEqual(graph.successPathCalls.map((proof) => proof.entryId).sort(), EXPECTED_SUCCESS_PATHS);
|
|
224
|
+
assert.equal(frozen.floors.successPathCalls, EXPECTED_SUCCESS_PATHS.length);
|
|
225
|
+
assert.ok(!graph.successPathCalls.some((proof) => proof.entryId.startsWith("specimen.mjs:9:")));
|
|
226
|
+
for (const proof of graph.successPathCalls) {
|
|
227
|
+
const owner = frozen.entries.find((entry) => entry.id === proof.entryId);
|
|
228
|
+
assert.equal(owner?.ownershipRecord?.kind, "success-path-call", proof.entryId);
|
|
229
|
+
assert.equal(owner.ownershipRecord.proofKind, proof.proofKind, proof.entryId);
|
|
230
|
+
assert.deepEqual(owner.ownershipRecord.dischargerEntryIds, proof.dischargerEntryIds, proof.entryId);
|
|
231
|
+
if (proof.proofKind !== "guard-call-dominated-by-owned-dischargers") continue;
|
|
232
|
+
assert.ok(proof.dischargerEntryIds.length > 0, proof.entryId);
|
|
233
|
+
assert.equal(typeof proof.conditionalOwnerId, "string", proof.entryId);
|
|
234
|
+
for (const id of [...proof.dischargerEntryIds, proof.conditionalOwnerId]) {
|
|
235
|
+
assert.ok(independentlyOwned(frozen.entries.find((entry) => entry.id === id)), `${proof.entryId}->${id}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("R5 success-path proof rejects caller arguments, guard-test calls, and optional calls unless a closed proof applies", () => {
|
|
241
|
+
const variants = [
|
|
242
|
+
["closed", "function render(value){ if(!value) fail(); return value; } export function probe(){ return render({}); }", 1],
|
|
243
|
+
["caller-argument", "function render(value){ if(!value) fail(); return value; } export function probe(value){ return render(value); }", 0],
|
|
244
|
+
["guard-test", "function render(value){ if(!value) fail(); return value; } export function probe(value){ if(render(value)) return {status:\"N0_TEST_CAPABLE\"}; }", 0],
|
|
245
|
+
["optional", "function render(value){ if(!value) fail(); return value; } export function probe(){ return render?.({}); }", 0],
|
|
246
|
+
];
|
|
247
|
+
for (const [name, body, expected] of variants) {
|
|
248
|
+
const root = fixture(`function fail(){ throw new Error("BAD"); } ${body}`);
|
|
249
|
+
try {
|
|
250
|
+
assert.equal(analyzeGuardGraph(root).successPathCalls.length, expected, name);
|
|
251
|
+
} finally {
|
|
252
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("R6 membership is exact-one with separately hash-bound caller anchors and independently owned internal outcomes", () => {
|
|
258
|
+
const graph = analyzeGuardGraph(SOURCE_ROOT);
|
|
259
|
+
const frozen = manifest();
|
|
260
|
+
assert.deepEqual(graph.delegatedOutcomeCalls.map((proof) => proof.entryId), EXPECTED_DELEGATED);
|
|
261
|
+
assert.equal(frozen.floors.delegatedOutcomeCalls, 1);
|
|
262
|
+
const proof = graph.delegatedOutcomeCalls[0];
|
|
263
|
+
const owner = frozen.entries.find((entry) => entry.id === proof.entryId)?.ownershipRecord;
|
|
264
|
+
assert.equal(owner?.kind, "delegated-outcome-call");
|
|
265
|
+
assert.deepEqual(owner.internalCallEntryIds, proof.internalCallEntryIds);
|
|
266
|
+
assert.deepEqual(owner.internalOutcomeEntryIds, proof.internalOutcomeEntryIds);
|
|
267
|
+
assert.deepEqual(owner.callerNullGuardOwnership, proof.callerNullGuard);
|
|
268
|
+
assert.deepEqual(owner.callerControlFlowOwnership, proof.callerControlFlow);
|
|
269
|
+
assert.notEqual(proof.callerNullGuard.id, proof.callerControlFlow.id);
|
|
270
|
+
for (const id of [...proof.internalCallEntryIds, ...proof.internalOutcomeEntryIds]) {
|
|
271
|
+
assert.ok(independentlyOwned(frozen.entries.find((entry) => entry.id === id)), `${proof.entryId}->${id}`);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test("R6 delegated-outcome proof fails closed on missing null control flow, throwing, dynamic, and aliased delegation", () => {
|
|
276
|
+
const sources = [
|
|
277
|
+
["good", `
|
|
278
|
+
function usage(){ process.exitCode = 64; }
|
|
279
|
+
function args(argv){ if(!argv){ usage(); return null; } return {}; }
|
|
280
|
+
export function main(argv){ const parsed = args(argv); if(!parsed) return; return {status:"N0_TEST_CAPABLE"}; }
|
|
281
|
+
`, 1, null],
|
|
282
|
+
["no-null-guard", `
|
|
283
|
+
function usage(){ process.exitCode = 64; }
|
|
284
|
+
function args(argv){ if(!argv){ usage(); return null; } return {}; }
|
|
285
|
+
export function main(argv){ return args(argv); }
|
|
286
|
+
`, 0, null],
|
|
287
|
+
["throwing", `
|
|
288
|
+
function usage(){ throw new Error("BAD"); }
|
|
289
|
+
function args(argv){ if(!argv){ usage(); return null; } return {}; }
|
|
290
|
+
export function main(argv){ const parsed = args(argv); if(!parsed) return; return {status:"N0_TEST_CAPABLE"}; }
|
|
291
|
+
`, 0, null],
|
|
292
|
+
["dynamic", `
|
|
293
|
+
function usage(){ process.exitCode = 64; }
|
|
294
|
+
function other(){}
|
|
295
|
+
function args(argv){ if(!argv){ (argv ? other : usage)(); return null; } return {}; }
|
|
296
|
+
export function main(argv){ const parsed = args(argv); if(!parsed) return; return {status:"N0_TEST_CAPABLE"}; }
|
|
297
|
+
`, 0, null],
|
|
298
|
+
["alias", `
|
|
299
|
+
function usage(){ process.exitCode = 64; }
|
|
300
|
+
const emit = usage;
|
|
301
|
+
function args(argv){ if(!argv){ emit(); return null; } return {}; }
|
|
302
|
+
export function main(argv){ const parsed = args(argv); if(!parsed) return; return {status:"N0_TEST_CAPABLE"}; }
|
|
303
|
+
`, 0, "CENSUS_REJECT_ALIAS"],
|
|
304
|
+
];
|
|
305
|
+
for (const [name, source, expected, errorCode] of sources) {
|
|
306
|
+
const root = fixture(source);
|
|
307
|
+
try {
|
|
308
|
+
if (errorCode) assert.throws(() => analyzeGuardGraph(root), (error) => error?.code === errorCode, name);
|
|
309
|
+
else assert.equal(analyzeGuardGraph(root).delegatedOutcomeCalls.length, expected, name);
|
|
310
|
+
} finally {
|
|
311
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { test } from "node:test";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { analyzeGuardGraph } from "./n0-guard-census-core.mjs";
|
|
9
|
+
import { applyMutations, replacementFor } from "./n0-guard-mutation-runner.mjs";
|
|
10
|
+
|
|
11
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const ROOT = path.resolve(HERE, "../../..");
|
|
13
|
+
|
|
14
|
+
function runCase(root, id) {
|
|
15
|
+
const result = spawnSync(process.execPath, ["providers/codex/test/n0-guard-counterexamples.mjs", id], {
|
|
16
|
+
cwd: root,
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
});
|
|
19
|
+
assert.equal(result.status, 0, result.stderr);
|
|
20
|
+
return JSON.parse(result.stdout);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const EXPECTED_OWNERSHIP = new Map([
|
|
24
|
+
["parser.mjs:41:19:rejecting-helper-call:d3df82140ecfc7d0", "mixed-ownership"],
|
|
25
|
+
["parser.mjs:77:22:rejecting-helper-call:4559b1577e5654c7", "normal-ownership"],
|
|
26
|
+
["parser.mjs:107:18:rejecting-helper-call:04f6cdc8d3d1a5f8", "normal-ownership"],
|
|
27
|
+
["parser.mjs:119:19:rejecting-helper-call:e792f84ed71527f6", "normal-ownership"],
|
|
28
|
+
["prompt.mjs:42:29:rejecting-helper-call:0f93f1bf1d83d8ce", "normal-ownership"],
|
|
29
|
+
["snapshot.mjs:113:21:rejecting-helper-call:7613fc44bd316ea4", "normal-ownership"],
|
|
30
|
+
["specimen.mjs:12:10:rejecting-helper-call:d808855d1bc13c94", "normal-ownership"],
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
test("every remaining reviewed first-argument sanitizer keeps its exact measured ownership and accepting witness", () => {
|
|
34
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "n0-sanitizer-pairs-"));
|
|
35
|
+
try {
|
|
36
|
+
fs.cpSync(path.join(ROOT, "providers"), path.join(root, "providers"), { recursive: true });
|
|
37
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, "providers/codex/test/n0-guard-census.json"), "utf8"));
|
|
38
|
+
const entries = manifest.entries.filter((entry) => entry.mutation?.operator === "sanitize-first-argument");
|
|
39
|
+
assert.equal(entries.length, EXPECTED_OWNERSHIP.size);
|
|
40
|
+
assert.deepEqual(entries.map((entry) => entry.id).sort(), [...EXPECTED_OWNERSHIP.keys()].sort());
|
|
41
|
+
const graph = analyzeGuardGraph(path.join(root, "providers/codex/n0-harness"));
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
assert.equal(entry.ownershipRecord?.kind, EXPECTED_OWNERSHIP.get(entry.id), entry.id);
|
|
44
|
+
assert.equal(entry.witness?.partition, "acceptFlipSet", entry.id);
|
|
45
|
+
const actual = graph.entries.find((candidate) => candidate.id === entry.id);
|
|
46
|
+
assert.ok(actual, entry.id);
|
|
47
|
+
const pristine = runCase(root, entry.witness.id);
|
|
48
|
+
assert.deepEqual(
|
|
49
|
+
{ accepted: pristine.accepted, code: pristine.code },
|
|
50
|
+
{ accepted: false, code: entry.witness.rejectCode },
|
|
51
|
+
entry.id,
|
|
52
|
+
);
|
|
53
|
+
const restore = applyMutations(root, [{ ...actual, replacement: replacementFor(entry) }]);
|
|
54
|
+
try {
|
|
55
|
+
const mutant = runCase(root, entry.witness.id);
|
|
56
|
+
assert.deepEqual(
|
|
57
|
+
{ accepted: mutant.accepted, code: mutant.code },
|
|
58
|
+
{ accepted: true, code: entry.witness.acceptCode },
|
|
59
|
+
entry.id,
|
|
60
|
+
);
|
|
61
|
+
} finally {
|
|
62
|
+
restore();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} finally {
|
|
66
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { test } from "node:test";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { analyzeGuardGraph } from "./n0-guard-census-core.mjs";
|
|
9
|
+
import { expectedPositiveCases } from "./n0-guard-counterexamples.mjs";
|
|
10
|
+
import { applyMutations, assertPristineMatrix, replacementFor } from "./n0-guard-mutation-runner.mjs";
|
|
11
|
+
|
|
12
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const ROOT = path.resolve(HERE, "../../..");
|
|
14
|
+
const ALLOWED_CONTEXTS = new Set(["reject-on-false", "reject-on-true", "non-enforcing"]);
|
|
15
|
+
const EXPECTED_SHARED_ATOMS = [
|
|
16
|
+
"lib.mjs:22:10:predicate-atom:b579cf79ff684260",
|
|
17
|
+
"lib.mjs:22:28:predicate-atom:f13c9e45b40ad616",
|
|
18
|
+
"lib.mjs:82:10:predicate-atom:b7fc7b5f4fb78cb6",
|
|
19
|
+
"lib.mjs:82:30:predicate-atom:d8edadc88ffeb3ca",
|
|
20
|
+
].sort();
|
|
21
|
+
|
|
22
|
+
function matrix(root) {
|
|
23
|
+
const result = spawnSync(process.execPath, ["providers/codex/test/n0-guard-counterexamples.mjs", "--all"], {
|
|
24
|
+
cwd: root,
|
|
25
|
+
encoding: "utf8",
|
|
26
|
+
timeout: 300_000,
|
|
27
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
28
|
+
});
|
|
29
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
30
|
+
return JSON.parse(result.stdout);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function changedPositiveIds(pristine, mutant) {
|
|
34
|
+
return Object.keys(expectedPositiveCases()).filter((id) => {
|
|
35
|
+
assert.equal(pristine[id]?.accepted, true, `pristine named positive ${id}`);
|
|
36
|
+
return JSON.stringify(mutant[id]) !== JSON.stringify(pristine[id]);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
test("shared-context predicate membership is mechanically closed at the exact four approved atoms", () => {
|
|
41
|
+
const graph = analyzeGuardGraph(path.join(ROOT, "providers/codex/n0-harness"));
|
|
42
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, "providers/codex/test/n0-guard-census.json"), "utf8"));
|
|
43
|
+
const candidates = graph.sharedContextPredicates.filter((proof) => {
|
|
44
|
+
assert.ok(proof.contexts.every((context) => ALLOWED_CONTEXTS.has(context)), `${proof.predicate}: unknown context`);
|
|
45
|
+
return new Set(proof.contexts).size >= 2;
|
|
46
|
+
});
|
|
47
|
+
assert.ok(candidates.length > 0);
|
|
48
|
+
|
|
49
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), "n0-shared-context-"));
|
|
50
|
+
try {
|
|
51
|
+
fs.cpSync(path.join(ROOT, "providers"), path.join(temp, "providers"), { recursive: true });
|
|
52
|
+
const pristine = matrix(temp);
|
|
53
|
+
assertPristineMatrix(pristine, expectedPositiveCases());
|
|
54
|
+
const tempGraph = analyzeGuardGraph(path.join(temp, "providers/codex/n0-harness"));
|
|
55
|
+
const derived = [];
|
|
56
|
+
|
|
57
|
+
for (const proof of candidates) {
|
|
58
|
+
for (const id of proof.atomIds) {
|
|
59
|
+
const actual = tempGraph.entries.find((entry) => entry.id === id);
|
|
60
|
+
assert.ok(actual, id);
|
|
61
|
+
const frozenProof = manifest.baseline.sharedContextPredicates.find((item) => item.functionKey === proof.functionKey);
|
|
62
|
+
const canonicalMutation = frozenProof?.canonicalAtomMutations?.find((item) => item.id === id)?.mutation;
|
|
63
|
+
assert.ok(canonicalMutation, `${id}: missing canonical mutation in frozen predicate proof`);
|
|
64
|
+
const restore = applyMutations(temp, [{ ...actual, replacement: replacementFor({ ...actual, mutation: canonicalMutation }) }]);
|
|
65
|
+
let regressed;
|
|
66
|
+
try {
|
|
67
|
+
regressed = changedPositiveIds(pristine, matrix(temp));
|
|
68
|
+
} finally {
|
|
69
|
+
restore();
|
|
70
|
+
}
|
|
71
|
+
if (regressed.length > 0) derived.push(id);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
assert.deepEqual(derived.sort(), EXPECTED_SHARED_ATOMS);
|
|
76
|
+
assert.deepEqual(
|
|
77
|
+
manifest.entries.filter((entry) => entry.ownershipRecord?.kind === "shared-context-predicate").map((entry) => entry.id).sort(),
|
|
78
|
+
EXPECTED_SHARED_ATOMS,
|
|
79
|
+
);
|
|
80
|
+
assert.equal(manifest.floors.sharedContextPredicateAtoms, EXPECTED_SHARED_ATOMS.length);
|
|
81
|
+
} finally {
|
|
82
|
+
fs.rmSync(temp, { recursive: true, force: true });
|
|
83
|
+
}
|
|
84
|
+
});
|