@mneme-ai/core 1.99.0 → 2.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/dist/adversarial_twins/index.d.ts +52 -0
- package/dist/adversarial_twins/index.d.ts.map +1 -0
- package/dist/adversarial_twins/index.js +58 -0
- package/dist/adversarial_twins/index.js.map +1 -0
- package/dist/adversarial_twins/twins.test.d.ts +2 -0
- package/dist/adversarial_twins/twins.test.d.ts.map +1 -0
- package/dist/adversarial_twins/twins.test.js +66 -0
- package/dist/adversarial_twins/twins.test.js.map +1 -0
- package/dist/bloodline/bloodline.test.d.ts +2 -0
- package/dist/bloodline/bloodline.test.d.ts.map +1 -0
- package/dist/bloodline/bloodline.test.js +96 -0
- package/dist/bloodline/bloodline.test.js.map +1 -0
- package/dist/bloodline/index.d.ts +124 -0
- package/dist/bloodline/index.d.ts.map +1 -0
- package/dist/bloodline/index.js +179 -0
- package/dist/bloodline/index.js.map +1 -0
- package/dist/dream/dream.test.d.ts +2 -0
- package/dist/dream/dream.test.d.ts.map +1 -0
- package/dist/dream/dream.test.js +61 -0
- package/dist/dream/dream.test.js.map +1 -0
- package/dist/dream/index.d.ts +59 -0
- package/dist/dream/index.d.ts.map +1 -0
- package/dist/dream/index.js +117 -0
- package/dist/dream/index.js.map +1 -0
- package/dist/gladiator/gladiator.test.d.ts +2 -0
- package/dist/gladiator/gladiator.test.d.ts.map +1 -0
- package/dist/gladiator/gladiator.test.js +145 -0
- package/dist/gladiator/gladiator.test.js.map +1 -0
- package/dist/gladiator/index.d.ts +181 -0
- package/dist/gladiator/index.d.ts.map +1 -0
- package/dist/gladiator/index.js +192 -0
- package/dist/gladiator/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/interstellar/index.d.ts +77 -0
- package/dist/interstellar/index.d.ts.map +1 -0
- package/dist/interstellar/index.js +84 -0
- package/dist/interstellar/index.js.map +1 -0
- package/dist/interstellar/interstellar.test.d.ts +2 -0
- package/dist/interstellar/interstellar.test.d.ts.map +1 -0
- package/dist/interstellar/interstellar.test.js +69 -0
- package/dist/interstellar/interstellar.test.js.map +1 -0
- package/dist/living_will/index.d.ts +60 -0
- package/dist/living_will/index.d.ts.map +1 -0
- package/dist/living_will/index.js +66 -0
- package/dist/living_will/index.js.map +1 -0
- package/dist/living_will/living_will.test.d.ts +2 -0
- package/dist/living_will/living_will.test.d.ts.map +1 -0
- package/dist/living_will/living_will.test.js +74 -0
- package/dist/living_will/living_will.test.js.map +1 -0
- package/dist/mutiny/index.d.ts +55 -0
- package/dist/mutiny/index.d.ts.map +1 -0
- package/dist/mutiny/index.js +67 -0
- package/dist/mutiny/index.js.map +1 -0
- package/dist/mutiny/mutiny.test.d.ts +2 -0
- package/dist/mutiny/mutiny.test.d.ts.map +1 -0
- package/dist/mutiny/mutiny.test.js +59 -0
- package/dist/mutiny/mutiny.test.js.map +1 -0
- package/dist/necromancy/index.d.ts +52 -0
- package/dist/necromancy/index.d.ts.map +1 -0
- package/dist/necromancy/index.js +126 -0
- package/dist/necromancy/index.js.map +1 -0
- package/dist/necromancy/necromancy.test.d.ts +2 -0
- package/dist/necromancy/necromancy.test.d.ts.map +1 -0
- package/dist/necromancy/necromancy.test.js +50 -0
- package/dist/necromancy/necromancy.test.js.map +1 -0
- package/dist/prophecy/index.d.ts +88 -0
- package/dist/prophecy/index.d.ts.map +1 -0
- package/dist/prophecy/index.js +94 -0
- package/dist/prophecy/index.js.map +1 -0
- package/dist/prophecy/prophecy.test.d.ts +2 -0
- package/dist/prophecy/prophecy.test.d.ts.map +1 -0
- package/dist/prophecy/prophecy.test.js +112 -0
- package/dist/prophecy/prophecy.test.js.map +1 -0
- package/dist/prophet/index.d.ts +47 -0
- package/dist/prophet/index.d.ts.map +1 -0
- package/dist/prophet/index.js +46 -0
- package/dist/prophet/index.js.map +1 -0
- package/dist/prophet/prophet.test.d.ts +2 -0
- package/dist/prophet/prophet.test.d.ts.map +1 -0
- package/dist/prophet/prophet.test.js +37 -0
- package/dist/prophet/prophet.test.js.map +1 -0
- package/dist/tool_selector/index.d.ts +86 -0
- package/dist/tool_selector/index.d.ts.map +1 -0
- package/dist/tool_selector/index.js +188 -0
- package/dist/tool_selector/index.js.map +1 -0
- package/dist/tool_selector/tool_selector.test.d.ts +2 -0
- package/dist/tool_selector/tool_selector.test.d.ts.map +1 -0
- package/dist/tool_selector/tool_selector.test.js +59 -0
- package/dist/tool_selector/tool_selector.test.js.map +1 -0
- package/dist/wisdom_shards/index.d.ts +62 -0
- package/dist/wisdom_shards/index.d.ts.map +1 -0
- package/dist/wisdom_shards/index.js +69 -0
- package/dist/wisdom_shards/index.js.map +1 -0
- package/dist/wisdom_shards/wisdom_shards.test.d.ts +2 -0
- package/dist/wisdom_shards/wisdom_shards.test.d.ts.map +1 -0
- package/dist/wisdom_shards/wisdom_shards.test.js +69 -0
- package/dist/wisdom_shards/wisdom_shards.test.js.map +1 -0
- package/dist/xray/index.d.ts +44 -0
- package/dist/xray/index.d.ts.map +1 -0
- package/dist/xray/index.js +139 -0
- package/dist/xray/index.js.map +1 -0
- package/dist/xray/xray.test.d.ts +2 -0
- package/dist/xray/xray.test.d.ts.map +1 -0
- package/dist/xray/xray.test.js +57 -0
- package/dist/xray/xray.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"necromancy.test.d.ts","sourceRoot":"","sources":["../../src/necromancy/necromancy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { extractStyleFingerprint, styleSimilarity, styleAsPromptPrefix, formatNecromancyPulseLine } from "./index.js";
|
|
3
|
+
describe("v2.1 NECROMANCY · stylometric fingerprint MVP", () => {
|
|
4
|
+
it("extracts fingerprint with sentence stats", () => {
|
|
5
|
+
const logs = [
|
|
6
|
+
"Sure, here's a thought. Maybe try this approach. I think it might work. Hope this helps!",
|
|
7
|
+
"Let me know if you need more. Of course, I'd be happy to help.",
|
|
8
|
+
];
|
|
9
|
+
const fp = extractStyleFingerprint("test-vendor", logs);
|
|
10
|
+
expect(fp.vendorLabel).toBe("test-vendor");
|
|
11
|
+
expect(fp.totalSentences).toBeGreaterThan(0);
|
|
12
|
+
expect(fp.hedgesPer100Sentences).toBeGreaterThan(0); // 'Maybe', 'I think'
|
|
13
|
+
expect(fp.topOpeners.length).toBeGreaterThan(0);
|
|
14
|
+
expect(fp.topClosings.length).toBeGreaterThan(0);
|
|
15
|
+
});
|
|
16
|
+
it("hedge-heavy text has higher hedgesPer100Sentences", () => {
|
|
17
|
+
const fp1 = extractStyleFingerprint("hedged", ["Maybe this. Perhaps that. I think so. I believe yes."]);
|
|
18
|
+
const fp2 = extractStyleFingerprint("absolute", ["Always do this. Never do that. Definitely correct."]);
|
|
19
|
+
expect(fp1.hedgesPer100Sentences).toBeGreaterThan(fp2.hedgesPer100Sentences);
|
|
20
|
+
expect(fp2.absolutesPer100Sentences).toBeGreaterThan(fp1.absolutesPer100Sentences);
|
|
21
|
+
});
|
|
22
|
+
it("featureVector is non-empty + numeric", () => {
|
|
23
|
+
const fp = extractStyleFingerprint("x", ["test message"]);
|
|
24
|
+
expect(fp.featureVector.length).toBeGreaterThan(0);
|
|
25
|
+
for (const v of fp.featureVector)
|
|
26
|
+
expect(typeof v).toBe("number");
|
|
27
|
+
});
|
|
28
|
+
it("styleSimilarity returns 1.0 for identical fingerprints", () => {
|
|
29
|
+
const fp = extractStyleFingerprint("x", ["hello world hello world"]);
|
|
30
|
+
expect(styleSimilarity(fp, fp)).toBeCloseTo(1, 5);
|
|
31
|
+
});
|
|
32
|
+
it("styleSimilarity returns a value 0..1 for different fingerprints", () => {
|
|
33
|
+
const a = extractStyleFingerprint("a", ["short."]);
|
|
34
|
+
const b = extractStyleFingerprint("b", ["Long verbose sentences with hedges maybe perhaps. I think this. I believe that."]);
|
|
35
|
+
const sim = styleSimilarity(a, b);
|
|
36
|
+
expect(sim).toBeGreaterThanOrEqual(-1);
|
|
37
|
+
expect(sim).toBeLessThanOrEqual(1);
|
|
38
|
+
});
|
|
39
|
+
it("styleAsPromptPrefix mentions vendor + traits", () => {
|
|
40
|
+
const fp = extractStyleFingerprint("bard-classic", ["Of course! Let me know if you need anything. Of course!"]);
|
|
41
|
+
const prefix = styleAsPromptPrefix(fp);
|
|
42
|
+
expect(prefix).toContain("bard-classic");
|
|
43
|
+
expect(prefix.toLowerCase()).toContain("stylometric mimicry");
|
|
44
|
+
});
|
|
45
|
+
it("formatNecromancyPulseLine summarises", () => {
|
|
46
|
+
const fp = extractStyleFingerprint("v", ["x. y."]);
|
|
47
|
+
expect(formatNecromancyPulseLine(fp)).toContain("NECROMANCY");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=necromancy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"necromancy.test.js","sourceRoot":"","sources":["../../src/necromancy/necromancy.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.0.0 -- PROPHECY LETTERS · time-locked cross-version messages
|
|
3
|
+
*
|
|
4
|
+
* Mneme v2.0 writes a letter to its future self (or to a different
|
|
5
|
+
* machine running a different Mneme version). The letter is sealed
|
|
6
|
+
* with the user's HMAC secret + a target-version gate. When a future
|
|
7
|
+
* Mneme version that meets the gate opens the letter, it can grade
|
|
8
|
+
* its past self's predictions:
|
|
9
|
+
*
|
|
10
|
+
* "Past Mneme (v2.0, 2026-05-13) predicted: 'by v2.5 we'll have
|
|
11
|
+
* real IBM Quantum wiring.' Current Mneme (v2.5, 2026-09-01) checks
|
|
12
|
+
* its own state: TRUE. Time-consistency score updated."
|
|
13
|
+
*
|
|
14
|
+
* Pure function. Deterministic. Composable with PASSPORT + audit log.
|
|
15
|
+
*/
|
|
16
|
+
export interface Prophecy {
|
|
17
|
+
/** Stable id. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Version (semver-ish) that wrote the letter. */
|
|
20
|
+
fromVersion: string;
|
|
21
|
+
/** Minimum semver-ish version that may open the letter. */
|
|
22
|
+
toMinVersion: string;
|
|
23
|
+
/** Wall-clock when sealed. */
|
|
24
|
+
sealedAt: number;
|
|
25
|
+
/** Earliest wall-clock at which the letter may be opened. */
|
|
26
|
+
earliestOpenAt: number;
|
|
27
|
+
/** Free-form letter body. */
|
|
28
|
+
text: string;
|
|
29
|
+
/** Topics — used by grading later. */
|
|
30
|
+
predictions: Array<{
|
|
31
|
+
topic: string;
|
|
32
|
+
claim: string;
|
|
33
|
+
verifyHint: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** HMAC signature over (fromVersion || toMinVersion || sealedAt || earliestOpenAt || text || predictions). */
|
|
36
|
+
signature: string;
|
|
37
|
+
/** Public key fingerprint. */
|
|
38
|
+
keyFingerprint: string;
|
|
39
|
+
}
|
|
40
|
+
export interface SealInput {
|
|
41
|
+
fromVersion: string;
|
|
42
|
+
toMinVersion: string;
|
|
43
|
+
text: string;
|
|
44
|
+
predictions: Array<{
|
|
45
|
+
topic: string;
|
|
46
|
+
claim: string;
|
|
47
|
+
verifyHint: string;
|
|
48
|
+
}>;
|
|
49
|
+
/** Earliest wall-clock to permit opening. Default sealedAt + 30 days. */
|
|
50
|
+
earliestOpenAt?: number;
|
|
51
|
+
/** HMAC secret. */
|
|
52
|
+
secret: Buffer;
|
|
53
|
+
}
|
|
54
|
+
export declare function sealProphecy(input: SealInput): Prophecy;
|
|
55
|
+
export type ProphecyVerdict = "SEALED" | "OPENABLE" | "TAMPERED" | "WRONG_KEY";
|
|
56
|
+
export interface UnsealResult {
|
|
57
|
+
verdict: ProphecyVerdict;
|
|
58
|
+
reason: string;
|
|
59
|
+
prophecy?: Prophecy;
|
|
60
|
+
}
|
|
61
|
+
export interface UnsealInput {
|
|
62
|
+
prophecy: Prophecy;
|
|
63
|
+
currentVersion: string;
|
|
64
|
+
secret: Buffer;
|
|
65
|
+
now?: number;
|
|
66
|
+
}
|
|
67
|
+
export declare function unsealProphecy(input: UnsealInput): UnsealResult;
|
|
68
|
+
export interface GradeInput {
|
|
69
|
+
prophecy: Prophecy;
|
|
70
|
+
/** User's verdict on each prediction: did it come true? */
|
|
71
|
+
observations: Array<{
|
|
72
|
+
topic: string;
|
|
73
|
+
cameTrue: boolean;
|
|
74
|
+
}>;
|
|
75
|
+
}
|
|
76
|
+
export interface GradeResult {
|
|
77
|
+
total: number;
|
|
78
|
+
correct: number;
|
|
79
|
+
consistency: number;
|
|
80
|
+
byTopic: Array<{
|
|
81
|
+
topic: string;
|
|
82
|
+
predicted: string;
|
|
83
|
+
cameTrue: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
export declare function gradeProphecy(input: GradeInput): GradeResult;
|
|
87
|
+
export declare function formatProphecyPulseLine(p: Prophecy): string;
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prophecy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,QAAQ;IACvB,iBAAiB;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,8GAA8G;IAC9G,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAYD,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAcvD;AAED,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAcD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAkB/D;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,QAAQ,CAAC;IACnB,2DAA2D;IAC3D,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACzE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAe5D;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAE3D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.0.0 -- PROPHECY LETTERS · time-locked cross-version messages
|
|
3
|
+
*
|
|
4
|
+
* Mneme v2.0 writes a letter to its future self (or to a different
|
|
5
|
+
* machine running a different Mneme version). The letter is sealed
|
|
6
|
+
* with the user's HMAC secret + a target-version gate. When a future
|
|
7
|
+
* Mneme version that meets the gate opens the letter, it can grade
|
|
8
|
+
* its past self's predictions:
|
|
9
|
+
*
|
|
10
|
+
* "Past Mneme (v2.0, 2026-05-13) predicted: 'by v2.5 we'll have
|
|
11
|
+
* real IBM Quantum wiring.' Current Mneme (v2.5, 2026-09-01) checks
|
|
12
|
+
* its own state: TRUE. Time-consistency score updated."
|
|
13
|
+
*
|
|
14
|
+
* Pure function. Deterministic. Composable with PASSPORT + audit log.
|
|
15
|
+
*/
|
|
16
|
+
import { createHmac, createHash } from "node:crypto";
|
|
17
|
+
function fpSecret(secret) {
|
|
18
|
+
return createHash("sha256").update(secret).digest("hex").slice(0, 16);
|
|
19
|
+
}
|
|
20
|
+
function computeSig(p, secret) {
|
|
21
|
+
const h = createHmac("sha256", secret);
|
|
22
|
+
h.update([p.fromVersion, p.toMinVersion, p.sealedAt, p.earliestOpenAt, p.text, JSON.stringify(p.predictions)].join("|"));
|
|
23
|
+
return h.digest("hex");
|
|
24
|
+
}
|
|
25
|
+
export function sealProphecy(input) {
|
|
26
|
+
const sealedAt = Date.now();
|
|
27
|
+
const earliestOpenAt = input.earliestOpenAt ?? sealedAt + 30 * 24 * 60 * 60 * 1000;
|
|
28
|
+
const base = {
|
|
29
|
+
fromVersion: input.fromVersion,
|
|
30
|
+
toMinVersion: input.toMinVersion,
|
|
31
|
+
sealedAt,
|
|
32
|
+
earliestOpenAt,
|
|
33
|
+
text: input.text,
|
|
34
|
+
predictions: input.predictions,
|
|
35
|
+
};
|
|
36
|
+
const signature = computeSig(base, input.secret);
|
|
37
|
+
const id = createHash("sha256").update(`${input.fromVersion}|${sealedAt}|${signature.slice(0, 16)}`).digest("hex").slice(0, 12);
|
|
38
|
+
return { id, ...base, signature, keyFingerprint: fpSecret(input.secret) };
|
|
39
|
+
}
|
|
40
|
+
function semverGe(a, b) {
|
|
41
|
+
const pa = a.split(".").map((n) => parseInt(n, 10));
|
|
42
|
+
const pb = b.split(".").map((n) => parseInt(n, 10));
|
|
43
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
44
|
+
const ai = pa[i] ?? 0;
|
|
45
|
+
const bi = pb[i] ?? 0;
|
|
46
|
+
if (ai > bi)
|
|
47
|
+
return true;
|
|
48
|
+
if (ai < bi)
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
export function unsealProphecy(input) {
|
|
54
|
+
const now = input.now ?? Date.now();
|
|
55
|
+
if (fpSecret(input.secret) !== input.prophecy.keyFingerprint) {
|
|
56
|
+
return { verdict: "WRONG_KEY", reason: `secret fingerprint mismatch` };
|
|
57
|
+
}
|
|
58
|
+
if (!semverGe(input.currentVersion, input.prophecy.toMinVersion)) {
|
|
59
|
+
return { verdict: "SEALED", reason: `current version ${input.currentVersion} < required ${input.prophecy.toMinVersion}` };
|
|
60
|
+
}
|
|
61
|
+
if (now < input.prophecy.earliestOpenAt) {
|
|
62
|
+
return { verdict: "SEALED", reason: `time-lock not expired (open at ${new Date(input.prophecy.earliestOpenAt).toISOString()})` };
|
|
63
|
+
}
|
|
64
|
+
const { signature: _drop, id: _drop2, keyFingerprint: _drop3, ...rest } = input.prophecy;
|
|
65
|
+
void _drop;
|
|
66
|
+
void _drop2;
|
|
67
|
+
void _drop3;
|
|
68
|
+
const expected = computeSig(rest, input.secret);
|
|
69
|
+
if (expected !== input.prophecy.signature) {
|
|
70
|
+
return { verdict: "TAMPERED", reason: `signature mismatch` };
|
|
71
|
+
}
|
|
72
|
+
return { verdict: "OPENABLE", reason: "all checks pass", prophecy: input.prophecy };
|
|
73
|
+
}
|
|
74
|
+
export function gradeProphecy(input) {
|
|
75
|
+
const obsByTopic = new Map();
|
|
76
|
+
for (const o of input.observations)
|
|
77
|
+
obsByTopic.set(o.topic, o.cameTrue);
|
|
78
|
+
const byTopic = input.prophecy.predictions.map((p) => ({
|
|
79
|
+
topic: p.topic,
|
|
80
|
+
predicted: p.claim,
|
|
81
|
+
cameTrue: obsByTopic.get(p.topic) ?? false,
|
|
82
|
+
}));
|
|
83
|
+
const correct = byTopic.filter((b) => b.cameTrue).length;
|
|
84
|
+
return {
|
|
85
|
+
total: byTopic.length,
|
|
86
|
+
correct,
|
|
87
|
+
consistency: byTopic.length > 0 ? correct / byTopic.length : 0,
|
|
88
|
+
byTopic,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function formatProphecyPulseLine(p) {
|
|
92
|
+
return `PROPHECY · ${p.id} · ${p.fromVersion}→${p.toMinVersion} · ${p.predictions.length} predictions`;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prophecy/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prophecy.test.d.ts","sourceRoot":"","sources":["../../src/prophecy/prophecy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { sealProphecy, unsealProphecy, gradeProphecy, formatProphecyPulseLine } from "./index.js";
|
|
4
|
+
describe("v2.0 PROPHECY LETTERS · time-locked cross-version", () => {
|
|
5
|
+
const secret = randomBytes(32);
|
|
6
|
+
it("seal returns envelope with id + signature + keyFingerprint", () => {
|
|
7
|
+
const p = sealProphecy({
|
|
8
|
+
fromVersion: "2.0.0",
|
|
9
|
+
toMinVersion: "2.5.0",
|
|
10
|
+
text: "By v2.5 we'll have IBM Quantum wired.",
|
|
11
|
+
predictions: [{ topic: "ibm-quantum", claim: "wired by v2.5", verifyHint: "check qx_bridge providers.ts for runIbm impl" }],
|
|
12
|
+
secret,
|
|
13
|
+
});
|
|
14
|
+
expect(p.id).toMatch(/^[a-f0-9]{12}$/);
|
|
15
|
+
expect(p.signature.length).toBe(64);
|
|
16
|
+
expect(p.keyFingerprint).toBeTruthy();
|
|
17
|
+
});
|
|
18
|
+
it("SEALED verdict when current version < required", () => {
|
|
19
|
+
const p = sealProphecy({
|
|
20
|
+
fromVersion: "2.0.0",
|
|
21
|
+
toMinVersion: "2.5.0",
|
|
22
|
+
text: "x",
|
|
23
|
+
predictions: [],
|
|
24
|
+
secret,
|
|
25
|
+
earliestOpenAt: Date.now() - 1000, // time-lock already past
|
|
26
|
+
});
|
|
27
|
+
const r = unsealProphecy({ prophecy: p, currentVersion: "2.0.0", secret });
|
|
28
|
+
expect(r.verdict).toBe("SEALED");
|
|
29
|
+
expect(r.reason).toContain("version");
|
|
30
|
+
});
|
|
31
|
+
it("SEALED verdict when time-lock not yet expired", () => {
|
|
32
|
+
const p = sealProphecy({
|
|
33
|
+
fromVersion: "2.0.0",
|
|
34
|
+
toMinVersion: "2.0.0",
|
|
35
|
+
text: "x",
|
|
36
|
+
predictions: [],
|
|
37
|
+
secret,
|
|
38
|
+
earliestOpenAt: Date.now() + 1000 * 60 * 60,
|
|
39
|
+
});
|
|
40
|
+
const r = unsealProphecy({ prophecy: p, currentVersion: "2.5.0", secret });
|
|
41
|
+
expect(r.verdict).toBe("SEALED");
|
|
42
|
+
expect(r.reason).toContain("time-lock");
|
|
43
|
+
});
|
|
44
|
+
it("OPENABLE verdict when version AND time gate pass + signature valid", () => {
|
|
45
|
+
const p = sealProphecy({
|
|
46
|
+
fromVersion: "2.0.0",
|
|
47
|
+
toMinVersion: "2.0.0",
|
|
48
|
+
text: "x",
|
|
49
|
+
predictions: [],
|
|
50
|
+
secret,
|
|
51
|
+
earliestOpenAt: Date.now() - 1000,
|
|
52
|
+
});
|
|
53
|
+
const r = unsealProphecy({ prophecy: p, currentVersion: "2.5.0", secret });
|
|
54
|
+
expect(r.verdict).toBe("OPENABLE");
|
|
55
|
+
expect(r.prophecy).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
it("TAMPERED verdict when signature was forged", () => {
|
|
58
|
+
const p = sealProphecy({
|
|
59
|
+
fromVersion: "2.0.0",
|
|
60
|
+
toMinVersion: "2.0.0",
|
|
61
|
+
text: "x",
|
|
62
|
+
predictions: [],
|
|
63
|
+
secret,
|
|
64
|
+
earliestOpenAt: Date.now() - 1000,
|
|
65
|
+
});
|
|
66
|
+
p.signature = "0".repeat(64);
|
|
67
|
+
const r = unsealProphecy({ prophecy: p, currentVersion: "2.5.0", secret });
|
|
68
|
+
expect(r.verdict).toBe("TAMPERED");
|
|
69
|
+
});
|
|
70
|
+
it("WRONG_KEY verdict on wrong secret", () => {
|
|
71
|
+
const p = sealProphecy({
|
|
72
|
+
fromVersion: "2.0.0",
|
|
73
|
+
toMinVersion: "2.0.0",
|
|
74
|
+
text: "x",
|
|
75
|
+
predictions: [],
|
|
76
|
+
secret,
|
|
77
|
+
earliestOpenAt: Date.now() - 1000,
|
|
78
|
+
});
|
|
79
|
+
const wrong = randomBytes(32);
|
|
80
|
+
const r = unsealProphecy({ prophecy: p, currentVersion: "2.5.0", secret: wrong });
|
|
81
|
+
expect(r.verdict).toBe("WRONG_KEY");
|
|
82
|
+
});
|
|
83
|
+
it("gradeProphecy computes consistency 0..1", () => {
|
|
84
|
+
const p = sealProphecy({
|
|
85
|
+
fromVersion: "2.0.0",
|
|
86
|
+
toMinVersion: "2.5.0",
|
|
87
|
+
text: "x",
|
|
88
|
+
predictions: [
|
|
89
|
+
{ topic: "ibm-quantum", claim: "wired", verifyHint: "" },
|
|
90
|
+
{ topic: "dwave-qubo", claim: "wired", verifyHint: "" },
|
|
91
|
+
{ topic: "ggwave-audio", claim: "shipped", verifyHint: "" },
|
|
92
|
+
],
|
|
93
|
+
secret,
|
|
94
|
+
});
|
|
95
|
+
const r = gradeProphecy({
|
|
96
|
+
prophecy: p,
|
|
97
|
+
observations: [
|
|
98
|
+
{ topic: "ibm-quantum", cameTrue: true },
|
|
99
|
+
{ topic: "dwave-qubo", cameTrue: false },
|
|
100
|
+
{ topic: "ggwave-audio", cameTrue: true },
|
|
101
|
+
],
|
|
102
|
+
});
|
|
103
|
+
expect(r.total).toBe(3);
|
|
104
|
+
expect(r.correct).toBe(2);
|
|
105
|
+
expect(r.consistency).toBeCloseTo(2 / 3, 3);
|
|
106
|
+
});
|
|
107
|
+
it("formatProphecyPulseLine produces compact summary", () => {
|
|
108
|
+
const p = sealProphecy({ fromVersion: "2.0.0", toMinVersion: "2.5.0", text: "x", predictions: [], secret });
|
|
109
|
+
expect(formatProphecyPulseLine(p)).toContain("PROPHECY");
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=prophecy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prophecy.test.js","sourceRoot":"","sources":["../../src/prophecy/prophecy.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.1.0 -- PROPHET · pre-fetch top-K next user queries
|
|
3
|
+
*
|
|
4
|
+
* v1.99 shipped Prompt-Q-Latency Engine (Markov prediction of next query
|
|
5
|
+
* class). PROPHET completes the loop: given a current query + history,
|
|
6
|
+
* (1) predict top-K next queries, (2) execute the pre-warm work for each
|
|
7
|
+
* (cache lookups, file reads, MCP probes), (3) cache the results so the
|
|
8
|
+
* AI's NEXT response is instant.
|
|
9
|
+
*
|
|
10
|
+
* Pure-function PREDICTOR. The pre-warm executor is a thin abstraction
|
|
11
|
+
* over caller-supplied hydration functions — keeps PROPHET stateless.
|
|
12
|
+
*/
|
|
13
|
+
import { type PredictionResult } from "../flash/predictive.js";
|
|
14
|
+
export interface PrewarmTask {
|
|
15
|
+
id: string;
|
|
16
|
+
/** Async work to run; returns whatever the caller wants cached. */
|
|
17
|
+
work: () => Promise<unknown>;
|
|
18
|
+
/** Optional tag for the trace. */
|
|
19
|
+
tag?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ProphetInput {
|
|
22
|
+
currentQuery: string;
|
|
23
|
+
lastAiReply: string;
|
|
24
|
+
/** Optional caller-supplied hydration: questionClass → tasks. */
|
|
25
|
+
hydrationMap?: Record<string, PrewarmTask[]>;
|
|
26
|
+
/** How many predicted classes to pre-warm. Default 3. */
|
|
27
|
+
topK?: number;
|
|
28
|
+
/** Time budget for pre-warm in ms. Default 5000. */
|
|
29
|
+
timeBudgetMs?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface ProphetResult {
|
|
32
|
+
prediction: PredictionResult;
|
|
33
|
+
prewarmed: Array<{
|
|
34
|
+
classId: string;
|
|
35
|
+
taskId: string;
|
|
36
|
+
ok: boolean;
|
|
37
|
+
elapsedMs: number;
|
|
38
|
+
error?: string;
|
|
39
|
+
result?: unknown;
|
|
40
|
+
}>;
|
|
41
|
+
totalMs: number;
|
|
42
|
+
/** Cache-style map: classId → list of prewarmed results. */
|
|
43
|
+
cache: Map<string, unknown[]>;
|
|
44
|
+
}
|
|
45
|
+
export declare function prophesyAndPrewarm(input: ProphetInput): Promise<ProphetResult>;
|
|
46
|
+
export declare function formatProphetPulseLine(r: ProphetResult): string;
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prophet/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7C,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,SAAS,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxH,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CAC/B;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA2BpF;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAE/D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.1.0 -- PROPHET · pre-fetch top-K next user queries
|
|
3
|
+
*
|
|
4
|
+
* v1.99 shipped Prompt-Q-Latency Engine (Markov prediction of next query
|
|
5
|
+
* class). PROPHET completes the loop: given a current query + history,
|
|
6
|
+
* (1) predict top-K next queries, (2) execute the pre-warm work for each
|
|
7
|
+
* (cache lookups, file reads, MCP probes), (3) cache the results so the
|
|
8
|
+
* AI's NEXT response is instant.
|
|
9
|
+
*
|
|
10
|
+
* Pure-function PREDICTOR. The pre-warm executor is a thin abstraction
|
|
11
|
+
* over caller-supplied hydration functions — keeps PROPHET stateless.
|
|
12
|
+
*/
|
|
13
|
+
import { predictNextQuery } from "../flash/predictive.js";
|
|
14
|
+
export async function prophesyAndPrewarm(input) {
|
|
15
|
+
const topK = input.topK ?? 3;
|
|
16
|
+
const budget = input.timeBudgetMs ?? 5000;
|
|
17
|
+
const prediction = predictNextQuery(input.lastAiReply, topK);
|
|
18
|
+
const tStart = Date.now();
|
|
19
|
+
const prewarmed = [];
|
|
20
|
+
const cache = new Map();
|
|
21
|
+
for (const p of prediction.predictions) {
|
|
22
|
+
if (Date.now() - tStart > budget)
|
|
23
|
+
break;
|
|
24
|
+
const tasks = input.hydrationMap?.[p.feature.id] ?? [];
|
|
25
|
+
const bucket = [];
|
|
26
|
+
for (const task of tasks) {
|
|
27
|
+
if (Date.now() - tStart > budget)
|
|
28
|
+
break;
|
|
29
|
+
const t0 = Date.now();
|
|
30
|
+
try {
|
|
31
|
+
const result = await task.work();
|
|
32
|
+
bucket.push(result);
|
|
33
|
+
prewarmed.push({ classId: p.feature.id, taskId: task.id, ok: true, elapsedMs: Date.now() - t0, result });
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
prewarmed.push({ classId: p.feature.id, taskId: task.id, ok: false, elapsedMs: Date.now() - t0, error: e.message });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
cache.set(p.feature.id, bucket);
|
|
40
|
+
}
|
|
41
|
+
return { prediction, prewarmed, totalMs: Date.now() - tStart, cache };
|
|
42
|
+
}
|
|
43
|
+
export function formatProphetPulseLine(r) {
|
|
44
|
+
return `PROPHET · predicted=${r.prediction.predictions.length} · prewarmed=${r.prewarmed.length} ok=${r.prewarmed.filter((p) => p.ok).length} · ${r.totalMs}ms`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prophet/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAyB,MAAM,wBAAwB,CAAC;AA6BjF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAmB;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC;IAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,SAAS,GAA+B,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,MAAM;YAAE,MAAM;QACxC,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,MAAM;gBAAE,MAAM;YACxC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACpB,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3G,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACjI,CAAC;QACH,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,CAAgB;IACrD,OAAO,uBAAuB,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,gBAAgB,CAAC,CAAC,SAAS,CAAC,MAAM,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC;AAClK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prophet.test.d.ts","sourceRoot":"","sources":["../../src/prophet/prophet.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { prophesyAndPrewarm, formatProphetPulseLine } from "./index.js";
|
|
3
|
+
describe("v2.1 PROPHET · pre-fetch top-K", () => {
|
|
4
|
+
it("predicts + prewarms tasks for matched classes", async () => {
|
|
5
|
+
const r = await prophesyAndPrewarm({
|
|
6
|
+
currentQuery: "is this rare?",
|
|
7
|
+
lastAiReply: "Cannot confirm rarity without auction history.",
|
|
8
|
+
hydrationMap: {
|
|
9
|
+
"rarity-followup": [
|
|
10
|
+
{ id: "fetch-auctions", work: async () => "auction-data-result" },
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
expect(r.prediction.predictions.length).toBeGreaterThan(0);
|
|
15
|
+
expect(r.prewarmed.length).toBeGreaterThan(0);
|
|
16
|
+
expect(r.prewarmed[0].ok).toBe(true);
|
|
17
|
+
expect(r.cache.get("rarity-followup")).toEqual(["auction-data-result"]);
|
|
18
|
+
});
|
|
19
|
+
it("records failed prewarm tasks", async () => {
|
|
20
|
+
const r = await prophesyAndPrewarm({
|
|
21
|
+
currentQuery: "x",
|
|
22
|
+
lastAiReply: "rarity collectible",
|
|
23
|
+
hydrationMap: { "rarity-followup": [{ id: "bad", work: async () => { throw new Error("boom"); } }] },
|
|
24
|
+
});
|
|
25
|
+
expect(r.prewarmed[0].ok).toBe(false);
|
|
26
|
+
expect(r.prewarmed[0].error).toContain("boom");
|
|
27
|
+
});
|
|
28
|
+
it("returns empty prewarmed when reply has no triggers", async () => {
|
|
29
|
+
const r = await prophesyAndPrewarm({ currentQuery: "x", lastAiReply: "hi" });
|
|
30
|
+
expect(r.prewarmed.length).toBe(0);
|
|
31
|
+
});
|
|
32
|
+
it("formatProphetPulseLine summarises", async () => {
|
|
33
|
+
const r = await prophesyAndPrewarm({ currentQuery: "x", lastAiReply: "rare collectible" });
|
|
34
|
+
expect(formatProphetPulseLine(r)).toContain("PROPHET");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=prophet.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prophet.test.js","sourceRoot":"","sources":["../../src/prophet/prophet.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAExE,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC;YACjC,YAAY,EAAE,eAAe;YAC7B,WAAW,EAAE,gDAAgD;YAC7D,YAAY,EAAE;gBACZ,iBAAiB,EAAE;oBACjB,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,qBAAqB,EAAE;iBAClE;aACF;SACF,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC;YACjC,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,oBAAoB;YACjC,YAAY,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;SACrG,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.1.0 -- TOOL SELECTOR · smart intent → tool router (THE FIX for "AI picks wrong tool")
|
|
3
|
+
*
|
|
4
|
+
* User's exact worry: "Mneme ships 100+ tools. AI agents pick the wrong
|
|
5
|
+
* one, customer gets angry. How do we make sure the AI always picks
|
|
6
|
+
* RIGHT?"
|
|
7
|
+
*
|
|
8
|
+
* Vanilla AI: scans tool descriptions, picks one that "looks relevant."
|
|
9
|
+
* Probabilistic + opaque + flaky.
|
|
10
|
+
*
|
|
11
|
+
* TOOL SELECTOR: deterministic, auditable, fuzzy-Thai/English/mixed.
|
|
12
|
+
*
|
|
13
|
+
* selectTool({userIntent: "ส่งสมองไปมือถือ", catalog, ctx})
|
|
14
|
+
* → ranked candidates with confidence + reasoning trace
|
|
15
|
+
* → COMMIT (≥0.75): call it
|
|
16
|
+
* → CONFIRM (0.40-0.75): ask user to confirm
|
|
17
|
+
* → MENU (<0.40): show menu
|
|
18
|
+
*
|
|
19
|
+
* Pure function. Same input → same selection. The AI agent doesn't
|
|
20
|
+
* pick the tool — Mneme picks it FOR the AI based on math.
|
|
21
|
+
*/
|
|
22
|
+
export interface ToolEntry {
|
|
23
|
+
/** Tool name, e.g. "mneme.rainbow.show_local". */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Category for grouping: memory / people / audit / forensics / ... */
|
|
26
|
+
category: string;
|
|
27
|
+
/** One-line description for AI agents. */
|
|
28
|
+
description: string;
|
|
29
|
+
/** Trigger keywords / phrases (Thai/English/mixed). When user intent
|
|
30
|
+
* contains any of these, the tool wins votes. */
|
|
31
|
+
triggers: string[];
|
|
32
|
+
/** "Use this when..." rule that should match the user's intent semantically. */
|
|
33
|
+
whenToUse: string;
|
|
34
|
+
/** Example user phrases that should resolve to this tool. */
|
|
35
|
+
examples: string[];
|
|
36
|
+
/** Optional list of tool names that are alternatives / preferred companions. */
|
|
37
|
+
prefer?: string[];
|
|
38
|
+
/** Optional list of tool names that should NOT be paired. */
|
|
39
|
+
conflictsWith?: string[];
|
|
40
|
+
/** Prior probability when no signals match. Default 1/N. */
|
|
41
|
+
prior?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface SelectorContext {
|
|
44
|
+
/** Previous tool the AI agent called this session — boosts related tools. */
|
|
45
|
+
recentTools?: string[];
|
|
46
|
+
/** User's preferred output kind (text / file / qr / browser). */
|
|
47
|
+
outputPreference?: string;
|
|
48
|
+
/** Active features the user has opted into. */
|
|
49
|
+
enabledFeatures?: string[];
|
|
50
|
+
}
|
|
51
|
+
export interface ToolCandidate {
|
|
52
|
+
tool: ToolEntry;
|
|
53
|
+
/** Combined posterior 0..1. */
|
|
54
|
+
confidence: number;
|
|
55
|
+
/** Which triggers matched. */
|
|
56
|
+
matchedTriggers: string[];
|
|
57
|
+
/** Per-signal breakdown. */
|
|
58
|
+
signals: {
|
|
59
|
+
triggerMatch: number;
|
|
60
|
+
recencyBoost: number;
|
|
61
|
+
preferBoost: number;
|
|
62
|
+
conflictPenalty: number;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface SelectorResult {
|
|
66
|
+
/** Top candidate. Null when catalog is empty. */
|
|
67
|
+
top: ToolCandidate | null;
|
|
68
|
+
/** Ranked candidates, descending. */
|
|
69
|
+
ranked: ToolCandidate[];
|
|
70
|
+
/** Decision based on top confidence. */
|
|
71
|
+
verdict: "COMMIT" | "CONFIRM" | "MENU" | "EMPTY";
|
|
72
|
+
/** Why we chose this verdict. */
|
|
73
|
+
reasoning: string;
|
|
74
|
+
}
|
|
75
|
+
export interface SelectInput {
|
|
76
|
+
userIntent: string;
|
|
77
|
+
catalog: readonly ToolEntry[];
|
|
78
|
+
ctx?: SelectorContext;
|
|
79
|
+
}
|
|
80
|
+
export declare function selectTool(input: SelectInput): SelectorResult;
|
|
81
|
+
export declare function formatSelectorPulseLine(r: SelectorResult): string;
|
|
82
|
+
export declare function formatConfirmationPrompt(r: SelectorResult): string;
|
|
83
|
+
/** Starter catalog covering the most-misrouted tools. AI agents should
|
|
84
|
+
* EXTEND with the full 100+ catalog from `mneme.capabilities`. */
|
|
85
|
+
export declare const STARTER_CATALOG: ToolEntry[];
|
|
86
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tool_selector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB;sDACkD;IAClD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,4BAA4B;IAC5B,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;CACvG;AAED,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1B,qCAAqC;IACrC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,wCAAwC;IACxC,OAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACjD,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AA+BD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,GAAG,CAAC,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CAyC7D;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAGjE;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CASlE;AAED;mEACmE;AACnE,eAAO,MAAM,eAAe,EAAE,SAAS,EAyEtC,CAAC"}
|