pi-mega-compact 0.20.39 → 0.20.41

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.
Files changed (97) hide show
  1. package/dist/config/vector-cortex-ml5d.js +28 -0
  2. package/dist/config/vector-cortex-ml5e.js +30 -0
  3. package/dist/config/vector-cortex.js +6 -6
  4. package/dist/config.js +1 -1
  5. package/dist/extensions/dashboard-server/api-contracts/cortex-improve.js +14 -0
  6. package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +13 -0
  7. package/dist/extensions/dashboard-server/route-dispatch.js +5 -1
  8. package/dist/extensions/dashboard-server/routes-cortex-improve.js +220 -0
  9. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
  10. package/dist/extensions/dashboard-server/routes.js +1 -0
  11. package/dist/extensions/mega-runtime/dashboard-snapshot.js +2 -2
  12. package/dist/src/config/vector-cortex-ml5d.js +28 -0
  13. package/dist/src/config/vector-cortex-ml5e.js +30 -0
  14. package/dist/src/config/vector-cortex.js +6 -6
  15. package/dist/src/config.js +1 -1
  16. package/dist/src/vector-cortex/encoder/promotion.js +58 -0
  17. package/dist/src/vector-cortex/improve.js +24 -0
  18. package/dist/vector-cortex/encoder/promotion.js +58 -0
  19. package/dist/vector-cortex/improve.js +24 -0
  20. package/extensions/dashboard-client/dist/assets/{AreaChart-DjXp8u2Y.js → AreaChart-BT7YPcp7.js} +2 -2
  21. package/extensions/dashboard-client/dist/assets/{AreaChart-DjXp8u2Y.js.map → AreaChart-BT7YPcp7.js.map} +1 -1
  22. package/extensions/dashboard-client/dist/assets/{BarChart-BZbus-dR.js → BarChart-DceGcBUh.js} +2 -2
  23. package/extensions/dashboard-client/dist/assets/{BarChart-BZbus-dR.js.map → BarChart-DceGcBUh.js.map} +1 -1
  24. package/extensions/dashboard-client/dist/assets/{CacheTab-DQ2CjxVW.js → CacheTab-B9lCouRl.js} +2 -2
  25. package/extensions/dashboard-client/dist/assets/{CacheTab-DQ2CjxVW.js.map → CacheTab-B9lCouRl.js.map} +1 -1
  26. package/extensions/dashboard-client/dist/assets/{EventsTab-DUpnOV1p.js → EventsTab-oqJ11jY7.js} +2 -2
  27. package/extensions/dashboard-client/dist/assets/{EventsTab-DUpnOV1p.js.map → EventsTab-oqJ11jY7.js.map} +1 -1
  28. package/extensions/dashboard-client/dist/assets/{HealthTab-Bul_xjcn.js → HealthTab-Dbosf2Ik.js} +2 -2
  29. package/extensions/dashboard-client/dist/assets/{HealthTab-Bul_xjcn.js.map → HealthTab-Dbosf2Ik.js.map} +1 -1
  30. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLUjdKd3.js → MaintenanceTab-6TiApCVE.js} +2 -2
  31. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLUjdKd3.js.map → MaintenanceTab-6TiApCVE.js.map} +1 -1
  32. package/extensions/dashboard-client/dist/assets/MemoryMapTab-cBsE4mTf.js +2 -0
  33. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BFy0hb6F.js.map → MemoryMapTab-cBsE4mTf.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{MetricsTab-BpYuUkq3.js → MetricsTab-CX-X9hhy.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{MetricsTab-BpYuUkq3.js.map → MetricsTab-CX-X9hhy.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{OverviewTab-z7yuT-uq.js → OverviewTab-CpPYaTJF.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{OverviewTab-z7yuT-uq.js.map → OverviewTab-CpPYaTJF.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{ReposTab-ClORoDy_.js → ReposTab-D_Ot4QbU.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{ReposTab-ClORoDy_.js.map → ReposTab-D_Ot4QbU.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{SessionsTab-CUpehIt9.js → SessionsTab-BUzO3iGK.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{SessionsTab-CUpehIt9.js.map → SessionsTab-BUzO3iGK.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{SetupTab-Cii80Fdz.js → SetupTab-Be4w9v4j.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{SetupTab-Cii80Fdz.js.map → SetupTab-Be4w9v4j.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BV2iCSdV.js → TimeSavedCard-Cx-g6CXH.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BV2iCSdV.js.map → TimeSavedCard-Cx-g6CXH.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{TurnsTab-1T86rHnD.js → TurnsTab-CC_7T7ad.js} +3 -3
  47. package/extensions/dashboard-client/dist/assets/{TurnsTab-1T86rHnD.js.map → TurnsTab-CC_7T7ad.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DKPleja8.js → VcStatusBadge-ZTItXSiH.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DKPleja8.js.map → VcStatusBadge-ZTItXSiH.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/VectorCortexTab-DgAUZ4Pg.js +2 -0
  51. package/extensions/dashboard-client/dist/assets/VectorCortexTab-DgAUZ4Pg.js.map +1 -0
  52. package/extensions/dashboard-client/dist/assets/WikiTab-DnKupXTv.js +2 -0
  53. package/extensions/dashboard-client/dist/assets/{WikiTab-DKTILa1M.js.map → WikiTab-DnKupXTv.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/button-CFt3e0yc.js +2 -0
  55. package/extensions/dashboard-client/dist/assets/{button-5fSU8BZj.js.map → button-CFt3e0yc.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{card-BFUnpXE_.js → card-C6ZjsHrl.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{card-BFUnpXE_.js.map → card-C6ZjsHrl.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/client-extra-DdEdGTIe.js +2 -0
  59. package/extensions/dashboard-client/dist/assets/client-extra-DdEdGTIe.js.map +1 -0
  60. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-xCzi6pWn.js → generateCategoricalChart-C9_fu2hc.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-xCzi6pWn.js.map → generateCategoricalChart-C9_fu2hc.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{index-DqjmZ88m.js → index-DY81TY4f.js} +11 -11
  63. package/extensions/dashboard-client/dist/assets/index-DY81TY4f.js.map +1 -0
  64. package/extensions/dashboard-client/dist/assets/{switch-CeZUPf_e.js → switch-BOqa1d6x.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{switch-CeZUPf_e.js.map → switch-BOqa1d6x.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/assets/{toggle-MQQwdkwD.js → toggle-DToFaIEd.js} +2 -2
  67. package/extensions/dashboard-client/dist/assets/{toggle-MQQwdkwD.js.map → toggle-DToFaIEd.js.map} +1 -1
  68. package/extensions/dashboard-client/dist/assets/{useSSE-BetS7QHN.js → useSSE-CZqkhU18.js} +2 -2
  69. package/extensions/dashboard-client/dist/assets/{useSSE-BetS7QHN.js.map → useSSE-CZqkhU18.js.map} +1 -1
  70. package/extensions/dashboard-client/dist/index.html +1 -1
  71. package/extensions/dashboard-client/src/api/client-extra.ts +19 -1
  72. package/extensions/dashboard-client/src/components/ModelImprovementCard.tsx +141 -0
  73. package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +6 -0
  74. package/extensions/dashboard-client/src/types/cortex-improve.ts +42 -0
  75. package/extensions/dashboard-server/api-contracts/cortex-improve.ts +82 -0
  76. package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +31 -0
  77. package/extensions/dashboard-server/api-contracts/index.ts +12 -0
  78. package/extensions/dashboard-server/route-dispatch.ts +4 -0
  79. package/extensions/dashboard-server/routes-cortex-improve.ts +256 -0
  80. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
  81. package/extensions/dashboard-server/routes.ts +4 -0
  82. package/extensions/mega-runtime/dashboard-snapshot.ts +2 -2
  83. package/package.json +1 -1
  84. package/src/config/vector-cortex-ml5d.ts +30 -0
  85. package/src/config/vector-cortex-ml5e.ts +32 -0
  86. package/src/config/vector-cortex.ts +6 -6
  87. package/src/config.ts +2 -0
  88. package/src/vector-cortex/encoder/promotion.ts +129 -0
  89. package/src/vector-cortex/improve.ts +28 -0
  90. package/extensions/dashboard-client/dist/assets/MemoryMapTab-BFy0hb6F.js +0 -2
  91. package/extensions/dashboard-client/dist/assets/VectorCortexTab-BRzvd_pU.js +0 -2
  92. package/extensions/dashboard-client/dist/assets/VectorCortexTab-BRzvd_pU.js.map +0 -1
  93. package/extensions/dashboard-client/dist/assets/WikiTab-DKTILa1M.js +0 -2
  94. package/extensions/dashboard-client/dist/assets/button-5fSU8BZj.js +0 -2
  95. package/extensions/dashboard-client/dist/assets/client-extra-BZbw21wu.js +0 -2
  96. package/extensions/dashboard-client/dist/assets/client-extra-BZbw21wu.js.map +0 -1
  97. package/extensions/dashboard-client/dist/assets/index-DqjmZ88m.js.map +0 -1
@@ -0,0 +1,28 @@
1
+ /**
2
+ * config/vector-cortex-ml5d.ts — ML5-D dashboard "Improve Cortex" flag.
3
+ *
4
+ * Sibling extract mirroring vector-cortex-ml5a.ts / vector-cortex-ml5b.ts /
5
+ * vector-cortex-ml5c.ts, so vector-cortex.ts stays under its 300-line soft
6
+ * limit (soft-as-hard gate). This is the dashboard "Improve Cortex" surface +
7
+ * promote workflow sprint flag.
8
+ * vector-cortex.ts re-exports the ENUM below and root src/config.ts re-exports
9
+ * it, so no consumer import path changes.
10
+ *
11
+ * ML5-D adds the dashboard ModelImprovementCard + the POST /api/cortex/improve
12
+ * and GET /api/cortex/improve/status/:jobId endpoints. The flag gates that
13
+ * surface only; when OFF the endpoints return 404/disabled and VectorCortexTab
14
+ * renders exactly as before (byte-identical to the ML5-C-era tab — no
15
+ * ModelImprovementCard, no improve job is ever spawned).
16
+ *
17
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
18
+ */
19
+ import { sprintFlag } from "./vector-cortex-flag.js";
20
+ /**
21
+ * ML5-D — dashboard "Improve Cortex" surface + promote workflow. Default ON.
22
+ * `MEGACOMPACT_ML5_D=0` disables and is byte-identical to the ML5-C survivor:
23
+ * both `/api/cortex/improve*` endpoints return 404 and VectorCortexTab omits the
24
+ * ModelImprovementCard. The flag gates the dashboard surface only; it does not
25
+ * gate the underlying ML5-A training pipeline or the encoder's mode-A/B/C
26
+ * selection (those are governed by ML5-A and the encoder independently).
27
+ */
28
+ export const ML5D_ENABLED = () => sprintFlag("MEGACOMPACT_ML5_D");
@@ -0,0 +1,30 @@
1
+ /**
2
+ * config/vector-cortex-ml5e.ts — ML5-E nightly retraining cron + feedback loop.
3
+ *
4
+ * Sibling extract mirroring vector-cortex-ml5a.ts / ml5b.ts / ml5c.ts / ml5d.ts,
5
+ * so vector-cortex.ts stays under its 300-line soft limit (soft-as-hard gate).
6
+ * vector-cortex.ts re-exports the ENUM below and root src/config.ts re-exports
7
+ * it, so no consumer import path changes.
8
+ *
9
+ * ML5-E turns one-shot training (ML5-D's Improve button) into a living loop:
10
+ * the user's own post-redaction conversation turns become fresh training signal,
11
+ * the five heads are re-fit nightly, calibration is re-validated, and mode-A
12
+ * promotion is re-checked without human intervention. The cron is system-
13
+ * configured (`crontab -e` on the operator device); the extension never installs
14
+ * or writes a crontab. The flag gates **invocation** only — the scripts
15
+ * (retrain-nightly.mjs, promotion-gate.mjs, promotion.ts) exist on disk
16
+ * regardless; `=0` means the runtime never invokes them and the dashboard's
17
+ * Improve Cortex flow is byte-identical to the ML5-D survivor.
18
+ *
19
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
20
+ */
21
+ import { sprintFlag } from "./vector-cortex-flag.js";
22
+ /**
23
+ * ML5-E — nightly retraining cron + feedback loop. Default ON.
24
+ * `MEGACOMPACT_ML5_E=0` disables and is byte-identical to the ML5-D survivor:
25
+ * the nightly retraining scripts are never invoked by the runtime, the
26
+ * promotion gate is inert, and the dashboard's Improve Cortex flow is
27
+ * byte-identical to the ML5-D tab. The flag gates invocation only — the scripts
28
+ * exist on disk regardless.
29
+ */
30
+ export const ML5E_ENABLED = () => sprintFlag("MEGACOMPACT_ML5_E");
@@ -9,9 +9,8 @@
9
9
  * them without re-declaring the ownership boundary. Pi-agnostic, dependency-free.
10
10
  */
11
11
  import { sprintFlag } from "./vector-cortex-flag.js";
12
- // VC0/VC1/VC2 foundation-phase flags extracted to vector-cortex-early.ts to keep
13
- // this file under the 300-line soft limit. Re-exported here so every existing
14
- // `from "./config/vector-cortex.js"` import keeps resolving unchanged.
12
+ // VC0/VC1/VC2 foundation-phase flags in vector-cortex-early.ts; re-exported
13
+ // so every existing `from "./config/vector-cortex.js"` import resolves unchanged.
15
14
  export { VC0A_ENABLED, VC0B_ENABLED, VC0C_ENABLED, VC1A_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, } from "./vector-cortex-early.js";
16
15
  /**
17
16
  * VC3A — capability-gated cortex store (CortexReader/Writer/Admin, CortexRecordV1).
@@ -239,10 +238,9 @@ export const VC8A_ENABLED = () => sprintFlag("MEGACOMPACT_VC8A");
239
238
  * mirroring VC4A..VC8A.
240
239
  */
241
240
  export const VC8B_ENABLED = () => sprintFlag("MEGACOMPACT_VC8B");
242
- // VC8C (canary selection + Rust parity) extracted to vector-cortex-vc8c.ts;
243
- // re-exported so existing `./config/vector-cortex.js` imports keep resolving.
241
+ // VC8C extracted to vector-cortex-vc8c.ts; re-exported so existing imports keep resolving.
244
242
  export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
245
- // Sibling extracts to stay under the 300-line soft limit.
243
+ // Sibling extracts: stay under the 300-line soft limit.
246
244
  export { VC9A_ENABLED } from "./vector-cortex-vc9a.js";
247
245
  export { VC9B_ENABLED } from "./vector-cortex-vc9b.js";
248
246
  export { VC9C_ENABLED } from "./vector-cortex-vc9c.js";
@@ -251,5 +249,7 @@ export { PCC_ENABLED } from "./vector-cortex-pcc.js";
251
249
  export { ML5A_ENABLED } from "./vector-cortex-ml5a.js";
252
250
  export { ML5B_ENABLED } from "./vector-cortex-ml5b.js";
253
251
  export { ML5C_ENABLED } from "./vector-cortex-ml5c.js";
252
+ export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
253
+ export { ML5E_ENABLED } from "./vector-cortex-ml5e.js";
254
254
  // Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
255
255
  export { BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./vector-cortex-breakers.js";
package/dist/config.js CHANGED
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
114
114
  // default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
115
115
  // so root consumers share one source of truth.
116
116
  // ---------------------------------------------------------------------------
117
- export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
117
+ export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * api-contracts/cortex-improve.ts — ML5-D "Improve Cortex" job API types.
3
+ *
4
+ * Types for POST /api/cortex/improve (launch a local ML5-A training job that
5
+ * re-qualifies the five heads against the latest local corpus) and GET
6
+ * /api/cortex/improve/status/:jobId (poll the in-process job state to a
7
+ * terminal qualified / demoted_to_B verdict). Local-only, aggregate surfaces:
8
+ * mode / verdict / digest / reason / progress — never message content or corpus
9
+ * rows (EVAL-REDACT-002).
10
+ *
11
+ * PREVENT-PI-004: type definitions only, no network code.
12
+ * PREVENT-011: no `any` type — all types are explicit.
13
+ */
14
+ export {};
@@ -54,4 +54,17 @@ export const EXTRA_ENDPOINTS = {
54
54
  path: "/api/prefix-stability",
55
55
  description: "Per-turn prompt-cache stable-prefix ratio trend (GET /api/prefix-stability?limit=N) read from prefix_stability rows in the local events log. Flag-off (MEGACOMPACT_PC_C=0) returns 404.",
56
56
  },
57
+ // ─── ML5-D Improve Cortex (dashboard Vector Cortex tab) ───────────
58
+ /** POST /api/cortex/improve — launch a local ML5-A training job. */
59
+ improveCortex: {
60
+ method: "POST",
61
+ path: "/api/cortex/improve",
62
+ description: "Launch a local ML5-A training job that re-qualifies the five heads against the latest local corpus and returns an opaque jobId. Requires confirm:true; flag-off returns 404. Local-only — never fetches anything.",
63
+ },
64
+ /** GET /api/cortex/improve/status/:jobId — poll an improve job. */
65
+ improveCortexStatus: {
66
+ method: "GET",
67
+ path: "/api/cortex/improve/status/:jobId",
68
+ description: "Poll an in-process Cortex improve job to terminal qualified / demoted_to_B. Unknown jobId or flag-off returns 404. Read-only, in-memory job state.",
69
+ },
57
70
  };
@@ -8,7 +8,7 @@
8
8
  * PREVENT-PI-004: local filesystem read only, no network.
9
9
  * PREVENT-011: no `any` type.
10
10
  */
11
- import { handleIndex, handleRepoIndex, handleEvents, handleGameState, handleGameScores, handlePerfSamples, handlePerf, handleAchievements, handleSessions, handleTopics, handleTurns, handleMaintenance, handleProviderCache, handleMemoryStatus, handleCacheStripes, handlePrefixStability, handleSetupStatus, handleSetupDetect, handleSetupConfigure, handleMemoryMap, handleRaptorTree, handleRaptorBuildHistory, handleContextHealth, handleCachePoison, handleHealthSettings, handleEmbedderHealth, handleRagSettings, handleRagMetrics, handleModelThresholds, handleWiki, handleVectorCortexEvaluation, handleVectorCortexHealth, handleVectorCortexBreakersReset, handleVectorCortexLedger, handleVectorCortexTopology, handleVectorCortexQuery, handleVectorCortexShards, handleVectorCortexResidual, handleVectorCortexReconstruct, handleVectorCortexPlans, handleVectorCortexRender, handleVectorCortexRollout, handleVectorCortexClosureProof, handleVectorCortexRestore, handleSetupCortexStatus, handleSetupCortexAction, handleSetupCortexActionLog, } from "./routes.js";
11
+ import { handleIndex, handleRepoIndex, handleEvents, handleGameState, handleGameScores, handlePerfSamples, handlePerf, handleAchievements, handleSessions, handleTopics, handleTurns, handleMaintenance, handleProviderCache, handleMemoryStatus, handleCacheStripes, handlePrefixStability, handleSetupStatus, handleSetupDetect, handleSetupConfigure, handleMemoryMap, handleRaptorTree, handleRaptorBuildHistory, handleContextHealth, handleCachePoison, handleHealthSettings, handleEmbedderHealth, handleRagSettings, handleRagMetrics, handleModelThresholds, handleWiki, handleVectorCortexEvaluation, handleVectorCortexHealth, handleVectorCortexBreakersReset, handleVectorCortexLedger, handleVectorCortexTopology, handleVectorCortexQuery, handleVectorCortexShards, handleVectorCortexResidual, handleVectorCortexReconstruct, handleVectorCortexPlans, handleVectorCortexRender, handleVectorCortexRollout, handleVectorCortexClosureProof, handleVectorCortexRestore, handleSetupCortexStatus, handleSetupCortexAction, handleSetupCortexActionLog, handleImproveCortex, handleImproveCortexStatus, } from "./routes.js";
12
12
  // VC6C repair lives in its own module (routes-vector-cortex-repair.ts) so the
13
13
  // heal route file stays well under the 400-line extension soft limit.
14
14
  import { handleVectorCortexRepair } from "./routes-vector-cortex-repair.js";
@@ -149,5 +149,9 @@ export function dispatchRoutes(req, res, ctx) {
149
149
  return true;
150
150
  if (handleSetupCortexActionLog(req, res, ctx))
151
151
  return true;
152
+ if (handleImproveCortex(req, res, ctx))
153
+ return true;
154
+ if (handleImproveCortexStatus(req, res, ctx))
155
+ return true;
152
156
  return false;
153
157
  }
@@ -0,0 +1,220 @@
1
+ /**
2
+ * dashboard-server/routes-cortex-improve.ts — ML5-D "Improve Cortex" job routes.
3
+ *
4
+ * POST /api/cortex/improve — confirmation-gated local ML5-A training
5
+ * GET /api/cortex/improve/status/:jobId — poll an in-process job to terminal
6
+ *
7
+ * The Improve action launches the committed ML5-A training pipeline
8
+ * (training/vector-cortex/train.py) as a background child_process against the
9
+ * latest local corpus, then re-qualifies the five heads. Job state is kept
10
+ * in-process in a Map<jobId, JobState> on this module; nothing is persisted
11
+ * across restarts (the status endpoint is read-only, in-memory).
12
+ *
13
+ * LOCAL ONLY (PREVENT-PI-004): the job spawns a local python process and reads
14
+ * local files — never a fetch. The `onnxruntime-node` native path is attempted
15
+ * only when MEGACOMPACT_ENCODER_NATIVE=1 (default OFF); otherwise the harness
16
+ * uses the WASM/trigram fallback. The status payload surfaces mode/verdict/
17
+ * digest/reason/progress only — never message or corpus content (EVAL-REDACT-002).
18
+ *
19
+ * Guardrails: PREVENT-011 (no `any`), PREVENT-001 (guarded JSON.parse via
20
+ * readJsonBody), flag-off byte-identical (no card + endpoints 404).
21
+ */
22
+ import { spawn } from "node:child_process";
23
+ import { createHash, randomBytes } from "node:crypto";
24
+ import { readFileSync, existsSync } from "node:fs";
25
+ import { join, dirname } from "node:path";
26
+ import { fileURLToPath } from "node:url";
27
+ import { sendJson, readJsonBody } from "./routes-vector-cortex-shared.js";
28
+ import { ML5D_ENABLED } from "../../src/config.js";
29
+ import { qualifyDecision } from "../../src/vector-cortex/improve.js";
30
+ /** Resolve the committed training entry by walking up to the repo root. */
31
+ function trainingScript() {
32
+ let dir = dirname(fileURLToPath(import.meta.url));
33
+ const rel = join("training", "vector-cortex", "train.py");
34
+ for (let i = 0; i < 8; i++) {
35
+ // guardrails-allow PREVENT-PI-004: local script read (loopback)
36
+ const candidate = join(dir, rel);
37
+ if (existsSync(candidate))
38
+ return candidate;
39
+ const next = dirname(dir);
40
+ if (next === dir)
41
+ break;
42
+ dir = next;
43
+ }
44
+ return null;
45
+ }
46
+ /** In-process job registry; nothing survives a server restart. */
47
+ const JOBS = new Map();
48
+ /** Opaque job token: sha256(ts+random) hex-sliced. */
49
+ function newJobId() {
50
+ return createHash("sha256")
51
+ .update(`${Date.now()}:${randomBytes(16).toString("hex")}`)
52
+ .digest("hex")
53
+ .slice(0, 24);
54
+ }
55
+ /**
56
+ * Spawn the ML5-A training pipeline in the background and drive the job state
57
+ * to a terminal qualified / demoted_to_B verdict. Honest: an empty corpus (the
58
+ * host state) makes train.py no-op and the job ends demoted_to_B.
59
+ */
60
+ function startJob(jobId) {
61
+ const script = trainingScript();
62
+ const boot = Date.now();
63
+ JOBS.set(jobId, { status: "improving", progress: 0, updatedAt: new Date().toISOString() });
64
+ if (script === null) {
65
+ settle(jobId, { status: "demoted_to_B", reason: "ENC_TRAIN_PIPELINE_ABSENT", progress: 1 });
66
+ return;
67
+ }
68
+ const env = { ...process.env };
69
+ const proc = spawn("python3", [script], {
70
+ env,
71
+ cwd: join(dirname(script), "..", ".."),
72
+ stdio: ["ignore", "pipe", "pipe"],
73
+ });
74
+ let output = "";
75
+ const step = () => {
76
+ const pct = Math.min(0.9, 0.1 + ((Date.now() - boot) / 60000) * 0.6);
77
+ const cur = JOBS.get(jobId);
78
+ if (cur && cur.status === "improving" && pct > cur.progress) {
79
+ JOBS.set(jobId, { ...cur, progress: pct, updatedAt: new Date().toISOString() });
80
+ }
81
+ };
82
+ const timer = setInterval(step, 2000);
83
+ const stop = () => clearInterval(timer);
84
+ proc.stdout?.on("data", (d) => {
85
+ output += d.toString();
86
+ });
87
+ proc.stderr?.on("data", (d) => {
88
+ output += d.toString();
89
+ });
90
+ proc.on("error", (err) => {
91
+ stop();
92
+ settle(jobId, {
93
+ status: "demoted_to_B",
94
+ reason: `ENC_TRAIN_SPAWN_FAILED:${err.message}`,
95
+ progress: 1,
96
+ });
97
+ });
98
+ proc.on("close", (code) => {
99
+ stop();
100
+ // Read the produced trained-heads artifact digest. The report line includes
101
+ // `trainedHeadsPath`; verify the file exists after a successful run.
102
+ const match = /trainedHeadsPath":\s*"([^"]+)"/.exec(output);
103
+ const assetPath = match?.[1];
104
+ let digest = null;
105
+ if (assetPath) {
106
+ // guardrails-allow PREVENT-PI-004: local artifact read (loopback)
107
+ try {
108
+ digest = createHash("sha256")
109
+ .update(readFileSync(assetPath))
110
+ .digest("hex")
111
+ .slice(0, 12);
112
+ }
113
+ catch {
114
+ digest = null;
115
+ }
116
+ }
117
+ const decision = qualifyDecision(code ?? -1, digest);
118
+ if (decision === "qualified") {
119
+ settle(jobId, {
120
+ status: "qualified",
121
+ progress: 1,
122
+ assetDigest: digest ?? undefined,
123
+ verdict: { mode: "A", assetDigestPrefix: digest ?? null, verdict: "qualified" },
124
+ });
125
+ }
126
+ else {
127
+ settle(jobId, {
128
+ status: "demoted_to_B",
129
+ reason: assetPath
130
+ ? "trained asset did not verify — demoted to mode B"
131
+ : "empty corpus (no groups) — no qualified asset emitted",
132
+ progress: 1,
133
+ });
134
+ }
135
+ });
136
+ }
137
+ /** Write a terminal job state (idempotent — only advances from improving). */
138
+ function settle(jobId, terminal) {
139
+ const cur = JOBS.get(jobId);
140
+ if (cur && cur.status !== "improving")
141
+ return;
142
+ JOBS.set(jobId, { ...terminal, updatedAt: new Date().toISOString() });
143
+ }
144
+ /** Flag-off response, byte-identical regardless of request (ML5-D absent). */
145
+ function sendDisabled(res) {
146
+ sendJson(res, 404, { error: "disabled" });
147
+ }
148
+ /**
149
+ * POST /api/cortex/improve (ML5-D). Returns true when it claims the request.
150
+ * Requires `confirm:true` server-side (mirrors the client window.confirm).
151
+ */
152
+ export function handleImproveCortex(req, res, _ctx) {
153
+ const url = req.url ?? "";
154
+ if (url !== "/api/cortex/improve")
155
+ return false;
156
+ if (req.method !== "POST") {
157
+ sendJson(res, 405, { error: "method_not_allowed" });
158
+ return true;
159
+ }
160
+ if (!ML5D_ENABLED()) {
161
+ sendDisabled(res);
162
+ return true;
163
+ }
164
+ readJsonBody(req, (parsed) => {
165
+ if (!parsed.ok) {
166
+ sendJson(res, 400, { error: "invalid_body" });
167
+ return;
168
+ }
169
+ if (parsed.value.confirm !== true) {
170
+ sendJson(res, 400, { error: "confirmation_required" });
171
+ return;
172
+ }
173
+ const jobId = newJobId();
174
+ startJob(jobId);
175
+ const body = { status: "improving", jobId };
176
+ sendJson(res, 200, body);
177
+ });
178
+ return true;
179
+ }
180
+ /**
181
+ * GET /api/cortex/improve/status/:jobId (ML5-D). Returns true when it claims the
182
+ * request. Flag-off or unknown jobId → 404. Read-only in-memory.
183
+ */
184
+ export function handleImproveCortexStatus(req, res, _ctx) {
185
+ const url = req.url ?? "";
186
+ const match = /^\/api\/cortex\/improve\/status\/([A-Za-z0-9]+)$/.exec(url);
187
+ if (!match)
188
+ return false;
189
+ if (req.method !== "GET") {
190
+ sendJson(res, 405, { error: "method_not_allowed" });
191
+ return true;
192
+ }
193
+ if (!ML5D_ENABLED()) {
194
+ sendDisabled(res);
195
+ return true;
196
+ }
197
+ const job = JOBS.get(match[1]);
198
+ if (!job) {
199
+ sendJson(res, 404, { error: "job_not_found" });
200
+ return true;
201
+ }
202
+ // Narrow job.status into the discriminated CortexImproveStatus variant. The
203
+ // terminal shapes require their payload fields, so construct per-state.
204
+ const body = job.status === "improving"
205
+ ? { status: "improving", progress: job.progress }
206
+ : job.status === "qualified"
207
+ ? {
208
+ status: "qualified",
209
+ progress: job.progress,
210
+ verdict: job.verdict ?? { mode: "A", assetDigestPrefix: null, verdict: "qualified" },
211
+ assetDigest: job.assetDigest ?? "",
212
+ }
213
+ : {
214
+ status: "demoted_to_B",
215
+ progress: job.progress,
216
+ reason: job.reason ?? "UNKNOWN_TERMINAL",
217
+ };
218
+ sendJson(res, 200, body);
219
+ return true;
220
+ }
@@ -55,5 +55,7 @@ export const VECTOR_CORTEX_SETTINGS = {
55
55
  boolDirect("MEGACOMPACT_PC_C", "PC-C Dashboard Cache Visibility", "Dashboard per-turn prompt-cache visibility: surfaces the per-turn stable-prefix ratio trend (GET /api/prefix-stability) in the CacheTab PrefixStabilityCard. Reads aggregate ratios/counts from the local monitoring events log only — no payload bytes. OFF = byte-identical predecessor (PC-B-era): /api/prefix-stability returns 404 and the CacheTab omits the PrefixStabilityCard.", true),
56
56
  boolDirect("MEGACOMPACT_ML5_A", "ML5-A Five-Head Training Load", "ML5-A real trained-head loading: loadHeadProjections (trained-heads-v1) feeds selectQualifiedEncoder (trainedHeadsPath atomic demotion) + loadCalibrationV1. ON (default) = a pinned trained-heads path must load for mode A. OFF = loaders return null and selection ignores trainedHeadsPath — byte-identical to the placeholder-weighted VC2C path.", true),
57
57
  boolDirect("MEGACOMPACT_ML5_C", "ML5-C Runtime Decision + Packaging", "ML5-C runtime backend selection (WASM vs native): selects the ONNX runtime backend based on the ML5-B bench record and platform support. ON (default) = the runtime-selection dispatch runs and emits vector_cortex_runtime_selected. OFF = no selection runs — encoder serves mode B trigram, byte-identical to ML5-B.", true),
58
+ boolDirect("MEGACOMPACT_ML5_D", "ML5-D Dashboard Improve Cortex", "ML5-D dashboard 'Improve Cortex' surface: the ModelImprovementCard + POST /api/cortex/improve + GET /api/cortex/improve/status/:jobId. ON (default) = the card renders and Improve launches a local ML5-A training job. OFF = both improve endpoints return 404 and VectorCortexTab omits the card, byte-identical to ML5-C.", true),
59
+ boolDirect("MEGACOMPACT_ML5_E", "ML5-E Nightly Retraining Cron", "ML5-E nightly retraining + feedback loop: the user's own post-redaction conversation turns become fresh training signal, the five heads are re-fit nightly via system cron, calibration is re-validated, and mode-A promotion is re-checked without human intervention. The cron is system-configured (crontab -e); the extension never installs or writes a crontab. Candidates are written to ~/.pi/mega-compact-encoder/candidates/ and promoted via the ML5-D Improve Cortex flow. ON (default) = the scripts may be invoked by the system cron. OFF = scripts are never invoked; byte-identical to ML5-D.", true),
58
60
  ],
59
61
  };
@@ -27,3 +27,4 @@ export { handleWiki } from "./routes-wiki.js";
27
27
  export { handleVectorCortexEvaluation, handleVectorCortexHealth, handleVectorCortexBreakersReset, handleVectorCortexLedger, handleVectorCortexTopology, handleVectorCortexQuery, handleVectorCortexShards, handleVectorCortexResidual, handleVectorCortexReconstruct, handleVectorCortexPlans, handleVectorCortexRender, handleVectorCortexRollout, handleVectorCortexClosureProof, handleVectorCortexRestore, } from "./routes-vector-cortex.js";
28
28
  export { handleSetupCortexStatus } from "./routes-setup-cortex.js";
29
29
  export { handleSetupCortexAction, handleSetupCortexActionLog, } from "./routes-setup-cortex-actions.js";
30
+ export { handleImproveCortex, handleImproveCortexStatus, } from "./routes-cortex-improve.js";
@@ -97,8 +97,8 @@ export function buildDashboardSnapshot(ctx) {
97
97
  // per-session in rt and there's no cumulative counter yet.
98
98
  total: ctx.repo.dedupCollapsed,
99
99
  sessionTokensSaved: ctx.rt.cacheHitTokens,
100
- // Cumulative tokens saved across all sessions in this repo
101
- // was a placeholder (dedupCollapsed * 100).
100
+ // Cumulative tokens saved across all sessions in this repo = the
101
+ // real repo counter (audit Table 1 stub 8 closed — no rolled-up math).
102
102
  totalTokensSaved: ctx.repo.tokensSaved,
103
103
  },
104
104
  compacts: {
@@ -0,0 +1,28 @@
1
+ /**
2
+ * config/vector-cortex-ml5d.ts — ML5-D dashboard "Improve Cortex" flag.
3
+ *
4
+ * Sibling extract mirroring vector-cortex-ml5a.ts / vector-cortex-ml5b.ts /
5
+ * vector-cortex-ml5c.ts, so vector-cortex.ts stays under its 300-line soft
6
+ * limit (soft-as-hard gate). This is the dashboard "Improve Cortex" surface +
7
+ * promote workflow sprint flag.
8
+ * vector-cortex.ts re-exports the ENUM below and root src/config.ts re-exports
9
+ * it, so no consumer import path changes.
10
+ *
11
+ * ML5-D adds the dashboard ModelImprovementCard + the POST /api/cortex/improve
12
+ * and GET /api/cortex/improve/status/:jobId endpoints. The flag gates that
13
+ * surface only; when OFF the endpoints return 404/disabled and VectorCortexTab
14
+ * renders exactly as before (byte-identical to the ML5-C-era tab — no
15
+ * ModelImprovementCard, no improve job is ever spawned).
16
+ *
17
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
18
+ */
19
+ import { sprintFlag } from "./vector-cortex-flag.js";
20
+ /**
21
+ * ML5-D — dashboard "Improve Cortex" surface + promote workflow. Default ON.
22
+ * `MEGACOMPACT_ML5_D=0` disables and is byte-identical to the ML5-C survivor:
23
+ * both `/api/cortex/improve*` endpoints return 404 and VectorCortexTab omits the
24
+ * ModelImprovementCard. The flag gates the dashboard surface only; it does not
25
+ * gate the underlying ML5-A training pipeline or the encoder's mode-A/B/C
26
+ * selection (those are governed by ML5-A and the encoder independently).
27
+ */
28
+ export const ML5D_ENABLED = () => sprintFlag("MEGACOMPACT_ML5_D");
@@ -0,0 +1,30 @@
1
+ /**
2
+ * config/vector-cortex-ml5e.ts — ML5-E nightly retraining cron + feedback loop.
3
+ *
4
+ * Sibling extract mirroring vector-cortex-ml5a.ts / ml5b.ts / ml5c.ts / ml5d.ts,
5
+ * so vector-cortex.ts stays under its 300-line soft limit (soft-as-hard gate).
6
+ * vector-cortex.ts re-exports the ENUM below and root src/config.ts re-exports
7
+ * it, so no consumer import path changes.
8
+ *
9
+ * ML5-E turns one-shot training (ML5-D's Improve button) into a living loop:
10
+ * the user's own post-redaction conversation turns become fresh training signal,
11
+ * the five heads are re-fit nightly, calibration is re-validated, and mode-A
12
+ * promotion is re-checked without human intervention. The cron is system-
13
+ * configured (`crontab -e` on the operator device); the extension never installs
14
+ * or writes a crontab. The flag gates **invocation** only — the scripts
15
+ * (retrain-nightly.mjs, promotion-gate.mjs, promotion.ts) exist on disk
16
+ * regardless; `=0` means the runtime never invokes them and the dashboard's
17
+ * Improve Cortex flow is byte-identical to the ML5-D survivor.
18
+ *
19
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
20
+ */
21
+ import { sprintFlag } from "./vector-cortex-flag.js";
22
+ /**
23
+ * ML5-E — nightly retraining cron + feedback loop. Default ON.
24
+ * `MEGACOMPACT_ML5_E=0` disables and is byte-identical to the ML5-D survivor:
25
+ * the nightly retraining scripts are never invoked by the runtime, the
26
+ * promotion gate is inert, and the dashboard's Improve Cortex flow is
27
+ * byte-identical to the ML5-D tab. The flag gates invocation only — the scripts
28
+ * exist on disk regardless.
29
+ */
30
+ export const ML5E_ENABLED = () => sprintFlag("MEGACOMPACT_ML5_E");
@@ -9,9 +9,8 @@
9
9
  * them without re-declaring the ownership boundary. Pi-agnostic, dependency-free.
10
10
  */
11
11
  import { sprintFlag } from "./vector-cortex-flag.js";
12
- // VC0/VC1/VC2 foundation-phase flags extracted to vector-cortex-early.ts to keep
13
- // this file under the 300-line soft limit. Re-exported here so every existing
14
- // `from "./config/vector-cortex.js"` import keeps resolving unchanged.
12
+ // VC0/VC1/VC2 foundation-phase flags in vector-cortex-early.ts; re-exported
13
+ // so every existing `from "./config/vector-cortex.js"` import resolves unchanged.
15
14
  export { VC0A_ENABLED, VC0B_ENABLED, VC0C_ENABLED, VC1A_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, } from "./vector-cortex-early.js";
16
15
  /**
17
16
  * VC3A — capability-gated cortex store (CortexReader/Writer/Admin, CortexRecordV1).
@@ -239,10 +238,9 @@ export const VC8A_ENABLED = () => sprintFlag("MEGACOMPACT_VC8A");
239
238
  * mirroring VC4A..VC8A.
240
239
  */
241
240
  export const VC8B_ENABLED = () => sprintFlag("MEGACOMPACT_VC8B");
242
- // VC8C (canary selection + Rust parity) extracted to vector-cortex-vc8c.ts;
243
- // re-exported so existing `./config/vector-cortex.js` imports keep resolving.
241
+ // VC8C extracted to vector-cortex-vc8c.ts; re-exported so existing imports keep resolving.
244
242
  export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
245
- // Sibling extracts to stay under the 300-line soft limit.
243
+ // Sibling extracts: stay under the 300-line soft limit.
246
244
  export { VC9A_ENABLED } from "./vector-cortex-vc9a.js";
247
245
  export { VC9B_ENABLED } from "./vector-cortex-vc9b.js";
248
246
  export { VC9C_ENABLED } from "./vector-cortex-vc9c.js";
@@ -251,5 +249,7 @@ export { PCC_ENABLED } from "./vector-cortex-pcc.js";
251
249
  export { ML5A_ENABLED } from "./vector-cortex-ml5a.js";
252
250
  export { ML5B_ENABLED } from "./vector-cortex-ml5b.js";
253
251
  export { ML5C_ENABLED } from "./vector-cortex-ml5c.js";
252
+ export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
253
+ export { ML5E_ENABLED } from "./vector-cortex-ml5e.js";
254
254
  // Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
255
255
  export { BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./vector-cortex-breakers.js";
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
114
114
  // default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
115
115
  // so root consumers share one source of truth.
116
116
  // ---------------------------------------------------------------------------
117
- export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
117
+ export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
@@ -0,0 +1,58 @@
1
+ /**
2
+ * vector-cortex/encoder/promotion.ts — ML5-E PromotionV1 ledger row type +
3
+ * append-only manifest helper + atomic digest-swap rollback.
4
+ *
5
+ * Pure-function discipline: zero I/O, no clock, no storage, no network
6
+ * (PREVENT-PI-004 / PREVENT-011). Every function is total over its inputs.
7
+ * The cron orchestrator (scripts/ml5/retrain-nightly.mjs) and the promotion
8
+ * gate (scripts/ml5/promotion-gate.mjs) consume these helpers; the acceptance
9
+ * aggregator (ml5e-acceptance.test.ts) validates them synthetically without a
10
+ * real training run.
11
+ *
12
+ * The promotion manifest is an APPEND-ONLY ledger: every new asset is a new
13
+ * entry, never an overwrite. Rollback restores a prior entry by SHA-256 via
14
+ * an atomic digest swap (flip the committed pointer to the prior entry's
15
+ * digest in one step) — no partial state is possible because the swap is a
16
+ * single value assignment.
17
+ */
18
+ // ---------------------------------------------------------------------------
19
+ // PromotionV1 — the ledger row recording one nightly training + promotion run.
20
+ // ---------------------------------------------------------------------------
21
+ /** Schema tag for the promotion ledger row. */
22
+ export const PROMOTION_SCHEMA = "promotion-v1";
23
+ /** Append a new asset entry to the manifest. Never mutates `entries`;
24
+ * returns a new manifest with the entry appended and `committed` updated. */
25
+ export function appendAsset(manifest, entry) {
26
+ return {
27
+ entries: [...manifest.entries, entry],
28
+ committed: entry.assetDigest,
29
+ };
30
+ }
31
+ /** Restore a prior asset by SHA-256: atomically swap the committed pointer
32
+ * to the prior entry. The prior entry MUST exist in the manifest (append-only
33
+ * guarantees it was never overwritten). Returns null when the digest is not
34
+ * found (defensive: append-only means it should always be findable). */
35
+ export function rollbackTo(manifest, digest) {
36
+ const found = manifest.entries.find((e) => e.assetDigest === digest);
37
+ if (!found)
38
+ return null;
39
+ return {
40
+ entries: manifest.entries,
41
+ committed: found.assetDigest,
42
+ };
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Pure decision rules.
46
+ // ---------------------------------------------------------------------------
47
+ /** Evaluate the promotion gate: promote only when all five heads pass AND the
48
+ * new asset beats the committed asset on the held-out dev set. Otherwise
49
+ * demote. No training data is ever the held-out set. */
50
+ export function promoteDecision(fiveHeadsOk, heldOutBeat) {
51
+ return fiveHeadsOk && heldOutBeat ? "promoted" : "demoted";
52
+ }
53
+ /** Whether a rollback is needed: the current asset at position N regressed
54
+ * relative to the asset at position N-1. True only when regression is
55
+ * confirmed and a prior asset digest exists to restore. */
56
+ export function rollbackNeeded(regressionConfirmed, priorAssetDigest) {
57
+ return regressionConfirmed && priorAssetDigest !== null;
58
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * vector-cortex/improve.ts — ML5-D "Improve Cortex" pure decision rule.
3
+ *
4
+ * The single pure decision of the improve job harness: given the training
5
+ * process exit code and whether a readable produced-asset digest exists,
6
+ * decide whether the five heads qualify (promote) or are demoted to mode B.
7
+ *
8
+ * Lives under src/ so both the dashboard-server route (routes-cortex-improve.ts)
9
+ * and the ML5-D acceptance aggregator (dist/vector-cortex/ml5d-acceptance.test.js)
10
+ * can import it — the mirrored dist/vector-cortex/ subtree carries this file via
11
+ * the publish-acceptance copyTree, so the acceptance suite needs no real
12
+ * training run.
13
+ *
14
+ * Pure, total over its inputs, zero I/O (PREVENT-PI-004 / PREVENT-011).
15
+ */
16
+ /**
17
+ * Terminal decision for an improve job: qualified only when the training
18
+ * process exited 0 AND a readable produced-asset digest exists; otherwise the
19
+ * job is demoted to mode B (honest degradation — an empty corpus or a failed
20
+ * train never fabricates a promotion).
21
+ */
22
+ export function qualifyDecision(exitCode, assetDigest) {
23
+ return exitCode === 0 && assetDigest !== null ? "qualified" : "demoted_to_B";
24
+ }