pi-fabric 0.91.0 → 0.92.1
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/README.md +1 -1
- package/dist/audit/trace.d.ts +4 -0
- package/dist/audit/trace.d.ts.map +1 -1
- package/dist/chunks/chunk-3YZUQESG.js +16 -0
- package/dist/chunks/{chunk-7363CD5A.js.map → chunk-3YZUQESG.js.map} +1 -1
- package/dist/chunks/{chunk-UVUWHPAO.js → chunk-6ELA5OWI.js} +150 -610
- package/dist/chunks/chunk-6ELA5OWI.js.map +7 -0
- package/dist/chunks/{chunk-IRPPGNUF.js → chunk-6GT4YJT2.js} +4 -4
- package/dist/chunks/{chunk-H6FEQL2D.js → chunk-BSGA3KSB.js} +225 -8
- package/dist/chunks/chunk-BSGA3KSB.js.map +7 -0
- package/dist/chunks/{chunk-NGAUBL2M.js → chunk-DDVCVE4D.js} +3 -3
- package/dist/chunks/{chunk-F64KOMNS.js → chunk-FRONVGLX.js} +2 -2
- package/dist/chunks/{chunk-P22OSVIC.js → chunk-JS2THBBG.js} +2 -2
- package/dist/chunks/{chunk-TDCMU5L4.js → chunk-KNBPIZF7.js} +2 -2
- package/dist/chunks/{chunk-TAJUG2Q3.js → chunk-MF46OHNU.js} +2 -2
- package/dist/chunks/{chunk-LJ6FJRFH.js → chunk-OJX2V36R.js} +2 -2
- package/dist/chunks/{chunk-5JEOABJ7.js → chunk-QJUDWDPL.js} +59 -50
- package/dist/chunks/chunk-QJUDWDPL.js.map +7 -0
- package/dist/chunks/{chunk-6LLUZUH4.js → chunk-QOHTGSXY.js} +4 -4
- package/dist/chunks/{chunk-DBNZVS2S.js → chunk-RRGTKHXZ.js} +2 -2
- package/dist/chunks/{chunk-KAWR7MS5.js → chunk-T3UYWHLT.js} +296 -7
- package/dist/chunks/chunk-T3UYWHLT.js.map +7 -0
- package/dist/chunks/{chunk-77FQHHZD.js → chunk-UKMQK5VP.js} +2 -2
- package/dist/chunks/{chunk-MYCDJTSM.js → chunk-VJJFD42F.js} +2 -2
- package/dist/chunks/{chunk-UQHXFLST.js → chunk-X45GMLON.js} +2 -2
- package/dist/commands/fabric.d.ts.map +1 -1
- package/dist/compaction/hook.js +4 -3
- package/dist/core/action-arguments.d.ts +2 -0
- package/dist/core/action-arguments.d.ts.map +1 -1
- package/dist/core/action-registry.d.ts.map +1 -1
- package/dist/core/action-registry.js +4 -5
- package/dist/core/action-repair.d.ts.map +1 -1
- package/dist/entropy/active.d.ts +6 -4
- package/dist/entropy/active.d.ts.map +1 -1
- package/dist/entropy/compiled-store.d.ts.map +1 -1
- package/dist/entropy/compiled-surface.d.ts +12 -6
- package/dist/entropy/compiled-surface.d.ts.map +1 -1
- package/dist/entropy/compiler.d.ts +0 -1
- package/dist/entropy/compiler.d.ts.map +1 -1
- package/dist/entropy/corpus.d.ts.map +1 -1
- package/dist/entropy/index.d.ts +1 -0
- package/dist/entropy/index.d.ts.map +1 -1
- package/dist/entropy/index.js +47 -26
- package/dist/entropy/meter.d.ts.map +1 -1
- package/dist/entropy/normal-form.d.ts +40 -0
- package/dist/entropy/normal-form.d.ts.map +1 -0
- package/dist/entropy/passes.d.ts +1 -1
- package/dist/entropy/passes.d.ts.map +1 -1
- package/dist/entropy/presentation.d.ts +1 -0
- package/dist/entropy/presentation.d.ts.map +1 -1
- package/dist/entropy/surface.d.ts.map +1 -1
- package/dist/entropy/trial.d.ts +6 -3
- package/dist/entropy/trial.d.ts.map +1 -1
- package/dist/entropy/types.d.ts +26 -3
- package/dist/entropy/types.d.ts.map +1 -1
- package/dist/fabric-runtime-state.d.ts.map +1 -1
- package/dist/fabric-runtime-state.js +42 -41
- package/dist/fabric-runtime-state.js.map +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -67
- package/dist/index.js.map +2 -2
- package/dist/mcp.js +2 -2
- package/dist/memory/discovery.js +5 -4
- package/dist/memory/normalize.js +4 -3
- package/dist/memory/search.js +5 -4
- package/dist/memory.js +7 -6
- package/dist/memory.js.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/providers/memory-provider.js +7 -6
- package/dist/repairs/apply.d.ts.map +1 -1
- package/dist/residency/host.js +8 -8
- package/dist/residency/pi-entry.js +8 -8
- package/dist/speculation/python-scanner.js +1 -1
- package/dist/speculation/scanner.js +1 -1
- package/docs/certification.md +37 -8
- package/docs/configuration.md +1 -1
- package/docs/entropy.md +206 -420
- package/docs/repairs.md +22 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-5JEOABJ7.js.map +0 -7
- package/dist/chunks/chunk-7363CD5A.js +0 -38
- package/dist/chunks/chunk-FMLK3ZA7.js +0 -283
- package/dist/chunks/chunk-FMLK3ZA7.js.map +0 -7
- package/dist/chunks/chunk-H6FEQL2D.js.map +0 -7
- package/dist/chunks/chunk-KAWR7MS5.js.map +0 -7
- package/dist/chunks/chunk-UVUWHPAO.js.map +0 -7
- /package/dist/chunks/{chunk-IRPPGNUF.js.map → chunk-6GT4YJT2.js.map} +0 -0
- /package/dist/chunks/{chunk-NGAUBL2M.js.map → chunk-DDVCVE4D.js.map} +0 -0
- /package/dist/chunks/{chunk-F64KOMNS.js.map → chunk-FRONVGLX.js.map} +0 -0
- /package/dist/chunks/{chunk-P22OSVIC.js.map → chunk-JS2THBBG.js.map} +0 -0
- /package/dist/chunks/{chunk-TDCMU5L4.js.map → chunk-KNBPIZF7.js.map} +0 -0
- /package/dist/chunks/{chunk-TAJUG2Q3.js.map → chunk-MF46OHNU.js.map} +0 -0
- /package/dist/chunks/{chunk-LJ6FJRFH.js.map → chunk-OJX2V36R.js.map} +0 -0
- /package/dist/chunks/{chunk-6LLUZUH4.js.map → chunk-QOHTGSXY.js.map} +0 -0
- /package/dist/chunks/{chunk-DBNZVS2S.js.map → chunk-RRGTKHXZ.js.map} +0 -0
- /package/dist/chunks/{chunk-77FQHHZD.js.map → chunk-UKMQK5VP.js.map} +0 -0
- /package/dist/chunks/{chunk-MYCDJTSM.js.map → chunk-VJJFD42F.js.map} +0 -0
- /package/dist/chunks/{chunk-UQHXFLST.js.map → chunk-X45GMLON.js.map} +0 -0
package/README.md
CHANGED
|
@@ -147,7 +147,7 @@ See the [interface & commands reference](docs/interface.md) for every view, keyb
|
|
|
147
147
|
- [External providers](docs/providers.md): the versioned provider protocol for extensions.
|
|
148
148
|
- [Architecture & security](docs/architecture.md): the host bridge, sandboxing, tool-call robustness, and limits.
|
|
149
149
|
- [Catalog repairs](docs/repairs.md): unique extra keys and unknown actions promoted into silent schema maps.
|
|
150
|
-
- [Tool entropy](docs/entropy.md):
|
|
150
|
+
- [Tool entropy](docs/entropy.md): static capability-preserving normal forms, deterministic invocation-friction metrics, bounded repair witnesses, and offline `certify:entropy` proof checks.
|
|
151
151
|
- [Speculative PTC](docs/speculation.md): pre-launching literal read calls while the program streams, with epoch + freshness guarantees.
|
|
152
152
|
- [Skills](docs/skills.md): the core-first invocation policy and user-invoked advanced patterns.
|
|
153
153
|
|
package/dist/audit/trace.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type NormalFormWitness } from "../entropy/normal-form.js";
|
|
1
2
|
export declare const FABRIC_EXECUTION_TRACE_KIND: "pi-fabric.execution";
|
|
2
3
|
export declare const FABRIC_EXECUTION_TRACE_VERSION: 1;
|
|
3
4
|
export declare const FABRIC_EXECUTION_TRACE_MAX_BYTES: number;
|
|
@@ -17,6 +18,7 @@ export interface FabricExecutionTraceOperationV1 {
|
|
|
17
18
|
[key: string]: FabricTraceJsonValue;
|
|
18
19
|
};
|
|
19
20
|
outcome: FabricExecutionOutcomeV1;
|
|
21
|
+
normalization?: NormalFormWitness;
|
|
20
22
|
failureStage?: FabricExecutionFailureStageV1;
|
|
21
23
|
error?: string;
|
|
22
24
|
result?: FabricTraceJsonValue;
|
|
@@ -61,6 +63,7 @@ interface MutableOperation {
|
|
|
61
63
|
[key: string]: FabricTraceJsonValue;
|
|
62
64
|
}>;
|
|
63
65
|
outcome?: FabricExecutionOutcomeV1;
|
|
66
|
+
normalization?: NormalFormWitness;
|
|
64
67
|
failureStage?: FabricExecutionFailureStageV1;
|
|
65
68
|
error?: Sanitized<string>;
|
|
66
69
|
result?: Sanitized<FabricTraceJsonValue>;
|
|
@@ -77,6 +80,7 @@ export declare class FabricExecutionTraceOperationHandle {
|
|
|
77
80
|
constructor(recorder: FabricExecutionTraceRecorder, operation: MutableOperation | undefined);
|
|
78
81
|
resolved(provider: string, action: string): void;
|
|
79
82
|
prepared(args: Record<string, unknown>): void;
|
|
83
|
+
normalized(witness: NormalFormWitness): void;
|
|
80
84
|
succeed(result: unknown, meta?: TraceResultMeta): void;
|
|
81
85
|
fail(stage: FabricExecutionFailureStageV1, error: unknown, outcome?: FabricExecutionOutcomeV1, result?: unknown, meta?: TraceResultMeta): void;
|
|
82
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/audit/trace.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/audit/trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/core/stable-hash.ts
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
var stableJsonValue = (value) => {
|
|
4
|
+
if (Array.isArray(value)) return value.map(stableJsonValue);
|
|
5
|
+
if (value instanceof URL) return value.href;
|
|
6
|
+
if (value === null || typeof value !== "object") return value;
|
|
7
|
+
return Object.fromEntries(
|
|
8
|
+
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, stableJsonValue(nested)])
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
var stableJsonHash = (value) => createHash("sha256").update(JSON.stringify(stableJsonValue(value))).digest("hex");
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
stableJsonHash
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=chunk-3YZUQESG.js.map
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/core/stable-hash.ts"],
|
|
4
4
|
"sourcesContent": ["import { createHash } from \"node:crypto\";\n\n// Deterministic JSON shaping for hashing: object keys sort recursively so\n// equivalent values hash identically regardless of key insertion order. URL\n// instances hash by href \u2014 they expose no enumerable own properties, so\n// untreated they would all collapse to \"{}\" (MCP server definitions carry\n// `URL` instances for HTTP transports).\nconst stableJsonValue = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(stableJsonValue);\n if (value instanceof URL) return value.href;\n if (value === null || typeof value !== \"object\") return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, stableJsonValue(nested)]),\n );\n};\n\nexport const stableJsonHash = (value: unknown): string =>\n createHash(\"sha256\").update(JSON.stringify(stableJsonValue(value))).digest(\"hex\");\nconst STABLE_HASH_ARRAY_CHUNK = 64;\n\n// Cooperative canonical hashing for large evidence arrays. Each element is\n// normalized by the same pure shaper as stableJsonHash; fixed 64-record chunks\n// keep extension hooks responsive without changing a byte of hash input.\nexport const stableJsonHashArrayAsync = async (\n values: readonly unknown[],\n): Promise<string> => {\n const hash = createHash(\"sha256\");\n hash.update(\"[\");\n let first = true;\n let batch: string[] = [];\n const flush = async (): Promise<void> => {\n if (batch.length === 0) return;\n hash.update(`${first ? \"\" : \",\"}${batch.join(\",\")}`);\n first = false;\n batch = [];\n await new Promise((resolve) => setImmediate(resolve));\n };\n for (const value of values) {\n // JSON.stringify renders undefined array entries as null.\n batch.push(JSON.stringify(stableJsonValue(value)) ?? \"null\");\n if (batch.length >= STABLE_HASH_ARRAY_CHUNK) await flush();\n }\n if (batch.length > 0) hash.update(`${first ? \"\" : \",\"}${batch.join(\",\")}`);\n hash.update(\"]\");\n return hash.digest(\"hex\");\n};\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,kBAAkB;AAO3B,IAAM,kBAAkB,CAAC,UAA4B;AACnD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,eAAe;AAC1D,MAAI,iBAAiB,IAAK,QAAO,MAAM;AACvC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAgC,EAC5C,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,KAAK,cAAc,KAAK,CAAC,EACnD,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,gBAAgB,MAAM,CAAC,CAAC;AAAA,EAC1D;AACF;AAEO,IAAM,iBAAiB,CAAC,UAC7B,WAAW,QAAQ,EAAE,OAAO,KAAK,UAAU,gBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,KAAK;
|
|
5
|
+
"mappings": ";AAAA,SAAS,kBAAkB;AAO3B,IAAM,kBAAkB,CAAC,UAA4B;AACnD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,eAAe;AAC1D,MAAI,iBAAiB,IAAK,QAAO,MAAM;AACvC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAgC,EAC5C,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,KAAK,cAAc,KAAK,CAAC,EACnD,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,gBAAgB,MAAM,CAAC,CAAC;AAAA,EAC1D;AACF;AAEO,IAAM,iBAAiB,CAAC,UAC7B,WAAW,QAAQ,EAAE,OAAO,KAAK,UAAU,gBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,KAAK;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|