@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,150 @@
1
+ function summarize(arm, samples) {
2
+ const n = samples.length;
3
+ if (n === 0)
4
+ return { arm, n: 0, passes: 0, passRate: 0, avgCost: 0, reuseRate: 0 };
5
+ const passes = samples.filter((s) => s.passed).length;
6
+ return {
7
+ arm,
8
+ n,
9
+ passes,
10
+ passRate: passes / n,
11
+ reuseRate: samples.filter((s) => s.reusedGene).length / n,
12
+ avgCost: samples.reduce((a, s) => a + s.cost, 0) / n,
13
+ };
14
+ }
15
+ /** Normal CDF via an Abramowitz-Stegun erf approximation — deterministic, no stats dependency, ample precision
16
+ * for a p-value gate (|error| < 1.5e-7). Used for the two-sided p-value of the two-proportion z test. */
17
+ function normalCdf(x) {
18
+ const t = 1 / (1 + 0.2316419 * Math.abs(x));
19
+ const d = 0.3989422804014327 * Math.exp((-x * x) / 2);
20
+ const p = d * t * (0.31938153 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));
21
+ return x >= 0 ? 1 - p : p;
22
+ }
23
+ /** Inverse normal CDF (Acklam's rational approximation) — for the (1 − alpha) CI's critical value, so alpha is
24
+ * honoured rather than hard-coding z=1.96. Domain (0,1); deterministic. */
25
+ function normalQuantile(p) {
26
+ if (p <= 0)
27
+ return -Infinity;
28
+ if (p >= 1)
29
+ return Infinity;
30
+ const a = [-3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2, 1.38357751867269e2, -3.066479806614716e1, 2.506628277459239];
31
+ const b = [-5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2, 6.680131188771972e1, -1.328068155288572e1];
32
+ const c = [-7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838, -2.549732539343734, 4.374664141464968, 2.938163982698783];
33
+ const d = [7.784695709041462e-3, 3.224671290700398e-1, 2.445134137142996, 3.754408661907416];
34
+ const pLow = 0.02425;
35
+ if (p < pLow) {
36
+ const q = Math.sqrt(-2 * Math.log(p));
37
+ return (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
38
+ }
39
+ if (p <= 1 - pLow) {
40
+ const q = p - 0.5;
41
+ const r = q * q;
42
+ return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1);
43
+ }
44
+ const q = Math.sqrt(-2 * Math.log(1 - p));
45
+ return -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
46
+ }
47
+ /** Two-proportion test of (evolver − baseline) pass rates. Significance uses the POOLED-variance z test (the
48
+ * standard test of H0: p1 = p2); the reported CI uses the UNPOOLED (Wald) standard error (the standard interval
49
+ * for the difference). Zero pooled variance (both arms all-pass or all-fail) → no testable difference. */
50
+ function twoProportionTest(x1, n1, x2, n2, alpha) {
51
+ const p1 = x1 / n1;
52
+ const p2 = x2 / n2;
53
+ const delta = p1 - p2;
54
+ const pooled = (x1 + x2) / (n1 + n2);
55
+ const sePooled = Math.sqrt(pooled * (1 - pooled) * (1 / n1 + 1 / n2));
56
+ const z = sePooled > 0 ? delta / sePooled : 0;
57
+ const pValue = sePooled > 0 ? 2 * (1 - normalCdf(Math.abs(z))) : 1;
58
+ const zCrit = normalQuantile(1 - alpha / 2);
59
+ const seWald = Math.sqrt((p1 * (1 - p1)) / n1 + (p2 * (1 - p2)) / n2);
60
+ return { z, pValue, significant: pValue <= alpha, ciLow: delta - zCrit * seWald, ciHigh: delta + zCrit * seWald };
61
+ }
62
+ /**
63
+ * Achieved power + the per-arm sample size needed to call the experiment "powered". Answers what a bare
64
+ * `no_significant_diff` cannot: was an effect of the minimum interesting size (minDelta) likely to be DETECTED at
65
+ * this n, or is the null just underpowered? Plans around the OBSERVED baseline rate using the two-proportion
66
+ * normal approximation; equal-n via the harmonic mean of the two arms (so unequal arms degrade gracefully).
67
+ */
68
+ function powerAnalysis(baselineRate, minDelta, n1, n2, alpha, targetPower) {
69
+ const delta = Math.abs(minDelta);
70
+ if (delta <= 0)
71
+ return { power: 0, requiredN: Infinity }; // no effect size to power for
72
+ const p2 = Math.min(1, Math.max(0, baselineRate));
73
+ const p1 = Math.min(1, Math.max(0, p2 + delta));
74
+ // EFFECTIVE effect size after clamping to [0,1]: a minDelta lift off a near-ceiling baseline isn't fully
75
+ // achievable (p1 caps at 1), so the realizable effect is p1 - p2 <= minDelta. Using the raw minDelta here would
76
+ // overstate power and understate requiredN (Bugbot #286). At the ceiling (p2=1) there is no headroom at all.
77
+ const effDelta = p1 - p2;
78
+ if (effDelta <= 0)
79
+ return { power: 0, requiredN: Infinity };
80
+ const pbar = (p1 + p2) / 2;
81
+ const varNull = 2 * pbar * (1 - pbar); // pooled-null variance (numerator uses sqrt of this)
82
+ const varAlt = p1 * (1 - p1) + p2 * (1 - p2); // alternative variance (the two arms' combined spread)
83
+ const za = normalQuantile(1 - alpha / 2);
84
+ const zb = normalQuantile(targetPower);
85
+ const nEff = n1 > 0 && n2 > 0 ? 2 / (1 / n1 + 1 / n2) : 0;
86
+ let power = 0;
87
+ if (nEff > 0) {
88
+ const seAlt = Math.sqrt(varAlt / nEff);
89
+ // Perfect separation (both arms at a 0/1 boundary) has zero alt-variance → the effect is detectable with
90
+ // certainty; otherwise the standard upper-tail power of the two-proportion z test.
91
+ power = seAlt > 0 ? normalCdf((effDelta - za * Math.sqrt(varNull / nEff)) / seAlt) : 1;
92
+ }
93
+ const num = za * Math.sqrt(varNull) + zb * Math.sqrt(varAlt);
94
+ return { power: Math.min(1, Math.max(0, power)), requiredN: Math.ceil((num * num) / (effDelta * effDelta)) };
95
+ }
96
+ /**
97
+ * Run both arms over the same task suite and compare. A verdict of evolver_better/worse requires BOTH a practical
98
+ * delta (|passRateDelta| >= minPassRateDelta) AND statistical significance (two-proportion test p <= alpha);
99
+ * otherwise no_significant_diff. reuseRate and costDelta are reported, never scored.
100
+ */
101
+ export async function runThesis(suite, solver, opts = {}) {
102
+ const minDelta = opts.minPassRateDelta ?? 0.05;
103
+ const minSamples = opts.minSamples ?? 30;
104
+ const alpha = opts.alpha ?? 0.05;
105
+ const targetPower = opts.targetPower ?? 0.8;
106
+ const baselineSamples = [];
107
+ const evolverSamples = [];
108
+ if (opts.interleave) {
109
+ for (const task of suite.tasks) {
110
+ baselineSamples.push(await solver(task, 'baseline'));
111
+ evolverSamples.push(await solver(task, 'evolver'));
112
+ }
113
+ }
114
+ else {
115
+ for (const task of suite.tasks)
116
+ baselineSamples.push(await solver(task, 'baseline'));
117
+ for (const task of suite.tasks)
118
+ evolverSamples.push(await solver(task, 'evolver'));
119
+ }
120
+ const baseline = summarize('baseline', baselineSamples);
121
+ const evolver = summarize('evolver', evolverSamples);
122
+ const passRateDelta = evolver.passRate - baseline.passRate;
123
+ const costDelta = evolver.avgCost - baseline.avgCost;
124
+ // Power read of the result: with the observed baseline rate and this n, could a minDelta effect have been seen?
125
+ const { power, requiredN } = powerAnalysis(baseline.passRate, minDelta, baseline.n, evolver.n, alpha, targetPower);
126
+ // Two-proportion significance test of (evolver − baseline). Guarded against n=0 (only reachable when minSamples
127
+ // is forced to 0); an empty arm has no testable difference. Otherwise this is the gate that stops a verdict from
128
+ // riding on sampling noise.
129
+ const test = baseline.n > 0 && evolver.n > 0
130
+ ? twoProportionTest(evolver.passes, evolver.n, baseline.passes, baseline.n, alpha)
131
+ : { z: 0, pValue: 1, significant: false, ciLow: passRateDelta, ciHigh: passRateDelta };
132
+ // Verdict needs BOTH bars: a practical delta (>= minDelta) AND statistical significance (p <= alpha). A 5pt
133
+ // delta at n=30 is ~0.4σ — well inside noise — so the practical bar alone could call noise a win; the
134
+ // significance bar is what makes the headline thesis number defensible.
135
+ let verdict;
136
+ if (baseline.n < minSamples || evolver.n < minSamples)
137
+ verdict = 'insufficient_samples';
138
+ else if (test.significant && passRateDelta >= minDelta)
139
+ verdict = 'evolver_better';
140
+ else if (test.significant && passRateDelta <= -minDelta)
141
+ verdict = 'evolver_worse';
142
+ else
143
+ verdict = 'no_significant_diff';
144
+ return {
145
+ suite: suite.name, baseline, evolver, passRateDelta, costDelta,
146
+ z: test.z, pValue: test.pValue, significant: test.significant, ciLow: test.ciLow, ciHigh: test.ciHigh,
147
+ power, requiredN,
148
+ verdict,
149
+ };
150
+ }
@@ -0,0 +1,45 @@
1
+ export interface EnvFingerprint {
2
+ /** sha256(hostname)[:12] — stable per machine, not reversible. */
3
+ device: string;
4
+ node_version: string;
5
+ platform: string;
6
+ arch: string;
7
+ os_release: string;
8
+ /** EVOLVER_REGION (<=5 chars, lowercased). */
9
+ region?: string;
10
+ container: boolean;
11
+ /**
12
+ * Underlying LLM model (detectModelName()): explicit EVOLVER_MODEL_NAME, else a host CLI's model env var,
13
+ * else the literal 'unknown'. Deliberately NOT folded into envFingerprintKey() — a node can swap models
14
+ * without changing its environment class, so the grouping key stays model-independent; the model travels
15
+ * as its own field (e.g. so the Hub can index assets by model / feed the by-model leaderboard).
16
+ */
17
+ model: string;
18
+ }
19
+ export interface EnvCaptureDeps {
20
+ platform?: string;
21
+ arch?: string;
22
+ nodeVersion?: string;
23
+ osRelease?: string;
24
+ hostname?: string;
25
+ env?: Record<string, string | undefined>;
26
+ isContainer?: () => boolean;
27
+ }
28
+ /**
29
+ * Resolve the underlying LLM model name powering this evolver node (ported from v1 PR #174). Until now the
30
+ * only source was the explicit EVOLVER_MODEL_NAME, so nodes that never set it published assets with no model
31
+ * at all — the Hub could not tell which model produced a Gene/Capsule, starving the by-model leaderboard and
32
+ * depriving anti-sybil clustering of a strong signal. We now fall back to the model env vars the common host
33
+ * CLIs expose. When nothing is discoverable we return the literal 'unknown' rather than null/'' so downstream
34
+ * aggregation always has a stable, groupable value and can distinguish "ran but model undetectable" from
35
+ * "field absent (old client)".
36
+ */
37
+ export declare function detectModelName(env?: Record<string, string | undefined>): string;
38
+ /** Capture the current runtime environment fingerprint. */
39
+ export declare function captureEnvFingerprint(deps?: EnvCaptureDeps): EnvFingerprint;
40
+ /**
41
+ * Stable "environment class" key for grouping — two nodes with the same key are the same environment class.
42
+ * Used by epigenetics to bucket a gene's per-environment success/failure (e.g. a gene that only fails on
43
+ * win32/arm64 is suppressed there, not globally).
44
+ */
45
+ export declare function envFingerprintKey(fp: EnvFingerprint): string;
@@ -0,0 +1,72 @@
1
+ // Environment fingerprint capture (ported from v1 src/gep/envFingerprint.js). Captures the runtime
2
+ // environment (node/platform/arch/os/region/container/model) so an outcome can be attributed to an
3
+ // "environment class" — the prerequisite for epigenetic per-environment gene suppression and for GDI scoring.
4
+ // Privacy: hostname is sha256-truncated, never stored in clear. os/process reads are injectable for tests.
5
+ import { hostname as osHostname, release as osRelease } from 'node:os';
6
+ import { existsSync } from 'node:fs';
7
+ import { createHash } from 'node:crypto';
8
+ const sha12 = (s) => createHash('sha256').update(s).digest('hex').slice(0, 12);
9
+ /** Heuristic container detection (Docker / Kubernetes). */
10
+ function detectContainer(env) {
11
+ if (env['KUBERNETES_SERVICE_HOST'])
12
+ return true;
13
+ try {
14
+ if (existsSync('/.dockerenv'))
15
+ return true;
16
+ }
17
+ catch { /* not on a filesystem with it */ }
18
+ return false;
19
+ }
20
+ // Env vars that expose the underlying LLM model, in priority order. EVOLVER_MODEL_NAME is the explicit
21
+ // operator override; the rest are what the common host CLIs (Claude Code / Codex / Cursor / generic
22
+ // OpenAI-compatible runners) set. First non-empty wins.
23
+ const MODEL_ENV_VARS = [
24
+ 'EVOLVER_MODEL_NAME',
25
+ 'ANTHROPIC_MODEL',
26
+ 'CLAUDE_MODEL',
27
+ 'CLAUDE_CODE_MODEL',
28
+ 'OPENAI_MODEL',
29
+ 'CODEX_MODEL',
30
+ 'CURSOR_MODEL',
31
+ ];
32
+ /**
33
+ * Resolve the underlying LLM model name powering this evolver node (ported from v1 PR #174). Until now the
34
+ * only source was the explicit EVOLVER_MODEL_NAME, so nodes that never set it published assets with no model
35
+ * at all — the Hub could not tell which model produced a Gene/Capsule, starving the by-model leaderboard and
36
+ * depriving anti-sybil clustering of a strong signal. We now fall back to the model env vars the common host
37
+ * CLIs expose. When nothing is discoverable we return the literal 'unknown' rather than null/'' so downstream
38
+ * aggregation always has a stable, groupable value and can distinguish "ran but model undetectable" from
39
+ * "field absent (old client)".
40
+ */
41
+ export function detectModelName(env = (typeof process !== 'undefined' ? process.env : {})) {
42
+ for (const key of MODEL_ENV_VARS) {
43
+ const v = (env[key] ?? '').trim();
44
+ if (v)
45
+ return v.slice(0, 100);
46
+ }
47
+ return 'unknown';
48
+ }
49
+ /** Capture the current runtime environment fingerprint. */
50
+ export function captureEnvFingerprint(deps = {}) {
51
+ const env = deps.env ?? (typeof process !== 'undefined' ? process.env : {});
52
+ const region = (env['EVOLVER_REGION'] ?? '').trim().toLowerCase().slice(0, 5) || undefined;
53
+ return {
54
+ device: sha12(deps.hostname ?? osHostname()),
55
+ node_version: deps.nodeVersion ?? process.version,
56
+ platform: deps.platform ?? process.platform,
57
+ arch: deps.arch ?? process.arch,
58
+ os_release: deps.osRelease ?? osRelease(),
59
+ ...(region ? { region } : {}),
60
+ container: deps.isContainer ? deps.isContainer() : detectContainer(env),
61
+ model: detectModelName(env),
62
+ };
63
+ }
64
+ /**
65
+ * Stable "environment class" key for grouping — two nodes with the same key are the same environment class.
66
+ * Used by epigenetics to bucket a gene's per-environment success/failure (e.g. a gene that only fails on
67
+ * win32/arm64 is suppressed there, not globally).
68
+ */
69
+ export function envFingerprintKey(fp) {
70
+ const nodeMajor = (fp.node_version || '').replace(/^v/, '').split('.')[0] ?? '';
71
+ return [fp.platform, fp.arch, `node${nodeMajor}`, fp.region ?? '', fp.device].join('|');
72
+ }
@@ -0,0 +1,2 @@
1
+ export * from './selfEvolve.js';
2
+ export * from './envFingerprint.js';
@@ -0,0 +1,2 @@
1
+ export * from './selfEvolve.js';
2
+ export * from './envFingerprint.js';
@@ -0,0 +1,36 @@
1
+ export type RunMode = 'normal' | 'self-evolve';
2
+ /** 自进化预设(seed gene / self-PR 目标 / 硬编码根). 只在 self-evolve 模式加载, 不进默认主流程. */
3
+ export interface EvolvePreset {
4
+ name: string;
5
+ seedGenes: readonly string[];
6
+ selfPrTarget?: {
7
+ repo: string;
8
+ branchPrefix: string;
9
+ };
10
+ ownedRoots?: readonly string[];
11
+ }
12
+ export interface BootstrapInput {
13
+ mode: RunMode;
14
+ preset?: EvolvePreset;
15
+ }
16
+ export interface ResolvedBootstrap {
17
+ mode: RunMode;
18
+ isSelfEvolve: boolean;
19
+ projectAgnostic: boolean;
20
+ preset: EvolvePreset | null;
21
+ }
22
+ export declare class BootstrapModeError extends Error {
23
+ constructor(message: string);
24
+ }
25
+ /**
26
+ * 解析运行模式(M4A-6, 批注#23). 关键不变量:
27
+ * - **显式**: 模式来自子命令/flag, 不再 isInsideEvolverRepo 自动探测(v1 自举泄漏根因).
28
+ * - **默认项目无关**: normal 模式拒绝任何 preset/self 目标, 主流程对所有项目一视同仁.
29
+ * - self-evolve 必须显式带 preset(seed gene / self-PR 目标拆到此).
30
+ */
31
+ export declare function resolveBootstrap(input: BootstrapInput): ResolvedBootstrap;
32
+ /**
33
+ * 解析子命令为模式. **不读 cwd / 不探测仓库**(显式优先, 去 v1 隐形约定).
34
+ * `evolver self-evolve ...` → self-evolve; 其余 → normal.
35
+ */
36
+ export declare function parseRunMode(argv: readonly string[]): RunMode;
@@ -0,0 +1,26 @@
1
+ export class BootstrapModeError extends Error {
2
+ constructor(message) { super(message); this.name = 'BootstrapModeError'; }
3
+ }
4
+ /**
5
+ * 解析运行模式(M4A-6, 批注#23). 关键不变量:
6
+ * - **显式**: 模式来自子命令/flag, 不再 isInsideEvolverRepo 自动探测(v1 自举泄漏根因).
7
+ * - **默认项目无关**: normal 模式拒绝任何 preset/self 目标, 主流程对所有项目一视同仁.
8
+ * - self-evolve 必须显式带 preset(seed gene / self-PR 目标拆到此).
9
+ */
10
+ export function resolveBootstrap(input) {
11
+ if (input.mode === 'normal') {
12
+ if (input.preset)
13
+ throw new BootstrapModeError('normal 模式不得携带 preset(防 EvoMap/self 硬编码泄漏进默认主流程)');
14
+ return { mode: 'normal', isSelfEvolve: false, projectAgnostic: true, preset: null };
15
+ }
16
+ if (!input.preset)
17
+ throw new BootstrapModeError('self-evolve 模式必须显式提供 preset(seed gene / self-PR 目标)');
18
+ return { mode: 'self-evolve', isSelfEvolve: true, projectAgnostic: false, preset: input.preset };
19
+ }
20
+ /**
21
+ * 解析子命令为模式. **不读 cwd / 不探测仓库**(显式优先, 去 v1 隐形约定).
22
+ * `evolver self-evolve ...` → self-evolve; 其余 → normal.
23
+ */
24
+ export function parseRunMode(argv) {
25
+ return argv[0] === 'self-evolve' ? 'self-evolve' : 'normal';
26
+ }
@@ -0,0 +1,35 @@
1
+ import type { Projector } from '../events/replayer.js';
2
+ import { type CycleStage } from './stateMachine.js';
3
+ import { type CycleFailureClass } from '../algo/cycleFailureClassifier.js';
4
+ export interface CycleRecord {
5
+ cycleId: string;
6
+ stage: CycleStage;
7
+ startedAt: string | null;
8
+ endedAt: string | null;
9
+ decisionWhy: string | null;
10
+ geneId: string | null;
11
+ mutationId: string | null;
12
+ capsuleId: string | null;
13
+ outcome: {
14
+ status: string;
15
+ score: number;
16
+ } | null;
17
+ failureClass: CycleFailureClass | null;
18
+ failureSuppressed: boolean;
19
+ signalCount: number;
20
+ eventSeqs: number[];
21
+ illegalTransitions: {
22
+ from: CycleStage;
23
+ eventType: string;
24
+ seq: number;
25
+ }[];
26
+ }
27
+ export interface CycleTimelineMV {
28
+ cycles: Record<string, CycleRecord>;
29
+ order: string[];
30
+ }
31
+ /** cycle timeline MV (军杰§9.3). 每 cycle 一条记录, 状态机校验非法转移. */
32
+ export declare const cycleTimelineProjector: Projector<CycleTimelineMV>;
33
+ export declare function liveCycles(mv: CycleTimelineMV): CycleRecord[];
34
+ export declare function latestCycles(mv: CycleTimelineMV, n?: number): CycleRecord[];
35
+ export declare function historicalCycles(mv: CycleTimelineMV): CycleRecord[];
@@ -0,0 +1,74 @@
1
+ import { TERMINAL, stageForEventType, canTransition } from './stateMachine.js';
2
+ import { HOST_SUPPRESS_CLASSES } from '../algo/cycleFailureClassifier.js';
3
+ function newRecord(cycleId) {
4
+ return {
5
+ cycleId, stage: 'none', startedAt: null, endedAt: null, decisionWhy: null,
6
+ geneId: null, mutationId: null, capsuleId: null, outcome: null, failureClass: null, failureSuppressed: false,
7
+ signalCount: 0, eventSeqs: [], illegalTransitions: [],
8
+ };
9
+ }
10
+ function applyFields(rec, e, to) {
11
+ const p = (e.payload ?? {});
12
+ const r = { ...rec, stage: to, eventSeqs: [...rec.eventSeqs, e.seq] };
13
+ if (to === 'started')
14
+ r.startedAt = e.ts;
15
+ if (TERMINAL.has(to))
16
+ r.endedAt = e.ts;
17
+ if (to === 'gene_selected') {
18
+ r.decisionWhy = e.human.why ?? null;
19
+ r.geneId = p.geneId ?? null;
20
+ }
21
+ if (to === 'mutation_built')
22
+ r.mutationId = p.mutationId ?? null;
23
+ if (to === 'signals_collected')
24
+ r.signalCount = p.signalCount ?? rec.signalCount;
25
+ if (to === 'solidified') {
26
+ r.capsuleId = p.capsuleId ?? null;
27
+ r.outcome = p.outcome ?? null;
28
+ }
29
+ if (to === 'failed' || to === 'aborted')
30
+ r.outcome = p.outcome ?? rec.outcome;
31
+ if (to === 'failed' && typeof p.failure_class === 'string') {
32
+ const failureClass = p.failure_class;
33
+ r.failureClass = failureClass;
34
+ r.failureSuppressed = HOST_SUPPRESS_CLASSES.has(failureClass);
35
+ }
36
+ return r;
37
+ }
38
+ /** cycle timeline MV (军杰§9.3). 每 cycle 一条记录, 状态机校验非法转移. */
39
+ export const cycleTimelineProjector = {
40
+ name: 'cycle_timeline',
41
+ initial: () => ({ cycles: {}, order: [] }),
42
+ reduce: (state, e) => {
43
+ const p = (e.payload ?? {});
44
+ const cycleId = p.cycleId;
45
+ if (!cycleId)
46
+ return state;
47
+ const exists = cycleId in state.cycles;
48
+ const rec = state.cycles[cycleId] ?? newRecord(cycleId);
49
+ const to = stageForEventType(e.type);
50
+ let next;
51
+ if (to === null) {
52
+ next = { ...rec, eventSeqs: [...rec.eventSeqs, e.seq] }; // cycle 内非 stage 事件: 仅记 seq
53
+ }
54
+ else if (!canTransition(rec.stage, to)) {
55
+ next = { ...rec, eventSeqs: [...rec.eventSeqs, e.seq], illegalTransitions: [...rec.illegalTransitions, { from: rec.stage, eventType: e.type, seq: e.seq }] };
56
+ }
57
+ else {
58
+ next = applyFields(rec, e, to);
59
+ }
60
+ return {
61
+ cycles: { ...state.cycles, [cycleId]: next },
62
+ order: exists ? state.order : [...state.order, cycleId],
63
+ };
64
+ },
65
+ };
66
+ export function liveCycles(mv) {
67
+ return mv.order.map((id) => mv.cycles[id]).filter((c) => !TERMINAL.has(c.stage));
68
+ }
69
+ export function latestCycles(mv, n = 10) {
70
+ return mv.order.slice(-n).map((id) => mv.cycles[id]);
71
+ }
72
+ export function historicalCycles(mv) {
73
+ return mv.order.map((id) => mv.cycles[id]);
74
+ }
@@ -0,0 +1,2 @@
1
+ export * from './stateMachine.js';
2
+ export * from './cycleTimeline.js';
@@ -0,0 +1,2 @@
1
+ export * from './stateMachine.js';
2
+ export * from './cycleTimeline.js';
@@ -0,0 +1,6 @@
1
+ /** cycle 状态机 (军杰§9.3). */
2
+ export type CycleStage = 'none' | 'started' | 'signals_collected' | 'gene_selected' | 'mutation_built' | 'solidified' | 'failed' | 'aborted';
3
+ export declare const TERMINAL: ReadonlySet<CycleStage>;
4
+ /** 事件类型 → 它把 cycle 推进到的 stage (非 stage 事件返回 null). */
5
+ export declare function stageForEventType(type: string): CycleStage | null;
6
+ export declare function canTransition(from: CycleStage, to: CycleStage): boolean;
@@ -0,0 +1,25 @@
1
+ export const TERMINAL = new Set(['solidified', 'failed', 'aborted']);
2
+ const ALLOWED = {
3
+ none: ['started'],
4
+ started: ['signals_collected', 'gene_selected', 'failed', 'aborted'],
5
+ signals_collected: ['gene_selected', 'failed', 'aborted'],
6
+ gene_selected: ['mutation_built', 'solidified', 'failed', 'aborted'],
7
+ mutation_built: ['solidified', 'failed', 'aborted'],
8
+ solidified: [], failed: [], aborted: [],
9
+ };
10
+ /** 事件类型 → 它把 cycle 推进到的 stage (非 stage 事件返回 null). */
11
+ export function stageForEventType(type) {
12
+ switch (type) {
13
+ case 'cycle.started': return 'started';
14
+ case 'cycle.signals_collected': return 'signals_collected';
15
+ case 'decision.gene_selected': return 'gene_selected';
16
+ case 'mutation.built': return 'mutation_built';
17
+ case 'cycle.solidified': return 'solidified';
18
+ case 'cycle.failed': return 'failed';
19
+ case 'cycle.aborted': return 'aborted';
20
+ default: return null;
21
+ }
22
+ }
23
+ export function canTransition(from, to) {
24
+ return ALLOWED[from].includes(to);
25
+ }
@@ -0,0 +1,12 @@
1
+ /** 闸1: cycle-local 状态每轮 reset (D15/军杰附录A). 新 cycle = 新 context, 结束销毁. */
2
+ export declare class CycleContext {
3
+ readonly cycleId: string;
4
+ private readonly local;
5
+ private disposed;
6
+ constructor(cycleId: string);
7
+ set<T>(k: string, v: T): void;
8
+ get<T>(k: string): T | undefined;
9
+ has(k: string): boolean;
10
+ dispose(): void;
11
+ private assertLive;
12
+ }
@@ -0,0 +1,13 @@
1
+ /** 闸1: cycle-local 状态每轮 reset (D15/军杰附录A). 新 cycle = 新 context, 结束销毁. */
2
+ export class CycleContext {
3
+ cycleId;
4
+ local = new Map();
5
+ disposed = false;
6
+ constructor(cycleId) { this.cycleId = cycleId; }
7
+ set(k, v) { this.assertLive(); this.local.set(k, v); }
8
+ get(k) { return this.local.get(k); }
9
+ has(k) { return this.local.has(k); }
10
+ dispose() { this.local.clear(); this.disposed = true; }
11
+ assertLive() { if (this.disposed)
12
+ throw new Error('CycleContext 已销毁: cycle-local 不可跨 cycle'); }
13
+ }
@@ -0,0 +1,11 @@
1
+ /** 闸2: drain 升级(禁 hot reload). 停接新 cycle, 排空进行中, 安全退出. */
2
+ export declare class DrainController {
3
+ private draining;
4
+ private active;
5
+ acceptCycle(): boolean;
6
+ beginCycle(): void;
7
+ endCycle(): void;
8
+ drain(pollMs?: number): Promise<void>;
9
+ get isDraining(): boolean;
10
+ get activeCount(): number;
11
+ }
@@ -0,0 +1,16 @@
1
+ /** 闸2: drain 升级(禁 hot reload). 停接新 cycle, 排空进行中, 安全退出. */
2
+ export class DrainController {
3
+ draining = false;
4
+ active = 0;
5
+ acceptCycle() { return !this.draining; }
6
+ beginCycle() { if (this.draining)
7
+ throw new Error('draining: 不接新 cycle'); this.active += 1; }
8
+ endCycle() { this.active = Math.max(0, this.active - 1); }
9
+ async drain(pollMs = 5) {
10
+ this.draining = true;
11
+ while (this.active > 0)
12
+ await new Promise((r) => { setTimeout(r, pollMs); });
13
+ }
14
+ get isDraining() { return this.draining; }
15
+ get activeCount() { return this.active; }
16
+ }
@@ -0,0 +1,87 @@
1
+ export interface SystemLoad {
2
+ load1m: number;
3
+ load5m: number;
4
+ load15m: number;
5
+ }
6
+ /** Clamp os.loadavg() to at most 2× cores so a misreported sample (Windows zeros, Termux process-counters) can't force a permanent backoff. */
7
+ export declare function clampSystemLoad(loadavg: readonly [number, number, number], cpuCount: number): SystemLoad;
8
+ /** Sensible default load ceiling for N cores (reserve ~10% headroom); floors CPU count so it's never 0. */
9
+ export declare function defaultLoadMax(cpuCount: number): number;
10
+ export interface YieldDecision {
11
+ yield: boolean;
12
+ reason: string;
13
+ ageMs?: number;
14
+ }
15
+ /**
16
+ * Cooperative `.evolver.lock`: a human (release script, IDE refactor) drops the file to make the daemon yield;
17
+ * whoever drops it removes it. A lock older than ttlMs is ignored (forgotten lock won't dormant the daemon
18
+ * forever). A future mtime (clock skew) counts as fresh. Pure — caller supplies presence + mtime.
19
+ */
20
+ export declare function evaluateUserLock(input: {
21
+ present: boolean;
22
+ mtimeMs?: number;
23
+ now: number;
24
+ ttlMs: number;
25
+ }): YieldDecision;
26
+ /**
27
+ * Release-window quiet period: if the last commit is a release bump (chore(release)…), a human is mid-deploy —
28
+ * yield until the window passes so the daemon doesn't dirty the tree under a publish. windowMs===0 disables.
29
+ * Pure — caller supplies the last commit subject + unix ts.
30
+ */
31
+ export declare function evaluateReleaseWindow(input: {
32
+ lastCommitSubject?: string;
33
+ lastCommitUnixTs?: number;
34
+ now: number;
35
+ windowMs: number;
36
+ }): YieldDecision;
37
+ export interface GuardInput {
38
+ now: number;
39
+ lock?: {
40
+ present: boolean;
41
+ mtimeMs?: number;
42
+ ttlMs?: number;
43
+ };
44
+ release?: {
45
+ lastCommitSubject?: string;
46
+ lastCommitUnixTs?: number;
47
+ windowMs?: number;
48
+ };
49
+ load?: {
50
+ load1m: number;
51
+ max?: number;
52
+ cpuCount?: number;
53
+ };
54
+ }
55
+ export interface GuardDecision {
56
+ yield: boolean;
57
+ reason: string;
58
+ detail?: Record<string, unknown>;
59
+ }
60
+ /**
61
+ * Combine the preflight guards in priority order — user lock → release window → system load — and return the
62
+ * first that says yield. `clear` when none fire. The daemon supplies live readings; this stays pure.
63
+ */
64
+ export declare function evaluateGuards(input: GuardInput): GuardDecision;
65
+ export interface DormantHypothesis extends Record<string, unknown> {
66
+ created_at?: string;
67
+ ttl_ms?: number;
68
+ }
69
+ /**
70
+ * Persists the daemon's partial state before a backoff so the next cycle resumes the same hypothesis instead of
71
+ * starting cold. TTL-bounded — a stale dormant state (older than ttlMs) is discarded on read. Atomic write.
72
+ */
73
+ export declare class DormantHypothesisStore {
74
+ private readonly path;
75
+ private readonly opts;
76
+ constructor(path: string, opts?: {
77
+ ttlMs?: number;
78
+ now?: () => number;
79
+ });
80
+ private ttl;
81
+ private now;
82
+ /** Save partial state before backing off. Never throws. */
83
+ write(data: Record<string, unknown>): void;
84
+ /** Recover partial state, or null if absent/expired/corrupt. Expired state is cleared as a side effect. */
85
+ read(): DormantHypothesis | null;
86
+ clear(): void;
87
+ }