pi-mega-compact 0.20.9 → 0.20.11
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/config/vector-cortex.js +16 -0
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/route-dispatch.js +5 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-repair.js +63 -0
- package/dist/src/config/vector-cortex.js +16 -0
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/cache/types.js +73 -0
- package/dist/src/vector-cortex/heal/_repair-fixture.js +70 -0
- package/dist/src/vector-cortex/heal/controller.js +165 -0
- package/dist/src/vector-cortex/heal/rebuild.js +136 -0
- package/dist/src/vector-cortex/heal/repair-emit.js +83 -0
- package/dist/src/vector-cortex/heal/repair-types.js +74 -0
- package/dist/src/vector-cortex/heal/types.js +1 -0
- package/dist/vector-cortex/heal/_repair-fixture.js +70 -0
- package/dist/vector-cortex/heal/controller.js +165 -0
- package/dist/vector-cortex/heal/rebuild.js +136 -0
- package/dist/vector-cortex/heal/repair-emit.js +83 -0
- package/dist/vector-cortex/heal/repair-types.js +74 -0
- package/dist/vector-cortex/heal/types.js +1 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-fxyq2KaH.js → AreaChart-BDMjyRQp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-fxyq2KaH.js.map → AreaChart-BDMjyRQp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-D5EqAINP.js → BarChart-CqzPzOkj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-D5EqAINP.js.map → BarChart-CqzPzOkj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-D4UWbzLo.js → CacheTab-Bo8SH9q8.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-D4UWbzLo.js.map → CacheTab-Bo8SH9q8.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-BiXquGrX.js → EventsTab-DIEs6zC-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-BiXquGrX.js.map → EventsTab-DIEs6zC-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-D5QvoTjy.js → HealthTab-3a8IjwIK.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-D5QvoTjy.js.map → HealthTab-3a8IjwIK.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-Cy_-CWgM.js → MaintenanceTab-CdKwAcXo.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-Cy_-CWgM.js.map → MaintenanceTab-CdKwAcXo.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DrAjgGOR.js → MemoryMapTab-D2hHuNj-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DrAjgGOR.js.map → MemoryMapTab-D2hHuNj-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-BvPHcuFN.js → MetricsTab-CFhIhqrr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-BvPHcuFN.js.map → MetricsTab-CFhIhqrr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-DsbIigOQ.js → OverviewTab-Dzp5ZoiA.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-DsbIigOQ.js.map → OverviewTab-Dzp5ZoiA.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-7v_uZX_a.js → ReposTab-CFJT9mDR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-7v_uZX_a.js.map → ReposTab-CFJT9mDR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BXGrv-6C.js → SessionsTab-BhP1z6_y.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BXGrv-6C.js.map → SessionsTab-BhP1z6_y.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-QRUXa65y.js → SetupTab-2Glh7MKk.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-QRUXa65y.js.map → SetupTab-2Glh7MKk.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-p327ZZKT.js → TimeSavedCard-DmwBDhkw.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-p327ZZKT.js.map → TimeSavedCard-DmwBDhkw.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BcmBSlik.js → TurnsTab-CYIaOUUZ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BcmBSlik.js.map → TurnsTab-CYIaOUUZ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DD7vGaRS.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DD7vGaRS.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-DLXFMuNy.js → WikiTab-CP-JEd17.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-DLXFMuNy.js.map → WikiTab-CP-JEd17.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-C9CghmRx.js → button-B1RhLsGs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-C9CghmRx.js.map → button-B1RhLsGs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-DWU-1y3t.js → card-BLPT2-8G.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-DWU-1y3t.js.map → card-BLPT2-8G.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Dayy9dGn.js → generateCategoricalChart-DVOMJzL2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Dayy9dGn.js.map → generateCategoricalChart-DVOMJzL2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-D9PsW3VZ.js → index-CuLdiHRl.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-D9PsW3VZ.js.map → index-CuLdiHRl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-CnLFAmVT.js → switch-C5tqzhcl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-CnLFAmVT.js.map → switch-C5tqzhcl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-HN5C7_vy.js → toggle-HcM6W2Yl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-HN5C7_vy.js.map → toggle-HcM6W2Yl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-DoJfk3Ce.js → useSSE-BtWUs2kL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-DoJfk3Ce.js.map → useSSE-BtWUs2kL.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/vector-cortex.ts +9 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexRepairCard.tsx +43 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexShardsCard.tsx +89 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +14 -60
- package/extensions/dashboard-client/src/types/vector-cortex.ts +17 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-heal.ts +38 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex.ts +1 -0
- package/extensions/dashboard-server/route-dispatch.ts +4 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
- package/extensions/dashboard-server/routes-vector-cortex-repair.ts +72 -0
- package/package.json +1 -1
- package/src/config/vector-cortex.ts +17 -0
- package/src/config.ts +1 -0
- package/src/vector-cortex/cache/types.ts +206 -0
- package/src/vector-cortex/heal/_repair-fixture.ts +138 -0
- package/src/vector-cortex/heal/controller.ts +189 -0
- package/src/vector-cortex/heal/rebuild.ts +200 -0
- package/src/vector-cortex/heal/repair-emit.ts +118 -0
- package/src/vector-cortex/heal/repair-types.ts +227 -0
- package/src/vector-cortex/heal/types.ts +28 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-D2fjKNyT.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-D2fjKNyT.js.map +0 -1
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
fetchVectorCortexRollout,
|
|
20
20
|
fetchVectorCortexClosureProof,
|
|
21
21
|
fetchVectorCortexRestore,
|
|
22
|
+
fetchVectorCortexRepair,
|
|
22
23
|
fetchVectorCortexShards,
|
|
23
24
|
fetchVectorCortexTopology,
|
|
24
25
|
resetVectorCortexBreaker,
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
type VectorCortexRolloutView,
|
|
33
34
|
type VectorCortexClosureProofView,
|
|
34
35
|
type VectorCortexRestoreView,
|
|
36
|
+
type VectorCortexRepairView,
|
|
35
37
|
type VectorCortexShardsView,
|
|
36
38
|
type VectorCortexTopologyView,
|
|
37
39
|
} from "../api/vector-cortex";
|
|
@@ -42,6 +44,11 @@ import { VectorCortexRenderCard } from "./VectorCortexRenderCard";
|
|
|
42
44
|
import { VectorCortexRolloutCard } from "./VectorCortexRolloutCard";
|
|
43
45
|
import { VectorCortexClosureCard } from "./VectorCortexClosureCard";
|
|
44
46
|
import { VectorCortexRestoreCard } from "./VectorCortexRestoreCard";
|
|
47
|
+
import { VectorCortexRepairCard } from "./VectorCortexRepairCard";
|
|
48
|
+
import {
|
|
49
|
+
VectorCortexShardsCard,
|
|
50
|
+
VectorCortexReconstructCard,
|
|
51
|
+
} from "./VectorCortexShardsCard";
|
|
45
52
|
import { VectorCortexPlansCard } from "./VectorCortexPlansCard";
|
|
46
53
|
import { VectorCortexTopologyCard } from "./VectorCortexTopologyCard";
|
|
47
54
|
import { VectorCortexLedgerCard } from "./VectorCortexLedgerCard";
|
|
@@ -71,6 +78,7 @@ export default function VectorCortexTab(): React.ReactElement {
|
|
|
71
78
|
const [rollout, setRollout] = useState<VectorCortexRolloutView | null>(null);
|
|
72
79
|
const [closureProof, setClosureProof] = useState<VectorCortexClosureProofView | null>(null);
|
|
73
80
|
const [restore, setRestore] = useState<VectorCortexRestoreView | null>(null);
|
|
81
|
+
const [repair, setRepair] = useState<VectorCortexRepairView | null>(null);
|
|
74
82
|
|
|
75
83
|
const poll = useCallback(() => {
|
|
76
84
|
fetchVectorCortexEvaluation()
|
|
@@ -112,6 +120,9 @@ export default function VectorCortexTab(): React.ReactElement {
|
|
|
112
120
|
fetchVectorCortexRestore().then(setRestore).catch(() => {
|
|
113
121
|
/* exact-source-restoration card is best-effort (VC6B) */
|
|
114
122
|
});
|
|
123
|
+
fetchVectorCortexRepair().then(setRepair).catch(() => {
|
|
124
|
+
/* self-healing derived-state card is best-effort (VC6C) */
|
|
125
|
+
});
|
|
115
126
|
}, []);
|
|
116
127
|
|
|
117
128
|
useEffect(() => {
|
|
@@ -263,71 +274,14 @@ export default function VectorCortexTab(): React.ReactElement {
|
|
|
263
274
|
</CardContent>
|
|
264
275
|
</Card>
|
|
265
276
|
<VectorCortexTopologyCard topology={topology} query={query} />
|
|
266
|
-
<
|
|
267
|
-
|
|
268
|
-
<div className="flex items-center justify-between">
|
|
269
|
-
<CardTitle>Dual-Tier Shards (VC4A)</CardTitle>
|
|
270
|
-
{shards?.enabled ? (
|
|
271
|
-
<Badge variant="success">ACTIVE</Badge>
|
|
272
|
-
) : (
|
|
273
|
-
<Badge variant="danger">OFF</Badge>
|
|
274
|
-
)}
|
|
275
|
-
</div>
|
|
276
|
-
</CardHeader>
|
|
277
|
-
<CardContent>
|
|
278
|
-
{!shards?.enabled ? (
|
|
279
|
-
<div className="vc-empty">Dual-tier shards disabled (VC4A off).</div>
|
|
280
|
-
) : (
|
|
281
|
-
<>
|
|
282
|
-
<div className="grid grid-cols-2 gap-4 md:grid-cols-4">
|
|
283
|
-
<Metric label="Semantic shards" value={String(shards.semanticCount)} />
|
|
284
|
-
<Metric label="Exact shards" value={String(shards.exactCount)} />
|
|
285
|
-
<Metric label="Byte total" value={String(shards.byteTotal)} />
|
|
286
|
-
<Metric label="Protected bytes" value={String(shards.protectedByteTotal)} />
|
|
287
|
-
</div>
|
|
288
|
-
<div className="mt-3 text-xs text-muted-foreground">
|
|
289
|
-
Reader-only count/byte aggregate; staged in-memory this sprint.
|
|
290
|
-
</div>
|
|
291
|
-
</>
|
|
292
|
-
)}
|
|
293
|
-
</CardContent>
|
|
294
|
-
</Card>
|
|
295
|
-
<Card>
|
|
296
|
-
<CardHeader>
|
|
297
|
-
<div className="flex items-center justify-between">
|
|
298
|
-
<CardTitle>Reconstruction Fidelity (VC4C)</CardTitle>
|
|
299
|
-
{reconstruct?.enabled ? (
|
|
300
|
-
<Badge variant="success">ACTIVE</Badge>
|
|
301
|
-
) : (
|
|
302
|
-
<Badge variant="danger">OFF</Badge>
|
|
303
|
-
)}
|
|
304
|
-
</div>
|
|
305
|
-
</CardHeader>
|
|
306
|
-
<CardContent>
|
|
307
|
-
{!reconstruct?.enabled ? (
|
|
308
|
-
<div className="vc-empty">Reconstruction fidelity disabled (VC4C off).</div>
|
|
309
|
-
) : (
|
|
310
|
-
<>
|
|
311
|
-
<div className="grid grid-cols-2 gap-4 md:grid-cols-4">
|
|
312
|
-
<Metric label="Closure attempts" value={String(reconstruct.closureAttempts)} />
|
|
313
|
-
<Metric label="Closure rejections" value={String(reconstruct.closureRejections)} />
|
|
314
|
-
<Metric label="Validated" value={String(reconstruct.validatedCount)} />
|
|
315
|
-
<Metric label="Invalidated" value={String(reconstruct.invalidatedCount)} />
|
|
316
|
-
<Metric label="Span total" value={String(reconstruct.spanTotal)} />
|
|
317
|
-
<Metric label="Byte total" value={String(reconstruct.byteTotal)} />
|
|
318
|
-
</div>
|
|
319
|
-
<div className="mt-3 text-xs text-muted-foreground">
|
|
320
|
-
Reader-only closure/validation aggregate; staged in-memory this sprint.
|
|
321
|
-
</div>
|
|
322
|
-
</>
|
|
323
|
-
)}
|
|
324
|
-
</CardContent>
|
|
325
|
-
</Card>
|
|
277
|
+
<VectorCortexShardsCard view={shards} />
|
|
278
|
+
<VectorCortexReconstructCard view={reconstruct} />
|
|
326
279
|
<VectorCortexPlansCard view={plans} />
|
|
327
280
|
<VectorCortexRenderCard view={render} />
|
|
328
281
|
<VectorCortexRolloutCard view={rollout} />
|
|
329
282
|
<VectorCortexClosureCard view={closureProof} />
|
|
330
283
|
<VectorCortexRestoreCard view={restore} />
|
|
284
|
+
<VectorCortexRepairCard view={repair} />
|
|
331
285
|
<VectorCortexLedgerCard ledger={ledger} />
|
|
332
286
|
</div>
|
|
333
287
|
);
|
|
@@ -225,6 +225,23 @@ export interface VectorCortexRestoreView {
|
|
|
225
225
|
updatedAt: string;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Reader-only self-healing derived-state view (VC6C). Counts + HEAL_REPAIR_*
|
|
230
|
+
* codes only — there is no payload endpoint, so no subsystem source bytes, gap
|
|
231
|
+
* ranges, high-water marks, root digests, or ledger text ever reach the client.
|
|
232
|
+
*/
|
|
233
|
+
export interface VectorCortexRepairView {
|
|
234
|
+
enabled: boolean;
|
|
235
|
+
mode: "A" | "B" | "C";
|
|
236
|
+
repairAttempts: number;
|
|
237
|
+
repairsPlanned: number;
|
|
238
|
+
pointersSwitched: number;
|
|
239
|
+
backoffs: number;
|
|
240
|
+
lastBackoffMs: number | null;
|
|
241
|
+
lastFailure: string | null;
|
|
242
|
+
updatedAt: string;
|
|
243
|
+
}
|
|
244
|
+
|
|
228
245
|
/** Reader-only closure-optimization diagnostics view (VC6A). Aggregate only. */
|
|
229
246
|
export interface VectorCortexClosureProofView {
|
|
230
247
|
enabled: boolean;
|
|
@@ -71,3 +71,41 @@ export interface VectorCortexRestoreView {
|
|
|
71
71
|
/** ISO timestamp of the snapshot. */
|
|
72
72
|
readonly updatedAt: string;
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Reader-only self-healing derived-state diagnostics view for
|
|
77
|
+
* GET /api/vector-cortex/repair (VC6C).
|
|
78
|
+
*
|
|
79
|
+
* COUNTS + ERROR CODES ONLY. Like the restore view, this surface deliberately
|
|
80
|
+
* carries no payload: no subsystem source bytes, no rebuilt derived rows, no
|
|
81
|
+
* subsystem names paired with their gap ranges, no high-water values, no root
|
|
82
|
+
* digests, and no ledger text (SECURITY_PRIVACY — a diagnostic surface never
|
|
83
|
+
* renders the authority's contents). Only the controller's rebuild counters,
|
|
84
|
+
* the backoff schedule's observable timing, and the last HEAL_REPAIR_* failure
|
|
85
|
+
* code are exposed; the per-subsystem gap detail lives in the structured event
|
|
86
|
+
* log, not the dashboard.
|
|
87
|
+
*/
|
|
88
|
+
export interface VectorCortexRepairView {
|
|
89
|
+
/** Whether the VC6C self-healing derived-controller flag is enabled. */
|
|
90
|
+
readonly enabled: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Runtime triad mode: "A" targeted single-subsystem rebuild, "B" full
|
|
93
|
+
* deterministic rebuild (ambiguous gap), "C" derived state disabled (both
|
|
94
|
+
* rebuild paths failed, or the controller is not running at all).
|
|
95
|
+
*/
|
|
96
|
+
readonly mode: "A" | "B" | "C";
|
|
97
|
+
/** Total rebuild attempts started by the controller (event counter). */
|
|
98
|
+
readonly repairAttempts: number;
|
|
99
|
+
/** Rebuilds planned after gap detection, before rate limiting (counter). */
|
|
100
|
+
readonly repairsPlanned: number;
|
|
101
|
+
/** Rebuilds that reached a verified atomic pointer switch (counter). */
|
|
102
|
+
readonly pointersSwitched: number;
|
|
103
|
+
/** Attempts deferred by the rate limiter / exponential backoff (counter). */
|
|
104
|
+
readonly backoffs: number;
|
|
105
|
+
/** Most recent deterministic backoff delay in ms, or null if none yet. */
|
|
106
|
+
readonly lastBackoffMs: number | null;
|
|
107
|
+
/** Last failure reason (a HEAL_REPAIR_* code), or null if none yet. */
|
|
108
|
+
readonly lastFailure: string | null;
|
|
109
|
+
/** ISO timestamp of the snapshot. */
|
|
110
|
+
readonly updatedAt: string;
|
|
111
|
+
}
|
|
@@ -57,6 +57,9 @@ import {
|
|
|
57
57
|
handleVectorCortexClosureProof,
|
|
58
58
|
handleVectorCortexRestore,
|
|
59
59
|
} from "./routes.js";
|
|
60
|
+
// VC6C repair lives in its own module (routes-vector-cortex-repair.ts) so the
|
|
61
|
+
// heal route file stays well under the 400-line extension soft limit.
|
|
62
|
+
import { handleVectorCortexRepair } from "./routes-vector-cortex-repair.js";
|
|
60
63
|
|
|
61
64
|
/**
|
|
62
65
|
* Dispatch a request through every registered route handler.
|
|
@@ -110,5 +113,6 @@ export function dispatchRoutes(
|
|
|
110
113
|
if (handleVectorCortexRollout(req, res, ctx)) return true;
|
|
111
114
|
if (handleVectorCortexClosureProof(req, res, ctx)) return true;
|
|
112
115
|
if (handleVectorCortexRestore(req, res, ctx)) return true;
|
|
116
|
+
if (handleVectorCortexRepair(req, res, ctx)) return true;
|
|
113
117
|
return false;
|
|
114
118
|
}
|
|
@@ -150,5 +150,11 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
|
|
|
150
150
|
"Exact source restoration: restores the original bytes of closure spans ONLY from an exact shard (mode A) or a verified ledger range scan (mode B) — never inferred, reconstructed, or paraphrased from embeddings or semantic text. Requests are hard-bounded at 64 spans / 4MiB (HEAL_RESTORE_LIMIT); every span's SHA-256 is recomputed and bytes are inserted only after all requested span metadata validates, so a single bad span fails the whole request closed (HEAL_RESTORE_DIGEST_MISMATCH, HEAL_RESTORE_RANGE_MISMATCH). When no exact source exists (HEAL_RESTORE_SOURCE_MISSING) the old context is omitted and the loss is disclosed (mode C) rather than filled in. OFF = byte-identical predecessor (VC6A).",
|
|
151
151
|
true,
|
|
152
152
|
),
|
|
153
|
+
boolDirect(
|
|
154
|
+
"MEGACOMPACT_VC6C",
|
|
155
|
+
"VC6C Self-Healing Derived State",
|
|
156
|
+
"Self-healing derived-state controller: detects gaps between each derived subsystem's high-water mark and the durable authority high-water, then rebuilds derived state by copy -> root-digest verification -> atomic pointer switch, so a partially rebuilt subsystem is never made visible. A targeted single-subsystem rebuild is mode A; an ambiguous gap escalates to a full deterministic rebuild (mode B); if both rebuild paths fail the derived state is disabled rather than served stale (mode C). Rebuilds are rate-limited to one per subsystem per 5 minutes with deterministic exponential backoff, so a persistently failing subsystem cannot spin. OFF = byte-identical predecessor (VC6B); no controller runs, so the dashboard reports mode C.",
|
|
157
|
+
true,
|
|
158
|
+
),
|
|
153
159
|
],
|
|
154
160
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-vector-cortex-repair.ts — VC6C self-healing
|
|
3
|
+
* derived-state dashboard route.
|
|
4
|
+
*
|
|
5
|
+
* Reader-only GET /api/vector-cortex/repair returning the self-healing
|
|
6
|
+
* controller's aggregate diagnostics: whether the flag is enabled, the runtime
|
|
7
|
+
* triad mode, cumulative rebuild/pointer-switch/backoff counters, the last
|
|
8
|
+
* deterministic backoff delay, and the last HEAL_REPAIR_* failure code.
|
|
9
|
+
*
|
|
10
|
+
* COUNTS + ERROR CODES ONLY. NEVER exposes subsystem source bytes, rebuilt
|
|
11
|
+
* derived rows, per-subsystem gap ranges, high-water marks, root digests, or
|
|
12
|
+
* ledger text (reader-only, SECURITY_PRIVACY — the per-subsystem gap detail
|
|
13
|
+
* lives in the structured event log, not the dashboard). There is no mutation
|
|
14
|
+
* seam here either: rebuilds are driven by the controller's own gap detection,
|
|
15
|
+
* never by a dashboard request, so non-GET is rejected outright.
|
|
16
|
+
*
|
|
17
|
+
* Split into its own file (rather than grown into routes-vector-cortex-heal.ts)
|
|
18
|
+
* to keep every extensions/ file well under the 400-line soft-as-hard limit.
|
|
19
|
+
*
|
|
20
|
+
* Guardrails: PREVENT-PI-004 (local in-process state only), PREVENT-011 (no
|
|
21
|
+
* `any`), reader-only aggregate (counts + codes only).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
25
|
+
import type { RouteContext } from "./routes-core.js";
|
|
26
|
+
import { VC6C_ENABLED } from "../../src/config.js";
|
|
27
|
+
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
28
|
+
import type { VectorCortexRepairView } from "./api-contracts/vector-cortex.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Reader-only GET /api/vector-cortex/repair (VC6C).
|
|
32
|
+
*
|
|
33
|
+
* Counts and HEAL_REPAIR_* codes only — this is a static reader-only aggregate
|
|
34
|
+
* seam (same shape as the VC6A/VC6B handlers): there is no payload endpoint and
|
|
35
|
+
* never will be, so no subsystem bytes, gap ranges, high-water marks, or root
|
|
36
|
+
* digests can leak here.
|
|
37
|
+
*/
|
|
38
|
+
export function handleVectorCortexRepair(
|
|
39
|
+
req: IncomingMessage,
|
|
40
|
+
res: ServerResponse,
|
|
41
|
+
_ctx: RouteContext,
|
|
42
|
+
): boolean {
|
|
43
|
+
const url = req.url ?? "";
|
|
44
|
+
const path = url.split("?")[0] ?? url;
|
|
45
|
+
if (path !== "/api/vector-cortex/repair") return false;
|
|
46
|
+
if (req.method !== "GET") {
|
|
47
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const enabled = VC6C_ENABLED();
|
|
52
|
+
// Flag-off routes to mode C: with VC6C off no self-healing controller runs at
|
|
53
|
+
// all, so neither the targeted rebuild (mode A) nor the full deterministic
|
|
54
|
+
// rebuild (mode B) path is available. Mode C is exactly the spec's "derived
|
|
55
|
+
// state disabled" outcome — the honest OFF view is that derived state is not
|
|
56
|
+
// being healed, rather than implying a rebuild path that is not wired.
|
|
57
|
+
// Mirrors how VC6B's OFF view reports the disclose-loss mode it actually takes.
|
|
58
|
+
const mode: "A" | "B" | "C" = enabled ? "A" : "C";
|
|
59
|
+
const body: VectorCortexRepairView = {
|
|
60
|
+
enabled,
|
|
61
|
+
mode,
|
|
62
|
+
repairAttempts: 0,
|
|
63
|
+
repairsPlanned: 0,
|
|
64
|
+
pointersSwitched: 0,
|
|
65
|
+
backoffs: 0,
|
|
66
|
+
lastBackoffMs: null,
|
|
67
|
+
lastFailure: null,
|
|
68
|
+
updatedAt: new Date().toISOString(),
|
|
69
|
+
};
|
|
70
|
+
sendJson(res, 200, body);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.11",
|
|
4
4
|
"description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -241,6 +241,23 @@ export const VC6A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC6A");
|
|
|
241
241
|
*/
|
|
242
242
|
export const VC6B_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC6B");
|
|
243
243
|
|
|
244
|
+
/**
|
|
245
|
+
* VC6C — self-healing derived controller. Default ON. `MEGACOMPACT_VC6C=0`
|
|
246
|
+
* disables and is byte-identical to the predecessor (VC6B): the `detectGaps` /
|
|
247
|
+
* `planRebuild` / `rebuildGeneration` / `switchPointer` arithmetic STILL RUNS (it
|
|
248
|
+
* is PURE — a high-water comparison plus a SHA-256 root-digest check, with an
|
|
249
|
+
* INJECTED clock and no storage or network), but the
|
|
250
|
+
* `vector_cortex_repair_planned` / `vector_cortex_repair_pointer_switched` /
|
|
251
|
+
* `vector_cortex_repair_backoff` events are never emitted and the dashboard
|
|
252
|
+
* repair diagnostics seam is suppressed. Flag OFF gates the reporter + dashboard
|
|
253
|
+
* seam, never the gap-detection/rebuild arithmetic (in particular, an unverified
|
|
254
|
+
* pointer switch stays refused with the flag off), so flag-off
|
|
255
|
+
* outbound/predecessor golden bytes match exactly. This flag MUST also be a
|
|
256
|
+
* dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS),
|
|
257
|
+
* mirroring VC4A/VC4B/VC4C/VC5A/VC5B/VC5C/VC6A/VC6B.
|
|
258
|
+
*/
|
|
259
|
+
export const VC6C_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC6C");
|
|
260
|
+
|
|
244
261
|
// ---------------------------------------------------------------------------
|
|
245
262
|
// Breaker state machine constants (TRIAD_RESILIENCE.md §breaker).
|
|
246
263
|
// Rolled numbers for one 60s window; VC0C consumes these at its breaker seam.
|
package/src/config.ts
CHANGED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/cache/types.ts — VC7A frozen range crystal contract.
|
|
3
|
+
*
|
|
4
|
+
* A CRYSTAL is a frozen, immutable rendering of a bounded set of source ranges.
|
|
5
|
+
* VC5B proved a render is deterministic; VC7A makes that determinism REUSABLE by
|
|
6
|
+
* freezing the rendered bytes under a key that names exactly what they depend on.
|
|
7
|
+
*
|
|
8
|
+
* THE IDENTITY RULE (the whole sprint in one sentence). A crystal is keyed by
|
|
9
|
+
* the source ranges it COVERS, the digest of those covered bytes, the VALIDATED
|
|
10
|
+
* dependency high-water it was rendered against, and the renderer/profile that
|
|
11
|
+
* produced it — and by NOTHING ELSE. In particular the GLOBAL LEDGER FRONTIER is
|
|
12
|
+
* deliberately excluded from identity. That exclusion is the point: appending an
|
|
13
|
+
* unrelated turn advances the global frontier on every single request, so a key
|
|
14
|
+
* that included it would invalidate every crystal continuously and the cache
|
|
15
|
+
* would never hit. Conversely, the four fields that ARE in the key are precisely
|
|
16
|
+
* the ones whose change would make the frozen bytes WRONG:
|
|
17
|
+
*
|
|
18
|
+
* - covered ranges / `coveredDigest` — different bytes render differently;
|
|
19
|
+
* - `dependencyHighWater` — a dependency that has since advanced
|
|
20
|
+
* may contradict what was frozen;
|
|
21
|
+
* - `rendererVersion` — a renderer change changes the output;
|
|
22
|
+
* - `profileId` + `profileVersion` — a provider profile changes framing.
|
|
23
|
+
*
|
|
24
|
+
* So: unrelated append leaves the key UNCHANGED (CRY-FRONTIER-001); one covered
|
|
25
|
+
* byte, one dependency tick, one renderer bump, or one profile bump invalidates
|
|
26
|
+
* it 100% (CRY-COVERED-002 / CRY-DEP-003).
|
|
27
|
+
*
|
|
28
|
+
* VALIDATED, NOT OBSERVED, HIGH-WATER. `dependencyHighWater` is the DURABLE
|
|
29
|
+
* contiguous authority high-water the render was VALIDATED against, not whatever
|
|
30
|
+
* the writer happened to see. TRIAD_RESILIENCE freezes the derived high-water
|
|
31
|
+
* during an authority outage precisely so a crystal cannot be minted claiming
|
|
32
|
+
* evidence the authority has not durably accepted.
|
|
33
|
+
*
|
|
34
|
+
* DIGEST CONVENTIONS (three fields, two shapes — do not mix them).
|
|
35
|
+
* - `DagSpan.digest` and `CrystalKeyV1.coveredDigest` are `sha256:<hex>`, WITH
|
|
36
|
+
* the prefix (they name COVERED SOURCE BYTES, matching the DAG span
|
|
37
|
+
* convention the ranges themselves carry).
|
|
38
|
+
* - `CrystalKeyV1.requestDigest` is BARE lowercase hex, matching
|
|
39
|
+
* `RenderManifestV1.requestDigest`.
|
|
40
|
+
* - `CrystalV1.contentDigest` (the store's content address) is BARE lowercase
|
|
41
|
+
* hex, matching `ExactShardV1.digest`.
|
|
42
|
+
* Mixing these would either make every lookup miss or — far worse — make a
|
|
43
|
+
* prefix-stripped comparison accidentally succeed across granularities.
|
|
44
|
+
*
|
|
45
|
+
* Pure types + registered conformance IDs: no storage, no console, no network
|
|
46
|
+
* (PREVENT-PI-004 / PREVENT-011).
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import type { DagSpan } from "../prompt-dag/types.js";
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The immutable identity of a frozen crystal.
|
|
53
|
+
*
|
|
54
|
+
* Every field here is an IDENTITY field: changing any one of them yields a
|
|
55
|
+
* different key, and the key is stable under any change to a field NOT listed
|
|
56
|
+
* here (most importantly the global ledger frontier).
|
|
57
|
+
*/
|
|
58
|
+
export interface CrystalKeyV1 {
|
|
59
|
+
/** Provider profile that framed the render (VC5B `ProviderProfile.id`). */
|
|
60
|
+
readonly profileId: string;
|
|
61
|
+
/** Profile version — a profile bump must invalidate frozen bytes. */
|
|
62
|
+
readonly profileVersion: string;
|
|
63
|
+
/** Digest of the canonical request shape, BARE lowercase hex (VC5B). */
|
|
64
|
+
readonly requestDigest: string;
|
|
65
|
+
/** The source ranges this crystal covers. Sorted + disjoint (see `crystal.ts`). */
|
|
66
|
+
readonly sourceRanges: readonly DagSpan[];
|
|
67
|
+
/** Digest over the covered ranges' pinned digests, `sha256:` prefixed. */
|
|
68
|
+
readonly coveredDigest: string;
|
|
69
|
+
/** VALIDATED durable dependency high-water — never the global frontier. */
|
|
70
|
+
readonly dependencyHighWater: bigint;
|
|
71
|
+
/** Renderer version that produced the frozen bytes (VC5B renderer). */
|
|
72
|
+
readonly rendererVersion: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A frozen crystal: immutable bytes plus the manifest that explains them.
|
|
77
|
+
*
|
|
78
|
+
* `bytes` are the rendered output verbatim. `contentDigest` is the SHA-256 of
|
|
79
|
+
* exactly those bytes (bare lowercase hex) and is what makes the store
|
|
80
|
+
* CONTENT-ADDRESSED: two writers who independently render the same key must
|
|
81
|
+
* produce the same digest, and if they do not, one of them is wrong and the
|
|
82
|
+
* store refuses rather than picking a winner (`CRY_KEY_COLLISION`).
|
|
83
|
+
*/
|
|
84
|
+
export interface CrystalV1 {
|
|
85
|
+
readonly schema: "crystal-v1";
|
|
86
|
+
/** Canonical encoding of the key (see `encodeCrystalKey`). */
|
|
87
|
+
readonly keyDigest: string;
|
|
88
|
+
/** The frozen rendered bytes, verbatim and immutable. */
|
|
89
|
+
readonly bytes: Uint8Array;
|
|
90
|
+
/** SHA-256 over `bytes`, BARE lowercase hex (the content address). */
|
|
91
|
+
readonly contentDigest: string;
|
|
92
|
+
/** Byte length of `bytes`, carried so readers need not touch the payload. */
|
|
93
|
+
readonly byteCount: number;
|
|
94
|
+
/** The identity this crystal was frozen under. */
|
|
95
|
+
readonly key: CrystalKeyV1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** VC7A failure codes (registered CRY codes). */
|
|
99
|
+
export type CrystalFailureCode =
|
|
100
|
+
/** Two covered ranges in the same session overlap — identity is ambiguous. */
|
|
101
|
+
| "CRY_RANGE_OVERLAP"
|
|
102
|
+
/** A key already exists with DIFFERENT bytes; the store never overwrites. */
|
|
103
|
+
| "CRY_KEY_COLLISION"
|
|
104
|
+
/** A covered range is malformed (reversed/negative seq or byte bounds). */
|
|
105
|
+
| "CRY_RANGE_INVALID"
|
|
106
|
+
/** The key names no covered ranges — a crystal must cover something. */
|
|
107
|
+
| "CRY_RANGE_EMPTY"
|
|
108
|
+
/** The key exceeds the covered-range or aggregate-byte bound. */
|
|
109
|
+
| "CRY_KEY_LIMIT"
|
|
110
|
+
/** The store is unavailable — triad mode C, nothing is served from cache. */
|
|
111
|
+
| "CRY_STORE_UNAVAILABLE";
|
|
112
|
+
|
|
113
|
+
/** The verdict of canonical key encoding. */
|
|
114
|
+
export type CrystalKeyResult =
|
|
115
|
+
| { readonly ok: true; readonly keyDigest: string; readonly key: CrystalKeyV1 }
|
|
116
|
+
| { readonly ok: false; readonly codes: readonly CrystalFailureCode[] };
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The verdict of a store write.
|
|
120
|
+
*
|
|
121
|
+
* `written` distinguishes a FIRST write from an idempotent re-write of identical
|
|
122
|
+
* bytes: both are `ok`, because re-freezing the same crystal is legitimate (two
|
|
123
|
+
* concurrent renders raced), but only the first actually stored anything. A
|
|
124
|
+
* different-bytes write is never `ok` and never mutates the stored crystal.
|
|
125
|
+
*/
|
|
126
|
+
export type CrystalWriteResult =
|
|
127
|
+
| { readonly ok: true; readonly written: boolean; readonly contentDigest: string }
|
|
128
|
+
| { readonly ok: false; readonly code: CrystalFailureCode; readonly contentDigest: string };
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Runtime triad mode for the crystal path (TRIAD_RESILIENCE).
|
|
132
|
+
*
|
|
133
|
+
* A — the crystal store answered the read (the fast, normal path);
|
|
134
|
+
* B — a miss or a collision forced a FRESH deterministic render. This is an
|
|
135
|
+
* INDEPENDENT algorithm: no crystal, no store index, the renderer runs
|
|
136
|
+
* from the plan exactly as it would have before VC7A existed;
|
|
137
|
+
* C — the store is unavailable, so the cache is BYPASSED entirely. Mode C
|
|
138
|
+
* serves nothing from cache and states the loss of old semantic context;
|
|
139
|
+
* it never substitutes a stale or partially-written crystal.
|
|
140
|
+
*/
|
|
141
|
+
export type CrystalMode = "A" | "B" | "C";
|
|
142
|
+
|
|
143
|
+
/** Reader-only aggregate for GET /api/vector-cortex/cache-crystals. */
|
|
144
|
+
export interface CrystalStoreStats {
|
|
145
|
+
readonly mode: CrystalMode;
|
|
146
|
+
/** Distinct crystals currently held. */
|
|
147
|
+
readonly crystalCount: number;
|
|
148
|
+
/** Aggregate frozen bytes held (sum of `byteCount`). */
|
|
149
|
+
readonly totalBytes: number;
|
|
150
|
+
/** Reads answered from the store (mode A). */
|
|
151
|
+
readonly hits: number;
|
|
152
|
+
/** Reads with no stored crystal, forcing a fresh render (mode B). */
|
|
153
|
+
readonly misses: number;
|
|
154
|
+
/** Bytes served from hits — the cache's observable benefit. */
|
|
155
|
+
readonly hitBytes: number;
|
|
156
|
+
/** First writes that actually stored a crystal. */
|
|
157
|
+
readonly writes: number;
|
|
158
|
+
/** Idempotent re-writes of byte-identical crystals. */
|
|
159
|
+
readonly duplicateWrites: number;
|
|
160
|
+
/** Same-key, different-bytes writes refused (`CRY_KEY_COLLISION`). */
|
|
161
|
+
readonly collisions: number;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Maximum covered ranges in one key. A key is caller-shaped input; this bound
|
|
166
|
+
* exists so a single lookup cannot be turned into an unbounded sort/hash of
|
|
167
|
+
* attacker-chosen ranges (CRY_KEY_LIMIT).
|
|
168
|
+
*/
|
|
169
|
+
export const CRYSTAL_LIMIT_RANGES = 256;
|
|
170
|
+
|
|
171
|
+
/** Maximum aggregate covered bytes across a key's ranges (8 MiB). */
|
|
172
|
+
export const CRYSTAL_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Registered VC7A crystal conformance ID range (CRY-001..015). The acceptance
|
|
176
|
+
* aggregator reads these rows from the v2 manifest and asserts each returns its
|
|
177
|
+
* manifest `ok`/`code`.
|
|
178
|
+
*/
|
|
179
|
+
export const CRYSTAL_IDS: readonly string[] = Array.from(
|
|
180
|
+
{ length: 15 },
|
|
181
|
+
(_v, i) => `CRY-${String(i + 1).padStart(3, "0")}`,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Registered VC7A provider-identity conformance rows (PRO-016..023), continuing
|
|
186
|
+
* VC5B's PRO-001..015. These pin the PROFILE half of crystal identity: a profile
|
|
187
|
+
* or renderer bump must invalidate, and a profile-irrelevant change must not.
|
|
188
|
+
*/
|
|
189
|
+
export const CRYSTAL_PROVIDER_IDS: readonly string[] = Array.from(
|
|
190
|
+
{ length: 8 },
|
|
191
|
+
(_v, i) => `PRO-${String(i + 16).padStart(3, "0")}`,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
/** Named VC7A conformance assertions (the sprint's headline rows). */
|
|
195
|
+
export const CRYSTAL_NAMED_IDS = [
|
|
196
|
+
"CRY-FRONTIER-001",
|
|
197
|
+
"CRY-COVERED-002",
|
|
198
|
+
"CRY-DEP-003",
|
|
199
|
+
] as const;
|
|
200
|
+
|
|
201
|
+
/** The two structured events the VC7A reporter emits. */
|
|
202
|
+
export type CrystalEventName =
|
|
203
|
+
| "vector_cortex_crystal_written"
|
|
204
|
+
| "vector_cortex_crystal_collision";
|
|
205
|
+
|
|
206
|
+
export type { DagSpan };
|