@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,90 @@
1
+ import { type CycleFailureClass } from '../algo/cycleFailureClassifier.js';
2
+ /** root_events 行(报表读视图). */
3
+ export interface ReportEvent {
4
+ type: string;
5
+ seq: number;
6
+ ts: string;
7
+ human?: {
8
+ title?: string;
9
+ detail?: string;
10
+ why?: string;
11
+ next?: string;
12
+ severity?: string;
13
+ };
14
+ payload?: Record<string, unknown>;
15
+ }
16
+ export declare function readEvents(eventsPath?: string): ReportEvent[];
17
+ export interface StatusReport {
18
+ totalEvents: number;
19
+ byType: Record<string, number>;
20
+ cycles: number;
21
+ lastTs: string | null;
22
+ }
23
+ export declare function statusReport(evts: readonly ReportEvent[]): StatusReport;
24
+ export interface CycleSummary {
25
+ cycleId: string;
26
+ events: number;
27
+ finalStage: string;
28
+ lastTs: string;
29
+ failureClass?: CycleFailureClass;
30
+ failureSuppressed?: boolean;
31
+ }
32
+ export declare function listCycles(evts: readonly ReportEvent[]): CycleSummary[];
33
+ export interface CycleTimeline {
34
+ cycleId: string;
35
+ timeline: Array<{
36
+ type: string;
37
+ title: string;
38
+ why?: string;
39
+ ts: string;
40
+ seq: number;
41
+ payload?: Record<string, unknown>;
42
+ }>;
43
+ }
44
+ export declare function showCycle(evts: readonly ReportEvent[], cycleId: string): CycleTimeline;
45
+ export interface TriggerRow {
46
+ patternId: string;
47
+ triggered: boolean;
48
+ value: number;
49
+ reasons: string[];
50
+ }
51
+ export declare function listTriggers(evts: readonly ReportEvent[]): TriggerRow[];
52
+ /** 每日总结(保活, M7-4): 当日 cycle 数/成功率/触发数. */
53
+ export interface DailySummary {
54
+ date: string;
55
+ cycles: number;
56
+ solidified: number;
57
+ failed: number;
58
+ triggered: number;
59
+ suppressed: number;
60
+ failureBuckets: Partial<Record<CycleFailureClass, number>>;
61
+ suppressedFailures: number;
62
+ }
63
+ export declare function dailySummary(evts: readonly ReportEvent[], dayPrefix: string): DailySummary;
64
+ export type NarrativeOutcome = 'success' | 'failed' | 'inert' | 'unknown';
65
+ export interface NarrativeEntry {
66
+ seq: number;
67
+ ts: string;
68
+ type: string;
69
+ title: string;
70
+ cycleId?: string;
71
+ summary?: string;
72
+ action?: string;
73
+ outcome?: NarrativeOutcome;
74
+ geneId?: string;
75
+ score?: number;
76
+ }
77
+ export interface NarrativeSnapshot {
78
+ totalEvents: number;
79
+ includedEvents: number;
80
+ cycles: number;
81
+ reflections: number;
82
+ outcomes: Record<NarrativeOutcome, number>;
83
+ entries: NarrativeEntry[];
84
+ }
85
+ export interface NarrativeSnapshotOptions {
86
+ limit?: number;
87
+ }
88
+ export declare const NARRATIVE_DEFAULT_LIMIT = 30;
89
+ export declare const NARRATIVE_MAX_LIMIT = 200;
90
+ export declare function buildNarrativeSnapshot(evts: readonly ReportEvent[], opts?: NarrativeSnapshotOptions): NarrativeSnapshot;
@@ -0,0 +1,244 @@
1
+ import { Ingestor } from './ingest.js';
2
+ import { rootEventsPath } from './paths.js';
3
+ import { HOST_SUPPRESS_CLASSES } from '../algo/cycleFailureClassifier.js';
4
+ export function readEvents(eventsPath) {
5
+ const ing = new Ingestor({ path: eventsPath ?? rootEventsPath() });
6
+ return ing.readAll();
7
+ }
8
+ const cycleIdOf = (e) => e.payload?.['cycleId'];
9
+ const failureClassOf = (e) => {
10
+ const v = e.payload?.['failure_class'];
11
+ return typeof v === 'string' ? v : undefined;
12
+ };
13
+ const suppressesFailure = (failureClass) => failureClass !== undefined && HOST_SUPPRESS_CLASSES.has(failureClass);
14
+ export function statusReport(evts) {
15
+ const byType = {};
16
+ const cycles = new Set();
17
+ for (const e of evts) {
18
+ byType[e.type] = (byType[e.type] ?? 0) + 1;
19
+ const c = cycleIdOf(e);
20
+ if (c)
21
+ cycles.add(c);
22
+ }
23
+ return { totalEvents: evts.length, byType, cycles: cycles.size, lastTs: evts.length ? evts[evts.length - 1].ts : null };
24
+ }
25
+ export function listCycles(evts) {
26
+ const byCycle = new Map();
27
+ for (const e of evts) {
28
+ const c = cycleIdOf(e);
29
+ if (!c)
30
+ continue;
31
+ (byCycle.get(c) ?? byCycle.set(c, []).get(c)).push(e);
32
+ }
33
+ const STAGE = new Set(['cycle.solidified', 'cycle.failed', 'cycle.aborted']);
34
+ return [...byCycle.entries()].map(([cycleId, es]) => {
35
+ const terminal = [...es].reverse().find((e) => STAGE.has(e.type));
36
+ const failureClass = terminal?.type === 'cycle.failed' ? failureClassOf(terminal) : undefined;
37
+ return {
38
+ cycleId,
39
+ events: es.length,
40
+ finalStage: terminal?.type.replace('cycle.', '') ?? 'in_progress',
41
+ lastTs: es[es.length - 1].ts,
42
+ ...(failureClass !== undefined ? { failureClass, failureSuppressed: suppressesFailure(failureClass) } : {}),
43
+ };
44
+ });
45
+ }
46
+ export function showCycle(evts, cycleId) {
47
+ const timeline = evts.filter((e) => cycleIdOf(e) === cycleId).map((e) => ({
48
+ type: e.type, title: e.human?.title ?? '', ts: e.ts, seq: e.seq,
49
+ ...(e.human?.why ? { why: e.human.why } : {}), ...(e.payload ? { payload: e.payload } : {}),
50
+ }));
51
+ return { cycleId, timeline };
52
+ }
53
+ export function listTriggers(evts) {
54
+ return evts.filter((e) => e.type === 'decision.triggered' || e.type === 'decision.suppressed').map((e) => ({
55
+ patternId: e.payload?.['patternId'] ?? '?',
56
+ triggered: e.type === 'decision.triggered',
57
+ value: e.payload?.['value'] ?? 0,
58
+ reasons: e.payload?.['reasons'] ?? (e.human?.why ? [e.human.why] : []),
59
+ }));
60
+ }
61
+ export function dailySummary(evts, dayPrefix) {
62
+ const today = evts.filter((e) => e.ts.startsWith(dayPrefix));
63
+ const count = (t) => today.filter((e) => e.type === t).length;
64
+ const cycleIds = new Set(today.map(cycleIdOf).filter(Boolean));
65
+ const failureBuckets = {};
66
+ let suppressedFailures = 0;
67
+ for (const e of today) {
68
+ if (e.type !== 'cycle.failed')
69
+ continue;
70
+ const failureClass = failureClassOf(e);
71
+ if (failureClass !== undefined) {
72
+ failureBuckets[failureClass] = (failureBuckets[failureClass] ?? 0) + 1;
73
+ if (suppressesFailure(failureClass))
74
+ suppressedFailures += 1;
75
+ }
76
+ }
77
+ return {
78
+ date: dayPrefix,
79
+ cycles: cycleIds.size,
80
+ solidified: count('cycle.solidified'),
81
+ failed: count('cycle.failed'),
82
+ triggered: count('decision.triggered'),
83
+ suppressed: count('decision.suppressed'),
84
+ failureBuckets,
85
+ suppressedFailures,
86
+ };
87
+ }
88
+ export const NARRATIVE_DEFAULT_LIMIT = 30;
89
+ export const NARRATIVE_MAX_LIMIT = 200;
90
+ const NARRATIVE_EVENTS = new Set([
91
+ 'reflection.recorded',
92
+ 'cycle.solidified',
93
+ 'cycle.failed',
94
+ 'cycle.aborted',
95
+ 'decision.gene_selected',
96
+ 'value.reuse_hit',
97
+ 'value.inject',
98
+ 'value.reuse_outcome',
99
+ 'value.recall',
100
+ ]);
101
+ const TOKEN_LIKE = /\b[A-Za-z0-9_-]{24,}\b|\b[A-Fa-f0-9]{16,}\b/g;
102
+ export function buildNarrativeSnapshot(evts, opts = {}) {
103
+ const limit = clampLimit(opts.limit);
104
+ const allEntries = evts.map(toNarrativeEntry).filter((entry) => entry !== null);
105
+ const entries = allEntries.slice(-limit);
106
+ const cycles = new Set();
107
+ const outcomes = { success: 0, failed: 0, inert: 0, unknown: 0 };
108
+ let reflections = 0;
109
+ for (const entry of entries) {
110
+ if (entry.cycleId)
111
+ cycles.add(entry.cycleId);
112
+ if (entry.type === 'reflection.recorded')
113
+ reflections += 1;
114
+ if (entry.outcome)
115
+ outcomes[entry.outcome] += 1;
116
+ }
117
+ return {
118
+ totalEvents: evts.length,
119
+ includedEvents: entries.length,
120
+ cycles: cycles.size,
121
+ reflections,
122
+ outcomes,
123
+ entries,
124
+ };
125
+ }
126
+ function toNarrativeEntry(event) {
127
+ if (!isNarrativeEvent(event))
128
+ return null;
129
+ const payload = event.payload ?? {};
130
+ const base = {
131
+ seq: event.seq,
132
+ ts: event.ts,
133
+ type: event.type,
134
+ title: cleanText(event.human?.title ?? event.type, 120) ?? event.type,
135
+ };
136
+ if (event.type === 'reflection.recorded') {
137
+ return cleanUndefined({
138
+ ...base,
139
+ cycleId: stringOf(payload['cycleId']),
140
+ summary: cleanText(stringOf(payload['summary']) ?? event.human?.detail ?? event.human?.why),
141
+ action: stringOf(payload['action']),
142
+ outcome: narrativeOutcome(stringOf(payload['outcome'])),
143
+ geneId: stringOf(payload['geneId']),
144
+ score: numberOf(payload['score']),
145
+ });
146
+ }
147
+ if (event.type === 'cycle.solidified' || event.type === 'cycle.failed' || event.type === 'cycle.aborted') {
148
+ const outcome = event.type === 'cycle.failed'
149
+ ? 'failed'
150
+ : event.type === 'cycle.aborted'
151
+ ? 'unknown'
152
+ : payload['producedValue'] === false
153
+ ? 'inert'
154
+ : narrativeOutcome(stringOf(asRecord(payload['outcome'])?.['status'])) ?? 'success';
155
+ return cleanUndefined({
156
+ ...base,
157
+ cycleId: stringOf(payload['cycleId']),
158
+ summary: cycleSummary(event, payload),
159
+ action: event.type.replace('cycle.', 'cycle_'),
160
+ outcome,
161
+ geneId: stringOf(payload['gene']),
162
+ score: numberOf(asRecord(payload['outcome'])?.['score']),
163
+ });
164
+ }
165
+ if (event.type === 'decision.gene_selected') {
166
+ return cleanUndefined({
167
+ ...base,
168
+ cycleId: stringOf(payload['cycleId']),
169
+ summary: cleanText(event.human?.detail ?? event.human?.why),
170
+ action: 'gene_selected',
171
+ geneId: stringOf(payload['selectedGeneId']) ?? stringOf(payload['geneId']) ?? stringOf(payload['gene']),
172
+ });
173
+ }
174
+ if (event.type.startsWith('actor.human.')) {
175
+ return cleanUndefined({
176
+ ...base,
177
+ cycleId: stringOf(payload['cycleId']),
178
+ summary: cleanText(stringOf(payload['reason']) ?? stringOf(payload['note']) ?? event.human?.detail ?? event.human?.why ?? event.human?.next),
179
+ action: event.type.replace('actor.human.', 'human_').replace(/\./g, '_'),
180
+ geneId: stringOf(payload['geneId']),
181
+ });
182
+ }
183
+ return cleanUndefined({
184
+ ...base,
185
+ cycleId: stringOf(payload['cycleId']),
186
+ summary: cleanText(event.human?.detail ?? event.human?.why ?? stringOf(payload['outcome'])),
187
+ action: event.type.replace('value.', 'value_'),
188
+ geneId: stringOf(payload['geneId']) ?? stringOf(payload['assetId']),
189
+ });
190
+ }
191
+ function isNarrativeEvent(event) {
192
+ return NARRATIVE_EVENTS.has(event.type) || event.type.startsWith('actor.human.');
193
+ }
194
+ function cycleSummary(event, payload) {
195
+ const outcome = asRecord(payload['outcome']);
196
+ return cleanText(event.human?.detail
197
+ ?? event.human?.why
198
+ ?? stringOf(payload['error'])
199
+ ?? stringOf(payload['reason'])
200
+ ?? stringListOf(payload['reasons'])
201
+ ?? stringOf(outcome?.['reason'])
202
+ ?? stringOf(payload['failure_class_reason'])
203
+ ?? stringOf(payload['failure_class']));
204
+ }
205
+ function clampLimit(limit) {
206
+ if (typeof limit !== 'number' || !Number.isFinite(limit))
207
+ return NARRATIVE_DEFAULT_LIMIT;
208
+ return Math.min(NARRATIVE_MAX_LIMIT, Math.max(1, Math.floor(limit)));
209
+ }
210
+ function cleanText(value, max = 240) {
211
+ if (!value)
212
+ return undefined;
213
+ const normalized = value.replace(/\s+/g, ' ').trim().replace(TOKEN_LIKE, '[redacted]');
214
+ if (!normalized)
215
+ return undefined;
216
+ return normalized.length <= max ? normalized : `${normalized.slice(0, max - 3)}...`;
217
+ }
218
+ function narrativeOutcome(value) {
219
+ if (value === 'success' || value === 'failed' || value === 'inert' || value === 'unknown')
220
+ return value;
221
+ return undefined;
222
+ }
223
+ function asRecord(value) {
224
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
225
+ }
226
+ function stringOf(value) {
227
+ return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
228
+ }
229
+ function stringListOf(value) {
230
+ if (!Array.isArray(value))
231
+ return undefined;
232
+ const parts = value.filter((item) => typeof item === 'string' && item.trim().length > 0);
233
+ return parts.length > 0 ? parts.join('; ') : undefined;
234
+ }
235
+ function numberOf(value) {
236
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
237
+ }
238
+ function cleanUndefined(record) {
239
+ for (const key of Object.keys(record)) {
240
+ if (record[key] === undefined)
241
+ delete record[key];
242
+ }
243
+ return record;
244
+ }
@@ -0,0 +1,70 @@
1
+ export type RetentionState = 'ok' | 'watch' | 'over_limit';
2
+ export declare const RETENTION_DEFAULT_MAX_ROOT_EVENTS = 100000;
3
+ export declare const RETENTION_DEFAULT_MAX_ROOT_BYTES: number;
4
+ export declare const RETENTION_DEFAULT_MAX_MATERIAL_RECORDS = 10000;
5
+ export declare const RETENTION_DEFAULT_MAX_MATERIAL_BYTES: number;
6
+ export declare const RETENTION_DEFAULT_WATCH_RATIO = 0.8;
7
+ export declare const RETENTION_DEFAULT_ROOT_TAIL_EVENTS: number;
8
+ export interface RetentionThresholds {
9
+ maxRecords: number;
10
+ maxBytes: number;
11
+ watchRatio: number;
12
+ }
13
+ export interface RootRetentionSnapshot {
14
+ name: 'root_events';
15
+ exists: boolean;
16
+ bytes: number;
17
+ records: number;
18
+ invalidLines: number;
19
+ state: RetentionState;
20
+ thresholds: RetentionThresholds;
21
+ firstSeq: number | null;
22
+ lastSeq: number | null;
23
+ firstTs: string | null;
24
+ lastTs: string | null;
25
+ protectTailEvents: number;
26
+ destructivePruneSafe: false;
27
+ reason: string;
28
+ }
29
+ export interface MaterialRetentionSnapshot {
30
+ name: 'material';
31
+ exists: boolean;
32
+ bytes: number;
33
+ records: number;
34
+ invalidLines: number;
35
+ state: RetentionState;
36
+ thresholds: RetentionThresholds;
37
+ firstCapturedAt: string | null;
38
+ lastCapturedAt: string | null;
39
+ cursorValid: boolean;
40
+ cursorInRange: boolean;
41
+ cursor: number;
42
+ effectiveCursor: number;
43
+ consumedPrefix: number;
44
+ pending: number;
45
+ destructivePruneSafe: false;
46
+ reason: string;
47
+ }
48
+ export interface RetentionReport {
49
+ generatedAt: string;
50
+ mode: 'read_only_policy';
51
+ destructivePruneSupported: false;
52
+ rootEvents: RootRetentionSnapshot;
53
+ material: MaterialRetentionSnapshot;
54
+ warnings: string[];
55
+ nextActions: string[];
56
+ }
57
+ export interface RetentionReportOptions {
58
+ rootEventsPath?: string;
59
+ materialStorePath?: string;
60
+ materialCursorPath?: string;
61
+ now?: () => number;
62
+ maxRootEvents?: number;
63
+ maxRootBytes?: number;
64
+ maxMaterialRecords?: number;
65
+ maxMaterialBytes?: number;
66
+ watchRatio?: number;
67
+ protectRootTailEvents?: number;
68
+ }
69
+ export declare function defaultMaterialCursorPath(path?: string): string;
70
+ export declare function buildRetentionReport(opts?: RetentionReportOptions): RetentionReport;
@@ -0,0 +1,177 @@
1
+ import { existsSync, readFileSync, statSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { material } from '../schema/material.js';
4
+ import { rootEvent } from './eventSchema.js';
5
+ import { materialStorePath as defaultMaterialStorePath, rootEventsPath as defaultRootEventsPath } from './paths.js';
6
+ import { NARRATIVE_MAX_LIMIT } from './reports.js';
7
+ export const RETENTION_DEFAULT_MAX_ROOT_EVENTS = 100_000;
8
+ export const RETENTION_DEFAULT_MAX_ROOT_BYTES = 64 * 1024 * 1024;
9
+ export const RETENTION_DEFAULT_MAX_MATERIAL_RECORDS = 10_000;
10
+ export const RETENTION_DEFAULT_MAX_MATERIAL_BYTES = 64 * 1024 * 1024;
11
+ export const RETENTION_DEFAULT_WATCH_RATIO = 0.8;
12
+ export const RETENTION_DEFAULT_ROOT_TAIL_EVENTS = Math.max(1_000, NARRATIVE_MAX_LIMIT);
13
+ export function defaultMaterialCursorPath(path = defaultMaterialStorePath()) {
14
+ return join(dirname(path), 'cycle-consumer.json');
15
+ }
16
+ export function buildRetentionReport(opts = {}) {
17
+ const now = new Date((opts.now ?? Date.now)()).toISOString();
18
+ const watchRatio = ratioOf(opts.watchRatio, RETENTION_DEFAULT_WATCH_RATIO);
19
+ const rootPath = opts.rootEventsPath ?? defaultRootEventsPath();
20
+ const materialPath = opts.materialStorePath ?? defaultMaterialStorePath();
21
+ const cursorPath = opts.materialCursorPath ?? defaultMaterialCursorPath(materialPath);
22
+ const rootThresholds = {
23
+ maxRecords: positiveInt(opts.maxRootEvents, RETENTION_DEFAULT_MAX_ROOT_EVENTS),
24
+ maxBytes: positiveInt(opts.maxRootBytes, RETENTION_DEFAULT_MAX_ROOT_BYTES),
25
+ watchRatio,
26
+ };
27
+ const materialThresholds = {
28
+ maxRecords: positiveInt(opts.maxMaterialRecords, RETENTION_DEFAULT_MAX_MATERIAL_RECORDS),
29
+ maxBytes: positiveInt(opts.maxMaterialBytes, RETENTION_DEFAULT_MAX_MATERIAL_BYTES),
30
+ watchRatio,
31
+ };
32
+ const rootEvents = rootSnapshot(rootPath, rootThresholds, positiveInt(opts.protectRootTailEvents, RETENTION_DEFAULT_ROOT_TAIL_EVENTS));
33
+ const material = materialSnapshot(materialPath, cursorPath, materialThresholds);
34
+ const warnings = buildWarnings(rootEvents, material);
35
+ const nextActions = buildNextActions(rootEvents, material);
36
+ return {
37
+ generatedAt: now,
38
+ mode: 'read_only_policy',
39
+ destructivePruneSupported: false,
40
+ rootEvents,
41
+ material,
42
+ warnings,
43
+ nextActions,
44
+ };
45
+ }
46
+ function rootSnapshot(path, thresholds, protectTailEvents) {
47
+ const stats = readJsonl(path, (value) => rootEvent.parse(value));
48
+ return {
49
+ name: 'root_events',
50
+ exists: stats.exists,
51
+ bytes: stats.bytes,
52
+ records: stats.records,
53
+ invalidLines: stats.invalidLines,
54
+ state: retentionState(stats.records, stats.bytes, thresholds),
55
+ thresholds,
56
+ firstSeq: stats.first?.seq ?? null,
57
+ lastSeq: stats.last?.seq ?? null,
58
+ firstTs: stats.first?.ts ?? null,
59
+ lastTs: stats.last?.ts ?? null,
60
+ protectTailEvents: Math.min(stats.records, protectTailEvents),
61
+ destructivePruneSafe: false,
62
+ reason: 'root_events is the replay and audit source; archive readers must exist before destructive prune is safe',
63
+ };
64
+ }
65
+ function materialSnapshot(path, cursorPath, thresholds) {
66
+ const stats = readJsonl(path, (value) => material.parse(value));
67
+ const cursor = readCycleCursor(cursorPath);
68
+ const cursorInRange = cursor.value >= 0 && cursor.value <= stats.records;
69
+ const effectiveCursor = cursorInRange ? cursor.value : clampCursor(cursor.value, stats.records);
70
+ return {
71
+ name: 'material',
72
+ exists: stats.exists,
73
+ bytes: stats.bytes,
74
+ records: stats.records,
75
+ invalidLines: stats.invalidLines,
76
+ state: retentionState(stats.records, stats.bytes, thresholds),
77
+ thresholds,
78
+ firstCapturedAt: stats.first?.capturedAt ?? null,
79
+ lastCapturedAt: stats.last?.capturedAt ?? null,
80
+ cursorValid: cursor.valid,
81
+ cursorInRange,
82
+ cursor: cursor.value,
83
+ effectiveCursor,
84
+ consumedPrefix: effectiveCursor,
85
+ pending: Math.max(0, stats.records - effectiveCursor),
86
+ destructivePruneSafe: false,
87
+ reason: 'material cursor is index-based; prune requires atomic archive plus cursor rewrite',
88
+ };
89
+ }
90
+ function readJsonl(path, parse) {
91
+ if (!existsSync(path)) {
92
+ return { exists: false, bytes: 0, records: 0, invalidLines: 0, first: null, last: null };
93
+ }
94
+ const bytes = statSync(path).size;
95
+ let records = 0;
96
+ let invalidLines = 0;
97
+ let first = null;
98
+ let last = null;
99
+ for (const line of readFileSync(path, 'utf8').split('\n')) {
100
+ if (!line)
101
+ continue;
102
+ try {
103
+ const parsed = parse(JSON.parse(line));
104
+ first ??= parsed;
105
+ last = parsed;
106
+ records += 1;
107
+ }
108
+ catch {
109
+ invalidLines += 1;
110
+ }
111
+ }
112
+ return { exists: true, bytes, records, invalidLines, first, last };
113
+ }
114
+ function readCycleCursor(path) {
115
+ if (!existsSync(path))
116
+ return { exists: false, valid: true, value: 0 };
117
+ try {
118
+ const parsed = JSON.parse(readFileSync(path, 'utf8'));
119
+ if (typeof parsed.cycle === 'number' && Number.isFinite(parsed.cycle)) {
120
+ return { exists: true, valid: true, value: Math.floor(parsed.cycle) };
121
+ }
122
+ return { exists: true, valid: false, value: 0 };
123
+ }
124
+ catch {
125
+ return { exists: true, valid: false, value: 0 };
126
+ }
127
+ }
128
+ function retentionState(records, bytes, thresholds) {
129
+ if (records > thresholds.maxRecords || bytes > thresholds.maxBytes)
130
+ return 'over_limit';
131
+ if (records >= thresholds.maxRecords * thresholds.watchRatio || bytes >= thresholds.maxBytes * thresholds.watchRatio)
132
+ return 'watch';
133
+ return 'ok';
134
+ }
135
+ function buildWarnings(root, mat) {
136
+ const out = [];
137
+ if (root.invalidLines > 0)
138
+ out.push(`root_events has ${root.invalidLines} invalid jsonl line(s); recover before rotating`);
139
+ if (mat.invalidLines > 0)
140
+ out.push(`material store has ${mat.invalidLines} invalid jsonl line(s); inspect before rotating`);
141
+ if (!mat.cursorValid)
142
+ out.push('material cursor is unreadable; retention uses effectiveCursor=0 until the cursor is repaired');
143
+ if (mat.cursorValid && !mat.cursorInRange)
144
+ out.push(`material cursor ${mat.cursor} is outside material record range 0..${mat.records}; retention uses effectiveCursor=${mat.effectiveCursor}`);
145
+ if (root.state === 'over_limit')
146
+ out.push('root_events exceeds retention thresholds; plan archive support before deleting audit lines');
147
+ if (mat.state === 'over_limit')
148
+ out.push('material store exceeds retention thresholds; archive consumed prefix only with cursor rewrite');
149
+ if (mat.pending > 0)
150
+ out.push(`material store has ${mat.pending} pending record(s); do not prune pending material`);
151
+ return out;
152
+ }
153
+ function buildNextActions(root, mat) {
154
+ const out = [
155
+ 'keep destructive prune disabled until archive readers are wired into reports, replay and cycle recovery',
156
+ ];
157
+ if (root.state !== 'ok')
158
+ out.push(`root_events ${root.state}: keep at least the last ${root.protectTailEvents} event(s) active after future archive`);
159
+ if (!mat.cursorValid || !mat.cursorInRange)
160
+ out.push('material: repair the cycle cursor before archiving consumed material');
161
+ if (mat.consumedPrefix > 0)
162
+ out.push(`material: ${mat.consumedPrefix} consumed prefix record(s) are archive candidates after atomic cursor rewrite exists`);
163
+ if (mat.pending > 0)
164
+ out.push('material: process or inspect pending records before any future prune');
165
+ return out;
166
+ }
167
+ function positiveInt(value, fallback) {
168
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
169
+ }
170
+ function ratioOf(value, fallback) {
171
+ if (typeof value !== 'number' || !Number.isFinite(value))
172
+ return fallback;
173
+ return Math.min(0.99, Math.max(0.1, value));
174
+ }
175
+ function clampCursor(value, records) {
176
+ return Math.min(records, Math.max(0, Math.floor(value)));
177
+ }
@@ -0,0 +1,5 @@
1
+ import type { RootEvent } from './eventSchema.js';
2
+ /** ingest 成功落盘后的 fan-out 接收口 (observer bus 实现之). */
3
+ export interface EventSink {
4
+ dispatch(event: RootEvent): void;
5
+ }
@@ -0,0 +1 @@
1
+ export {};