@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,125 @@
1
+ // Signal expansion & tag classification (ported from v1 src/gep/learningSignals.js).
2
+ // Raw signals (e.g. '429') are expanded into broader semantic tags (e.g. 'problem:reliability',
3
+ // 'action:repair') so gene selection can match by MEANING, not just literal string intersection —
4
+ // closing the recall gap where a '429' signal could not reach a gene tagged for 'repair'.
5
+ // Regex → semantic tags. A rule fires if its pattern matches anywhere in the lowercased signal text.
6
+ // The reliability / protocol / performance / capability families also carry CN/JA/KO synonyms so a
7
+ // non-Latin signal ('错误' / 'エラー' / '오류') expands to the same tags an English one would and can
8
+ // reach an English-keyworded gene through tagOverlapScore. This is the v2-native port of v1 #99's
9
+ // multilingual signals_match aliases: v1 attached `|`-pipe synonyms to shipped seed genes, but v2 has
10
+ // no seed-gene catalog and no pipe-alias parsing — its expansion rules ARE the shared signal vocabulary.
11
+ const EXPANSION_RULES = [
12
+ { re: /(error|exception|failed|unstable|log_error|runtime|429|错误|异常|エラー|오류|例外|예외|失败|失敗|실패|不稳定|不安定|불안정)/, tags: ['problem:reliability', 'action:repair'] },
13
+ // Korean 감사 alone is a homograph (audit == "thank you"), so it is matched only via compounds / audit-context
14
+ // phrases (감사로그 / 감사추적 / 감사 로그 / 감사 추적 / 코드 감사) — never bare 감사, so benign gratitude text like
15
+ // '감사합니다' cannot fire. Bare CN 提示 (= hint/notice) is likewise omitted; only the unambiguous 提示词 (= prompt)
16
+ // is matched. The 'reusable' cluster (可复用 / 再利用 / 재사용) recalls the optimize/protocol family (v1 #99).
17
+ { re: /(protocol|prompt|audit|gep|schema|drift|reusable|协议|プロトコル|프로토콜|提示词|プロンプト|프롬프트|审计|監査|可复用|再利用|재사용|감사로그|감사추적|감사 로그|감사 추적|코드 감사)/, tags: ['problem:protocol', 'action:optimize', 'area:prompt'] },
18
+ { re: /(perf|performance|bottleneck|latency|slow|throughput|性能|瓶颈|パフォーマンス|성능|병목)/, tags: ['problem:performance', 'action:optimize'] },
19
+ // 功能/機能/기능 alone are too broad: as unanchored substrings they match the malfunction vocabulary
20
+ // (機能不全 / 기능장애 / 功能障碍), which are reliability problems — use the v1 #99 feature-request compounds.
21
+ { re: /(feature|capability_gap|user_feature_request|external_opportunity|stagnation recommendation|功能请求|機能リクエスト|기능요청|能力缺口|機能ギャップ|역량공백|改进建议|改善提案|개선제안|外部机会|外部機会|외부기회)/, tags: ['problem:capability', 'action:innovate'] },
22
+ { re: /(stagnation|plateau|steady_state|saturation|empty_cycle_loop|loop_detected|recurring)/, tags: ['problem:stagnation', 'action:innovate'] },
23
+ { re: /(task|worker|heartbeat|hub|commitment|assignment|orchestration)/, tags: ['area:orchestration'] },
24
+ // Tool-integrity (ported from v1 #99 gene_tool_integrity): bypassing a registered tool or looping on raw
25
+ // shell is an orchestration-discipline / validation risk. CN/JA/KO aliases included for recall parity.
26
+ { re: /(tool_bypass|tool_loop|工具绕过|工具循环|ツール迂回|ツールループ|도구우회|도구반복)/, tags: ['area:orchestration', 'risk:validation'] },
27
+ { re: /(memory|narrative|reflection)/, tags: ['area:memory'] },
28
+ { re: /(skill|dashboard)/, tags: ['area:skills'] },
29
+ { re: /(validation|canary|rollback|constraint|blast radius|destructive)/, tags: ['risk:validation'] },
30
+ ];
31
+ /**
32
+ * Expand a signal list into literal signals + namespace prefixes + semantic category tags.
33
+ * e.g. ['429', 'auth:token'] → ['429', 'auth:token', 'auth', 'problem:reliability', 'action:repair'].
34
+ */
35
+ export function expandSignals(signals, extraText = '') {
36
+ const tags = new Set();
37
+ for (const s of signals) {
38
+ const str = String(s);
39
+ tags.add(str);
40
+ const base = str.split(':')[0];
41
+ if (base && base !== str)
42
+ tags.add(base); // namespace prefix (e.g. 'auth:token' → 'auth')
43
+ }
44
+ const text = (signals.join(' ') + ' ' + extraText).toLowerCase().normalize('NFKC');
45
+ for (const rule of EXPANSION_RULES) {
46
+ if (rule.re.test(text))
47
+ for (const t of rule.tags)
48
+ tags.add(t);
49
+ }
50
+ return [...tags];
51
+ }
52
+ /**
53
+ * Tokenize free text into a lowercased bag of words (letter/number runs of length >= 2).
54
+ * Unicode-aware (`\p{L}\p{N}`): a Latin-only `[^a-z0-9]+` split silently dropped CJK / Cyrillic /
55
+ * Arabic content, so CN/JA/KO signals like '错误' / 'タスク失敗' / '오류' tokenized to [] and the
56
+ * {@link bagCosine} recall path scored 0 on every cycle for non-Latin users (ported from v1 #99,
57
+ * which fixed the same Latin-only regex in selector.tokenize). Lowercased then NFKC-normalized before splitting (the established house idiom in
58
+ * signatures.ts), so full-width / half-width IME forms ('429' / 'ERROR' / 'エラー') fold to the
59
+ * normal forms the rules and gene text already use, and punctuation/symbols are stripped so
60
+ * 'error.' and 'error' tokenize identically.
61
+ */
62
+ function tokenize(text) {
63
+ return text.toLowerCase().normalize('NFKC').split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 2);
64
+ }
65
+ /**
66
+ * Bag-of-words cosine similarity (0..1) between two free-text strings (ported from v1 scoreGeneSemantic).
67
+ * Term-frequency vectors, cosine of the angle. Returns 0 when either side has no tokens or they share none.
68
+ * This is the lexical-similarity recall path that complements {@link tagOverlapScore}'s curated tags:
69
+ * a signal 'timeout_slow' and a gene summarized "fix the slow timeout" share the 'timeout'/'slow' tokens
70
+ * even when neither the literal signal nor the expansion rules connect them.
71
+ */
72
+ export function bagCosine(a, b) {
73
+ const av = new Map();
74
+ const bv = new Map();
75
+ for (const t of tokenize(a))
76
+ av.set(t, (av.get(t) ?? 0) + 1);
77
+ for (const t of tokenize(b))
78
+ bv.set(t, (bv.get(t) ?? 0) + 1);
79
+ if (av.size === 0 || bv.size === 0)
80
+ return 0;
81
+ let dot = 0;
82
+ for (const [t, c] of av)
83
+ dot += c * (bv.get(t) ?? 0);
84
+ if (dot === 0)
85
+ return 0;
86
+ const mag = (m) => Math.sqrt([...m.values()].reduce((s, c) => s + c * c, 0));
87
+ return dot / (mag(av) * mag(bv));
88
+ }
89
+ /** Expand a gene's category + signals_match + id + summary into its semantic tag set. */
90
+ export function geneTags(gene) {
91
+ const inputs = [];
92
+ if (gene.category)
93
+ inputs.push('action:' + gene.category.toLowerCase());
94
+ if (gene.signalsMatch)
95
+ inputs.push(...gene.signalsMatch);
96
+ if (gene.geneId)
97
+ inputs.push(gene.geneId);
98
+ if (gene.summary)
99
+ inputs.push(gene.summary);
100
+ return expandSignals(inputs, '');
101
+ }
102
+ /**
103
+ * Semantic tag overlap (0..1): fraction of the expanded SIGNAL tags that the gene's expanded tags cover.
104
+ * Normalized on the signal (query) side so a gene with a long id/summary is not penalized by noise.
105
+ * This is the recall component: '429' and a gene tagged 'error'/'repair' both expand to
106
+ * 'problem:reliability'/'action:repair', so they overlap even with zero literal string match.
107
+ *
108
+ * Known v1→v2 fidelity delta: a lone non-Latin signal caps near ~2/3 here — its raw token ('错误') is in the
109
+ * signal tag-set but never on the English-keyworded gene side, while an exact English signal short-circuits to
110
+ * literal=1.0 upstream in expandedMatchScore. v1 #99 gave CJK full literal credit via pipe-aliases; v2 reaches
111
+ * the right gene at ~2/3 strength. Lifting this to parity is a scoring-design change beyond this signal port.
112
+ */
113
+ export function tagOverlapScore(signals, gene) {
114
+ const sigTags = expandSignals(signals);
115
+ if (sigTags.length === 0)
116
+ return 0;
117
+ const geneTagSet = new Set(geneTags(gene));
118
+ if (geneTagSet.size === 0)
119
+ return 0;
120
+ let hits = 0;
121
+ for (const t of sigTags)
122
+ if (geneTagSet.has(t))
123
+ hits++;
124
+ return hits / sigTags.length;
125
+ }
@@ -0,0 +1,25 @@
1
+ /** 信号源的最小结构(结构化匹配 runtime-adapters 的 NormalizedTurn; core 不跨包依赖, 守边界). */
2
+ export interface SignalSourceTurn {
3
+ text?: string;
4
+ toolName?: string;
5
+ toolResult?: string;
6
+ errorMessage?: string;
7
+ isMeta?: boolean;
8
+ }
9
+ /** 信号强度三条腿(批注#13): strong=零成本结构化判断 / agent=自标记 / weak=需 LLM 分析. */
10
+ export type SignalStrength = 'strong' | 'agent' | 'weak';
11
+ export interface ExtractedSignal {
12
+ id: string;
13
+ strength: SignalStrength;
14
+ kind: string;
15
+ text: string;
16
+ toolName?: string;
17
+ needsAnalysis: boolean;
18
+ }
19
+ /** Whether a candidate signal text is harness-coordination noise rather than a real engineering problem. */
20
+ export declare function isHarnessNoise(text: string): boolean;
21
+ /**
22
+ * 从 tool_use/tool_result/assistant 文本提取信号(M4A-2). **不读文件内容**, 只看 tool 事件+文本(批注#7/#11).
23
+ * 三条腿: tool 错误结果/显式 Error=strong; agent 标记=agent; 困难措辞无结构=weak(defer LLM).
24
+ */
25
+ export declare function extractSignals(turns: readonly SignalSourceTurn[]): ExtractedSignal[];
@@ -0,0 +1,57 @@
1
+ import { ulid as makeUlid } from 'ulid';
2
+ /** agent 显式信号标记(第三条腿; 与 evolver 显式信号注入旁枝呼应). */
3
+ const AGENT_MARKERS = [/\bEVOLVE_SIGNAL:\s*(.+)/i, /\[SIGNAL\]\s*(.+)/i];
4
+ /** 结构化强信号: 栈/退出码/显式 Error — 零成本判断, 不动 LLM. */
5
+ const STRONG_TEXT = /(^|\n)\s*(Error:|Traceback|Exception|FAILED|panic:|\bexit code [1-9])/;
6
+ /** 弱信号: 表达困难但无结构, 需 LLM 拼语境. */
7
+ const DIFFICULTY = /(无法|失败|搞不定|stuck|can'?t|unable to|not working|报错|卡住)/i;
8
+ /**
9
+ * Harness-coordination noise — agent/tool mechanics, NOT engineering problems to evolve genes for.
10
+ * Observation showed these dominate the "strong" leg (tool errors) and drown out real problems: the agent
11
+ * re-reads a stale file, a string-replace misses, a permission is declined, a request aborts. Dropping them
12
+ * keeps the signal corpus about the environment's *engineering* problems, not the harness's own retry chatter.
13
+ */
14
+ const HARNESS_NOISE = /(tool_use_error|has not been read yet|has been modified since|modified since read|String to replace not found|old_string|InputValidationError|permission denied by user|user doesn't want|Request was aborted|operation was aborted|File has not been read)/i;
15
+ /** Whether a candidate signal text is harness-coordination noise rather than a real engineering problem. */
16
+ export function isHarnessNoise(text) {
17
+ return HARNESS_NOISE.test(text);
18
+ }
19
+ /**
20
+ * 从 tool_use/tool_result/assistant 文本提取信号(M4A-2). **不读文件内容**, 只看 tool 事件+文本(批注#7/#11).
21
+ * 三条腿: tool 错误结果/显式 Error=strong; agent 标记=agent; 困难措辞无结构=weak(defer LLM).
22
+ */
23
+ export function extractSignals(turns) {
24
+ const out = [];
25
+ for (const t of turns) {
26
+ if (t.isMeta)
27
+ continue;
28
+ // 腿1 strong: tool_result 报错(is_error) — 但先滤掉 harness 协调噪声(不是工程问题)
29
+ if (t.errorMessage) {
30
+ if (!isHarnessNoise(t.errorMessage)) {
31
+ out.push({ id: makeUlid(), strength: 'strong', kind: 'error_result', text: t.errorMessage.slice(0, 2000), ...(t.toolName ? { toolName: t.toolName } : {}), needsAnalysis: false });
32
+ }
33
+ continue;
34
+ }
35
+ const text = t.text ?? '';
36
+ if (!text.trim())
37
+ continue;
38
+ // 腿3 agent: 显式标记
39
+ const marker = AGENT_MARKERS.map((re) => text.match(re)).find(Boolean);
40
+ if (marker) {
41
+ out.push({ id: makeUlid(), strength: 'agent', kind: 'agent_marked', text: (marker[1] ?? text).trim().slice(0, 2000), needsAnalysis: false });
42
+ continue;
43
+ }
44
+ // 腿1 strong: 结构化 Error 文本(同样滤掉 harness 噪声)
45
+ if (STRONG_TEXT.test(text)) {
46
+ if (!isHarnessNoise(text)) {
47
+ out.push({ id: makeUlid(), strength: 'strong', kind: 'structured_error', text: text.slice(0, 2000), needsAnalysis: false });
48
+ }
49
+ continue;
50
+ }
51
+ // 腿2 weak: 困难措辞无结构 → 交 LLM
52
+ if (DIFFICULTY.test(text)) {
53
+ out.push({ id: makeUlid(), strength: 'weak', kind: 'difficulty', text: text.slice(0, 2000), needsAnalysis: true });
54
+ }
55
+ }
56
+ return out;
57
+ }
@@ -0,0 +1,6 @@
1
+ export * from './extractor.js';
2
+ export * from './signalGate.js';
3
+ export * from './expand.js';
4
+ export * from './traceSignals.js';
5
+ export * from './metaSignals.js';
6
+ export * from './cycleHistoryFromEvents.js';
@@ -0,0 +1,6 @@
1
+ export * from './extractor.js';
2
+ export * from './signalGate.js';
3
+ export * from './expand.js';
4
+ export * from './traceSignals.js';
5
+ export * from './metaSignals.js';
6
+ export * from './cycleHistoryFromEvents.js';
@@ -0,0 +1,57 @@
1
+ /** Counters describing the recent shape of the evolution loop, mirroring v1 analyzeRecentHistory. */
2
+ export interface CycleHistory {
3
+ /** Trailing run of consecutive 'repair'-intent cycles at the tail. */
4
+ consecutiveRepairCount: number;
5
+ /** Empty cycles (zero blast radius) within the recent window. */
6
+ emptyCycleCount: number;
7
+ /** Trailing run of consecutive empty cycles at the tail (saturation). */
8
+ consecutiveEmptyCycles: number;
9
+ /** Trailing run of consecutive failed cycles at the tail. */
10
+ consecutiveFailureCount: number;
11
+ /** Fraction of the recent window that failed (0..1). */
12
+ recentFailureRatio: number;
13
+ /** geneId → times used within the recent window (informs which gene dominates a failure loop). */
14
+ geneFreq: Readonly<Record<string, number>>;
15
+ }
16
+ /** A normalized per-cycle record (v2-shaped mirror of v1's recentEvents entries). All fields optional. */
17
+ export interface CycleRecord {
18
+ /** Intent category of the cycle ('repair' | 'optimize' | 'innovate' | 'explore' | ...). */
19
+ intent?: string;
20
+ /** Final cycle outcome. */
21
+ outcome?: {
22
+ status?: 'success' | 'failed';
23
+ score?: number;
24
+ };
25
+ /** Change footprint; files===0 && lines===0 (or meta.emptyCycle) marks an empty cycle. */
26
+ blastRadius?: {
27
+ files?: number;
28
+ lines?: number;
29
+ };
30
+ /** Explicit empty-cycle marker (when blast radius is unavailable). */
31
+ emptyCycle?: boolean;
32
+ /** Genes used in the cycle (for failure-loop gene frequency). */
33
+ genesUsed?: readonly string[];
34
+ }
35
+ /**
36
+ * Derive the v1 history counters from a normalized cycle-record window (newest LAST), mirroring v1
37
+ * analyzeRecentHistory. Pure + deterministic. Use {@link cycleRecordsFromEvents} to adapt the v2 event log.
38
+ */
39
+ export declare function deriveCycleHistory(records: readonly CycleRecord[]): CycleHistory;
40
+ /**
41
+ * Compute the history-derived meta-signal vocabulary from the loop's recent shape (ported v1 signals.js
42
+ * ~555-655 for the signals NOT already owned by exploration/bans). The returned signals are MEANT to be
43
+ * merged into the cycle's signal set so strategy selection (resolveStrategy) and signal expansion can react.
44
+ *
45
+ * Ports (thresholds faithful to v1):
46
+ * - consecutiveRepairCount >= 3 → repair_loop_detected + force_innovation_after_repair_loop
47
+ * - emptyCycleCount >= 4 → empty_cycle_loop_detected
48
+ * - consecutiveEmptyCycles >= 5 → force_steady_state + evolution_saturation
49
+ * - consecutiveEmptyCycles >= 3 → evolution_saturation (+ explore_opportunity)
50
+ * - consecutiveFailureCount>= 3 → consecutive_failure_streak_<N>
51
+ * - consecutiveFailureCount>= 5 → failure_loop_detected (ban_gene deferred to algo/bans.ts)
52
+ * - recentFailureRatio >= 0.75 → high_failure_ratio + force_innovation_after_repair_loop
53
+ *
54
+ * Deferred (handled elsewhere, see RECONCILIATION above): plateau_pivot_* → algo/exploration.ts;
55
+ * ban_gene:<top> → algo/bans.ts.
56
+ */
57
+ export declare function computeMetaSignals(history: CycleHistory): string[];
@@ -0,0 +1,158 @@
1
+ // Meta-signal vocabulary (ported from v1 src/gep/signals.js analyzeRecentHistory + the meta-signal pass).
2
+ // These are HISTORY-DERIVED signals that drive STRATEGY ADAPTATION: when the evolution loop gets stuck
3
+ // (repair loops, empty cycles, saturation, failure streaks, high failure ratio) the loop emits signals that
4
+ // downstream strategy selection reacts to — e.g. evolution_saturation → steady-state, repair_loop_detected /
5
+ // high_failure_ratio → innovate. v2 had only restored plateau→drift (algo/exploration.ts); this restores the
6
+ // rest of the vocabulary so the loop can adapt to being stuck instead of spinning.
7
+ //
8
+ // RECONCILIATION (reuse, don't duplicate):
9
+ // - PLATEAU: v1 also emitted plateau_pivot_required/_suggested here from recent outcome scores. v2 already
10
+ // owns plateau detection in algo/exploration.ts (detectPlateau over the cycle-outcome stream, which then
11
+ // forces drift in gene selection). We DO NOT re-derive plateau here; callers keep using exploration.ts.
12
+ // - BAN_GENE: v1 emitted ban_gene:<topGene> on a long failure streak. v2 already owns gene banning in
13
+ // algo/bans.ts (bannedGenesFromFailures, signal-overlap based) which drops failing genes from the
14
+ // candidate set directly — a stronger mechanism than a soft signal. We DO NOT emit ban_gene here; the
15
+ // failure-streak meta-signals below are the strategy-posture half, bans.ts is the candidate-exclusion half.
16
+ //
17
+ // Pure + deterministic: input is a normalized cycle-history view; no clock / fs / env reads.
18
+ const RECENT_WINDOW = 10; // v1: last 10 events
19
+ const FREQ_WINDOW = 8; // v1: gene/failure frequency over the last 8
20
+ /** Is a record an empty cycle (no real change)? Mirrors v1: meta.empty_cycle || (files===0 && lines===0). */
21
+ function isEmptyCycle(r) {
22
+ if (r.emptyCycle)
23
+ return true;
24
+ const br = r.blastRadius;
25
+ return !!br && (br.files ?? -1) === 0 && (br.lines ?? -1) === 0;
26
+ }
27
+ function isFailed(r) {
28
+ return r.outcome?.status === 'failed';
29
+ }
30
+ /**
31
+ * Derive the v1 history counters from a normalized cycle-record window (newest LAST), mirroring v1
32
+ * analyzeRecentHistory. Pure + deterministic. Use {@link cycleRecordsFromEvents} to adapt the v2 event log.
33
+ */
34
+ export function deriveCycleHistory(records) {
35
+ const empty = {
36
+ consecutiveRepairCount: 0,
37
+ emptyCycleCount: 0,
38
+ consecutiveEmptyCycles: 0,
39
+ consecutiveFailureCount: 0,
40
+ recentFailureRatio: 0,
41
+ geneFreq: {},
42
+ };
43
+ if (!Array.isArray(records) || records.length === 0)
44
+ return empty;
45
+ const recent = records.slice(-RECENT_WINDOW);
46
+ const tail = recent.slice(-FREQ_WINDOW);
47
+ // Consecutive repair-intent cycles at the tail.
48
+ let consecutiveRepairCount = 0;
49
+ for (let i = recent.length - 1; i >= 0; i--) {
50
+ if (recent[i].intent === 'repair')
51
+ consecutiveRepairCount++;
52
+ else
53
+ break;
54
+ }
55
+ // Empty cycles within the frequency window + gene frequency.
56
+ let emptyCycleCount = 0;
57
+ const geneFreq = {};
58
+ for (const r of tail) {
59
+ if (isEmptyCycle(r))
60
+ emptyCycleCount++;
61
+ for (const g of r.genesUsed ?? [])
62
+ geneFreq[String(g)] = (geneFreq[String(g)] ?? 0) + 1;
63
+ }
64
+ // Consecutive empty cycles at the tail (saturation).
65
+ let consecutiveEmptyCycles = 0;
66
+ for (let i = recent.length - 1; i >= 0; i--) {
67
+ if (isEmptyCycle(recent[i]))
68
+ consecutiveEmptyCycles++;
69
+ else
70
+ break;
71
+ }
72
+ // Consecutive failures at the tail. Empty cycles are zero-blast no-ops in v1's history model: even when the
73
+ // terminal status is failed, they break the failure streak instead of extending it.
74
+ let consecutiveFailureCount = 0;
75
+ for (let i = recent.length - 1; i >= 0; i--) {
76
+ if (isEmptyCycle(recent[i]))
77
+ break;
78
+ if (isFailed(recent[i]))
79
+ consecutiveFailureCount++;
80
+ else
81
+ break;
82
+ }
83
+ // Failure ratio over the frequency window, excluding empty cycles from both numerator and denominator.
84
+ let recentFailureCount = 0;
85
+ let nonEmptyCycleCount = 0;
86
+ for (const r of tail) {
87
+ if (isEmptyCycle(r))
88
+ continue;
89
+ nonEmptyCycleCount++;
90
+ if (isFailed(r))
91
+ recentFailureCount++;
92
+ }
93
+ return {
94
+ consecutiveRepairCount,
95
+ emptyCycleCount,
96
+ consecutiveEmptyCycles,
97
+ consecutiveFailureCount,
98
+ recentFailureRatio: nonEmptyCycleCount > 0 ? recentFailureCount / nonEmptyCycleCount : 0,
99
+ geneFreq,
100
+ };
101
+ }
102
+ /**
103
+ * Compute the history-derived meta-signal vocabulary from the loop's recent shape (ported v1 signals.js
104
+ * ~555-655 for the signals NOT already owned by exploration/bans). The returned signals are MEANT to be
105
+ * merged into the cycle's signal set so strategy selection (resolveStrategy) and signal expansion can react.
106
+ *
107
+ * Ports (thresholds faithful to v1):
108
+ * - consecutiveRepairCount >= 3 → repair_loop_detected + force_innovation_after_repair_loop
109
+ * - emptyCycleCount >= 4 → empty_cycle_loop_detected
110
+ * - consecutiveEmptyCycles >= 5 → force_steady_state + evolution_saturation
111
+ * - consecutiveEmptyCycles >= 3 → evolution_saturation (+ explore_opportunity)
112
+ * - consecutiveFailureCount>= 3 → consecutive_failure_streak_<N>
113
+ * - consecutiveFailureCount>= 5 → failure_loop_detected (ban_gene deferred to algo/bans.ts)
114
+ * - recentFailureRatio >= 0.75 → high_failure_ratio + force_innovation_after_repair_loop
115
+ *
116
+ * Deferred (handled elsewhere, see RECONCILIATION above): plateau_pivot_* → algo/exploration.ts;
117
+ * ban_gene:<top> → algo/bans.ts.
118
+ */
119
+ export function computeMetaSignals(history) {
120
+ const signals = [];
121
+ // Repair loop: 3+ consecutive repair-intent cycles → push to innovate to break the loop.
122
+ if (history.consecutiveRepairCount >= 3) {
123
+ signals.push('repair_loop_detected');
124
+ signals.push('force_innovation_after_repair_loop');
125
+ }
126
+ // Empty-cycle loop: many zero-change cycles in the window → the loop is spinning without effect.
127
+ if (history.emptyCycleCount >= 4) {
128
+ signals.push('empty_cycle_loop_detected');
129
+ }
130
+ // Saturation (graceful degradation): consecutive empty cycles → steady-state / saturation posture.
131
+ if (history.consecutiveEmptyCycles >= 5) {
132
+ signals.push('force_steady_state');
133
+ signals.push('evolution_saturation');
134
+ }
135
+ else if (history.consecutiveEmptyCycles >= 3) {
136
+ signals.push('evolution_saturation');
137
+ }
138
+ // Exploration opportunity: when saturated, nudge proactive exploration rather than idling.
139
+ if (history.consecutiveEmptyCycles >= 3) {
140
+ signals.push('explore_opportunity');
141
+ }
142
+ // Failure streak awareness: tell the loop "you have failed N times in a row — slow down".
143
+ if (history.consecutiveFailureCount >= 3) {
144
+ signals.push('consecutive_failure_streak_' + history.consecutiveFailureCount);
145
+ if (history.consecutiveFailureCount >= 5) {
146
+ signals.push('failure_loop_detected');
147
+ // NB: v1 also pushed ban_gene:<topGene> here. v2 defers gene banning to algo/bans.ts
148
+ // (bannedGenesFromFailures), which excludes the failing gene from the candidate set directly.
149
+ }
150
+ }
151
+ // High failure ratio in the recent window → break out by innovating.
152
+ if (history.recentFailureRatio >= 0.75) {
153
+ signals.push('high_failure_ratio');
154
+ signals.push('force_innovation_after_repair_loop');
155
+ }
156
+ // De-dup while preserving first-seen order.
157
+ return [...new Set(signals)];
158
+ }
@@ -0,0 +1,15 @@
1
+ import type { ExtractedSignal } from './extractor.js';
2
+ export interface ScoredSignal extends ExtractedSignal {
3
+ signature: string;
4
+ occurrences: number;
5
+ score: number;
6
+ }
7
+ export interface SignalGateConfig {
8
+ minScore?: number;
9
+ maxOutput?: number;
10
+ }
11
+ /**
12
+ * 信号打分 + 去重闸(M4A-3, task 队列前最后一道). 同签名去重并累计 occurrences(持久=更高分),
13
+ * 丢弃低分, 截断防低质信号灌爆 task 队列(批注#18).
14
+ */
15
+ export declare function signalGate(signals: readonly ExtractedSignal[], cfg?: SignalGateConfig): ScoredSignal[];
@@ -0,0 +1,40 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { normalizeText } from '../signatures/signatures.js';
3
+ const STRENGTH_WEIGHT = { strong: 1.0, agent: 0.8, weak: 0.4 };
4
+ function signatureOf(s) {
5
+ return createHash('sha1').update(`${s.kind}\x1f${normalizeText(s.text)}`).digest('hex').slice(0, 16);
6
+ }
7
+ /** 单信号基础分 = 强度权重 ×(0.7 + 特异度). 特异度: 带 toolName/具体 kind 加成. */
8
+ function baseScore(s) {
9
+ let specificity = 0;
10
+ if (s.toolName)
11
+ specificity += 0.2;
12
+ if (s.kind !== 'difficulty')
13
+ specificity += 0.1;
14
+ return STRENGTH_WEIGHT[s.strength] * (0.7 + specificity);
15
+ }
16
+ /**
17
+ * 信号打分 + 去重闸(M4A-3, task 队列前最后一道). 同签名去重并累计 occurrences(持久=更高分),
18
+ * 丢弃低分, 截断防低质信号灌爆 task 队列(批注#18).
19
+ */
20
+ export function signalGate(signals, cfg = {}) {
21
+ const minScore = cfg.minScore ?? 0.3;
22
+ const maxOutput = cfg.maxOutput ?? 50;
23
+ const merged = new Map();
24
+ for (const s of signals) {
25
+ const sig = signatureOf(s);
26
+ const existing = merged.get(sig);
27
+ if (existing) {
28
+ existing.occurrences += 1;
29
+ // 持久信号加成(对数, 边际递减)
30
+ existing.score = baseScore(existing) * (1 + Math.min(0.5, Math.log10(existing.occurrences + 1)));
31
+ }
32
+ else {
33
+ merged.set(sig, { ...s, signature: sig, occurrences: 1, score: baseScore(s) });
34
+ }
35
+ }
36
+ return [...merged.values()]
37
+ .filter((s) => s.score >= minScore)
38
+ .sort((a, b) => b.score - a.score)
39
+ .slice(0, maxOutput);
40
+ }
@@ -0,0 +1,44 @@
1
+ import type { ExtractedSignal } from './extractor.js';
2
+ /**
3
+ * Minimal structural shape of one parsed llm-trace JSONL record. snake_case on purpose: these are the
4
+ * on-disk wire field names of the proxy's LlmTurnTrace. The shape is DUPLICATED structurally rather than
5
+ * imported because evolver-core must stay proxy-agnostic (the same boundary discipline as
6
+ * SignalSourceTurn vs runtime-adapters' NormalizedTurn). Fields are `unknown` because the input is
7
+ * untrusted JSON — every rule narrows with typeof checks, and a corrupt record simply matches no rule.
8
+ */
9
+ export interface LlmTraceRecord {
10
+ event?: unknown;
11
+ status?: unknown;
12
+ fallback?: unknown;
13
+ stop_reason?: unknown;
14
+ ttfb_ms?: unknown;
15
+ latency_ms?: unknown;
16
+ error?: unknown;
17
+ upstream_mode?: unknown;
18
+ }
19
+ /** Thresholds for the aggregate rules. Defaults are deliberately conservative — see each rule's comment. */
20
+ export interface TraceSignalThresholds {
21
+ /** Min upstream 5xx responses in the batch before they count as a pattern. Default 2. */
22
+ min5xx?: number;
23
+ /** Min upstream 429 responses before rate-limit pressure is a signal. Default 3. */
24
+ minRateLimited?: number;
25
+ /** Min 401/403 responses before credential breakage is assumed. Default 2. */
26
+ minAuthFailures?: number;
27
+ /** Min `stop_reason: max_tokens` turns before truncation pressure is a signal. Default 3. */
28
+ minTruncations?: number;
29
+ /** Min occurrences of a POLICY fallback (downgrade_blocked) before it is a signal. Default 3. */
30
+ minPolicyFallbacks?: number;
31
+ /** TTFB at/above this many ms counts as a slow turn. Default 30000. */
32
+ slowTtfbMs?: number;
33
+ /** Min slow turns before sustained latency fires. Default 5. */
34
+ minSlowTurns?: number;
35
+ /** Min share of eligible (successful) turns that must be slow. Default 0.2. */
36
+ minSlowShare?: number;
37
+ }
38
+ /**
39
+ * Extract economic/reliability signals from a batch of llm-trace records. Returns the SAME signal shape as
40
+ * `extractSignals` (one batch-aggregated signal per fired rule, not one per record — a day file holds
41
+ * thousands of turns and per-record emission would flood every downstream consumer with duplicates).
42
+ * Records whose `event` is not `'llm_turn'` are ignored, so callers can pass a raw parsed JSONL batch.
43
+ */
44
+ export declare function extractTraceSignals(records: readonly LlmTraceRecord[], cfg?: TraceSignalThresholds): ExtractedSignal[];