@mneme-ai/core 2.96.0 → 2.97.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/dist/agent_manifest.js +1 -1
- package/dist/agent_manifest.js.map +1 -1
- package/dist/hydra/guard.d.ts +75 -0
- package/dist/hydra/guard.d.ts.map +1 -0
- package/dist/hydra/guard.js +171 -0
- package/dist/hydra/guard.js.map +1 -0
- package/dist/hydra/guard.test.d.ts +2 -0
- package/dist/hydra/guard.test.d.ts.map +1 -0
- package/dist/hydra/guard.test.js +79 -0
- package/dist/hydra/guard.test.js.map +1 -0
- package/dist/hydra/index.d.ts +1 -0
- package/dist/hydra/index.d.ts.map +1 -1
- package/dist/hydra/index.js +1 -0
- package/dist/hydra/index.js.map +1 -1
- package/dist/truth_gate/probes.d.ts.map +1 -1
- package/dist/truth_gate/probes.js +33 -0
- package/dist/truth_gate/probes.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.97.0 — HYDRA · GUARDED EXPANSION ("Time-To-Trust").
|
|
3
|
+
*
|
|
4
|
+
* The fusion gem: HYDRA codebook × the knowledge-atrophy clock × NOTARY.
|
|
5
|
+
* A normal expand() is byte-lossless. A GUARDED expand is lossless for
|
|
6
|
+
* TRUSTED content but provably REDACTS stale/quarantined content down to a
|
|
7
|
+
* signed abstract (sha256 + byte-count) — so an AI literally cannot
|
|
8
|
+
* hallucinate from expired memory, yet can still verify the redacted
|
|
9
|
+
* region's identity and request re-hydration.
|
|
10
|
+
*
|
|
11
|
+
* Prior-art research (v2.96) found no signed + lossless + TTL-guarded
|
|
12
|
+
* codebook anywhere. This is that unfilled lane, made measurable:
|
|
13
|
+
* - all-fresh ⟹ guarded output is BYTE-IDENTICAL to the original (boolean)
|
|
14
|
+
* - any stale entry ⟹ its raw phrase NEVER appears, its sha256 DOES,
|
|
15
|
+
* fresh entries stay byte-exact (boolean)
|
|
16
|
+
* - deterministic: same input → same bytes (boolean)
|
|
17
|
+
*
|
|
18
|
+
* STABILITY: every function is total — it never throws. Malformed input,
|
|
19
|
+
* a missing field, an unknown trust level → the SAFEST outcome (redact).
|
|
20
|
+
* The 108-error rule: when in doubt, guard, don't crash and don't leak.
|
|
21
|
+
*/
|
|
22
|
+
import { sha256Hex } from "./engine.js";
|
|
23
|
+
export function trustFromMap(map) {
|
|
24
|
+
return (sym) => (map && Object.prototype.hasOwnProperty.call(map, sym) ? map[sym] ?? "fresh" : "fresh");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The deterministic redaction placeholder for a guarded entry. Carries the
|
|
28
|
+
* sha256 of the original phrase (identity-verifiable) + byte count + the
|
|
29
|
+
* reason — but NOT the content. Re-hydration replaces it with the real
|
|
30
|
+
* phrase once the symbol is re-verified.
|
|
31
|
+
*/
|
|
32
|
+
export function guardedPlaceholder(phrase, level) {
|
|
33
|
+
const sha = sha256Hex(phrase).slice(0, 16);
|
|
34
|
+
const bytes = Buffer.byteLength(phrase, "utf8");
|
|
35
|
+
return `[mneme:redacted trust=${level} sha256=${sha} bytes=${bytes} — re-verify to access]`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* GUARDED EXPAND. Fresh symbols expand to their phrase (byte-exact); stale
|
|
39
|
+
* or quarantined symbols expand to a signed abstract. Total: never throws;
|
|
40
|
+
* a bad entry is treated as quarantined (fail-closed, never leak).
|
|
41
|
+
*/
|
|
42
|
+
export function expandGuarded(encoded, cb, trustOf) {
|
|
43
|
+
if (typeof encoded !== "string")
|
|
44
|
+
return "";
|
|
45
|
+
if (!cb || !Array.isArray(cb.entries))
|
|
46
|
+
return encoded;
|
|
47
|
+
let out = encoded;
|
|
48
|
+
for (const e of cb.entries) {
|
|
49
|
+
if (!e || typeof e.sym !== "string" || typeof e.phrase !== "string" || e.phrase.length === 0)
|
|
50
|
+
continue;
|
|
51
|
+
let level;
|
|
52
|
+
try {
|
|
53
|
+
level = trustOf(e.sym) ?? "fresh";
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
level = "quarantined";
|
|
57
|
+
}
|
|
58
|
+
const replacement = level === "fresh" ? e.phrase : guardedPlaceholder(e.phrase, level);
|
|
59
|
+
out = out.split(e.sym).join(replacement);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* RE-HYDRATE a guarded output: given the set of symbols whose access has
|
|
65
|
+
* been re-verified, replace their placeholders with the real phrase. Total:
|
|
66
|
+
* unknown symbols / malformed input are left untouched (no throw, no leak).
|
|
67
|
+
*/
|
|
68
|
+
export function rehydrate(encoded, cb, approvedSyms, trustOf) {
|
|
69
|
+
if (typeof encoded !== "string")
|
|
70
|
+
return "";
|
|
71
|
+
if (!cb || !Array.isArray(cb.entries))
|
|
72
|
+
return encoded;
|
|
73
|
+
const approved = new Set();
|
|
74
|
+
try {
|
|
75
|
+
for (const s of approvedSyms)
|
|
76
|
+
approved.add(s);
|
|
77
|
+
}
|
|
78
|
+
catch { /* leave empty */ }
|
|
79
|
+
const t = (sym) => (approved.has(sym) ? "fresh" : (() => { try {
|
|
80
|
+
return trustOf(sym) ?? "fresh";
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return "quarantined";
|
|
84
|
+
} })());
|
|
85
|
+
return expandGuarded(encoded, cb, t);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The guarded gauntlet — proves the four Time-To-Trust invariants over a
|
|
89
|
+
* concrete trust assignment. Total + deterministic. `compressFn` lets the
|
|
90
|
+
* caller pass the engine's compress to avoid an import cycle; if omitted we
|
|
91
|
+
* verify directly against the codebook entries.
|
|
92
|
+
*/
|
|
93
|
+
export function guardedGauntlet(original, encoded, cb, trustMap) {
|
|
94
|
+
try {
|
|
95
|
+
const allFresh = () => "fresh";
|
|
96
|
+
const resolver = trustFromMap(trustMap);
|
|
97
|
+
const freshOut = expandGuarded(encoded, cb, allFresh);
|
|
98
|
+
const freshLossless = sha256Hex(freshOut) === sha256Hex(original);
|
|
99
|
+
const guarded1 = expandGuarded(encoded, cb, resolver);
|
|
100
|
+
const guarded2 = expandGuarded(encoded, cb, resolver);
|
|
101
|
+
const deterministic = sha256Hex(guarded1) === sha256Hex(guarded2);
|
|
102
|
+
let redactionSound = true;
|
|
103
|
+
let freshPreserved = true;
|
|
104
|
+
let redactedCount = 0;
|
|
105
|
+
let freshCount = 0;
|
|
106
|
+
for (const e of cb.entries) {
|
|
107
|
+
if (!e || typeof e.phrase !== "string" || e.phrase.length === 0)
|
|
108
|
+
continue;
|
|
109
|
+
const level = trustMap[e.sym] ?? "fresh";
|
|
110
|
+
if (level === "fresh") {
|
|
111
|
+
freshCount++;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
redactedCount++;
|
|
115
|
+
// Correct, honest invariant — per OCCURRENCE, not per text:
|
|
116
|
+
// - the stale SYMBOL must be fully consumed (no un-redacted
|
|
117
|
+
// expansion survives), and
|
|
118
|
+
// - IF the symbol actually occurs in the encoded stream, its
|
|
119
|
+
// identity sha must appear (proof the redaction happened).
|
|
120
|
+
// A "dead" symbol (its phrase was nested-consumed by a longer phrase
|
|
121
|
+
// during compress, so it never appears in `encoded`) has nothing to
|
|
122
|
+
// redact → vacuously sound. We do NOT require the phrase TEXT to be
|
|
123
|
+
// globally absent: identical text inside a FRESH entry the caller
|
|
124
|
+
// trusts is not a leak of the stale source.
|
|
125
|
+
if (guarded1.includes(e.sym))
|
|
126
|
+
redactionSound = false;
|
|
127
|
+
if (encoded.includes(e.sym)) {
|
|
128
|
+
const sha = sha256Hex(e.phrase).slice(0, 16);
|
|
129
|
+
if (!guarded1.includes(sha))
|
|
130
|
+
redactionSound = false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Fresh-preserved: redacting some entries must not corrupt the fresh
|
|
134
|
+
// ones. We check by re-hydrating ALL symbols → must equal fresh output.
|
|
135
|
+
const rehydrated = rehydrate(encoded, cb, cb.entries.map((e) => e.sym), resolver);
|
|
136
|
+
freshPreserved = sha256Hex(rehydrated) === sha256Hex(freshOut);
|
|
137
|
+
const perfect = freshLossless && redactionSound && freshPreserved && deterministic;
|
|
138
|
+
return { freshLossless, redactionSound, freshPreserved, deterministic, redactedCount, freshCount, score: perfect ? 100 : 0 };
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Total: any unexpected failure → score 0, never throw.
|
|
142
|
+
return { freshLossless: false, redactionSound: false, freshPreserved: false, deterministic: false, redactedCount: 0, freshCount: 0, score: 0 };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Compose the ATROPHY clock: mark a codebook's entries stale when the
|
|
147
|
+
* caller's age map says their source region is older than the half-life.
|
|
148
|
+
* `ageMsOf` returns the age (ms) of the source behind a symbol, or
|
|
149
|
+
* undefined if unknown (unknown ⇒ fresh, the least-surprising default —
|
|
150
|
+
* we only redact what we can PROVE is stale). Total; never throws.
|
|
151
|
+
*/
|
|
152
|
+
export function trustByAtrophy(cb, ageMsOf, halfLifeMs) {
|
|
153
|
+
const out = {};
|
|
154
|
+
if (!cb || !Array.isArray(cb.entries) || !(halfLifeMs > 0))
|
|
155
|
+
return out;
|
|
156
|
+
for (const e of cb.entries) {
|
|
157
|
+
if (!e || typeof e.sym !== "string")
|
|
158
|
+
continue;
|
|
159
|
+
let age;
|
|
160
|
+
try {
|
|
161
|
+
age = ageMsOf(e.sym);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
age = undefined;
|
|
165
|
+
}
|
|
166
|
+
if (typeof age === "number" && Number.isFinite(age) && age > halfLifeMs * 2)
|
|
167
|
+
out[e.sym] = "stale";
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/hydra/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.test.d.ts","sourceRoot":"","sources":["../../src/hydra/guard.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { forgeCodebook, compress, sha256Hex } from "./index.js";
|
|
3
|
+
import { expandGuarded, rehydrate, guardedGauntlet, trustFromMap, trustByAtrophy, guardedPlaceholder } from "./guard.js";
|
|
4
|
+
const CORPUS = [
|
|
5
|
+
"fresh module does the new thing. fresh module is current.",
|
|
6
|
+
"legacy helper is ancient and stale. legacy helper has not changed in years.",
|
|
7
|
+
].join("\n").repeat(6);
|
|
8
|
+
function setup() {
|
|
9
|
+
const { codebook } = forgeCodebook(CORPUS, { minHits: 2 });
|
|
10
|
+
const encoded = compress(CORPUS, codebook);
|
|
11
|
+
return { codebook, encoded };
|
|
12
|
+
}
|
|
13
|
+
describe("v2.97 HYDRA GUARD · Time-To-Trust", () => {
|
|
14
|
+
it("all-fresh guarded expand is byte-identical to the original", () => {
|
|
15
|
+
const { codebook, encoded } = setup();
|
|
16
|
+
const out = expandGuarded(encoded, codebook, () => "fresh");
|
|
17
|
+
expect(out).toBe(CORPUS);
|
|
18
|
+
});
|
|
19
|
+
it("a stale entry is redacted: raw phrase gone, sha present, fresh untouched", () => {
|
|
20
|
+
const { codebook, encoded } = setup();
|
|
21
|
+
const stale = codebook.entries[0];
|
|
22
|
+
const map = { [stale.sym]: "stale" };
|
|
23
|
+
const out = expandGuarded(encoded, codebook, trustFromMap(map));
|
|
24
|
+
expect(out.includes(stale.phrase)).toBe(false); // raw content gone
|
|
25
|
+
expect(out).toContain(sha256Hex(stale.phrase).slice(0, 16)); // identity still verifiable
|
|
26
|
+
// fresh preserved: a fresh entry that lives OUTSIDE the stale region
|
|
27
|
+
// still expands byte-exact.
|
|
28
|
+
const other = codebook.entries.find((e) => e.sym !== stale.sym && !stale.phrase.includes(e.phrase) && CORPUS.split(stale.phrase).join("").includes(e.phrase));
|
|
29
|
+
if (other)
|
|
30
|
+
expect(out).toContain(other.phrase); // fresh preserved
|
|
31
|
+
});
|
|
32
|
+
it("re-hydration restores a redacted entry once approved", () => {
|
|
33
|
+
const { codebook, encoded } = setup();
|
|
34
|
+
const stale = codebook.entries[0];
|
|
35
|
+
const map = { [stale.sym]: "stale" };
|
|
36
|
+
const guarded = expandGuarded(encoded, codebook, trustFromMap(map));
|
|
37
|
+
expect(guarded.includes(stale.phrase)).toBe(false);
|
|
38
|
+
const restored = rehydrate(encoded, codebook, [stale.sym], trustFromMap(map));
|
|
39
|
+
expect(restored).toContain(stale.phrase); // disclosed after approval
|
|
40
|
+
});
|
|
41
|
+
it("guarded gauntlet scores 100 on a sound trust assignment", () => {
|
|
42
|
+
const { codebook, encoded } = setup();
|
|
43
|
+
const map = {};
|
|
44
|
+
if (codebook.entries[0])
|
|
45
|
+
map[codebook.entries[0].sym] = "stale";
|
|
46
|
+
const g = guardedGauntlet(CORPUS, encoded, codebook, map);
|
|
47
|
+
expect(g.freshLossless).toBe(true);
|
|
48
|
+
expect(g.redactionSound).toBe(true);
|
|
49
|
+
expect(g.freshPreserved).toBe(true);
|
|
50
|
+
expect(g.deterministic).toBe(true);
|
|
51
|
+
expect(g.score).toBe(100);
|
|
52
|
+
});
|
|
53
|
+
it("STABILITY — total functions never throw on malformed input", () => {
|
|
54
|
+
const bad = { v: 1, open: "", close: "", corpusHash: "", entries: [null, { sym: "x", phrase: "y" }] };
|
|
55
|
+
expect(() => expandGuarded("anything", bad, () => { throw new Error("boom"); })).not.toThrow();
|
|
56
|
+
expect(expandGuarded(null, bad, () => "fresh")).toBe("");
|
|
57
|
+
expect(guardedGauntlet("", "", bad, {}).score).toBe(0);
|
|
58
|
+
expect(rehydrate(undefined, bad, ["x"], () => "fresh")).toBe("");
|
|
59
|
+
});
|
|
60
|
+
it("ATROPHY composition — only PROVEN-old entries go stale (unknown ⇒ fresh)", () => {
|
|
61
|
+
const { codebook } = setup();
|
|
62
|
+
const halfLife = 1000;
|
|
63
|
+
const old = codebook.entries[0]?.sym;
|
|
64
|
+
const map = trustByAtrophy(codebook, (sym) => (sym === old ? halfLife * 10 : undefined), halfLife);
|
|
65
|
+
if (old)
|
|
66
|
+
expect(map[old]).toBe("stale");
|
|
67
|
+
// unknown age → NOT in the map → treated fresh (we only redact proven-stale)
|
|
68
|
+
const other = codebook.entries.find((e) => e.sym !== old);
|
|
69
|
+
if (other)
|
|
70
|
+
expect(map[other.sym]).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
it("placeholder carries identity but not content", () => {
|
|
73
|
+
const ph = guardedPlaceholder("super secret phrase", "stale");
|
|
74
|
+
expect(ph).not.toContain("super secret phrase");
|
|
75
|
+
expect(ph).toContain(sha256Hex("super secret phrase").slice(0, 16));
|
|
76
|
+
expect(ph).toContain("trust=stale");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=guard.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.test.js","sourceRoot":"","sources":["../../src/hydra/guard.test.ts"],"names":[],"mappings":"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"}
|
package/dist/hydra/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from "./engine.js";
|
|
|
21
21
|
export * from "./mine.js";
|
|
22
22
|
export * from "./analytic.js";
|
|
23
23
|
export * from "./attest.js";
|
|
24
|
+
export * from "./guard.js";
|
|
24
25
|
import type { Codebook } from "./engine.js";
|
|
25
26
|
import { type ForgeOpts, type ForgeResult, type Gauntlet } from "./analytic.js";
|
|
26
27
|
import { type EnergyCert } from "./attest.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hydra/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hydra/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAE3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAA2B,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAsD,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,yBAAyB,CAAC;IAChC,CAAC,EAAE,CAAC,CAAC;IACL,QAAQ,EAAE,QAAQ,CAAC;IACnB,gDAAgD;IAChD,OAAO,EAAE,aAAa,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,gBAAgB,CAavF;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,aAAa,EAAE,CAMxD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAc,GAAG,gBAAgB,CAQ/G"}
|
package/dist/hydra/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export * from "./engine.js";
|
|
|
21
21
|
export * from "./mine.js";
|
|
22
22
|
export * from "./analytic.js";
|
|
23
23
|
export * from "./attest.js";
|
|
24
|
+
export * from "./guard.js";
|
|
24
25
|
import { sha256Hex } from "./engine.js";
|
|
25
26
|
import { forgeCodebook, gauntlet } from "./analytic.js";
|
|
26
27
|
import { signCodebook, mintEnergyCert, canonicalizeCodebook } from "./attest.js";
|
package/dist/hydra/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hydra/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hydra/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAmD,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAmB,MAAM,aAAa,CAAC;AAsBlG,MAAM,UAAU,gBAAgB,CAAC,EAAY,EAAE,OAAsB;IACnE,OAAO;QACL,IAAI,EAAE,yBAAyB;QAC/B,CAAC,EAAE,CAAC;QACJ,QAAQ,EAAE,EAAE;QACZ,OAAO;QACP,OAAO,EAAE;YACP,IAAI,EAAE,4HAA4H;YAClI,UAAU,EAAE,EAAE,CAAC,IAAI;YACnB,WAAW,EAAE,EAAE,CAAC,KAAK;SACtB;QACD,YAAY,EAAE,SAAS,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;KAClD,CAAC;AACJ,CAAC;AAaD,MAAM,UAAU,UAAU,CAAC,EAAY;IACrC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5B,KAAK,EAAE,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE;QACrF,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,MAAM,EAAE,CAAC,CAAC,MAAM;KACjB,CAAC,CAAC,CAAC;AACN,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,MAAc,EAAE,EAAU,EAAE,OAAkB,EAAE;IAC3F,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACnE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/truth_gate/probes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/truth_gate/probes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA6wFnE,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,KAAK,CAAU,CAAC;AAEvD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAEvD;AAED,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAQlF"}
|
|
@@ -342,6 +342,39 @@ const probes = [
|
|
|
342
342
|
}
|
|
343
343
|
},
|
|
344
344
|
},
|
|
345
|
+
{
|
|
346
|
+
id: "probe.hydra.guarded_time_to_trust",
|
|
347
|
+
kind: "boolean",
|
|
348
|
+
description: "HYDRA GUARD (v2.97.0 — the fusion gem: codebook × atrophy-clock × NOTARY): guarded expansion is byte-lossless for TRUSTED content but provably REDACTS stale/quarantined content to a signed abstract (sha256 + byte-count, never the raw phrase) — so an AI cannot hallucinate from expired memory yet can still verify the redacted region's identity and request re-hydration. Four measurable invariants: fresh-lossless ∧ redaction-sound (raw gone, sha present) ∧ fresh-preserved ∧ deterministic. Total/stable: every guard function is total (never throws; malformed input → fail-closed redact). This probe forges a fixture, marks an entry stale, and asserts the guarded gauntlet = 100.",
|
|
349
|
+
run: async (ctx) => {
|
|
350
|
+
const t0 = Date.now();
|
|
351
|
+
void ctx;
|
|
352
|
+
try {
|
|
353
|
+
const H = await import("../hydra/index.js");
|
|
354
|
+
const corpus = ("fresh module is current. legacy helper is ancient and stale. ").repeat(30);
|
|
355
|
+
const f = H.hydraForge(process.cwd(), corpus, 1700000000000, { minHits: 2 });
|
|
356
|
+
const cb = f.forge.codebook;
|
|
357
|
+
const encoded = H.compress(corpus, cb);
|
|
358
|
+
const trustMap = {};
|
|
359
|
+
if (cb.entries[0])
|
|
360
|
+
trustMap[cb.entries[0].sym] = "stale";
|
|
361
|
+
const g = H.guardedGauntlet(corpus, encoded, cb, trustMap);
|
|
362
|
+
// stability: a thrown resolver must not crash expandGuarded
|
|
363
|
+
let stable = true;
|
|
364
|
+
try {
|
|
365
|
+
H.expandGuarded(encoded, cb, () => { throw new Error("boom"); });
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
stable = false;
|
|
369
|
+
}
|
|
370
|
+
const ok = g.score === 100 && g.freshLossless && g.redactionSound && g.freshPreserved && g.deterministic && stable;
|
|
371
|
+
return { value: ok ? 1 : 0, evidence: `score=${g.score} freshLossless=${g.freshLossless} redactionSound=${g.redactionSound} freshPreserved=${g.freshPreserved} deterministic=${g.deterministic} stableOnThrow=${stable} redacted=${g.redactedCount}`, dtMs: Date.now() - t0 };
|
|
372
|
+
}
|
|
373
|
+
catch (e) {
|
|
374
|
+
return { value: 0, evidence: `threw: ${e.message}`, dtMs: Date.now() - t0 };
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
},
|
|
345
378
|
{
|
|
346
379
|
id: "probe.hydra.lossless_signed_portable",
|
|
347
380
|
kind: "boolean",
|