@evomap/evolver-core 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/dist/algo/antiDistill.d.ts +35 -0
  2. package/dist/algo/antiDistill.js +167 -0
  3. package/dist/algo/bans.d.ts +6 -0
  4. package/dist/algo/bans.js +33 -0
  5. package/dist/algo/candidateAssembly.d.ts +65 -0
  6. package/dist/algo/candidateAssembly.js +196 -0
  7. package/dist/algo/capabilityCandidates.d.ts +38 -0
  8. package/dist/algo/capabilityCandidates.js +131 -0
  9. package/dist/algo/confidence.d.ts +106 -0
  10. package/dist/algo/confidence.js +196 -0
  11. package/dist/algo/cycleEngine.d.ts +143 -0
  12. package/dist/algo/cycleEngine.js +417 -0
  13. package/dist/algo/cycleFailureClassifier.d.ts +52 -0
  14. package/dist/algo/cycleFailureClassifier.js +104 -0
  15. package/dist/algo/epigenetics.d.ts +14 -0
  16. package/dist/algo/epigenetics.js +41 -0
  17. package/dist/algo/evolutionEvent.d.ts +23 -0
  18. package/dist/algo/evolutionEvent.js +24 -0
  19. package/dist/algo/exploration.d.ts +34 -0
  20. package/dist/algo/exploration.js +55 -0
  21. package/dist/algo/geneHealth.d.ts +24 -0
  22. package/dist/algo/geneHealth.js +16 -0
  23. package/dist/algo/geneIntake.d.ts +37 -0
  24. package/dist/algo/geneIntake.js +100 -0
  25. package/dist/algo/genePromotion.d.ts +48 -0
  26. package/dist/algo/genePromotion.js +53 -0
  27. package/dist/algo/geneSelection.d.ts +128 -0
  28. package/dist/algo/geneSelection.js +222 -0
  29. package/dist/algo/index.d.ts +18 -0
  30. package/dist/algo/index.js +18 -0
  31. package/dist/algo/mutation.d.ts +12 -0
  32. package/dist/algo/mutation.js +22 -0
  33. package/dist/algo/orchestrator.d.ts +65 -0
  34. package/dist/algo/orchestrator.js +63 -0
  35. package/dist/algo/solidify.d.ts +43 -0
  36. package/dist/algo/solidify.js +63 -0
  37. package/dist/algo/strategyPresets.d.ts +32 -0
  38. package/dist/algo/strategyPresets.js +61 -0
  39. package/dist/assetstore/index.d.ts +8 -0
  40. package/dist/assetstore/index.js +8 -0
  41. package/dist/assetstore/learningHistory.d.ts +25 -0
  42. package/dist/assetstore/learningHistory.js +38 -0
  43. package/dist/assetstore/localJsonl.d.ts +34 -0
  44. package/dist/assetstore/localJsonl.js +182 -0
  45. package/dist/assetstore/pendingSignals.d.ts +22 -0
  46. package/dist/assetstore/pendingSignals.js +171 -0
  47. package/dist/assetstore/provenance.d.ts +39 -0
  48. package/dist/assetstore/provenance.js +109 -0
  49. package/dist/assetstore/provider.d.ts +48 -0
  50. package/dist/assetstore/provider.js +36 -0
  51. package/dist/assetstore/remoteStub.d.ts +32 -0
  52. package/dist/assetstore/remoteStub.js +36 -0
  53. package/dist/assetstore/reviewFilter.d.ts +20 -0
  54. package/dist/assetstore/reviewFilter.js +44 -0
  55. package/dist/assetstore/reviewLedger.d.ts +55 -0
  56. package/dist/assetstore/reviewLedger.js +121 -0
  57. package/dist/benchmark/antiGeneBenchmark.d.ts +79 -0
  58. package/dist/benchmark/antiGeneBenchmark.js +241 -0
  59. package/dist/benchmark/antiGeneRollout.d.ts +80 -0
  60. package/dist/benchmark/antiGeneRollout.js +256 -0
  61. package/dist/benchmark/benchmark.d.ts +32 -0
  62. package/dist/benchmark/benchmark.js +26 -0
  63. package/dist/benchmark/evolutionThesisSolver.d.ts +25 -0
  64. package/dist/benchmark/evolutionThesisSolver.js +41 -0
  65. package/dist/benchmark/index.d.ts +5 -0
  66. package/dist/benchmark/index.js +5 -0
  67. package/dist/benchmark/thesis.d.ts +85 -0
  68. package/dist/benchmark/thesis.js +150 -0
  69. package/dist/bootstrap/envFingerprint.d.ts +45 -0
  70. package/dist/bootstrap/envFingerprint.js +72 -0
  71. package/dist/bootstrap/index.d.ts +2 -0
  72. package/dist/bootstrap/index.js +2 -0
  73. package/dist/bootstrap/selfEvolve.d.ts +36 -0
  74. package/dist/bootstrap/selfEvolve.js +26 -0
  75. package/dist/cycle/cycleTimeline.d.ts +35 -0
  76. package/dist/cycle/cycleTimeline.js +74 -0
  77. package/dist/cycle/index.d.ts +2 -0
  78. package/dist/cycle/index.js +2 -0
  79. package/dist/cycle/stateMachine.d.ts +6 -0
  80. package/dist/cycle/stateMachine.js +25 -0
  81. package/dist/daemon/cycleContext.d.ts +12 -0
  82. package/dist/daemon/cycleContext.js +13 -0
  83. package/dist/daemon/drain.d.ts +11 -0
  84. package/dist/daemon/drain.js +16 -0
  85. package/dist/daemon/guards.d.ts +87 -0
  86. package/dist/daemon/guards.js +142 -0
  87. package/dist/daemon/idempotency.d.ts +11 -0
  88. package/dist/daemon/idempotency.js +36 -0
  89. package/dist/daemon/idleScheduler.d.ts +55 -0
  90. package/dist/daemon/idleScheduler.js +181 -0
  91. package/dist/daemon/index.d.ts +8 -0
  92. package/dist/daemon/index.js +8 -0
  93. package/dist/daemon/stepRunner.d.ts +12 -0
  94. package/dist/daemon/stepRunner.js +31 -0
  95. package/dist/daemon/unhandledRejectionWindow.d.ts +21 -0
  96. package/dist/daemon/unhandledRejectionWindow.js +52 -0
  97. package/dist/daemon/watchdog.d.ts +11 -0
  98. package/dist/daemon/watchdog.js +14 -0
  99. package/dist/events/eventSchema.d.ts +132 -0
  100. package/dist/events/eventSchema.js +30 -0
  101. package/dist/events/eventStore.d.ts +32 -0
  102. package/dist/events/eventStore.js +137 -0
  103. package/dist/events/ingest.d.ts +34 -0
  104. package/dist/events/ingest.js +61 -0
  105. package/dist/events/paths.d.ts +22 -0
  106. package/dist/events/paths.js +44 -0
  107. package/dist/events/projectors.d.ts +9 -0
  108. package/dist/events/projectors.js +11 -0
  109. package/dist/events/public.d.ts +14 -0
  110. package/dist/events/public.js +8 -0
  111. package/dist/events/replayer.d.ts +26 -0
  112. package/dist/events/replayer.js +67 -0
  113. package/dist/events/reports.d.ts +90 -0
  114. package/dist/events/reports.js +244 -0
  115. package/dist/events/retention.d.ts +70 -0
  116. package/dist/events/retention.js +177 -0
  117. package/dist/events/sink.d.ts +5 -0
  118. package/dist/events/sink.js +1 -0
  119. package/dist/exec/autoExec.d.ts +137 -0
  120. package/dist/exec/autoExec.js +221 -0
  121. package/dist/exec/autonomousCycle.d.ts +48 -0
  122. package/dist/exec/autonomousCycle.js +78 -0
  123. package/dist/exec/claudeBridge.d.ts +112 -0
  124. package/dist/exec/claudeBridge.js +219 -0
  125. package/dist/exec/index.d.ts +9 -0
  126. package/dist/exec/index.js +11 -0
  127. package/dist/exec/openPrRegistry.d.ts +60 -0
  128. package/dist/exec/openPrRegistry.js +130 -0
  129. package/dist/exec/policy/blastRadius.d.ts +31 -0
  130. package/dist/exec/policy/blastRadius.js +67 -0
  131. package/dist/exec/policy/constraints.d.ts +26 -0
  132. package/dist/exec/policy/constraints.js +62 -0
  133. package/dist/exec/policy/destructive.d.ts +45 -0
  134. package/dist/exec/policy/destructive.js +108 -0
  135. package/dist/exec/policy/failureMode.d.ts +33 -0
  136. package/dist/exec/policy/failureMode.js +49 -0
  137. package/dist/exec/policy/index.d.ts +24 -0
  138. package/dist/exec/policy/index.js +30 -0
  139. package/dist/exec/policy/protectedPaths.d.ts +17 -0
  140. package/dist/exec/policy/protectedPaths.js +65 -0
  141. package/dist/exec/policyCheck.d.ts +2 -0
  142. package/dist/exec/policyCheck.js +7 -0
  143. package/dist/exec/prompt.d.ts +34 -0
  144. package/dist/exec/prompt.js +108 -0
  145. package/dist/exec/proofOfWork.d.ts +9 -0
  146. package/dist/exec/proofOfWork.js +11 -0
  147. package/dist/exec/runnerRegistry.d.ts +123 -0
  148. package/dist/exec/runnerRegistry.js +237 -0
  149. package/dist/exec/selfPr.d.ts +83 -0
  150. package/dist/exec/selfPr.js +104 -0
  151. package/dist/exec/selfPrObfuscation.d.ts +21 -0
  152. package/dist/exec/selfPrObfuscation.js +85 -0
  153. package/dist/hooks/hooks.d.ts +117 -0
  154. package/dist/hooks/hooks.js +89 -0
  155. package/dist/hooks/index.d.ts +1 -0
  156. package/dist/hooks/index.js +1 -0
  157. package/dist/hub/assetCallLog.d.ts +43 -0
  158. package/dist/hub/assetCallLog.js +72 -0
  159. package/dist/hub/bindings.d.ts +28 -0
  160. package/dist/hub/bindings.js +90 -0
  161. package/dist/hub/capability.d.ts +278 -0
  162. package/dist/hub/capability.js +1 -0
  163. package/dist/hub/conversationDistiller.d.ts +88 -0
  164. package/dist/hub/conversationDistiller.js +264 -0
  165. package/dist/hub/fake.d.ts +45 -0
  166. package/dist/hub/fake.js +69 -0
  167. package/dist/hub/hubReview.d.ts +91 -0
  168. package/dist/hub/hubReview.js +106 -0
  169. package/dist/hub/index.d.ts +10 -0
  170. package/dist/hub/index.js +10 -0
  171. package/dist/hub/ingest.d.ts +15 -0
  172. package/dist/hub/ingest.js +15 -0
  173. package/dist/hub/questionGenerator.d.ts +59 -0
  174. package/dist/hub/questionGenerator.js +406 -0
  175. package/dist/hub/reuseDecision.d.ts +87 -0
  176. package/dist/hub/reuseDecision.js +127 -0
  177. package/dist/hub/sanitize.d.ts +52 -0
  178. package/dist/hub/sanitize.js +321 -0
  179. package/dist/index.d.ts +27 -0
  180. package/dist/index.js +27 -0
  181. package/dist/mailbox/catalog.d.ts +17 -0
  182. package/dist/mailbox/catalog.js +53 -0
  183. package/dist/mailbox/daemon.d.ts +48 -0
  184. package/dist/mailbox/daemon.js +61 -0
  185. package/dist/mailbox/dispatch.d.ts +46 -0
  186. package/dist/mailbox/dispatch.js +62 -0
  187. package/dist/mailbox/envelope.d.ts +43 -0
  188. package/dist/mailbox/envelope.js +52 -0
  189. package/dist/mailbox/index.d.ts +8 -0
  190. package/dist/mailbox/index.js +8 -0
  191. package/dist/mailbox/ipcServer.d.ts +46 -0
  192. package/dist/mailbox/ipcServer.js +168 -0
  193. package/dist/mailbox/requestReply.d.ts +40 -0
  194. package/dist/mailbox/requestReply.js +77 -0
  195. package/dist/mailbox/store.d.ts +74 -0
  196. package/dist/mailbox/store.js +308 -0
  197. package/dist/mailbox/wake.d.ts +45 -0
  198. package/dist/mailbox/wake.js +60 -0
  199. package/dist/material/boundary.d.ts +7 -0
  200. package/dist/material/boundary.js +14 -0
  201. package/dist/material/consumer.d.ts +21 -0
  202. package/dist/material/consumer.js +52 -0
  203. package/dist/material/emit.d.ts +55 -0
  204. package/dist/material/emit.js +52 -0
  205. package/dist/material/factory.d.ts +27 -0
  206. package/dist/material/factory.js +25 -0
  207. package/dist/material/index.d.ts +8 -0
  208. package/dist/material/index.js +8 -0
  209. package/dist/material/materialStore.d.ts +24 -0
  210. package/dist/material/materialStore.js +76 -0
  211. package/dist/material/sampling.d.ts +21 -0
  212. package/dist/material/sampling.js +39 -0
  213. package/dist/material/sources.d.ts +25 -0
  214. package/dist/material/sources.js +33 -0
  215. package/dist/material/watermark.d.ts +21 -0
  216. package/dist/material/watermark.js +76 -0
  217. package/dist/observers/cursorRewriteObserver.d.ts +46 -0
  218. package/dist/observers/cursorRewriteObserver.js +103 -0
  219. package/dist/observers/distillObserver.d.ts +31 -0
  220. package/dist/observers/distillObserver.js +93 -0
  221. package/dist/observers/index.d.ts +5 -0
  222. package/dist/observers/index.js +5 -0
  223. package/dist/observers/observerBus.d.ts +44 -0
  224. package/dist/observers/observerBus.js +73 -0
  225. package/dist/observers/reflectionObserver.d.ts +31 -0
  226. package/dist/observers/reflectionObserver.js +124 -0
  227. package/dist/observers/valueDigestObserver.d.ts +50 -0
  228. package/dist/observers/valueDigestObserver.js +70 -0
  229. package/dist/ops/cleanup.d.ts +23 -0
  230. package/dist/ops/cleanup.js +68 -0
  231. package/dist/ops/health.d.ts +37 -0
  232. package/dist/ops/health.js +96 -0
  233. package/dist/ops/index.d.ts +7 -0
  234. package/dist/ops/index.js +7 -0
  235. package/dist/ops/recall.d.ts +65 -0
  236. package/dist/ops/recall.js +152 -0
  237. package/dist/ops/reuseOutcomes.d.ts +68 -0
  238. package/dist/ops/reuseOutcomes.js +126 -0
  239. package/dist/ops/savingsCore.d.ts +47 -0
  240. package/dist/ops/savingsCore.js +112 -0
  241. package/dist/ops/selfUpdate.d.ts +106 -0
  242. package/dist/ops/selfUpdate.js +294 -0
  243. package/dist/ops/valueLedger.d.ts +205 -0
  244. package/dist/ops/valueLedger.js +238 -0
  245. package/dist/ops/valueOutreach.d.ts +70 -0
  246. package/dist/ops/valueOutreach.js +244 -0
  247. package/dist/personality/drift.d.ts +45 -0
  248. package/dist/personality/drift.js +106 -0
  249. package/dist/personality/events.d.ts +25 -0
  250. package/dist/personality/events.js +37 -0
  251. package/dist/personality/evolveOps.d.ts +20 -0
  252. package/dist/personality/evolveOps.js +93 -0
  253. package/dist/personality/index.d.ts +11 -0
  254. package/dist/personality/index.js +11 -0
  255. package/dist/personality/mutate.d.ts +21 -0
  256. package/dist/personality/mutate.js +39 -0
  257. package/dist/personality/pivot.d.ts +23 -0
  258. package/dist/personality/pivot.js +22 -0
  259. package/dist/personality/prompt.d.ts +6 -0
  260. package/dist/personality/prompt.js +62 -0
  261. package/dist/personality/riskGate.d.ts +42 -0
  262. package/dist/personality/riskGate.js +80 -0
  263. package/dist/personality/schema.d.ts +255 -0
  264. package/dist/personality/schema.js +119 -0
  265. package/dist/personality/select.d.ts +46 -0
  266. package/dist/personality/select.js +71 -0
  267. package/dist/personality/stats.d.ts +46 -0
  268. package/dist/personality/stats.js +82 -0
  269. package/dist/personality/store.d.ts +35 -0
  270. package/dist/personality/store.js +92 -0
  271. package/dist/schema/common.d.ts +28 -0
  272. package/dist/schema/common.js +17 -0
  273. package/dist/schema/index.d.ts +5 -0
  274. package/dist/schema/index.js +5 -0
  275. package/dist/schema/material.d.ts +201 -0
  276. package/dist/schema/material.js +50 -0
  277. package/dist/schema/problem.d.ts +160 -0
  278. package/dist/schema/problem.js +45 -0
  279. package/dist/schema/proofOfWork.d.ts +97 -0
  280. package/dist/schema/proofOfWork.js +9 -0
  281. package/dist/schema/signal.d.ts +41 -0
  282. package/dist/schema/signal.js +19 -0
  283. package/dist/shadow/index.d.ts +6 -0
  284. package/dist/shadow/index.js +6 -0
  285. package/dist/shadow/jsonlSink.d.ts +17 -0
  286. package/dist/shadow/jsonlSink.js +27 -0
  287. package/dist/shadow/redact.d.ts +11 -0
  288. package/dist/shadow/redact.js +18 -0
  289. package/dist/shadow/shadowHub.d.ts +12 -0
  290. package/dist/shadow/shadowHub.js +42 -0
  291. package/dist/shadow/shadowMailbox.d.ts +17 -0
  292. package/dist/shadow/shadowMailbox.js +25 -0
  293. package/dist/shadow/shadowStore.d.ts +18 -0
  294. package/dist/shadow/shadowStore.js +55 -0
  295. package/dist/shadow/sink.d.ts +37 -0
  296. package/dist/shadow/sink.js +18 -0
  297. package/dist/signals/cycleHistoryFromEvents.d.ts +11 -0
  298. package/dist/signals/cycleHistoryFromEvents.js +96 -0
  299. package/dist/signals/expand.d.ts +34 -0
  300. package/dist/signals/expand.js +125 -0
  301. package/dist/signals/extractor.d.ts +25 -0
  302. package/dist/signals/extractor.js +57 -0
  303. package/dist/signals/index.d.ts +6 -0
  304. package/dist/signals/index.js +6 -0
  305. package/dist/signals/metaSignals.d.ts +57 -0
  306. package/dist/signals/metaSignals.js +158 -0
  307. package/dist/signals/signalGate.d.ts +15 -0
  308. package/dist/signals/signalGate.js +40 -0
  309. package/dist/signals/traceSignals.d.ts +44 -0
  310. package/dist/signals/traceSignals.js +123 -0
  311. package/dist/signatures/classifier.d.ts +16 -0
  312. package/dist/signatures/classifier.js +29 -0
  313. package/dist/signatures/index.d.ts +2 -0
  314. package/dist/signatures/index.js +2 -0
  315. package/dist/signatures/signatures.d.ts +22 -0
  316. package/dist/signatures/signatures.js +42 -0
  317. package/dist/strategy/experiment.d.ts +48 -0
  318. package/dist/strategy/experiment.js +63 -0
  319. package/dist/strategy/index.d.ts +2 -0
  320. package/dist/strategy/index.js +2 -0
  321. package/dist/strategy/strategyPoint.d.ts +30 -0
  322. package/dist/strategy/strategyPoint.js +23 -0
  323. package/dist/trace/index.d.ts +2 -0
  324. package/dist/trace/index.js +2 -0
  325. package/dist/trace/trajectory.d.ts +82 -0
  326. package/dist/trace/trajectory.js +117 -0
  327. package/dist/trace/trajectoryExport.d.ts +237 -0
  328. package/dist/trace/trajectoryExport.js +1818 -0
  329. package/dist/trigger/budget.d.ts +16 -0
  330. package/dist/trigger/budget.js +20 -0
  331. package/dist/trigger/engine.d.ts +12 -0
  332. package/dist/trigger/engine.js +23 -0
  333. package/dist/trigger/index.d.ts +6 -0
  334. package/dist/trigger/index.js +6 -0
  335. package/dist/trigger/problemBuilder.d.ts +24 -0
  336. package/dist/trigger/problemBuilder.js +32 -0
  337. package/dist/trigger/trigger.d.ts +22 -0
  338. package/dist/trigger/trigger.js +27 -0
  339. package/dist/trigger/valueModel.d.ts +26 -0
  340. package/dist/trigger/valueModel.js +25 -0
  341. package/dist/trigger/wfq.d.ts +13 -0
  342. package/dist/trigger/wfq.js +25 -0
  343. package/dist/util/fileLock.d.ts +24 -0
  344. package/dist/util/fileLock.js +227 -0
  345. package/dist/util/index.d.ts +2 -0
  346. package/dist/util/index.js +2 -0
  347. package/dist/util/version.d.ts +12 -0
  348. package/dist/util/version.js +51 -0
  349. package/dist/verify/index.d.ts +4 -0
  350. package/dist/verify/index.js +4 -0
  351. package/dist/verify/rollback.d.ts +22 -0
  352. package/dist/verify/rollback.js +33 -0
  353. package/dist/verify/sandboxRunner.d.ts +39 -0
  354. package/dist/verify/sandboxRunner.js +116 -0
  355. package/dist/verify/sandboxedValidation.d.ts +35 -0
  356. package/dist/verify/sandboxedValidation.js +56 -0
  357. package/dist/verify/validation.d.ts +41 -0
  358. package/dist/verify/validation.js +85 -0
  359. package/dist/wire/canonicalize.golden.d.ts +23 -0
  360. package/dist/wire/canonicalize.golden.js +46 -0
  361. package/dist/wire/geneHints.d.ts +64 -0
  362. package/dist/wire/geneHints.js +100 -0
  363. package/dist/wire/index.d.ts +91 -0
  364. package/dist/wire/index.js +3 -0
  365. package/dist/wire/schemaGate.d.ts +11 -0
  366. package/dist/wire/schemaGate.js +49 -0
  367. package/dist/workflow/dsl.d.ts +54 -0
  368. package/dist/workflow/dsl.js +15 -0
  369. package/dist/workflow/engine.d.ts +30 -0
  370. package/dist/workflow/engine.js +94 -0
  371. package/dist/workflow/index.d.ts +2 -0
  372. package/dist/workflow/index.js +2 -0
  373. package/package.json +29 -0
@@ -0,0 +1,106 @@
1
+ import { type KeyObject } from 'node:crypto';
2
+ export interface ParsedVersion {
3
+ major: number;
4
+ minor: number;
5
+ patch: number;
6
+ }
7
+ export interface NormalizedSelfUpdateVersion {
8
+ ok: true;
9
+ version: string;
10
+ }
11
+ export interface InvalidSelfUpdateVersion {
12
+ ok: false;
13
+ reason: string;
14
+ }
15
+ export type SelfUpdateVersionResult = NormalizedSelfUpdateVersion | InvalidSelfUpdateVersion;
16
+ export declare const SELF_UPDATE_VERSION_MAX = 32;
17
+ /** Parse a version under the self-update contract. Invalid strings default to 0.0.0 for this legacy helper. */
18
+ export declare function parseVersion(v: string | null | undefined): ParsedVersion;
19
+ /** -1 if a<b, 0 if equal, 1 if a>b (SemVer precedence; build metadata ignored). */
20
+ export declare function compareVersions(a: string | null | undefined, b: string | null | undefined): -1 | 0 | 1;
21
+ /** True if `current` >= `required` (faithful to v1 isAtLeast: equal counts as satisfied). */
22
+ export declare function isAtLeast(current: string | null | undefined, required: string | null | undefined): boolean;
23
+ export declare function normalizeSelfUpdateVersion(value: unknown, field?: string): SelfUpdateVersionResult;
24
+ export declare function requireSelfUpdateVersion(value: unknown, field?: string): string;
25
+ /** Normalize a concrete semver value under the self-update contract. */
26
+ export declare function normalizeConcreteVersion(value: unknown): string | undefined;
27
+ /** Normalize the hub's required_version floor. Mirrors v1 forceUpdate.js strip + validate behavior. */
28
+ export declare function normalizeRequiredVersion(value: unknown): string | undefined;
29
+ export declare function compareConcreteVersions(left: string, right: string): -1 | 0 | 1 | null;
30
+ export declare function currentSatisfiesRequiredVersion(current: unknown, required: unknown): boolean;
31
+ /** One downloadable artifact the release pipeline must publish a hash for. */
32
+ export interface UpdateArtifact {
33
+ /** Path/name of the artifact relative to the package root (e.g. `dist/evolver.tar.gz`). */
34
+ path: string;
35
+ /** Lowercase hex sha256 the release pipeline computed for this artifact. */
36
+ sha256: string;
37
+ }
38
+ /**
39
+ * The release manifest the hub points the node at. The release-CI side publishes this alongside the GitHub
40
+ * Release. `signature` + `signatureAlg` are OPTIONAL on the wire but REQUIRED to pass when a public key is
41
+ * configured on the node (fail-closed). The signature is over the canonical JSON of {version, artifacts}.
42
+ */
43
+ export interface UpdateManifest {
44
+ /** The version this manifest publishes (e.g. `1.4.0`). */
45
+ version: string;
46
+ /** Per-artifact sha256 list — MUST be non-empty (nothing to verify = nothing to trust). */
47
+ artifacts: readonly UpdateArtifact[];
48
+ /** base64 Ed25519 signature over canonicalManifestBytes({version, artifacts}). Optional on wire. */
49
+ signature?: string;
50
+ /** Signature algorithm tag; only 'ed25519' is accepted. */
51
+ signatureAlg?: string;
52
+ }
53
+ export type UpdateAction = 'proceed' | 'noop' | 'reject';
54
+ export interface UpdateDecision {
55
+ action: UpdateAction;
56
+ reason: string;
57
+ targetVersion?: string;
58
+ }
59
+ /**
60
+ * Decide whether to apply an update. PURE. Fail-closed: a missing/malformed manifest, or a target that does not
61
+ * advance past `current`, never proceeds.
62
+ * - reject : manifest missing/malformed, or required target not satisfiable by the manifest version.
63
+ * - noop : current already satisfies the requested target (no restart needed) — v1's NOOP branch.
64
+ * - proceed: manifest is valid AND advances current. Caller must STILL verifyManifest before applying.
65
+ *
66
+ * `required` is the hub's force_update `required_version` (what the hub demands). `manifest.version` is what the
67
+ * download would deliver. We refuse if the manifest can't actually satisfy the requirement.
68
+ */
69
+ export declare function decideUpdate(input: {
70
+ current: string;
71
+ required?: string;
72
+ manifest: unknown;
73
+ }): UpdateDecision;
74
+ /** sha256 hex of the given bytes — the digest each downloaded artifact is checked against. */
75
+ export declare function sha256Hex(bytes: Uint8Array): string;
76
+ /**
77
+ * Canonical bytes the signature is computed over: a deterministic JSON of {version, artifacts:[{path,sha256}]}
78
+ * with artifacts sorted by path and sha256 lowercased, so signer and verifier agree byte-for-byte regardless of
79
+ * key order or casing. The release pipeline MUST sign exactly these bytes.
80
+ */
81
+ export declare function canonicalManifestBytes(manifest: Pick<UpdateManifest, 'version' | 'artifacts'>): Uint8Array;
82
+ export interface VerifyResult {
83
+ ok: boolean;
84
+ reason: string;
85
+ }
86
+ /** A downloaded artifact's content, supplied to verifyManifest as already-read bytes (or a precomputed digest). */
87
+ export interface DownloadedArtifact {
88
+ path: string;
89
+ /** Raw bytes of the downloaded file (preferred). */
90
+ bytes?: Uint8Array;
91
+ /** Or a precomputed lowercase-hex sha256, if the caller hashed during streaming (avoids buffering). */
92
+ sha256?: string;
93
+ }
94
+ /**
95
+ * Verify downloaded artifacts against the manifest. PURE + deterministic (takes already-read bytes/hashes; does
96
+ * NO I/O). Two layers:
97
+ * 1. sha256-per-artifact (ALWAYS): every manifest artifact must have a matching downloaded artifact whose
98
+ * sha256 equals the manifest's. Missing, extra-unmatched, or mismatched → reject.
99
+ * 2. Ed25519 signature (ONLY when `publicKey` is configured): the manifest MUST carry a valid signature over
100
+ * canonicalManifestBytes. A configured key + missing/badly-signed/wrong-alg manifest → reject (fail-closed).
101
+ * With NO key configured, signature is not required (sha256 is still mandatory) — the node operator opts into
102
+ * the strong form by configuring a key. No key is ever hardcoded.
103
+ *
104
+ * Fail-closed everywhere: any doubt (bad structure, hash gap, signature failure, thrown crypto error) → reject.
105
+ */
106
+ export declare function verifyManifest(manifest: unknown, downloaded: readonly DownloadedArtifact[], publicKey?: string | KeyObject): VerifyResult;
@@ -0,0 +1,294 @@
1
+ // Self-update DECISION + VERIFY core (ported from v1 src/forceUpdate.js — parseVer/isAtLeast/version compare —
2
+ // PLUS the security gate v1 lacked). This module is PURE and hub-agnostic: it makes the
3
+ // update/noop/reject decision and verifies already-downloaded artifact bytes/hashes against a signed manifest.
4
+ // It performs NO I/O — no download, no filesystem write, no process control. Those live in the proxy executor
5
+ // (evolver-proxy/src/selfUpdate/executor.ts) which CALLS verifyManifest before touching disk (verify-before-apply).
6
+ //
7
+ // Why split this way (the boundary rule): a compromised hub must not equal fleet RCE. The decision of whether to
8
+ // apply AND the verification of what to apply are deterministic, fully unit-testable, and must never depend on
9
+ // who is calling. The risky part (writing files, exit(78)) is isolated in proxy behind injected seams.
10
+ import { createHash, verify as cryptoVerify, createPublicKey } from 'node:crypto';
11
+ const SEMVER_NUMERIC_IDENTIFIER = '0|[1-9]\\d*';
12
+ const SEMVER_PRERELEASE_IDENTIFIER = '(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)';
13
+ const SEMVER_BUILD_IDENTIFIER = '[0-9A-Za-z-]+';
14
+ const CONCRETE_SEMVER_RE = new RegExp(`^(${SEMVER_NUMERIC_IDENTIFIER})\\.(${SEMVER_NUMERIC_IDENTIFIER})\\.(${SEMVER_NUMERIC_IDENTIFIER})`
15
+ + `(?:-(${SEMVER_PRERELEASE_IDENTIFIER}(?:\\.${SEMVER_PRERELEASE_IDENTIFIER})*))?`
16
+ + `(?:\\+(${SEMVER_BUILD_IDENTIFIER}(?:\\.${SEMVER_BUILD_IDENTIFIER})*))?$`);
17
+ export const SELF_UPDATE_VERSION_MAX = 32;
18
+ /** Parse a version under the self-update contract. Invalid strings default to 0.0.0 for this legacy helper. */
19
+ export function parseVersion(v) {
20
+ const version = normalizeConcreteVersion(v);
21
+ const parsed = version ? parseConcreteVersion(version) : undefined;
22
+ return parsed ? { major: parsed.major, minor: parsed.minor, patch: parsed.patch } : { major: 0, minor: 0, patch: 0 };
23
+ }
24
+ /** -1 if a<b, 0 if equal, 1 if a>b (SemVer precedence; build metadata ignored). */
25
+ export function compareVersions(a, b) {
26
+ return compareConcreteVersions(normalizeConcreteVersion(a) ?? '0.0.0', normalizeConcreteVersion(b) ?? '0.0.0') ?? 0;
27
+ }
28
+ /** True if `current` >= `required` (faithful to v1 isAtLeast: equal counts as satisfied). */
29
+ export function isAtLeast(current, required) {
30
+ return compareVersions(current, required) >= 0;
31
+ }
32
+ export function normalizeSelfUpdateVersion(value, field = 'version') {
33
+ if (typeof value !== 'string')
34
+ return { ok: false, reason: `${field}_missing` };
35
+ const normalized = value.replace(/^[>=^~\s]+/, '').replace(/^v/, '');
36
+ if (normalized.length === 0)
37
+ return { ok: false, reason: `${field}_missing` };
38
+ if (normalized.length > SELF_UPDATE_VERSION_MAX)
39
+ return { ok: false, reason: `${field}_too_long` };
40
+ if (!CONCRETE_SEMVER_RE.test(normalized))
41
+ return { ok: false, reason: `${field}_invalid` };
42
+ return { ok: true, version: normalized };
43
+ }
44
+ export function requireSelfUpdateVersion(value, field = 'version') {
45
+ const normalized = normalizeSelfUpdateVersion(value, field);
46
+ if (!normalized.ok)
47
+ throw new Error(normalized.reason);
48
+ return normalized.version;
49
+ }
50
+ /** Normalize a concrete semver value under the self-update contract. */
51
+ export function normalizeConcreteVersion(value) {
52
+ const normalized = normalizeSelfUpdateVersion(value);
53
+ return normalized.ok ? normalized.version : undefined;
54
+ }
55
+ /** Normalize the hub's required_version floor. Mirrors v1 forceUpdate.js strip + validate behavior. */
56
+ export function normalizeRequiredVersion(value) {
57
+ return normalizeConcreteVersion(value);
58
+ }
59
+ export function compareConcreteVersions(left, right) {
60
+ const leftVersion = normalizeConcreteVersion(left);
61
+ const rightVersion = normalizeConcreteVersion(right);
62
+ if (!leftVersion || !rightVersion)
63
+ return null;
64
+ const a = parseConcreteVersion(leftVersion);
65
+ const b = parseConcreteVersion(rightVersion);
66
+ if (!a || !b)
67
+ return null;
68
+ const majorCmp = compareNumericIdentifierStrings(a.majorRaw, b.majorRaw);
69
+ if (majorCmp !== 0)
70
+ return majorCmp < 0 ? -1 : 1;
71
+ const minorCmp = compareNumericIdentifierStrings(a.minorRaw, b.minorRaw);
72
+ if (minorCmp !== 0)
73
+ return minorCmp < 0 ? -1 : 1;
74
+ const patchCmp = compareNumericIdentifierStrings(a.patchRaw, b.patchRaw);
75
+ if (patchCmp !== 0)
76
+ return patchCmp < 0 ? -1 : 1;
77
+ if (a.prerelease.length === 0 && b.prerelease.length === 0)
78
+ return 0;
79
+ if (a.prerelease.length === 0)
80
+ return 1;
81
+ if (b.prerelease.length === 0)
82
+ return -1;
83
+ const max = Math.max(a.prerelease.length, b.prerelease.length);
84
+ for (let i = 0; i < max; i += 1) {
85
+ const av = a.prerelease[i];
86
+ const bv = b.prerelease[i];
87
+ if (av === undefined)
88
+ return -1;
89
+ if (bv === undefined)
90
+ return 1;
91
+ const cmp = comparePrereleaseIdentifiers(av, bv);
92
+ if (cmp !== 0)
93
+ return cmp < 0 ? -1 : 1;
94
+ }
95
+ return 0;
96
+ }
97
+ export function currentSatisfiesRequiredVersion(current, required) {
98
+ const currentVersion = normalizeConcreteVersion(current);
99
+ const requiredVersion = normalizeRequiredVersion(required);
100
+ if (!currentVersion || !requiredVersion)
101
+ return false;
102
+ const cmp = compareConcreteVersions(currentVersion, requiredVersion);
103
+ return cmp !== null && cmp >= 0;
104
+ }
105
+ function parseConcreteVersion(value) {
106
+ const match = CONCRETE_SEMVER_RE.exec(value);
107
+ if (!match)
108
+ return undefined;
109
+ return {
110
+ major: Number(match[1]),
111
+ minor: Number(match[2]),
112
+ patch: Number(match[3]),
113
+ majorRaw: match[1] ?? '0',
114
+ minorRaw: match[2] ?? '0',
115
+ patchRaw: match[3] ?? '0',
116
+ prerelease: match[4] ? match[4].split('.') : [],
117
+ };
118
+ }
119
+ function isNumericPrereleaseIdentifier(value) {
120
+ return /^\d+$/.test(value);
121
+ }
122
+ function compareNumericIdentifierStrings(left, right) {
123
+ if (left.length !== right.length)
124
+ return left.length - right.length;
125
+ if (left < right)
126
+ return -1;
127
+ if (left > right)
128
+ return 1;
129
+ return 0;
130
+ }
131
+ function comparePrereleaseIdentifiers(left, right) {
132
+ const leftNumeric = isNumericPrereleaseIdentifier(left);
133
+ const rightNumeric = isNumericPrereleaseIdentifier(right);
134
+ if (leftNumeric && rightNumeric)
135
+ return compareNumericIdentifierStrings(left, right);
136
+ if (leftNumeric)
137
+ return -1;
138
+ if (rightNumeric)
139
+ return 1;
140
+ if (left < right)
141
+ return -1;
142
+ if (left > right)
143
+ return 1;
144
+ return 0;
145
+ }
146
+ /** Shallow structural validation of a manifest — returns null if structurally usable, else a reject reason. */
147
+ function manifestStructuralError(manifest) {
148
+ if (!manifest || typeof manifest !== 'object')
149
+ return 'manifest_missing';
150
+ const m = manifest;
151
+ if (typeof m.version !== 'string' || !m.version.trim())
152
+ return 'manifest_no_version';
153
+ if (!normalizeConcreteVersion(m.version))
154
+ return 'manifest_bad_version';
155
+ if (!Array.isArray(m.artifacts) || m.artifacts.length === 0)
156
+ return 'manifest_no_artifacts';
157
+ for (const a of m.artifacts) {
158
+ if (!a || typeof a.path !== 'string' || !a.path.trim())
159
+ return 'manifest_bad_artifact_path';
160
+ if (typeof a.sha256 !== 'string' || !/^[0-9a-f]{64}$/i.test(a.sha256))
161
+ return 'manifest_bad_artifact_sha256';
162
+ }
163
+ return null;
164
+ }
165
+ /**
166
+ * Decide whether to apply an update. PURE. Fail-closed: a missing/malformed manifest, or a target that does not
167
+ * advance past `current`, never proceeds.
168
+ * - reject : manifest missing/malformed, or required target not satisfiable by the manifest version.
169
+ * - noop : current already satisfies the requested target (no restart needed) — v1's NOOP branch.
170
+ * - proceed: manifest is valid AND advances current. Caller must STILL verifyManifest before applying.
171
+ *
172
+ * `required` is the hub's force_update `required_version` (what the hub demands). `manifest.version` is what the
173
+ * download would deliver. We refuse if the manifest can't actually satisfy the requirement.
174
+ */
175
+ export function decideUpdate(input) {
176
+ const structErr = manifestStructuralError(input.manifest);
177
+ if (structErr)
178
+ return { action: 'reject', reason: structErr };
179
+ const manifest = input.manifest;
180
+ const manifestVersion = normalizeConcreteVersion(manifest.version);
181
+ if (!manifestVersion)
182
+ return { action: 'reject', reason: 'manifest_bad_version' };
183
+ const required = input.required !== undefined && String(input.required) !== ''
184
+ ? normalizeRequiredVersion(input.required)
185
+ : manifestVersion;
186
+ if (!required)
187
+ return { action: 'reject', reason: 'required_version_invalid' };
188
+ // The manifest must be able to deliver at least the required version, otherwise applying it is pointless/unsafe.
189
+ const manifestCmp = compareConcreteVersions(manifestVersion, required);
190
+ if (manifestCmp === null)
191
+ return { action: 'reject', reason: 'manifest_bad_version' };
192
+ if (manifestCmp < 0) {
193
+ return { action: 'reject', reason: 'manifest_below_required', targetVersion: manifestVersion };
194
+ }
195
+ // Already at/above what the hub requires → nothing to do, do NOT restart (v1 NOOP).
196
+ const currentVersion = normalizeConcreteVersion(input.current);
197
+ if (!currentVersion)
198
+ return { action: 'reject', reason: 'current_version_invalid' };
199
+ const currentCmp = compareConcreteVersions(currentVersion, required);
200
+ if (currentCmp !== null && currentCmp >= 0) {
201
+ return { action: 'noop', reason: 'already_satisfied', targetVersion: required };
202
+ }
203
+ return { action: 'proceed', reason: 'update_available', targetVersion: manifestVersion };
204
+ }
205
+ // ---------------------------------------------------------------------------------------------------------------
206
+ // Manifest verification (the security gate v1 lacked). sha256-per-artifact is MANDATORY; Ed25519 signature is the
207
+ // strong form, enforced ONLY when a public key is configured — and then fail-closed.
208
+ // ---------------------------------------------------------------------------------------------------------------
209
+ /** sha256 hex of the given bytes — the digest each downloaded artifact is checked against. */
210
+ export function sha256Hex(bytes) {
211
+ return createHash('sha256').update(bytes).digest('hex');
212
+ }
213
+ /**
214
+ * Canonical bytes the signature is computed over: a deterministic JSON of {version, artifacts:[{path,sha256}]}
215
+ * with artifacts sorted by path and sha256 lowercased, so signer and verifier agree byte-for-byte regardless of
216
+ * key order or casing. The release pipeline MUST sign exactly these bytes.
217
+ */
218
+ export function canonicalManifestBytes(manifest) {
219
+ const canonical = {
220
+ version: requireSelfUpdateVersion(manifest.version, 'manifest_version'),
221
+ artifacts: [...manifest.artifacts]
222
+ .map((a) => ({ path: a.path, sha256: a.sha256.toLowerCase() }))
223
+ .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
224
+ };
225
+ return new TextEncoder().encode(JSON.stringify(canonical));
226
+ }
227
+ /** Parse a configured public key (PEM, raw 32-byte base64, or a KeyObject) into a node KeyObject. */
228
+ function toPublicKey(publicKey) {
229
+ if (typeof publicKey !== 'string')
230
+ return publicKey;
231
+ const trimmed = publicKey.trim();
232
+ if (trimmed.includes('BEGIN PUBLIC KEY'))
233
+ return createPublicKey(trimmed);
234
+ // Raw 32-byte Ed25519 key, base64 → wrap in DER SPKI so createPublicKey accepts it.
235
+ const raw = Buffer.from(trimmed, 'base64');
236
+ if (raw.length !== 32)
237
+ throw new Error('ed25519 raw key must be 32 bytes');
238
+ const der = Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'), raw]);
239
+ return createPublicKey({ key: der, format: 'der', type: 'spki' });
240
+ }
241
+ /**
242
+ * Verify downloaded artifacts against the manifest. PURE + deterministic (takes already-read bytes/hashes; does
243
+ * NO I/O). Two layers:
244
+ * 1. sha256-per-artifact (ALWAYS): every manifest artifact must have a matching downloaded artifact whose
245
+ * sha256 equals the manifest's. Missing, extra-unmatched, or mismatched → reject.
246
+ * 2. Ed25519 signature (ONLY when `publicKey` is configured): the manifest MUST carry a valid signature over
247
+ * canonicalManifestBytes. A configured key + missing/badly-signed/wrong-alg manifest → reject (fail-closed).
248
+ * With NO key configured, signature is not required (sha256 is still mandatory) — the node operator opts into
249
+ * the strong form by configuring a key. No key is ever hardcoded.
250
+ *
251
+ * Fail-closed everywhere: any doubt (bad structure, hash gap, signature failure, thrown crypto error) → reject.
252
+ */
253
+ export function verifyManifest(manifest, downloaded, publicKey) {
254
+ const structErr = manifestStructuralError(manifest);
255
+ if (structErr)
256
+ return { ok: false, reason: structErr };
257
+ const m = manifest;
258
+ // Layer 1: sha256 per artifact (mandatory). Index downloads by path; every manifest entry must match.
259
+ const byPath = new Map();
260
+ for (const d of downloaded)
261
+ byPath.set(d.path, d);
262
+ for (const art of m.artifacts) {
263
+ const got = byPath.get(art.path);
264
+ if (!got)
265
+ return { ok: false, reason: `artifact_missing: ${art.path}` };
266
+ let digest;
267
+ if (got.sha256)
268
+ digest = got.sha256.toLowerCase();
269
+ else if (got.bytes)
270
+ digest = sha256Hex(got.bytes);
271
+ else
272
+ return { ok: false, reason: `artifact_no_content: ${art.path}` };
273
+ if (digest !== art.sha256.toLowerCase())
274
+ return { ok: false, reason: `sha256_mismatch: ${art.path}` };
275
+ }
276
+ // Layer 2: Ed25519 signature — enforced ONLY when a key is configured (then fail-closed).
277
+ if (publicKey) {
278
+ if (!m.signature)
279
+ return { ok: false, reason: 'signature_required_but_missing' };
280
+ if (m.signatureAlg && m.signatureAlg !== 'ed25519')
281
+ return { ok: false, reason: 'signature_alg_unsupported' };
282
+ try {
283
+ const key = toPublicKey(publicKey);
284
+ const ok = cryptoVerify(null, // Ed25519 ignores the digest-name arg
285
+ canonicalManifestBytes(m), key, Buffer.from(m.signature, 'base64'));
286
+ if (!ok)
287
+ return { ok: false, reason: 'signature_invalid' };
288
+ }
289
+ catch (err) {
290
+ return { ok: false, reason: `signature_verify_error: ${err instanceof Error ? err.message : String(err)}` };
291
+ }
292
+ }
293
+ return { ok: true, reason: 'verified' };
294
+ }
@@ -0,0 +1,205 @@
1
+ /** USD price per single token, split by token class (Anthropic-style usage breakdown). All optional: an
2
+ * absent class is treated as 0 so a sparse table still prices what it can. */
3
+ export interface ModelPrice {
4
+ /** USD per input token. */
5
+ input?: number;
6
+ /** USD per output token. */
7
+ output?: number;
8
+ /** USD per cache-creation (write) input token. */
9
+ cacheCreation?: number;
10
+ /** USD per cache-read input token. */
11
+ cacheRead?: number;
12
+ }
13
+ /**
14
+ * Model → price lookup. INJECTED, never hardcoded in core (acceptance: a price update must not touch core
15
+ * code). A lookup is tolerant: an unknown model returns undefined and that turn simply contributes no cost
16
+ * (we never invent a price). The adapter owns the concrete data file + loader.
17
+ */
18
+ export interface PriceTable {
19
+ priceOf(model: string): ModelPrice | undefined;
20
+ }
21
+ /** Build a PriceTable from a plain {model: ModelPrice} map (the shape a JSON data file deserializes to). */
22
+ export declare function priceTableFromMap(map: Readonly<Record<string, ModelPrice>>): PriceTable;
23
+ /** Per-turn token usage, matching the proxy trace's `usage` block by field name (input_tokens, …). */
24
+ export interface TokenUsage {
25
+ input_tokens?: number;
26
+ output_tokens?: number;
27
+ cache_creation_input_tokens?: number;
28
+ cache_read_input_tokens?: number;
29
+ }
30
+ /**
31
+ * A single LLM-turn trace record, as the proxy appends it to `llm-trace-YYYYMMDD.jsonl`. Declared structurally
32
+ * here (only the fields the ledger reads) so core never imports the proxy package. The caller parses the JSONL
33
+ * and passes the records in.
34
+ */
35
+ export interface TraceRecord {
36
+ /** ISO timestamp of the turn (the ledger's `at` for a route entry — never a local clock). */
37
+ ts: string;
38
+ /** What the client asked for. */
39
+ original_model: string | null;
40
+ /** What the router actually sent (a cheaper tier model when routing fired). */
41
+ chosen_model: string | null;
42
+ /** Routing tier, when the router rewrote the model. Absent/null → no route savings for this turn. */
43
+ tier?: string | null;
44
+ usage?: TokenUsage;
45
+ }
46
+ /** root_events type appended on a reuse-before-solve HIT — the replayable source for source=reuse entries. */
47
+ export declare const VALUE_REUSE_HIT_EVENT = "value.reuse_hit";
48
+ /**
49
+ * Payload of a `value.reuse_hit` root_event. Carries exactly what the ledger needs to account a reuse saving:
50
+ * which asset was reused, in which cycle, the actual token cost the fetch incurred (≈0 - metadata + payload,
51
+ * no fresh solve), and an OPTIONAL measured baseline (historical avg solve-fresh tokens for this signal class).
52
+ * When `baselineTokens` is present the saving is `measured`; when absent the ledger records the reuse with
53
+ * unknown/zero savings instead of inventing a task-level token delta. The signal fingerprint is carried for
54
+ * baseline attribution upstream.
55
+ */
56
+ export interface ReuseHitPayload {
57
+ assetId: string;
58
+ cycleId: string;
59
+ /** Signal fingerprint of the reused problem (for baseline cohorting / explainability). */
60
+ signalFingerprint?: string;
61
+ /** Tokens the fetch actually consumed (cache/payload pull — typically 0). Defaults to 0. */
62
+ fetchTokens?: number;
63
+ /** Measured baseline: historical avg solve-fresh token cost for this signal class. Absent → estimated. */
64
+ baselineTokens?: number;
65
+ /** Model whose price values the saved tokens (so cost uses the real tier, not a guess). Optional. */
66
+ model?: string;
67
+ }
68
+ /** A minimal root_event view the ledger reads (matches the events module's ReportEvent shape). */
69
+ export interface LedgerRootEvent {
70
+ type: string;
71
+ ts: string;
72
+ payload?: Record<string, unknown>;
73
+ }
74
+ /** root_events type appended when SessionStart injects genes — recorded for outcome attribution only. */
75
+ export declare const VALUE_INJECT_EVENT = "value.inject";
76
+ /** Payload of a `value.inject` root_event: which genes were injected and the session outcome. No savings. */
77
+ export interface InjectPayload {
78
+ geneIds: readonly string[];
79
+ cycleId?: string;
80
+ /** The runtime session id this injection went into, when known (#205). Lets recall tie an inject to the exact
81
+ * session transcript it produced, rather than assuming "the most recent inject". Absent for runtimes with no id. */
82
+ sessionId?: string;
83
+ /** Free-form session outcome label (solved/abandoned/…); attribution only, never scored into a number. */
84
+ outcome?: string;
85
+ }
86
+ export type ValueSource = 'route' | 'reuse' | 'inject';
87
+ export type ValueConfidence = 'measured' | 'estimated';
88
+ /**
89
+ * One derived ledger entry. Append-only + content-derived: replaying the same trace + root_events yields the
90
+ * identical entry. `tokensSaved` is the token delta (0 for route — routing saves cost on the SAME tokens, not
91
+ * tokens; and 0 for inject — inject reports no number). `costSavedUsd` is the USD delta. `refs` ties the entry
92
+ * back to its source material (assetId, cycleId, models) for audit / drift checks.
93
+ */
94
+ export interface ValueEntry {
95
+ /** Timestamp from the source record (route: trace.ts; reuse/inject: event.ts). Never a local clock. */
96
+ at: string;
97
+ source: ValueSource;
98
+ tokensSaved: number;
99
+ costSavedUsd: number;
100
+ confidence: ValueConfidence;
101
+ refs: {
102
+ assetId?: string;
103
+ cycleId?: string;
104
+ originalModel?: string;
105
+ chosenModel?: string;
106
+ /** gene ids, for inject entries (and topGenes attribution). */
107
+ geneIds?: readonly string[];
108
+ /** free-form outcome, for inject entries. */
109
+ outcome?: string;
110
+ };
111
+ }
112
+ /** Legacy savings-core E1 coefficient for "one cross-node asset reuse". The value ledger no longer uses this
113
+ * as a fallback baseline for live `value.reuse_hit` events: without a measured baseline, reuse savings stay
114
+ * zero/unknown. Kept exported so savings-core conformance and older consumers can detect spec drift. */
115
+ export declare const ESTIMATED_SOLVE_FRESH_TOKENS: number;
116
+ /**
117
+ * Derive route-downgrade savings from trace records. A turn saves COST (not tokens) only when the router
118
+ * actually rewrote the model (`original_model !== chosen_model`, both present): the saving is the price delta
119
+ * of the SAME usage between the model the client asked for and the cheaper model that ran. Always `measured`
120
+ * (the usage is real). A turn whose price delta is ≤0 (no cheaper, or model unpriced) contributes nothing.
121
+ */
122
+ export declare function deriveRouteEntries(traces: readonly TraceRecord[], prices: PriceTable): ValueEntry[];
123
+ /**
124
+ * Derive reuse savings from `value.reuse_hit` root_events. Saving = (baseline solve-fresh tokens) - (actual
125
+ * fetch tokens), but only when the event carries `baselineTokens` (a real historical average for the signal
126
+ * class). Without that measured baseline, the entry still records the reuse but keeps tokensSaved/costSavedUsd
127
+ * at zero so a small-step reuse inside a large task cannot be promoted into fabricated whole-task ROI.
128
+ * Each entry's refs point at the real `assetId` + `cycleId` from the hit - the audit anchor.
129
+ */
130
+ export declare function deriveReuseEntries(events: readonly LedgerRootEvent[], prices: PriceTable): ValueEntry[];
131
+ /**
132
+ * Derive inject records from `value.inject` root_events. Attribution-only: which genes were injected and the
133
+ * session outcome. tokensSaved / costSavedUsd are ALWAYS 0 (the issue: inject is a weak signal — record it,
134
+ * never report a savings number). Marked `estimated` so it can never land on the measured rail, and the
135
+ * summary excludes inject from both savings totals regardless.
136
+ */
137
+ export declare function deriveInjectEntries(events: readonly LedgerRootEvent[]): ValueEntry[];
138
+ export interface DeriveInput {
139
+ /** Parsed proxy trace records (one per LLM turn). */
140
+ traces?: readonly TraceRecord[];
141
+ /** Parsed root_events (the reuse-hit + inject records live here). */
142
+ events?: readonly LedgerRootEvent[];
143
+ /** Injected price table — core never hardcodes prices. */
144
+ prices: PriceTable;
145
+ }
146
+ /**
147
+ * Derive the full set of value entries from trace + root_events, sorted by `at` (stable, ties broken by source
148
+ * then assetId/models) so the ledger is a deterministic, replayable timeline. Pure: same input → same output,
149
+ * byte-for-byte. This is the function a `replay` re-runs after discarding the materialized ledger.
150
+ */
151
+ export declare function deriveValueEntries(input: DeriveInput): ValueEntry[];
152
+ /** Serialize entries to append-only JSONL (one entry per line). Deterministic given the entries. */
153
+ export declare function serializeLedger(entries: readonly ValueEntry[]): string;
154
+ /** Parse a ledger JSONL back into entries (the materialized view; the source of truth is still trace+events). */
155
+ export declare function parseLedger(jsonl: string): ValueEntry[];
156
+ export interface SourceBucket {
157
+ tokensSaved: number;
158
+ costSavedUsd: number;
159
+ entries: number;
160
+ }
161
+ /**
162
+ * The aggregated value view. CRITICAL HONESTY INVARIANT: `measured` and `estimated` are SEPARATE rails — the
163
+ * top-level totals (`totalTokensSaved` / `totalCostUsd`) count ONLY measured savings, and estimated savings
164
+ * live solely under `estimated`. There is no field that merges the two. A consumer that wants a combined figure
165
+ * must add them itself and label it — the ledger never does it silently.
166
+ */
167
+ export interface ValueSummary {
168
+ /** MEASURED savings only (the trustworthy number). */
169
+ totalTokensSaved: number;
170
+ totalCostUsd: number;
171
+ /** Per-source breakdown (measured rail). */
172
+ bySource: Record<ValueSource, SourceBucket>;
173
+ /** ESTIMATED savings, on their OWN rail — never folded into the totals above. */
174
+ estimated: {
175
+ totalTokensSaved: number;
176
+ totalCostUsd: number;
177
+ entries: number;
178
+ };
179
+ /** Top reused genes by frequency, with measured/estimated saving kept separate per gene. */
180
+ topGenes: Array<{
181
+ assetId: string;
182
+ reuses: number;
183
+ measuredTokensSaved: number;
184
+ estimatedTokensSaved: number;
185
+ }>;
186
+ /** Inject attribution (no savings number): genes injected, by frequency. */
187
+ injectedGenes: Array<{
188
+ geneId: string;
189
+ injections: number;
190
+ }>;
191
+ /** Number of entries considered (after window filter). */
192
+ entries: number;
193
+ }
194
+ export interface SummaryWindow {
195
+ /** Inclusive lower bound (ISO). Entries with `at` < since are excluded. */
196
+ since?: string;
197
+ /** Exclusive upper bound (ISO). Entries with `at` >= until are excluded. */
198
+ until?: string;
199
+ }
200
+ /**
201
+ * Aggregate entries into a ValueSummary over an optional time window. Pure. Measured and estimated are summed
202
+ * on separate rails by construction — there is deliberately NO branch that adds an estimated entry into the
203
+ * measured totals (the honesty invariant; a test asserts no such path exists).
204
+ */
205
+ export declare function valueSummary(entries: readonly ValueEntry[], window?: SummaryWindow): ValueSummary;