@provos/ironcurtain 0.11.0 → 0.12.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 (365) hide show
  1. package/README.md +9 -7
  2. package/dist/cli-help.d.ts +12 -0
  3. package/dist/cli-help.js +21 -0
  4. package/dist/cli-help.js.map +1 -1
  5. package/dist/cli.js +8 -6
  6. package/dist/cli.js.map +1 -1
  7. package/dist/config/agent-model-guard.d.ts +14 -0
  8. package/dist/config/agent-model-guard.js +24 -0
  9. package/dist/config/agent-model-guard.js.map +1 -0
  10. package/dist/config/config-command.js +116 -1
  11. package/dist/config/config-command.js.map +1 -1
  12. package/dist/config/first-start.js +2 -8
  13. package/dist/config/first-start.js.map +1 -1
  14. package/dist/config/model-provider.d.ts +9 -0
  15. package/dist/config/model-provider.js +13 -0
  16. package/dist/config/model-provider.js.map +1 -1
  17. package/dist/config/paths.d.ts +48 -6
  18. package/dist/config/paths.js +63 -8
  19. package/dist/config/paths.js.map +1 -1
  20. package/dist/config/user-config.d.ts +48 -1
  21. package/dist/config/user-config.js +49 -1
  22. package/dist/config/user-config.js.map +1 -1
  23. package/dist/daemon/daemon-command.js +14 -5
  24. package/dist/daemon/daemon-command.js.map +1 -1
  25. package/dist/daemon/ironcurtain-daemon.d.ts +18 -0
  26. package/dist/daemon/ironcurtain-daemon.js +22 -1
  27. package/dist/daemon/ironcurtain-daemon.js.map +1 -1
  28. package/dist/daemon-client/daemon-client.d.ts +123 -0
  29. package/dist/daemon-client/daemon-client.js +324 -0
  30. package/dist/daemon-client/daemon-client.js.map +1 -0
  31. package/dist/docker/adapters/codex.d.ts +9 -0
  32. package/dist/docker/adapters/codex.js +297 -0
  33. package/dist/docker/adapters/codex.js.map +1 -0
  34. package/dist/docker/agent-adapter.d.ts +5 -1
  35. package/dist/docker/agent-adapter.js +2 -0
  36. package/dist/docker/agent-adapter.js.map +1 -1
  37. package/dist/docker/agent-registry.js +5 -0
  38. package/dist/docker/agent-registry.js.map +1 -1
  39. package/dist/docker/apple-container-manager.d.ts +49 -0
  40. package/dist/docker/apple-container-manager.js +464 -0
  41. package/dist/docker/apple-container-manager.js.map +1 -0
  42. package/dist/docker/code-mode-proxy.d.ts +11 -0
  43. package/dist/docker/code-mode-proxy.js +3 -1
  44. package/dist/docker/code-mode-proxy.js.map +1 -1
  45. package/dist/docker/container-lifecycle.d.ts +2 -2
  46. package/dist/docker/container-lifecycle.js.map +1 -1
  47. package/dist/docker/container-runtime.d.ts +29 -0
  48. package/dist/docker/container-runtime.js +76 -0
  49. package/dist/docker/container-runtime.js.map +1 -0
  50. package/dist/docker/docker-agent-session.js +30 -1
  51. package/dist/docker/docker-agent-session.js.map +1 -1
  52. package/dist/docker/docker-infrastructure.d.ts +186 -9
  53. package/dist/docker/docker-infrastructure.js +521 -77
  54. package/dist/docker/docker-infrastructure.js.map +1 -1
  55. package/dist/docker/docker-manager.d.ts +25 -5
  56. package/dist/docker/docker-manager.js +262 -22
  57. package/dist/docker/docker-manager.js.map +1 -1
  58. package/dist/docker/docker-probe.d.ts +45 -0
  59. package/dist/docker/docker-probe.js +86 -0
  60. package/dist/docker/docker-probe.js.map +1 -0
  61. package/dist/docker/docker-progress-sink.d.ts +1 -1
  62. package/dist/docker/mitm-proxy.d.ts +52 -1
  63. package/dist/docker/mitm-proxy.js +234 -10
  64. package/dist/docker/mitm-proxy.js.map +1 -1
  65. package/dist/docker/network-topology.d.ts +81 -0
  66. package/dist/docker/network-topology.js +160 -0
  67. package/dist/docker/network-topology.js.map +1 -0
  68. package/dist/docker/oauth-credentials.d.ts +13 -0
  69. package/dist/docker/oauth-credentials.js +125 -0
  70. package/dist/docker/oauth-credentials.js.map +1 -1
  71. package/dist/docker/package-types.d.ts +1 -1
  72. package/dist/docker/provider-config.d.ts +29 -1
  73. package/dist/docker/provider-config.js +93 -3
  74. package/dist/docker/provider-config.js.map +1 -1
  75. package/dist/docker/provision-lock.d.ts +46 -0
  76. package/dist/docker/provision-lock.js +152 -0
  77. package/dist/docker/provision-lock.js.map +1 -0
  78. package/dist/docker/pty-session.d.ts +15 -0
  79. package/dist/docker/pty-session.js +139 -67
  80. package/dist/docker/pty-session.js.map +1 -1
  81. package/dist/docker/registry-proxy.d.ts +46 -0
  82. package/dist/docker/registry-proxy.js +255 -1
  83. package/dist/docker/registry-proxy.js.map +1 -1
  84. package/dist/docker/resource-limits.d.ts +14 -5
  85. package/dist/docker/resource-limits.js +11 -8
  86. package/dist/docker/resource-limits.js.map +1 -1
  87. package/dist/docker/trajectory-capture.d.ts +79 -0
  88. package/dist/docker/trajectory-capture.js +521 -0
  89. package/dist/docker/trajectory-capture.js.map +1 -0
  90. package/dist/docker/trajectory-reassembler.d.ts +286 -0
  91. package/dist/docker/trajectory-reassembler.js +990 -0
  92. package/dist/docker/trajectory-reassembler.js.map +1 -0
  93. package/dist/docker/trajectory-tap.d.ts +100 -0
  94. package/dist/docker/trajectory-tap.js +410 -0
  95. package/dist/docker/trajectory-tap.js.map +1 -0
  96. package/dist/docker/trajectory-types.d.ts +187 -0
  97. package/dist/docker/trajectory-types.js +43 -0
  98. package/dist/docker/trajectory-types.js.map +1 -0
  99. package/dist/docker/types.d.ts +53 -7
  100. package/dist/doctor/checks.d.ts +36 -3
  101. package/dist/doctor/checks.js +102 -15
  102. package/dist/doctor/checks.js.map +1 -1
  103. package/dist/doctor/doctor-command.js +39 -9
  104. package/dist/doctor/doctor-command.js.map +1 -1
  105. package/dist/doctor/mcp-liveness.d.ts +1 -1
  106. package/dist/doctor/mcp-liveness.js +12 -4
  107. package/dist/doctor/mcp-liveness.js.map +1 -1
  108. package/dist/index.js +30 -12
  109. package/dist/index.js.map +1 -1
  110. package/dist/mux/mux-app.d.ts +2 -0
  111. package/dist/mux/mux-app.js +1 -0
  112. package/dist/mux/mux-app.js.map +1 -1
  113. package/dist/mux/mux-command.js +19 -6
  114. package/dist/mux/mux-command.js.map +1 -1
  115. package/dist/mux/pty-bridge.d.ts +2 -0
  116. package/dist/mux/pty-bridge.js +3 -0
  117. package/dist/mux/pty-bridge.js.map +1 -1
  118. package/dist/observe/observe-command.js +112 -125
  119. package/dist/observe/observe-command.js.map +1 -1
  120. package/dist/persona/broad-policy-validator.d.ts +95 -0
  121. package/dist/persona/broad-policy-validator.js +171 -0
  122. package/dist/persona/broad-policy-validator.js.map +1 -0
  123. package/dist/persona/compile-persona-policy.d.ts +54 -2
  124. package/dist/persona/compile-persona-policy.js +29 -4
  125. package/dist/persona/compile-persona-policy.js.map +1 -1
  126. package/dist/persona/event-bus-progress-reporter.d.ts +57 -0
  127. package/dist/persona/event-bus-progress-reporter.js +66 -0
  128. package/dist/persona/event-bus-progress-reporter.js.map +1 -0
  129. package/dist/persona/persona-command.js +46 -76
  130. package/dist/persona/persona-command.js.map +1 -1
  131. package/dist/persona/persona-compile-orchestrator.d.ts +101 -0
  132. package/dist/persona/persona-compile-orchestrator.js +504 -0
  133. package/dist/persona/persona-compile-orchestrator.js.map +1 -0
  134. package/dist/persona/persona-service.d.ts +137 -0
  135. package/dist/persona/persona-service.js +263 -0
  136. package/dist/persona/persona-service.js.map +1 -0
  137. package/dist/persona/policy-mutation-audit.d.ts +109 -0
  138. package/dist/persona/policy-mutation-audit.js +179 -0
  139. package/dist/persona/policy-mutation-audit.js.map +1 -0
  140. package/dist/persona/rule-delta.d.ts +30 -0
  141. package/dist/persona/rule-delta.js +82 -0
  142. package/dist/persona/rule-delta.js.map +1 -0
  143. package/dist/persona/types.d.ts +12 -0
  144. package/dist/pipeline/annotate.js +10 -2
  145. package/dist/pipeline/annotate.js.map +1 -1
  146. package/dist/pipeline/compile.js +14 -2
  147. package/dist/pipeline/compile.js.map +1 -1
  148. package/dist/pipeline/pipeline-runner.d.ts +63 -4
  149. package/dist/pipeline/pipeline-runner.js +159 -50
  150. package/dist/pipeline/pipeline-runner.js.map +1 -1
  151. package/dist/pipeline/pipeline-shared.d.ts +32 -3
  152. package/dist/pipeline/pipeline-shared.js +76 -8
  153. package/dist/pipeline/pipeline-shared.js.map +1 -1
  154. package/dist/pipeline/refresh-lists.js +3 -5
  155. package/dist/pipeline/refresh-lists.js.map +1 -1
  156. package/dist/sandbox/index.d.ts +19 -4
  157. package/dist/sandbox/index.js +31 -18
  158. package/dist/sandbox/index.js.map +1 -1
  159. package/dist/session/index.js +10 -1
  160. package/dist/session/index.js.map +1 -1
  161. package/dist/session/preflight.d.ts +1 -30
  162. package/dist/session/preflight.js +52 -85
  163. package/dist/session/preflight.js.map +1 -1
  164. package/dist/session/types.d.ts +9 -0
  165. package/dist/signal/bot-command.js +6 -1
  166. package/dist/signal/bot-command.js.map +1 -1
  167. package/dist/signal/setup-signal.js +1 -1
  168. package/dist/signal/setup-signal.js.map +1 -1
  169. package/dist/signal/signal-container.d.ts +3 -3
  170. package/dist/signal/signal-container.js +2 -2
  171. package/dist/signal/signal-container.js.map +1 -1
  172. package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
  173. package/dist/trusted-process/call-circuit-breaker.js +22 -3
  174. package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
  175. package/dist/trusted-process/container-command.d.ts +35 -0
  176. package/dist/trusted-process/container-command.js +49 -0
  177. package/dist/trusted-process/container-command.js.map +1 -0
  178. package/dist/trusted-process/mcp-proxy-server.js +35 -3
  179. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  180. package/dist/trusted-process/policy-engine.js +13 -2
  181. package/dist/trusted-process/policy-engine.js.map +1 -1
  182. package/dist/trusted-process/tcp-server-transport.d.ts +12 -1
  183. package/dist/trusted-process/tcp-server-transport.js +9 -1
  184. package/dist/trusted-process/tcp-server-transport.js.map +1 -1
  185. package/dist/trusted-process/tool-call-coordinator.d.ts +22 -8
  186. package/dist/trusted-process/tool-call-coordinator.js +149 -65
  187. package/dist/trusted-process/tool-call-coordinator.js.map +1 -1
  188. package/dist/trusted-process/tool-call-pipeline.d.ts +8 -0
  189. package/dist/trusted-process/tool-call-pipeline.js +68 -34
  190. package/dist/trusted-process/tool-call-pipeline.js.map +1 -1
  191. package/dist/util/atomic-write.d.ts +31 -0
  192. package/dist/util/atomic-write.js +43 -0
  193. package/dist/util/atomic-write.js.map +1 -0
  194. package/dist/web-ui/conn-registry.d.ts +14 -0
  195. package/dist/web-ui/conn-registry.js +25 -0
  196. package/dist/web-ui/conn-registry.js.map +1 -0
  197. package/dist/web-ui/dispatch/persona-dispatch.d.ts +46 -2
  198. package/dist/web-ui/dispatch/persona-dispatch.js +209 -56
  199. package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -1
  200. package/dist/web-ui/dispatch/session-dispatch.js +22 -4
  201. package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
  202. package/dist/web-ui/dispatch/types.d.ts +23 -0
  203. package/dist/web-ui/dispatch/types.js +4 -0
  204. package/dist/web-ui/dispatch/types.js.map +1 -1
  205. package/dist/web-ui/dispatch/workflow-dispatch.js +116 -5
  206. package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -1
  207. package/dist/web-ui/json-rpc-dispatch.js +1 -1
  208. package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
  209. package/dist/web-ui/web-event-bus.d.ts +25 -1
  210. package/dist/web-ui/web-event-bus.js.map +1 -1
  211. package/dist/web-ui/web-ui-server.d.ts +14 -0
  212. package/dist/web-ui/web-ui-server.js +16 -0
  213. package/dist/web-ui/web-ui-server.js.map +1 -1
  214. package/dist/web-ui/web-ui-types.d.ts +133 -5
  215. package/dist/web-ui/web-ui-types.js.map +1 -1
  216. package/dist/web-ui-static/assets/index-BD5U6ILh.css +1 -0
  217. package/dist/web-ui-static/assets/index-FMsHWEfK.js +79 -0
  218. package/dist/web-ui-static/index.html +2 -2
  219. package/dist/workflow/cli-shared.d.ts +62 -0
  220. package/dist/workflow/cli-shared.js +117 -0
  221. package/dist/workflow/cli-shared.js.map +1 -0
  222. package/dist/workflow/cli-support.js +0 -2
  223. package/dist/workflow/cli-support.js.map +1 -1
  224. package/dist/workflow/container-snapshots.d.ts +29 -0
  225. package/dist/workflow/container-snapshots.js +137 -0
  226. package/dist/workflow/container-snapshots.js.map +1 -0
  227. package/dist/workflow/daemon-gate-commands.d.ts +21 -0
  228. package/dist/workflow/daemon-gate-commands.js +599 -0
  229. package/dist/workflow/daemon-gate-commands.js.map +1 -0
  230. package/dist/workflow/discovery.d.ts +29 -0
  231. package/dist/workflow/discovery.js +67 -7
  232. package/dist/workflow/discovery.js.map +1 -1
  233. package/dist/workflow/lane-template.d.ts +89 -0
  234. package/dist/workflow/lane-template.js +141 -0
  235. package/dist/workflow/lane-template.js.map +1 -0
  236. package/dist/workflow/lint.d.ts +7 -1
  237. package/dist/workflow/lint.js +186 -3
  238. package/dist/workflow/lint.js.map +1 -1
  239. package/dist/workflow/machine-builder.d.ts +90 -2
  240. package/dist/workflow/machine-builder.js +222 -29
  241. package/dist/workflow/machine-builder.js.map +1 -1
  242. package/dist/workflow/message-log.d.ts +15 -1
  243. package/dist/workflow/message-log.js.map +1 -1
  244. package/dist/workflow/orchestrator.d.ts +505 -1
  245. package/dist/workflow/orchestrator.js +1722 -69
  246. package/dist/workflow/orchestrator.js.map +1 -1
  247. package/dist/workflow/prompt-builder.js +2 -1
  248. package/dist/workflow/prompt-builder.js.map +1 -1
  249. package/dist/workflow/run-state-command.js +1 -1
  250. package/dist/workflow/run-state-command.js.map +1 -1
  251. package/dist/workflow/status-parser.js +19 -4
  252. package/dist/workflow/status-parser.js.map +1 -1
  253. package/dist/workflow/types.d.ts +123 -23
  254. package/dist/workflow/types.js +2 -0
  255. package/dist/workflow/types.js.map +1 -1
  256. package/dist/workflow/validate.d.ts +23 -1
  257. package/dist/workflow/validate.js +311 -22
  258. package/dist/workflow/validate.js.map +1 -1
  259. package/dist/workflow/workflow-command.d.ts +0 -17
  260. package/dist/workflow/workflow-command.js +110 -88
  261. package/dist/workflow/workflow-command.js.map +1 -1
  262. package/dist/workflow/workflow-discovery.d.ts +2 -0
  263. package/dist/workflow/workflow-discovery.js +22 -1
  264. package/dist/workflow/workflow-discovery.js.map +1 -1
  265. package/dist/workflow/workflow-manager.d.ts +34 -0
  266. package/dist/workflow/workflow-manager.js +52 -1
  267. package/dist/workflow/workflow-manager.js.map +1 -1
  268. package/dist/workflow/workflows/design-and-code/README.md +50 -0
  269. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
  270. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
  271. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
  272. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
  273. package/dist/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
  274. package/dist/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
  275. package/dist/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
  276. package/dist/workflow/workflows/evolve/scripts/LICENSE +201 -0
  277. package/dist/workflow/workflows/evolve/scripts/README.md +314 -0
  278. package/dist/workflow/workflows/evolve/scripts/evolve-brief +16 -0
  279. package/dist/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
  280. package/dist/workflow/workflows/evolve/scripts/evolve-db +16 -0
  281. package/dist/workflow/workflows/evolve/scripts/evolve-eval +16 -0
  282. package/dist/workflow/workflows/evolve/scripts/evolve-files +16 -0
  283. package/dist/workflow/workflows/evolve/scripts/evolve-summary +16 -0
  284. package/dist/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
  285. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
  286. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
  287. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
  288. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
  289. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
  290. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
  291. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
  292. package/dist/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
  293. package/dist/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
  294. package/dist/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
  295. package/dist/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
  296. package/dist/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
  297. package/dist/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
  298. package/dist/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
  299. package/dist/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
  300. package/dist/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
  301. package/dist/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
  302. package/dist/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
  303. package/dist/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
  304. package/dist/workflow/workflows/evolve/scripts/requirements.txt +2 -0
  305. package/dist/workflow/workflows/evolve/workflow.yaml +646 -0
  306. package/dist/workflow/workflows/test-email-summary/workflow.yaml +1 -0
  307. package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
  308. package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
  309. package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
  310. package/dist/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
  311. package/docker/Dockerfile.base +22 -0
  312. package/docker/Dockerfile.base.arm64 +18 -0
  313. package/docker/Dockerfile.claude-code +3 -1
  314. package/docker/Dockerfile.codex +17 -0
  315. package/docker/Dockerfile.goose +3 -1
  316. package/docker/entrypoint-claude-code.sh +6 -45
  317. package/docker/entrypoint-codex.sh +42 -0
  318. package/docker/entrypoint-goose.sh +5 -24
  319. package/docker/entrypoint-uid-remap.sh +93 -0
  320. package/package.json +9 -4
  321. package/src/workflow/workflows/design-and-code/README.md +50 -0
  322. package/src/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
  323. package/src/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
  324. package/src/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
  325. package/src/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
  326. package/src/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
  327. package/src/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
  328. package/src/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
  329. package/src/workflow/workflows/evolve/scripts/LICENSE +201 -0
  330. package/src/workflow/workflows/evolve/scripts/README.md +314 -0
  331. package/src/workflow/workflows/evolve/scripts/evolve-brief +16 -0
  332. package/src/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
  333. package/src/workflow/workflows/evolve/scripts/evolve-db +16 -0
  334. package/src/workflow/workflows/evolve/scripts/evolve-eval +16 -0
  335. package/src/workflow/workflows/evolve/scripts/evolve-files +16 -0
  336. package/src/workflow/workflows/evolve/scripts/evolve-summary +16 -0
  337. package/src/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
  338. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
  339. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
  340. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
  341. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
  342. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
  343. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
  344. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
  345. package/src/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
  346. package/src/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
  347. package/src/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
  348. package/src/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
  349. package/src/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
  350. package/src/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
  351. package/src/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
  352. package/src/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
  353. package/src/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
  354. package/src/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
  355. package/src/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
  356. package/src/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
  357. package/src/workflow/workflows/evolve/scripts/requirements.txt +2 -0
  358. package/src/workflow/workflows/evolve/workflow.yaml +646 -0
  359. package/src/workflow/workflows/test-email-summary/workflow.yaml +1 -0
  360. package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
  361. package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
  362. package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
  363. package/src/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
  364. package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
  365. package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
@@ -0,0 +1,343 @@
1
+ """Run-spec persistence, preflight gating, and path guards."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import copy
6
+ import json
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+ from typing import Any, Dict, Iterable, List, Optional
10
+
11
+ import yaml
12
+
13
+ from .sampling_config import (
14
+ DEFAULT_ISLAND_FEATURE_BINS,
15
+ DEFAULT_ISLAND_FEATURE_DIMENSIONS,
16
+ sampling_summary_lines,
17
+ validate_custom_sampler_for_workspace as validate_sampling_custom_sampler_for_workspace,
18
+ )
19
+
20
+
21
+ DEFAULT_RUN_SPEC: Dict[str, Any] = {
22
+ "objective": "",
23
+ "evaluation": {
24
+ "core_score": "",
25
+ "secondary_metrics": [],
26
+ "command": "",
27
+ "script_path": "",
28
+ "timeout_secs": 0,
29
+ "success_criteria": [],
30
+ },
31
+ "budget": {
32
+ "max_rounds": 0,
33
+ "patience": 0,
34
+ },
35
+ "stop_conditions": [],
36
+ "mutation_scope": {
37
+ "writable_paths": [],
38
+ "primary_targets": [],
39
+ },
40
+ "sampling": {
41
+ "algorithm": "ucb1",
42
+ "sample_n": 3,
43
+ "feature_dimensions": list(DEFAULT_ISLAND_FEATURE_DIMENSIONS),
44
+ "feature_bins": DEFAULT_ISLAND_FEATURE_BINS,
45
+ "custom_sampler_path": "",
46
+ "custom_sampler_class": "",
47
+ },
48
+ "cognition": {
49
+ "source_mode": "",
50
+ "seed_files": [],
51
+ "seed_notes": [],
52
+ },
53
+ "approval": {
54
+ "confirmed": False,
55
+ },
56
+ }
57
+
58
+ REQUIRED_FIELD_CHECKS = {
59
+ "objective": lambda spec: bool(str(spec.get("objective", "")).strip()),
60
+ "evaluation.core_score": lambda spec: bool(
61
+ str(spec.get("evaluation", {}).get("core_score", "")).strip()
62
+ ),
63
+ "evaluation.command_or_script": lambda spec: bool(
64
+ str(spec.get("evaluation", {}).get("command", "")).strip()
65
+ or str(spec.get("evaluation", {}).get("script_path", "")).strip()
66
+ ),
67
+ "evaluation.timeout_secs": lambda spec: int(
68
+ spec.get("evaluation", {}).get("timeout_secs", 0) or 0
69
+ )
70
+ > 0,
71
+ "evaluation.success_criteria": lambda spec: bool(
72
+ spec.get("evaluation", {}).get("success_criteria")
73
+ ),
74
+ "budget.max_rounds": lambda spec: int(spec.get("budget", {}).get("max_rounds", 0) or 0)
75
+ > 0,
76
+ "budget.patience": lambda spec: int(spec.get("budget", {}).get("patience", 0) or 0) >= 0,
77
+ "stop_conditions": lambda spec: bool(spec.get("stop_conditions")),
78
+ "mutation_scope.writable_paths": lambda spec: bool(
79
+ spec.get("mutation_scope", {}).get("writable_paths")
80
+ ),
81
+ "mutation_scope.primary_targets": lambda spec: bool(
82
+ spec.get("mutation_scope", {}).get("primary_targets")
83
+ ),
84
+ "sampling.algorithm": lambda spec: bool(
85
+ str(spec.get("sampling", {}).get("algorithm", "")).strip()
86
+ ),
87
+ "sampling.sample_n": lambda spec: int(spec.get("sampling", {}).get("sample_n", 0) or 0) > 0,
88
+ "sampling.custom_sampler": lambda spec: (
89
+ str(spec.get("sampling", {}).get("algorithm", "")).strip() != "custom"
90
+ or (
91
+ bool(str(spec.get("sampling", {}).get("custom_sampler_path", "")).strip())
92
+ and bool(str(spec.get("sampling", {}).get("custom_sampler_class", "")).strip())
93
+ )
94
+ ),
95
+ "cognition.source_mode": lambda spec: bool(
96
+ str(spec.get("cognition", {}).get("source_mode", "")).strip()
97
+ ),
98
+ }
99
+
100
+
101
+ def default_run_spec() -> Dict[str, Any]:
102
+ return copy.deepcopy(DEFAULT_RUN_SPEC)
103
+
104
+
105
+ def deep_merge(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
106
+ merged = copy.deepcopy(base)
107
+ for key, value in override.items():
108
+ if isinstance(value, dict) and isinstance(merged.get(key), dict):
109
+ merged[key] = deep_merge(merged[key], value)
110
+ else:
111
+ merged[key] = copy.deepcopy(value)
112
+ return merged
113
+
114
+
115
+ def build_run_dir(workspace_root: Path, run_name: str) -> Path:
116
+ return Path(workspace_root).resolve() / ".evolve_runs" / run_name
117
+
118
+
119
+ def ensure_run_layout(run_dir: Path) -> Dict[str, Path]:
120
+ run_dir = Path(run_dir).resolve()
121
+ layout = {
122
+ "run_dir": run_dir,
123
+ "best": run_dir / "best",
124
+ "cognition_data": run_dir / "cognition_data",
125
+ "database_data": run_dir / "database_data",
126
+ "steps": run_dir / "steps",
127
+ }
128
+ run_dir.mkdir(parents=True, exist_ok=True)
129
+ for path in layout.values():
130
+ path.mkdir(parents=True, exist_ok=True)
131
+ round_log = run_dir / "round_log.jsonl"
132
+ if not round_log.exists():
133
+ round_log.write_text("", encoding="utf-8")
134
+ return layout
135
+
136
+
137
+ def workspace_root_for_run(run_dir: Path) -> Path:
138
+ run_dir = Path(run_dir).resolve()
139
+ return run_dir.parent.parent
140
+
141
+
142
+ def spec_path(run_dir: Path) -> Path:
143
+ return Path(run_dir) / "run_spec.yaml"
144
+
145
+
146
+ def load_run_spec(run_dir: Path) -> Dict[str, Any]:
147
+ path = spec_path(run_dir)
148
+ if not path.exists():
149
+ return default_run_spec()
150
+ with open(path, "r", encoding="utf-8") as handle:
151
+ loaded = yaml.safe_load(handle) or {}
152
+ return deep_merge(default_run_spec(), loaded)
153
+
154
+
155
+ def save_run_spec(run_dir: Path, spec: Dict[str, Any]) -> Path:
156
+ path = spec_path(run_dir)
157
+ with open(path, "w", encoding="utf-8") as handle:
158
+ yaml.safe_dump(spec, handle, allow_unicode=True, sort_keys=False)
159
+ return path
160
+
161
+
162
+ def normalize_spec_path(workspace_root: Path, raw_path: str) -> str:
163
+ path = Path(raw_path)
164
+ if not path.is_absolute():
165
+ return raw_path.replace("\\", "/")
166
+
167
+ resolved = path.resolve()
168
+ workspace_root = Path(workspace_root).resolve()
169
+ try:
170
+ return resolved.relative_to(workspace_root).as_posix()
171
+ except ValueError:
172
+ return str(resolved)
173
+
174
+
175
+ def resolve_path(workspace_root: Path, raw_path: str) -> Path:
176
+ path = Path(raw_path)
177
+ if path.is_absolute():
178
+ return path.resolve()
179
+ return (Path(workspace_root).resolve() / path).resolve()
180
+
181
+
182
+ def compute_missing_fields(spec: Dict[str, Any]) -> List[str]:
183
+ return compute_missing_fields_for_workspace(spec)
184
+
185
+
186
+ def compute_missing_fields_for_workspace(
187
+ spec: Dict[str, Any],
188
+ workspace_root: Optional[Path] = None,
189
+ ) -> List[str]:
190
+ missing = []
191
+ for field, check in REQUIRED_FIELD_CHECKS.items():
192
+ if not check(spec):
193
+ missing.append(field)
194
+ custom_sampler_error = validate_custom_sampler_for_workspace(spec, workspace_root)
195
+ if custom_sampler_error:
196
+ missing.append("sampling.custom_sampler_valid")
197
+ return missing
198
+
199
+
200
+ def validate_custom_sampler_for_workspace(
201
+ spec: Dict[str, Any],
202
+ workspace_root: Optional[Path] = None,
203
+ ) -> str:
204
+ return validate_sampling_custom_sampler_for_workspace(spec, workspace_root)
205
+
206
+
207
+ def write_preflight_summary(run_dir: Path, spec: Dict[str, Any]) -> Path:
208
+ workspace_root = workspace_root_for_run(run_dir)
209
+ missing = compute_missing_fields_for_workspace(spec, workspace_root)
210
+ confirmed = bool(spec.get("approval", {}).get("confirmed", False))
211
+ status = "READY" if confirmed and not missing else "PENDING"
212
+ lines = [
213
+ "# Preflight Summary",
214
+ "",
215
+ f"- Status: `{status}`",
216
+ f"- Objective: {spec.get('objective', '') or '(missing)'}",
217
+ f"- Core score: {spec.get('evaluation', {}).get('core_score', '') or '(missing)'}",
218
+ f"- Secondary metrics: {', '.join(spec.get('evaluation', {}).get('secondary_metrics', [])) or '(none)'}",
219
+ f"- Evaluation command: {spec.get('evaluation', {}).get('command', '') or '(missing)'}",
220
+ f"- Evaluation script: {spec.get('evaluation', {}).get('script_path', '') or '(missing)'}",
221
+ f"- Evaluation timeout (s): {spec.get('evaluation', {}).get('timeout_secs', 0) or '(missing)'}",
222
+ f"- Success criteria: {', '.join(spec.get('evaluation', {}).get('success_criteria', [])) or '(missing)'}",
223
+ f"- Budget: max_rounds={spec.get('budget', {}).get('max_rounds', 0)}, patience={spec.get('budget', {}).get('patience', 0)}",
224
+ f"- Stop conditions: {', '.join(spec.get('stop_conditions', [])) or '(missing)'}",
225
+ f"- Writable paths: {', '.join(spec.get('mutation_scope', {}).get('writable_paths', [])) or '(missing)'}",
226
+ f"- Primary targets: {', '.join(spec.get('mutation_scope', {}).get('primary_targets', [])) or '(missing)'}",
227
+ *sampling_summary_lines(spec, workspace_root),
228
+ f"- Cognition source mode: {spec.get('cognition', {}).get('source_mode', '') or '(missing)'}",
229
+ f"- Cognition seed files: {', '.join(spec.get('cognition', {}).get('seed_files', [])) or '(none)'}",
230
+ f"- Cognition seed notes: {', '.join(spec.get('cognition', {}).get('seed_notes', [])) or '(none)'}",
231
+ f"- Approval confirmed: {confirmed}",
232
+ ]
233
+ lines.extend(
234
+ [
235
+ "",
236
+ "## Missing fields",
237
+ ]
238
+ )
239
+ if missing:
240
+ lines.extend([f"- {field}" for field in missing])
241
+ else:
242
+ lines.append("- none")
243
+
244
+ path = Path(run_dir) / "preflight_summary.md"
245
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
246
+ return path
247
+
248
+
249
+ def initialize_cognition_seed_file(run_dir: Path, spec: Dict[str, Any]) -> Path:
250
+ path = Path(run_dir) / "cognition_seed.md"
251
+ if path.exists():
252
+ return path
253
+
254
+ notes = spec.get("cognition", {}).get("seed_notes", [])
255
+ lines = [
256
+ "# Cognition Seed Draft",
257
+ "",
258
+ f"- source_mode: {spec.get('cognition', {}).get('source_mode', '') or 'pending'}",
259
+ "- Fill this file during preflight and keep the JSON blocks machine-readable.",
260
+ "",
261
+ "## Notes",
262
+ ]
263
+ if notes:
264
+ lines.extend([f"- {note}" for note in notes])
265
+ else:
266
+ lines.append("- Add user-provided or approved research notes here.")
267
+ lines.extend(
268
+ [
269
+ "",
270
+ "## JSON seeds",
271
+ "",
272
+ "```json",
273
+ "[",
274
+ ' {',
275
+ ' "content": "Replace this with a reusable heuristic or observation.",',
276
+ ' "source": "user",',
277
+ ' "metadata": {"kind": "heuristic"}',
278
+ " }",
279
+ "]",
280
+ "```",
281
+ "",
282
+ ]
283
+ )
284
+ path.write_text("\n".join(lines), encoding="utf-8")
285
+ return path
286
+
287
+
288
+ def require_evolve_ready(run_dir: Path) -> Dict[str, Any]:
289
+ spec = load_run_spec(run_dir)
290
+ missing = compute_missing_fields_for_workspace(spec, workspace_root_for_run(run_dir))
291
+ if missing:
292
+ raise ValueError(
293
+ "Preflight is incomplete. Missing fields: " + ", ".join(missing)
294
+ )
295
+ if not spec.get("approval", {}).get("confirmed", False):
296
+ raise PermissionError("Preflight is not confirmed yet.")
297
+ return spec
298
+
299
+
300
+ def ensure_path_allowed(run_dir: Path, target_path: Path) -> Path:
301
+ spec = load_run_spec(run_dir)
302
+ run_dir = Path(run_dir).resolve()
303
+ target_path = Path(target_path).resolve()
304
+
305
+ if target_path.is_relative_to(run_dir):
306
+ return target_path
307
+
308
+ workspace_root = workspace_root_for_run(run_dir)
309
+ allowed_paths = spec.get("mutation_scope", {}).get("writable_paths", [])
310
+ resolved_roots = [resolve_path(workspace_root, raw_path) for raw_path in allowed_paths]
311
+
312
+ for allowed_root in resolved_roots:
313
+ if target_path.is_relative_to(allowed_root):
314
+ return target_path
315
+
316
+ raise PermissionError(
317
+ f"Path is outside the approved mutation scope: {target_path}"
318
+ )
319
+
320
+
321
+ def append_round_log(run_dir: Path, event: str, payload: Dict[str, Any]) -> Path:
322
+ entry = {
323
+ "timestamp": datetime.now().isoformat(),
324
+ "event": event,
325
+ "payload": payload,
326
+ }
327
+ path = Path(run_dir) / "round_log.jsonl"
328
+ with open(path, "a", encoding="utf-8") as handle:
329
+ handle.write(json.dumps(entry, ensure_ascii=False) + "\n")
330
+ return path
331
+
332
+
333
+ def load_structured_file(path: Path) -> Dict[str, Any]:
334
+ path = Path(path)
335
+ if path.suffix.lower() == ".json":
336
+ return json.loads(path.read_text(encoding="utf-8"))
337
+ return yaml.safe_load(path.read_text(encoding="utf-8")) or {}
338
+
339
+
340
+ def flatten_list(values: Iterable[str] | None) -> List[str]:
341
+ if not values:
342
+ return []
343
+ return [value for value in values if value]
@@ -0,0 +1,173 @@
1
+ """Shared helpers for run-level sampling configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List, Optional, Tuple
8
+
9
+ from .algorithms.factory import load_custom_sampler_class
10
+
11
+
12
+ DEFAULT_SAMPLING_ALGORITHM = "ucb1"
13
+ DEFAULT_SAMPLE_N = 3
14
+ DEFAULT_ISLAND_FEATURE_DIMENSIONS = ["complexity", "diversity"]
15
+ DEFAULT_ISLAND_FEATURE_BINS = 10
16
+ SAMPLING_CONFIG_IMMUTABLE_ERROR = (
17
+ "Sampling configuration is run-level and cannot change after nodes exist. "
18
+ "Start a new run if you want a different algorithm or island feature setup."
19
+ )
20
+
21
+
22
+ def _sampling_section(spec: Dict[str, Any]) -> Dict[str, Any]:
23
+ return spec.get("sampling", {})
24
+
25
+
26
+ def _sampling_algorithm_value(spec: Dict[str, Any]) -> str:
27
+ return str(_sampling_section(spec).get("algorithm", "") or "").strip()
28
+
29
+
30
+ def configured_sampling_algorithm(spec: Dict[str, Any]) -> str:
31
+ return _sampling_algorithm_value(spec) or DEFAULT_SAMPLING_ALGORITHM
32
+
33
+
34
+ def configured_sample_n(spec: Dict[str, Any]) -> int:
35
+ return int(_sampling_section(spec).get("sample_n", DEFAULT_SAMPLE_N) or DEFAULT_SAMPLE_N)
36
+
37
+
38
+ def sampling_config_fingerprint(spec: Dict[str, Any]) -> Dict[str, Any]:
39
+ sampling = _sampling_section(spec)
40
+ return {
41
+ "algorithm": sampling.get("algorithm", DEFAULT_SAMPLING_ALGORITHM),
42
+ "feature_dimensions": list(
43
+ sampling.get("feature_dimensions", []) or DEFAULT_ISLAND_FEATURE_DIMENSIONS
44
+ ),
45
+ "feature_bins": int(sampling.get("feature_bins", DEFAULT_ISLAND_FEATURE_BINS) or DEFAULT_ISLAND_FEATURE_BINS),
46
+ "custom_sampler_path": str(sampling.get("custom_sampler_path", "") or ""),
47
+ "custom_sampler_class": str(sampling.get("custom_sampler_class", "") or ""),
48
+ }
49
+
50
+
51
+ def run_has_recorded_nodes(run_dir: Path) -> bool:
52
+ data_file = Path(run_dir) / "database_data" / "nodes.json"
53
+ if not data_file.exists():
54
+ return False
55
+ try:
56
+ payload = json.loads(data_file.read_text(encoding="utf-8"))
57
+ except json.JSONDecodeError:
58
+ return True
59
+ return bool(payload.get("nodes", {}))
60
+
61
+
62
+ def resolve_sampling_path(workspace_root: Path, raw_path: str) -> Path:
63
+ path = Path(raw_path)
64
+ if path.is_absolute():
65
+ return path.resolve()
66
+ return (Path(workspace_root).resolve() / path).resolve()
67
+
68
+
69
+ def custom_sampler_runtime_config(
70
+ spec: Dict[str, Any],
71
+ workspace_root: Optional[Path] = None,
72
+ ) -> Dict[str, Any]:
73
+ sampling = _sampling_section(spec)
74
+ custom_path = str(sampling.get("custom_sampler_path", "") or "").strip()
75
+ custom_class = str(sampling.get("custom_sampler_class", "") or "").strip()
76
+ if not custom_path:
77
+ return {}
78
+
79
+ resolved_path = (
80
+ resolve_sampling_path(Path(workspace_root), custom_path)
81
+ if workspace_root is not None
82
+ else Path(custom_path).resolve()
83
+ )
84
+ search_paths = [str(resolved_path.parent)]
85
+ if workspace_root is not None:
86
+ search_paths.append(str(Path(workspace_root).resolve()))
87
+ runtime_config: Dict[str, Any] = {
88
+ "custom_sampler_path": str(resolved_path),
89
+ "custom_sampler_search_paths": search_paths,
90
+ }
91
+ if custom_class:
92
+ runtime_config["custom_sampler_class"] = custom_class
93
+ return runtime_config
94
+
95
+
96
+ def build_database_sampling_config(
97
+ spec: Dict[str, Any],
98
+ workspace_root: Path,
99
+ ) -> Tuple[str, Dict[str, Any]]:
100
+ algorithm = configured_sampling_algorithm(spec)
101
+ if algorithm == "island":
102
+ return (
103
+ algorithm,
104
+ {
105
+ "feature_dimensions": list(
106
+ _sampling_section(spec).get("feature_dimensions")
107
+ or DEFAULT_ISLAND_FEATURE_DIMENSIONS
108
+ ),
109
+ "feature_bins": int(
110
+ _sampling_section(spec).get("feature_bins", DEFAULT_ISLAND_FEATURE_BINS)
111
+ or DEFAULT_ISLAND_FEATURE_BINS
112
+ ),
113
+ },
114
+ )
115
+ if algorithm == "custom":
116
+ return algorithm, custom_sampler_runtime_config(spec, workspace_root)
117
+ return algorithm, {}
118
+
119
+
120
+ def validate_custom_sampler_for_workspace(
121
+ spec: Dict[str, Any],
122
+ workspace_root: Optional[Path] = None,
123
+ ) -> str:
124
+ if configured_sampling_algorithm(spec) != "custom":
125
+ return ""
126
+
127
+ runtime_config = custom_sampler_runtime_config(spec, workspace_root)
128
+ custom_path = str(_sampling_section(spec).get("custom_sampler_path", "") or "").strip()
129
+ custom_class = str(_sampling_section(spec).get("custom_sampler_class", "") or "").strip()
130
+ if not custom_path or not custom_class:
131
+ return ""
132
+
133
+ try:
134
+ load_custom_sampler_class(
135
+ runtime_config["custom_sampler_path"],
136
+ custom_class,
137
+ search_paths=runtime_config.get("custom_sampler_search_paths"),
138
+ )
139
+ except Exception as exc: # pragma: no cover - surfaced validation path
140
+ return str(exc)
141
+ return ""
142
+
143
+
144
+ def sampling_summary_lines(
145
+ spec: Dict[str, Any],
146
+ workspace_root: Optional[Path] = None,
147
+ ) -> List[str]:
148
+ sampling = _sampling_section(spec)
149
+ sampling_algorithm = _sampling_algorithm_value(spec) or "(missing)"
150
+ lines = [
151
+ f"- Sampling algorithm: {sampling_algorithm}",
152
+ f"- Sample count: {sampling.get('sample_n', 0)}",
153
+ ]
154
+ if sampling_algorithm == "island":
155
+ feature_dimensions = sampling.get("feature_dimensions", []) or DEFAULT_ISLAND_FEATURE_DIMENSIONS
156
+ lines.extend(
157
+ [
158
+ f"- Island feature dimensions: {', '.join(feature_dimensions)}",
159
+ f"- Island feature bins: {sampling.get('feature_bins', DEFAULT_ISLAND_FEATURE_BINS)}",
160
+ "- Island built-ins: complexity=len(code), diversity=code-difference heuristic",
161
+ ]
162
+ )
163
+ elif sampling_algorithm == "custom":
164
+ lines.extend(
165
+ [
166
+ f"- Custom sampler path: {sampling.get('custom_sampler_path', '') or '(missing)'}",
167
+ f"- Custom sampler class: {sampling.get('custom_sampler_class', '') or '(missing)'}",
168
+ ]
169
+ )
170
+ custom_sampler_error = validate_custom_sampler_for_workspace(spec, workspace_root)
171
+ if custom_sampler_error:
172
+ lines.append(f"- Custom sampler validation error: {custom_sampler_error}")
173
+ return lines
@@ -0,0 +1,93 @@
1
+ """Core data structures for the Evolve skill runtime."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from datetime import datetime
7
+ from typing import Any, Dict, List, Optional
8
+
9
+
10
+ @dataclass
11
+ class Node:
12
+ """One recorded evolution node."""
13
+
14
+ name: str = ""
15
+ created_at: str = ""
16
+ parent: List[int] = field(default_factory=list)
17
+ motivation: str = ""
18
+ code: str = ""
19
+ results: Dict[str, Any] = field(default_factory=dict)
20
+ analysis: str = ""
21
+ meta_info: Dict[str, Any] = field(default_factory=dict)
22
+ id: Optional[int] = None
23
+ visit_count: int = 0
24
+ score: float = 0.0
25
+
26
+ def __post_init__(self) -> None:
27
+ if not self.created_at:
28
+ self.created_at = datetime.now().isoformat()
29
+
30
+ def to_dict(self) -> Dict[str, Any]:
31
+ return {
32
+ "id": self.id,
33
+ "name": self.name,
34
+ "created_at": self.created_at,
35
+ "parent": self.parent,
36
+ "motivation": self.motivation,
37
+ "code": self.code,
38
+ "results": self.results,
39
+ "analysis": self.analysis,
40
+ "meta_info": self.meta_info,
41
+ "visit_count": self.visit_count,
42
+ "score": self.score,
43
+ }
44
+
45
+ @classmethod
46
+ def from_dict(cls, data: Dict[str, Any]) -> "Node":
47
+ return cls(
48
+ id=data.get("id"),
49
+ name=data.get("name", ""),
50
+ created_at=data.get("created_at", ""),
51
+ parent=data.get("parent", []),
52
+ motivation=data.get("motivation", ""),
53
+ code=data.get("code", ""),
54
+ results=data.get("results", {}),
55
+ analysis=data.get("analysis", ""),
56
+ meta_info=data.get("meta_info", {}),
57
+ visit_count=data.get("visit_count", 0),
58
+ score=data.get("score", 0.0),
59
+ )
60
+
61
+ def get_context_text(self) -> str:
62
+ return " ".join(
63
+ value
64
+ for value in [self.name, self.motivation, self.analysis]
65
+ if value
66
+ )
67
+
68
+
69
+ @dataclass
70
+ class CognitionItem:
71
+ """One cognition item stored for semantic retrieval."""
72
+
73
+ content: str
74
+ source: str = ""
75
+ metadata: Dict[str, Any] = field(default_factory=dict)
76
+ id: Optional[str] = None
77
+
78
+ def to_dict(self) -> Dict[str, Any]:
79
+ return {
80
+ "id": self.id,
81
+ "content": self.content,
82
+ "source": self.source,
83
+ "metadata": self.metadata,
84
+ }
85
+
86
+ @classmethod
87
+ def from_dict(cls, data: Dict[str, Any]) -> "CognitionItem":
88
+ return cls(
89
+ id=data.get("id"),
90
+ content=data.get("content", ""),
91
+ source=data.get("source", ""),
92
+ metadata=data.get("metadata", {}),
93
+ )