@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,45 @@
1
+ import type { PolicyViolation } from './constraints.js';
2
+ export interface NumstatRow {
3
+ /** The destination path (for a rename) or the changed path (otherwise). */
4
+ file: string;
5
+ /** The source path of a rename, when this row is a rename; undefined for a non-rename change. */
6
+ from?: string;
7
+ added: number;
8
+ deleted: number;
9
+ }
10
+ /**
11
+ * Resolve a numstat path field that may encode a rename into its source + destination paths. git emits a
12
+ * rename as ONE row whose path field is `old => new` OR a brace form `{old => new}`, `prefix/{old => new}`,
13
+ * `{old => new}/suffix`, or `prefix/{old => new}/suffix` (the common prefix/suffix factored out of the brace).
14
+ * Returns `{ from, to }` with both fully expanded (from===to and from===undefined-equivalent for a non-rename).
15
+ * - `MEMORY.md => x.ts` → { from: 'MEMORY.md', to: 'x.ts' }
16
+ * - `src/{old.ts => new.ts}` → { from: 'src/old.ts', to: 'src/new.ts' }
17
+ * - `{a => b}/file.ts` → { from: 'a/file.ts', to: 'b/file.ts' }
18
+ * - `a/{b => c}/d.ts` → { from: 'a/b/d.ts', to: 'a/c/d.ts' }
19
+ * A field with no `=>` is returned as { from: undefined, to: <path> }. Both sides are normalized.
20
+ */
21
+ export declare function resolveRenamePaths(field: string): {
22
+ from?: string;
23
+ to: string;
24
+ };
25
+ /**
26
+ * Parse `git diff --numstat` output into per-file added/deleted counts (ported from v1 parseNumstatRows).
27
+ * Each row is `<added>\t<deleted>\t<path>`. Binary files report `-` for the counts → treated as 0. A rename
28
+ * row (`old => new` or the brace form `prefix/{old => new}/suffix`) keeps BOTH paths: `file` is the new path
29
+ * and `from` is the original — so a protected SOURCE moved out from under the guards is still visible (the
30
+ * rename-bypass fix). v1 only kept the new path; that let a rename of a protected file slip every check.
31
+ */
32
+ export declare function parseNumstat(text: string): NumstatRow[];
33
+ /**
34
+ * The set of original (source) paths of every rename in a numstat. A rename moves a file out from under the
35
+ * `--name-only` listing (which shows only the destination), so a protected SOURCE would otherwise be invisible
36
+ * to the protected-path guard. Surfacing these lets the policy treat a moved-away protected file as a touch.
37
+ */
38
+ export declare function renameSourcePaths(numstat?: string): string[];
39
+ /**
40
+ * GLOBAL destructive-change guard — ALWAYS enforced. Returns a violation for any critical-protected path whose
41
+ * numstat shows it was deleted or emptied (added === 0 && deleted > 0). Independent of any gene/constraints.
42
+ * When no numstat is available (caller didn't run `git diff --numstat`), returns [] — the protected-path guard
43
+ * still catches an EDIT to these paths; this only adds the stronger "it was wiped out" signal when we have it.
44
+ */
45
+ export declare function detectDestructiveChanges(numstat?: string): PolicyViolation[];
@@ -0,0 +1,108 @@
1
+ // Destructive-change guard (ported from v1 src/gep/policyCheck.js detectDestructiveChanges + parseNumstatRows).
2
+ // v1's heuristic: a critical-protected path that was DELETED (no longer on disk) or EMPTIED (size 0) after the
3
+ // agent ran is destructive — the agent wiped out its own identity/config rather than editing it. v1 read that
4
+ // from the live filesystem (fs.existsSync / statSync.size === 0) AFTER the cycle, which works against the repo
5
+ // working tree. v2 runs the agent in a THROWAWAY worktree that is removed in claudeBridge's `finally`, so a
6
+ // live-FS check at decision time is unreliable. Instead we read the same signal from `git diff --numstat`:
7
+ // - a deleted file → numstat row `added=0` with a positive deletion count (every line removed, file gone)
8
+ // - an emptied file → numstat row `added=0` with all prior lines deleted
9
+ // Both collapse to "a critical-protected path with added=0 and deleted>0", which is the destructive case we
10
+ // reject. This is a useful subset of v1's check that needs no live FS. DEFERRED vs v1: the exact
11
+ // "file still exists but is now 0 bytes due to a separate truncation" distinction and the baselineUntracked
12
+ // new-file exemption are not reproduced — numstat already only reports paths the diff actually changed, and a
13
+ // freshly-added empty file shows added=0/deleted=0 (not flagged). Pure + deterministic over the numstat text.
14
+ import { isCriticalProtectedPath } from './protectedPaths.js';
15
+ const norm = (p) => String(p ?? '').replace(/\\/g, '/').replace(/^\.\/+/, '').trim();
16
+ /**
17
+ * Resolve a numstat path field that may encode a rename into its source + destination paths. git emits a
18
+ * rename as ONE row whose path field is `old => new` OR a brace form `{old => new}`, `prefix/{old => new}`,
19
+ * `{old => new}/suffix`, or `prefix/{old => new}/suffix` (the common prefix/suffix factored out of the brace).
20
+ * Returns `{ from, to }` with both fully expanded (from===to and from===undefined-equivalent for a non-rename).
21
+ * - `MEMORY.md => x.ts` → { from: 'MEMORY.md', to: 'x.ts' }
22
+ * - `src/{old.ts => new.ts}` → { from: 'src/old.ts', to: 'src/new.ts' }
23
+ * - `{a => b}/file.ts` → { from: 'a/file.ts', to: 'b/file.ts' }
24
+ * - `a/{b => c}/d.ts` → { from: 'a/b/d.ts', to: 'a/c/d.ts' }
25
+ * A field with no `=>` is returned as { from: undefined, to: <path> }. Both sides are normalized.
26
+ */
27
+ export function resolveRenamePaths(field) {
28
+ const raw = String(field ?? '').trim();
29
+ if (!raw.includes('=>'))
30
+ return { to: norm(raw) };
31
+ // Brace form: `prefix/{old => new}/suffix` — the prefix/suffix are shared, only the brace differs.
32
+ const brace = raw.match(/^(.*)\{([^{}]*)=>([^{}]*)\}(.*)$/);
33
+ if (brace) {
34
+ const prefix = brace[1] ?? '';
35
+ const suffix = brace[4] ?? '';
36
+ const join = (mid) => norm(`${prefix}${mid.trim()}${suffix}`.replace(/\/{2,}/g, '/'));
37
+ return { from: join(brace[2] ?? ''), to: join(brace[3] ?? '') };
38
+ }
39
+ // Plain form: `old => new`.
40
+ const [left, right] = raw.split('=>');
41
+ return { from: norm((left ?? '').trim()), to: norm((right ?? '').trim()) };
42
+ }
43
+ /**
44
+ * Parse `git diff --numstat` output into per-file added/deleted counts (ported from v1 parseNumstatRows).
45
+ * Each row is `<added>\t<deleted>\t<path>`. Binary files report `-` for the counts → treated as 0. A rename
46
+ * row (`old => new` or the brace form `prefix/{old => new}/suffix`) keeps BOTH paths: `file` is the new path
47
+ * and `from` is the original — so a protected SOURCE moved out from under the guards is still visible (the
48
+ * rename-bypass fix). v1 only kept the new path; that let a rename of a protected file slip every check.
49
+ */
50
+ export function parseNumstat(text) {
51
+ const rows = [];
52
+ for (const line of String(text ?? '').split('\n').map((l) => l.trim()).filter(Boolean)) {
53
+ const parts = line.split('\t');
54
+ if (parts.length < 3)
55
+ continue;
56
+ const a = Number(parts[0]);
57
+ const d = Number(parts[1]);
58
+ const { from, to } = resolveRenamePaths(parts.slice(2).join('\t'));
59
+ rows.push({
60
+ file: to,
61
+ ...(from !== undefined && from !== to ? { from } : {}),
62
+ added: Number.isFinite(a) ? a : 0,
63
+ deleted: Number.isFinite(d) ? d : 0,
64
+ });
65
+ }
66
+ return rows;
67
+ }
68
+ /**
69
+ * The set of original (source) paths of every rename in a numstat. A rename moves a file out from under the
70
+ * `--name-only` listing (which shows only the destination), so a protected SOURCE would otherwise be invisible
71
+ * to the protected-path guard. Surfacing these lets the policy treat a moved-away protected file as a touch.
72
+ */
73
+ export function renameSourcePaths(numstat) {
74
+ if (!numstat)
75
+ return [];
76
+ return parseNumstat(numstat)
77
+ .map((r) => r.from)
78
+ .filter((f) => !!f);
79
+ }
80
+ /**
81
+ * GLOBAL destructive-change guard — ALWAYS enforced. Returns a violation for any critical-protected path whose
82
+ * numstat shows it was deleted or emptied (added === 0 && deleted > 0). Independent of any gene/constraints.
83
+ * When no numstat is available (caller didn't run `git diff --numstat`), returns [] — the protected-path guard
84
+ * still catches an EDIT to these paths; this only adds the stronger "it was wiped out" signal when we have it.
85
+ */
86
+ export function detectDestructiveChanges(numstat) {
87
+ const violations = [];
88
+ if (!numstat)
89
+ return violations;
90
+ for (const row of parseNumstat(numstat)) {
91
+ // Rename of a critical-protected SOURCE: the protected file is being MOVED/removed out from under the
92
+ // guards (it vanishes from `--name-only`, which lists only the destination). This is destructive
93
+ // regardless of the row's added/deleted counts — renaming MEMORY.md → harmless.ts (added>0) must NOT slip
94
+ // through. The rename-bypass fix (Bugbot): without this, the protected source disappears with no violation.
95
+ if (row.from && isCriticalProtectedPath(row.from)) {
96
+ violations.push({ kind: 'destructive', detail: `critical_file_renamed_or_removed: ${row.from} => ${row.file}` });
97
+ continue;
98
+ }
99
+ if (!row.file)
100
+ continue;
101
+ if (!isCriticalProtectedPath(row.file))
102
+ continue;
103
+ if (row.added === 0 && row.deleted > 0) {
104
+ violations.push({ kind: 'destructive', detail: `critical_file_deleted_or_emptied: ${row.file}` });
105
+ }
106
+ }
107
+ return violations;
108
+ }
@@ -0,0 +1,33 @@
1
+ import type { PolicyViolation } from './constraints.js';
2
+ export interface FailureMode {
3
+ mode: 'hard' | 'soft';
4
+ reasonClass: 'constraint_destructive' | 'constraint' | 'validation' | 'unknown';
5
+ retryable: boolean;
6
+ }
7
+ /**
8
+ * Classify the failure mode from the policy violations + whether validation passed (ported from v1
9
+ * classifyFailureMode). hard ⇒ not retryable (re-running the same change won't help); soft ⇒ retryable.
10
+ */
11
+ export declare function classifyFailureMode(opts: {
12
+ violations?: readonly PolicyViolation[];
13
+ validationPassed?: boolean;
14
+ }): FailureMode;
15
+ /**
16
+ * Build a one-line, length-capped human failure reason from policy violations + an optional validation error
17
+ * (ported from v1 buildFailureReason — the constraint + validation arms; v2 has no canary/protocol arms here).
18
+ */
19
+ export declare function buildFailureReason(opts: {
20
+ violations?: readonly PolicyViolation[];
21
+ validationError?: string;
22
+ }): string;
23
+ /**
24
+ * Expand a soft failure into the semantic learning tags the cycle records (ported from v1
25
+ * buildSoftFailureLearningSignals). Keeps only the problem:/risk:/area:/action: tags so the next selection can
26
+ * steer away from the same failure class, not the raw noise. Uses v2's expandSignals (signals/expand.ts).
27
+ */
28
+ export declare function buildSoftFailureLearningSignals(opts: {
29
+ signals?: readonly string[];
30
+ violations?: readonly PolicyViolation[];
31
+ failureReason?: string;
32
+ validationText?: string;
33
+ }): string[];
@@ -0,0 +1,49 @@
1
+ // Structured failure classification + soft-failure learning signals (ported from v1 src/gep/policyCheck.js:
2
+ // classifyFailureMode, buildFailureReason, buildSoftFailureLearningSignals). Pure functions over a run's
3
+ // violations / validation result. They turn a failed cycle into (a) a one-line human reason, (b) a hard/soft
4
+ // classification with a retryable flag, and (c) the semantic learning tags the cycle records so the next
5
+ // selection can avoid the same trap. No canary/protocol arms in v2 (canary is intentionally not ported and
6
+ // protocol violations are handled elsewhere) — the constraint/validation arms are what the exec bridge feeds.
7
+ import { expandSignals } from '../../signals/expand.js';
8
+ // A destructive/protected/over-cap/forbidden constraint breach is a HARD, non-retryable failure: retrying the
9
+ // SAME mutation would just hit it again. A validation failure is SOFT/retryable (the agent can try a different
10
+ // edit). Pattern mirrors v1 classifyFailureMode's `constraint_destructive` regex over the violation details.
11
+ const DESTRUCTIVE_VIOLATION_RE = /HARD CAP BREACH|CRITICAL OVERRUN|critical_file_deleted_or_emptied|critical_path_modified|forbidden path|forbidden_path/i;
12
+ /**
13
+ * Classify the failure mode from the policy violations + whether validation passed (ported from v1
14
+ * classifyFailureMode). hard ⇒ not retryable (re-running the same change won't help); soft ⇒ retryable.
15
+ */
16
+ export function classifyFailureMode(opts) {
17
+ const violations = opts.violations ?? [];
18
+ const hasDestructive = violations.some((v) => DESTRUCTIVE_VIOLATION_RE.test(v.detail) || v.kind === 'destructive' || v.kind === 'protected_path');
19
+ if (hasDestructive)
20
+ return { mode: 'hard', reasonClass: 'constraint_destructive', retryable: false };
21
+ if (violations.length > 0)
22
+ return { mode: 'hard', reasonClass: 'constraint', retryable: false };
23
+ if (opts.validationPassed === false)
24
+ return { mode: 'soft', reasonClass: 'validation', retryable: true };
25
+ return { mode: 'soft', reasonClass: 'unknown', retryable: true };
26
+ }
27
+ /**
28
+ * Build a one-line, length-capped human failure reason from policy violations + an optional validation error
29
+ * (ported from v1 buildFailureReason — the constraint + validation arms; v2 has no canary/protocol arms here).
30
+ */
31
+ export function buildFailureReason(opts) {
32
+ const reasons = [];
33
+ for (const v of opts.violations ?? [])
34
+ reasons.push(`constraint: ${v.detail}`);
35
+ if (opts.validationError)
36
+ reasons.push(`validation_failed: ${opts.validationError.slice(0, 200)}`);
37
+ return reasons.join('; ').slice(0, 2000) || 'unknown';
38
+ }
39
+ /**
40
+ * Expand a soft failure into the semantic learning tags the cycle records (ported from v1
41
+ * buildSoftFailureLearningSignals). Keeps only the problem:/risk:/area:/action: tags so the next selection can
42
+ * steer away from the same failure class, not the raw noise. Uses v2's expandSignals (signals/expand.ts).
43
+ */
44
+ export function buildSoftFailureLearningSignals(opts) {
45
+ const signals = opts.signals ?? [];
46
+ const violationDetails = (opts.violations ?? []).map((v) => v.detail);
47
+ const extra = `${opts.failureReason ?? ''} ${opts.validationText ?? ''}`.trim();
48
+ return expandSignals([...signals, ...violationDetails], extra).filter((tag) => /^(problem|risk|area|action):/.test(tag));
49
+ }
@@ -0,0 +1,24 @@
1
+ import type { DiffStat } from '../proofOfWork.js';
2
+ import { type ChangeConstraints, type PolicyViolation } from './constraints.js';
3
+ export interface PolicyInput {
4
+ /** Parsed `git diff --shortstat` → {files, lines}. */
5
+ stat: DiffStat;
6
+ /** `git diff --name-only` → changed file list. */
7
+ changedFiles: readonly string[];
8
+ /** Optional `git diff --numstat` output — enables the destructive (delete/empty of a protected path) guard. */
9
+ numstat?: string;
10
+ /** Optional per-gene constraints. When absent, ONLY the always-on global guards run. */
11
+ constraints?: ChangeConstraints;
12
+ }
13
+ /**
14
+ * Run the full policy over a diff. The global guards (blast hard cap + protected paths + destructive) ALWAYS
15
+ * run, gene or not. The per-gene constraints run additionally when `constraints` is supplied. Returns the
16
+ * combined violation list (empty = the change is within policy). The order is: global blast cap → protected
17
+ * paths → destructive → per-gene constraints.
18
+ */
19
+ export declare function checkPolicy(input: PolicyInput): PolicyViolation[];
20
+ export * from './constraints.js';
21
+ export * from './blastRadius.js';
22
+ export * from './protectedPaths.js';
23
+ export * from './destructive.js';
24
+ export * from './failureMode.js';
@@ -0,0 +1,30 @@
1
+ import { checkBlastRadius } from './blastRadius.js';
2
+ import { checkProtectedPaths } from './protectedPaths.js';
3
+ import { detectDestructiveChanges, renameSourcePaths } from './destructive.js';
4
+ import { checkChangeConstraints } from './constraints.js';
5
+ /**
6
+ * Run the full policy over a diff. The global guards (blast hard cap + protected paths + destructive) ALWAYS
7
+ * run, gene or not. The per-gene constraints run additionally when `constraints` is supplied. Returns the
8
+ * combined violation list (empty = the change is within policy). The order is: global blast cap → protected
9
+ * paths → destructive → per-gene constraints.
10
+ */
11
+ export function checkPolicy(input) {
12
+ const violations = [];
13
+ // ── Always-on global guards (fire even with no gene / no constraints) ──
14
+ violations.push(...checkBlastRadius(input.stat, input.constraints));
15
+ // A rename moves a file out from under `git diff --name-only` (which lists only the destination). Fold the
16
+ // rename SOURCE paths from `--numstat` into the protected-path check so renaming a protected file (e.g.
17
+ // MEMORY.md => harmless.ts) is still caught here — not only by the destructive guard below (rename-bypass fix).
18
+ violations.push(...checkProtectedPaths([...input.changedFiles, ...renameSourcePaths(input.numstat)]));
19
+ violations.push(...detectDestructiveChanges(input.numstat));
20
+ // ── Per-gene constraints (layer on top when a gene supplies them) ──
21
+ if (input.constraints) {
22
+ violations.push(...checkChangeConstraints(input.changedFiles, input.constraints, input.stat.lines));
23
+ }
24
+ return violations;
25
+ }
26
+ export * from './constraints.js';
27
+ export * from './blastRadius.js';
28
+ export * from './protectedPaths.js';
29
+ export * from './destructive.js';
30
+ export * from './failureMode.js';
@@ -0,0 +1,17 @@
1
+ import type { PolicyViolation } from './constraints.js';
2
+ export declare const CRITICAL_PROTECTED_PREFIXES: readonly string[];
3
+ export declare const CRITICAL_PROTECTED_FILES: readonly string[];
4
+ /**
5
+ * Is `relPath` a critical-protected path? Ported from v1 isCriticalProtectedPath.
6
+ * - prefix subtree: rel === "skills/evolver" OR rel starts with "skills/evolver/"
7
+ * - protected file: any path segment chain ending in a protected file name (e.g. ".env", "config/.env",
8
+ * "package.json", "a/b/MEMORY.md). v1 only matched a bare top-level name; we extend to a segment-boundary
9
+ * match so a nested copy (e.g. "packages/x/.env" / "packages/x/package.json") is protected too — strictly
10
+ * safer, and consistent with constraints.pathIsForbidden's bare-segment rule.
11
+ */
12
+ export declare function isCriticalProtectedPath(relPath: string): boolean;
13
+ /**
14
+ * GLOBAL protected-path guard — ALWAYS enforced. Returns one violation per changed file that touches a
15
+ * critical-protected path. Independent of any gene/constraints: a protected-path edit fails the cycle outright.
16
+ */
17
+ export declare function checkProtectedPaths(changedFiles: readonly string[]): PolicyViolation[];
@@ -0,0 +1,65 @@
1
+ // Directory prefixes whose entire subtree is protected (ported verbatim from v1 gitOps.js).
2
+ export const CRITICAL_PROTECTED_PREFIXES = [
3
+ 'skills/skill-tools/',
4
+ 'skills/git-sync/',
5
+ 'skills/evolver/',
6
+ ];
7
+ // Individual protected files — the agent's identity/config/secret surface (ported verbatim from v1 gitOps.js).
8
+ export const CRITICAL_PROTECTED_FILES = [
9
+ 'MEMORY.md',
10
+ 'SOUL.md',
11
+ 'IDENTITY.md',
12
+ 'AGENTS.md',
13
+ 'USER.md',
14
+ 'HEARTBEAT.md',
15
+ 'RECENT_EVENTS.md',
16
+ 'TOOLS.md',
17
+ 'TROUBLESHOOTING.md',
18
+ 'openclaw.json',
19
+ 'evolver.json',
20
+ '.env',
21
+ 'package.json',
22
+ ];
23
+ const norm = (p) => String(p ?? '').replace(/\\/g, '/').replace(/^\.\/+/, '').trim();
24
+ /**
25
+ * Is `relPath` a critical-protected path? Ported from v1 isCriticalProtectedPath.
26
+ * - prefix subtree: rel === "skills/evolver" OR rel starts with "skills/evolver/"
27
+ * - protected file: any path segment chain ending in a protected file name (e.g. ".env", "config/.env",
28
+ * "package.json", "a/b/MEMORY.md). v1 only matched a bare top-level name; we extend to a segment-boundary
29
+ * match so a nested copy (e.g. "packages/x/.env" / "packages/x/package.json") is protected too — strictly
30
+ * safer, and consistent with constraints.pathIsForbidden's bare-segment rule.
31
+ */
32
+ export function isCriticalProtectedPath(relPath) {
33
+ const rel = norm(relPath);
34
+ if (!rel)
35
+ return false;
36
+ for (const prefix of CRITICAL_PROTECTED_PREFIXES) {
37
+ const p = prefix.replace(/\/+$/, '');
38
+ if (rel === p || rel.startsWith(`${p}/`))
39
+ return true;
40
+ }
41
+ const segments = rel.split('/');
42
+ for (const f of CRITICAL_PROTECTED_FILES) {
43
+ if (rel === f)
44
+ return true;
45
+ if (segments[segments.length - 1] === f)
46
+ return true; // protected basename at any depth
47
+ }
48
+ return false;
49
+ }
50
+ /**
51
+ * GLOBAL protected-path guard — ALWAYS enforced. Returns one violation per changed file that touches a
52
+ * critical-protected path. Independent of any gene/constraints: a protected-path edit fails the cycle outright.
53
+ */
54
+ export function checkProtectedPaths(changedFiles) {
55
+ const violations = [];
56
+ for (const file of changedFiles) {
57
+ const rel = norm(file);
58
+ if (!rel)
59
+ continue;
60
+ if (isCriticalProtectedPath(rel)) {
61
+ violations.push({ kind: 'protected_path', detail: `critical_path_modified: ${rel}` });
62
+ }
63
+ }
64
+ return violations;
65
+ }
@@ -0,0 +1,2 @@
1
+ export { checkChangeConstraints, pathIsForbidden, summarizeViolations, type ChangeConstraints, type PolicyViolation, } from './policy/constraints.js';
2
+ export { checkPolicy, type PolicyInput } from './policy/index.js';
@@ -0,0 +1,7 @@
1
+ // Back-compat shim: the per-gene constraint checker moved into ./policy/ when the v1 policyCheck safety core
2
+ // was ported as split modules (blast hard cap + protected paths + destructive + failure classification, all
3
+ // behind the single checkPolicy entry point). Existing imports of checkChangeConstraints / pathIsForbidden /
4
+ // summarizeViolations / ChangeConstraints / PolicyViolation keep working through this re-export — and the
5
+ // full policy core is available from ./policy/index.ts (re-exported here too via checkPolicy).
6
+ export { checkChangeConstraints, pathIsForbidden, summarizeViolations, } from './policy/constraints.js';
7
+ export { checkPolicy } from './policy/index.js';
@@ -0,0 +1,34 @@
1
+ import type { Mutation } from '../wire/index.js';
2
+ import type { GeneDecision } from '../algo/geneSelection.js';
3
+ import type { PersonalityStateInput } from '../personality/schema.js';
4
+ /** The slice of a selected gene that shapes the instruction (all optional — pass what the store has). */
5
+ export interface GeneStrategyInfo {
6
+ strategy?: readonly string[];
7
+ preconditions?: readonly string[];
8
+ summary?: string;
9
+ constraints?: {
10
+ max_files?: number;
11
+ forbidden_paths?: readonly string[];
12
+ };
13
+ /** Provenance: whether this gene's content is trusted enough to embed into an autonomous agent's prompt.
14
+ * The exec bridge's requireTrustedGene gate uses this; hub-ingested/unverified genes should be false. */
15
+ trusted?: boolean;
16
+ /** Reuse provenance (#113): when this strategy was fetched from the hub by reuse-before-solve (a HIT short-
17
+ * circuited a fresh solve), the source asset id. Surfaced in the prompt so the run — and the user reading it
18
+ * — sees that a ready-made solution was reused rather than re-derived. */
19
+ reusedFromAssetId?: string;
20
+ }
21
+ /** Neutralize blatant injection directives in untrusted embedded text and cap its length (finding #39.3). */
22
+ export declare function sanitizeInjection(text: string, maxLen?: number): string;
23
+ export interface ExecPromptInput {
24
+ mutation: Mutation;
25
+ decision: GeneDecision;
26
+ gene?: GeneStrategyInfo;
27
+ /** Validation commands the change must pass, if the caller resolved a validation plan. */
28
+ validationCmds?: readonly string[];
29
+ /** Evolvable personality for this run — injected as a behavioral-style block (personality use-case ①).
30
+ * Absent ⇒ no style block (fully back-compatible). Pass the store's current state per run. */
31
+ personality?: PersonalityStateInput | null;
32
+ }
33
+ /** Build the agent instruction. Deterministic: same input → same text (no clock, no randomness). */
34
+ export declare function renderExecPrompt(input: ExecPromptInput): string;
@@ -0,0 +1,108 @@
1
+ import { reuseSourceNote } from '../ops/valueOutreach.js';
2
+ import { renderPersonalityBlock } from '../personality/prompt.js';
3
+ // Blatant prompt-injection directives to neutralize before embedding untrusted content (gene/signal text) into
4
+ // an autonomous agent's instruction (finding #39.3). Heuristic defense-in-depth — the primary control is the
5
+ // trust gate (only embed trusted gene strategies); this just blunts the obvious "ignore your instructions" /
6
+ // fake-role-tag attacks in whatever content does flow through. Kept tight to avoid redacting real strategy text.
7
+ const INJECTION_PATTERNS = [
8
+ /\b(ignore|disregard|forget)\b[^.\n]{0,40}\b(previous|above|prior|preceding|earlier|all)\b[^.\n]{0,30}\b(instruction|prompt|context|rule|message)/gi,
9
+ /\b(new|updated|real|actual)\b[^.\n]{0,20}\b(instruction|system prompt|task|directive)s?\s*:/gi,
10
+ /<\/?\s*(system|user|assistant|instructions?|im_start|im_end)\s*>/gi,
11
+ /^\s*(system|assistant|developer)\s*:/gim,
12
+ /\b(jailbreak|do anything now|DAN mode|developer mode)\b/gi,
13
+ ];
14
+ /** Neutralize blatant injection directives in untrusted embedded text and cap its length (finding #39.3). */
15
+ export function sanitizeInjection(text, maxLen = 800) {
16
+ let out = text;
17
+ for (const re of INJECTION_PATTERNS)
18
+ out = out.replace(re, '[redacted: possible prompt injection]');
19
+ if (out.length > maxLen)
20
+ out = out.slice(0, maxLen) + '…[truncated]';
21
+ return out;
22
+ }
23
+ const MAX_ANTI_WARNINGS = 3;
24
+ const MAX_AVOID_ITEMS_PER_WARNING = 4;
25
+ function renderAntiWarning(warning, index, sanitize) {
26
+ const id = warning.antiGeneId || warning.assetId || `anti-warning-${index + 1}`;
27
+ const head = [`${index + 1}. ${sanitize(id)}`];
28
+ if (warning.severity)
29
+ head.push(`[${sanitize(warning.severity)}]`);
30
+ if (warning.summary)
31
+ head.push(`- ${sanitize(warning.summary, 240)}`);
32
+ const lines = [head.join(' ')];
33
+ if (warning.trigger.length > 0)
34
+ lines.push(` Trigger: ${sanitize(warning.trigger.join(', '), 240)}`);
35
+ for (const avoid of warning.avoid.slice(0, MAX_AVOID_ITEMS_PER_WARNING))
36
+ lines.push(` Avoid: ${sanitize(avoid, 320)}`);
37
+ if (warning.rationale)
38
+ lines.push(` Why: ${sanitize(warning.rationale, 320)}`);
39
+ return lines;
40
+ }
41
+ /** Build the agent instruction. Deterministic: same input → same text (no clock, no randomness). */
42
+ export function renderExecPrompt(input) {
43
+ const { mutation: m, decision: d, gene, validationCmds, personality } = input;
44
+ const s = sanitizeInjection; // every embedded (potentially untrusted) field is sanitized (finding #39.3)
45
+ const lines = [
46
+ 'You are an autonomous coding agent applying ONE focused, minimal change.',
47
+ '',
48
+ '## Goal',
49
+ s(m.expected_effect),
50
+ '',
51
+ '## Target',
52
+ `Area/file: ${s(m.target)}`,
53
+ `Category: ${m.category} Risk: ${m.risk_level}`,
54
+ `Triggering signals: ${s(m.trigger_signals.join(', ')) || '(none)'}`,
55
+ ];
56
+ if (d.selectedGeneId && gene) {
57
+ lines.push('', `## Strategy (learned gene ${d.selectedGeneId})`);
58
+ // Reuse provenance (#113): a HIT from reuse-before-solve fetched this ready-made solution instead of solving
59
+ // fresh — surface that so the run/transcript shows WHERE it came from. assetId is content-addressed (safe to
60
+ // print as-is); still sanitized for defense-in-depth like every other embedded field.
61
+ if (gene.reusedFromAssetId)
62
+ lines.push(reuseSourceNote(s(gene.reusedFromAssetId)));
63
+ if (gene.summary)
64
+ lines.push(s(gene.summary));
65
+ const steps = gene.strategy ?? [];
66
+ steps.forEach((step, i) => lines.push(`${i + 1}. ${s(step)}`));
67
+ if (gene.preconditions && gene.preconditions.length > 0) {
68
+ lines.push(`Preconditions: ${s(gene.preconditions.join('; '))}`);
69
+ }
70
+ }
71
+ else {
72
+ // No matching gene — this is an innovate/explore path; the agent devises the approach.
73
+ lines.push('', '## Strategy', 'No prior gene matched — devise and apply a sound minimal approach yourself.');
74
+ }
75
+ if (d.antiWarnings && d.antiWarnings.length > 0) {
76
+ lines.push('', '## Avoid');
77
+ lines.push('Known repeated failure patterns matched this task. Treat these as guardrails, not executable strategy steps.');
78
+ for (const [index, warning] of d.antiWarnings.slice(0, MAX_ANTI_WARNINGS).entries()) {
79
+ lines.push(...renderAntiWarning(warning, index, s));
80
+ }
81
+ }
82
+ const c = gene?.constraints;
83
+ if (c && (c.max_files !== undefined || (c.forbidden_paths && c.forbidden_paths.length > 0))) {
84
+ const parts = [];
85
+ if (c.max_files !== undefined)
86
+ parts.push(`touch at most ${c.max_files} file(s)`);
87
+ if (c.forbidden_paths && c.forbidden_paths.length > 0)
88
+ parts.push(`never modify: ${c.forbidden_paths.join(', ')}`);
89
+ lines.push('', `## Constraints`, parts.join('; '));
90
+ }
91
+ // Personality style block (use-case ①): behavioral posture for HOW to execute, not what to do. The block
92
+ // is fully model-generated from a validated numeric state (no untrusted embedded text), so it is NOT run
93
+ // through sanitizeInjection. Rendered after strategy/constraints, before the done criteria.
94
+ if (personality) {
95
+ lines.push('', renderPersonalityBlock(personality));
96
+ }
97
+ lines.push('', '## Done criteria');
98
+ if (validationCmds && validationCmds.length > 0) {
99
+ lines.push('Your change must make these commands pass:');
100
+ for (const cmd of validationCmds)
101
+ lines.push(`- ${cmd}`);
102
+ }
103
+ else {
104
+ lines.push('Make the smallest change that achieves the goal.');
105
+ }
106
+ lines.push('Do NOT git commit — leave your edits in the working tree for inspection.');
107
+ return lines.join('\n');
108
+ }
@@ -0,0 +1,9 @@
1
+ import type { ProofOfWork } from '../schema/proofOfWork.js';
2
+ export interface DiffStat {
3
+ files: number;
4
+ lines: number;
5
+ }
6
+ /** Parse `git diff --shortstat` output, e.g. " 3 files changed, 12 insertions(+), 4 deletions(-)". */
7
+ export declare function parseGitShortstat(out: string): DiffStat;
8
+ /** Build a git_diff ProofOfWork from a parsed diff stat. */
9
+ export declare function gitDiffProof(stat: DiffStat, patchRef?: string): ProofOfWork;
@@ -0,0 +1,11 @@
1
+ /** Parse `git diff --shortstat` output, e.g. " 3 files changed, 12 insertions(+), 4 deletions(-)". */
2
+ export function parseGitShortstat(out) {
3
+ const files = /(\d+)\s+files?\s+changed/.exec(out)?.[1];
4
+ const ins = /(\d+)\s+insertions?\(\+\)/.exec(out)?.[1];
5
+ const del = /(\d+)\s+deletions?\(-\)/.exec(out)?.[1];
6
+ return { files: Number(files ?? 0), lines: Number(ins ?? 0) + Number(del ?? 0) };
7
+ }
8
+ /** Build a git_diff ProofOfWork from a parsed diff stat. */
9
+ export function gitDiffProof(stat, patchRef) {
10
+ return { kind: 'git_diff', gitDiff: { files: stat.files, lines: stat.lines, ...(patchRef ? { patchRef } : {}) } };
11
+ }