@voybio/ace-swarm 0.1.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 (334) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/LICENSE +186 -0
  3. package/README.md +229 -0
  4. package/assets/.agents/ACE/ACE-Init/AGENTS.md +210 -0
  5. package/assets/.agents/ACE/ACE-Init/instructions.md +118 -0
  6. package/assets/.agents/ACE/ACE_coders/AGENTS.md +154 -0
  7. package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +216 -0
  8. package/assets/.agents/ACE/AGENT_REGISTRY.md +70 -0
  9. package/assets/.agents/ACE/AGENT_REGISTRY_7.md +9 -0
  10. package/assets/.agents/ACE/DIRECTIVE_KERNEL.md +234 -0
  11. package/assets/.agents/ACE/UI/AGENTS.md +115 -0
  12. package/assets/.agents/ACE/UI/instructions.md +178 -0
  13. package/assets/.agents/ACE/VOS/ACE_VOS_MISSING_INFO_MATRIX.md +42 -0
  14. package/assets/.agents/ACE/VOS/AGENTS.md +72 -0
  15. package/assets/.agents/ACE/VOS/instructions.md +211 -0
  16. package/assets/.agents/ACE/agent-astgrep/AGENTS.md +123 -0
  17. package/assets/.agents/ACE/agent-astgrep/instructions.md +91 -0
  18. package/assets/.agents/ACE/agent-builder/AGENTS.md +172 -0
  19. package/assets/.agents/ACE/agent-builder/instructions.md +137 -0
  20. package/assets/.agents/ACE/agent-docs/AGENTS.md +159 -0
  21. package/assets/.agents/ACE/agent-docs/instructions.md +133 -0
  22. package/assets/.agents/ACE/agent-eval/AGENTS.md +46 -0
  23. package/assets/.agents/ACE/agent-eval/instructions.md +56 -0
  24. package/assets/.agents/ACE/agent-memory/AGENTS.md +49 -0
  25. package/assets/.agents/ACE/agent-memory/instructions.md +50 -0
  26. package/assets/.agents/ACE/agent-observability/AGENTS.md +46 -0
  27. package/assets/.agents/ACE/agent-observability/instructions.md +50 -0
  28. package/assets/.agents/ACE/agent-ops/AGENTS.md +201 -0
  29. package/assets/.agents/ACE/agent-ops/instructions.md +136 -0
  30. package/assets/.agents/ACE/agent-qa/AGENTS.md +189 -0
  31. package/assets/.agents/ACE/agent-qa/instructions.md +121 -0
  32. package/assets/.agents/ACE/agent-release/AGENTS.md +48 -0
  33. package/assets/.agents/ACE/agent-release/instructions.md +49 -0
  34. package/assets/.agents/ACE/agent-research/AGENTS.md +160 -0
  35. package/assets/.agents/ACE/agent-research/instructions.md +118 -0
  36. package/assets/.agents/ACE/agent-security/AGENTS.md +48 -0
  37. package/assets/.agents/ACE/agent-security/instructions.md +50 -0
  38. package/assets/.agents/ACE/agent-skeptic/AGENTS.md +178 -0
  39. package/assets/.agents/ACE/agent-skeptic/instructions.md +196 -0
  40. package/assets/.agents/ACE/agent-spec/AGENTS.md +169 -0
  41. package/assets/.agents/ACE/agent-spec/instructions.md +116 -0
  42. package/assets/.agents/ACE/orchestrator/AGENTS.md +365 -0
  43. package/assets/.agents/ACE/orchestrator/instructions.md +231 -0
  44. package/assets/.agents/skills/ace-orchestrator/SKILL.md +63 -0
  45. package/assets/.agents/skills/ace-orchestrator/references/engineering-bootstrap-playbook.md +360 -0
  46. package/assets/.agents/skills/astgrep-index/SKILL.md +58 -0
  47. package/assets/.agents/skills/codemunch/SKILL.md +65 -0
  48. package/assets/.agents/skills/codemunch/references/ast-driven-protocol.md +543 -0
  49. package/assets/.agents/skills/codesnipe/SKILL.md +64 -0
  50. package/assets/.agents/skills/codesnipe/references/dual-codebase-playbook.md +671 -0
  51. package/assets/.agents/skills/eval-harness/SKILL.md +203 -0
  52. package/assets/.agents/skills/handoff-lint/SKILL.md +164 -0
  53. package/assets/.agents/skills/incident-commander/SKILL.md +174 -0
  54. package/assets/.agents/skills/landing-review-watcher/SKILL.md +68 -0
  55. package/assets/.agents/skills/memory-curator/SKILL.md +179 -0
  56. package/assets/.agents/skills/problem-triage/SKILL.md +57 -0
  57. package/assets/.agents/skills/problem-triage/agents/openai.yaml +3 -0
  58. package/assets/.agents/skills/release-sentry/SKILL.md +189 -0
  59. package/assets/.agents/skills/risk-quant/SKILL.md +190 -0
  60. package/assets/.agents/skills/schema-forge/SKILL.md +174 -0
  61. package/assets/.agents/skills/skill-auditor/SKILL.md +52 -0
  62. package/assets/.agents/skills/state-auditor/SKILL.md +182 -0
  63. package/assets/.github/hooks/ace-copilot.json +68 -0
  64. package/assets/agent-state/ACE_WORKFLOW.md +131 -0
  65. package/assets/agent-state/ARTIFACT_MANIFEST.json +5 -0
  66. package/assets/agent-state/AST_GREP_COMMANDS.md +121 -0
  67. package/assets/agent-state/AST_GREP_INDEX.json +13 -0
  68. package/assets/agent-state/AST_GREP_INDEX.md +15 -0
  69. package/assets/agent-state/DECISIONS.md +7 -0
  70. package/assets/agent-state/EVIDENCE_LOG.md +7 -0
  71. package/assets/agent-state/HANDOFF.json +24 -0
  72. package/assets/agent-state/INTERFACE_REGISTRY.md +75 -0
  73. package/assets/agent-state/MODULES/gates/gate-autonomy.json +7 -0
  74. package/assets/agent-state/MODULES/gates/gate-completeness.json +7 -0
  75. package/assets/agent-state/MODULES/gates/gate-correctness.json +7 -0
  76. package/assets/agent-state/MODULES/gates/gate-evaluation.json +7 -0
  77. package/assets/agent-state/MODULES/gates/gate-operability.json +7 -0
  78. package/assets/agent-state/MODULES/gates/gate-security.json +7 -0
  79. package/assets/agent-state/MODULES/gates/gate-typescript-public-surface.json +7 -0
  80. package/assets/agent-state/MODULES/registry.json +41 -0
  81. package/assets/agent-state/MODULES/roles/capability-astgrep.json +49 -0
  82. package/assets/agent-state/MODULES/roles/capability-build.json +39 -0
  83. package/assets/agent-state/MODULES/roles/capability-docs.json +38 -0
  84. package/assets/agent-state/MODULES/roles/capability-eval.json +20 -0
  85. package/assets/agent-state/MODULES/roles/capability-memory.json +20 -0
  86. package/assets/agent-state/MODULES/roles/capability-observability.json +20 -0
  87. package/assets/agent-state/MODULES/roles/capability-ops.json +45 -0
  88. package/assets/agent-state/MODULES/roles/capability-qa.json +40 -0
  89. package/assets/agent-state/MODULES/roles/capability-release.json +21 -0
  90. package/assets/agent-state/MODULES/roles/capability-research.json +44 -0
  91. package/assets/agent-state/MODULES/roles/capability-security.json +21 -0
  92. package/assets/agent-state/MODULES/roles/capability-skeptic.json +48 -0
  93. package/assets/agent-state/MODULES/roles/capability-spec.json +42 -0
  94. package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +289 -0
  95. package/assets/agent-state/MODULES/schemas/ARTIFACT_MANIFEST.schema.json +185 -0
  96. package/assets/agent-state/MODULES/schemas/HANDOFF.agent-state.schema.json +124 -0
  97. package/assets/agent-state/MODULES/schemas/HANDOFF.schema.json +55 -0
  98. package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +290 -0
  99. package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +144 -0
  100. package/assets/agent-state/MODULES/schemas/STATUS_EVENT.schema.json +84 -0
  101. package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +138 -0
  102. package/assets/agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json +134 -0
  103. package/assets/agent-state/MODULES/schemas/VERICIFY_BRIDGE_SNAPSHOT.schema.json +157 -0
  104. package/assets/agent-state/MODULES/schemas/VERICIFY_PROCESS_POST_LOG.schema.json +93 -0
  105. package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +133 -0
  106. package/assets/agent-state/PROVENANCE_LOG.md +28 -0
  107. package/assets/agent-state/QUALITY_GATES.md +15 -0
  108. package/assets/agent-state/RISKS.md +8 -0
  109. package/assets/agent-state/SCOPE.md +20 -0
  110. package/assets/agent-state/SKILL_CATALOG.md +48 -0
  111. package/assets/agent-state/STATUS.md +8 -0
  112. package/assets/agent-state/STATUS_EVENTS.ndjson +1 -0
  113. package/assets/agent-state/TASK.md +18 -0
  114. package/assets/agent-state/TEAL_CONFIG.md +117 -0
  115. package/assets/agent-state/handoff-registry.json +5 -0
  116. package/assets/agent-state/index-fingerprints.json +7 -0
  117. package/assets/agent-state/index.json +32 -0
  118. package/assets/agent-state/run-ledger.json +5 -0
  119. package/assets/agent-state/runtime-executor-sessions.json +5 -0
  120. package/assets/agent-state/runtime-tool-specs.json +5 -0
  121. package/assets/agent-state/runtime-workspaces.json +5 -0
  122. package/assets/agent-state/todo-state.json +7 -0
  123. package/assets/agent-state/tracker-snapshot.json +7 -0
  124. package/assets/agent-state/vericify/ace-bridge.json +60 -0
  125. package/assets/agent-state/vericify/process-posts.json +5 -0
  126. package/assets/instructions/ACE.instructions.md +187 -0
  127. package/assets/instructions/ACE_Coder.instructions.md +146 -0
  128. package/assets/instructions/ACE_UI.instructions.md +178 -0
  129. package/assets/instructions/ACE_VOS.instructions.md +211 -0
  130. package/assets/scripts/ace-hook-dispatch.mjs +538 -0
  131. package/assets/scripts/bootstrap-workspace.sh +27 -0
  132. package/assets/scripts/copilot-hook-dispatch.mjs +3 -0
  133. package/assets/scripts/eval-harness.sh +68 -0
  134. package/assets/scripts/render-mcp-configs.sh +396 -0
  135. package/assets/tasks/README.md +48 -0
  136. package/assets/tasks/SWARM_HANDOFF.example.json +53 -0
  137. package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +55 -0
  138. package/assets/tasks/SWARM_HANDOFF.example_vos_to_ui.json +55 -0
  139. package/assets/tasks/SWARM_HANDOFF.template.json +52 -0
  140. package/assets/tasks/cli_work_split.md +22 -0
  141. package/assets/tasks/lessons.md +17 -0
  142. package/assets/tasks/role_tasks.md +206 -0
  143. package/assets/tasks/todo.md +23 -0
  144. package/dist/ace-autonomy.d.ts +137 -0
  145. package/dist/ace-autonomy.js +472 -0
  146. package/dist/ace-context.d.ts +29 -0
  147. package/dist/ace-context.js +240 -0
  148. package/dist/ace-internal-tools.d.ts +8 -0
  149. package/dist/ace-internal-tools.js +76 -0
  150. package/dist/ace-server-instructions.d.ts +12 -0
  151. package/dist/ace-server-instructions.js +324 -0
  152. package/dist/agent-runtime/role-adapters.d.ts +29 -0
  153. package/dist/agent-runtime/role-adapters.js +573 -0
  154. package/dist/astgrep-index.d.ts +24 -0
  155. package/dist/astgrep-index.js +476 -0
  156. package/dist/cli.d.ts +3 -0
  157. package/dist/cli.js +591 -0
  158. package/dist/git-ops.d.ts +53 -0
  159. package/dist/git-ops.js +238 -0
  160. package/dist/handoff-registry.d.ts +71 -0
  161. package/dist/handoff-registry.js +422 -0
  162. package/dist/helpers.d.ts +126 -0
  163. package/dist/helpers.js +1687 -0
  164. package/dist/index-store.d.ts +51 -0
  165. package/dist/index-store.js +328 -0
  166. package/dist/index.d.ts +3 -0
  167. package/dist/index.js +7 -0
  168. package/dist/internal-tool-runtime.d.ts +21 -0
  169. package/dist/internal-tool-runtime.js +136 -0
  170. package/dist/job-scheduler.d.ts +175 -0
  171. package/dist/job-scheduler.js +1217 -0
  172. package/dist/kanban.d.ts +27 -0
  173. package/dist/kanban.js +339 -0
  174. package/dist/local-model-runtime.d.ts +40 -0
  175. package/dist/local-model-runtime.js +174 -0
  176. package/dist/model-bridge.d.ts +54 -0
  177. package/dist/model-bridge.js +587 -0
  178. package/dist/orchestrator-supervisor.d.ts +100 -0
  179. package/dist/orchestrator-supervisor.js +399 -0
  180. package/dist/problem-triage.d.ts +23 -0
  181. package/dist/problem-triage.js +448 -0
  182. package/dist/prompts.d.ts +7 -0
  183. package/dist/prompts.js +628 -0
  184. package/dist/public-surface.d.ts +30 -0
  185. package/dist/public-surface.js +316 -0
  186. package/dist/resources.d.ts +7 -0
  187. package/dist/resources.js +545 -0
  188. package/dist/run-ledger.d.ts +36 -0
  189. package/dist/run-ledger.js +257 -0
  190. package/dist/runtime-command.d.ts +18 -0
  191. package/dist/runtime-command.js +76 -0
  192. package/dist/runtime-executor.d.ts +104 -0
  193. package/dist/runtime-executor.js +985 -0
  194. package/dist/runtime-profile.d.ts +116 -0
  195. package/dist/runtime-profile.js +532 -0
  196. package/dist/runtime-tool-specs.d.ts +68 -0
  197. package/dist/runtime-tool-specs.js +527 -0
  198. package/dist/safe-edit.d.ts +52 -0
  199. package/dist/safe-edit.js +255 -0
  200. package/dist/schemas.d.ts +44 -0
  201. package/dist/schemas.js +830 -0
  202. package/dist/semantic-cache.d.ts +147 -0
  203. package/dist/semantic-cache.js +552 -0
  204. package/dist/semantic-hash.d.ts +83 -0
  205. package/dist/semantic-hash.js +346 -0
  206. package/dist/server.d.ts +10 -0
  207. package/dist/server.js +46 -0
  208. package/dist/shared.d.ts +136 -0
  209. package/dist/shared.js +269 -0
  210. package/dist/skill-auditor.d.ts +26 -0
  211. package/dist/skill-auditor.js +184 -0
  212. package/dist/skill-catalog.d.ts +60 -0
  213. package/dist/skill-catalog.js +305 -0
  214. package/dist/status-events.d.ts +40 -0
  215. package/dist/status-events.js +269 -0
  216. package/dist/store/ace-packed-store.d.ts +69 -0
  217. package/dist/store/ace-packed-store.js +434 -0
  218. package/dist/store/bootstrap-store.d.ts +46 -0
  219. package/dist/store/bootstrap-store.js +242 -0
  220. package/dist/store/catalog-builder.d.ts +21 -0
  221. package/dist/store/catalog-builder.js +68 -0
  222. package/dist/store/importer.d.ts +19 -0
  223. package/dist/store/importer.js +157 -0
  224. package/dist/store/knowledge-bake.d.ts +59 -0
  225. package/dist/store/knowledge-bake.js +339 -0
  226. package/dist/store/materializers/hook-context-materializer.d.ts +25 -0
  227. package/dist/store/materializers/hook-context-materializer.js +100 -0
  228. package/dist/store/materializers/host-file-materializer.d.ts +37 -0
  229. package/dist/store/materializers/host-file-materializer.js +271 -0
  230. package/dist/store/materializers/todo-syncer.d.ts +30 -0
  231. package/dist/store/materializers/todo-syncer.js +140 -0
  232. package/dist/store/materializers/vericify-projector.d.ts +38 -0
  233. package/dist/store/materializers/vericify-projector.js +239 -0
  234. package/dist/store/repositories/discovery-repository.d.ts +24 -0
  235. package/dist/store/repositories/discovery-repository.js +58 -0
  236. package/dist/store/repositories/handoff-repository.d.ts +31 -0
  237. package/dist/store/repositories/handoff-repository.js +67 -0
  238. package/dist/store/repositories/ledger-repository.d.ts +26 -0
  239. package/dist/store/repositories/ledger-repository.js +49 -0
  240. package/dist/store/repositories/runtime-kv-repository.d.ts +16 -0
  241. package/dist/store/repositories/runtime-kv-repository.js +36 -0
  242. package/dist/store/repositories/scheduler-repository.d.ts +50 -0
  243. package/dist/store/repositories/scheduler-repository.js +123 -0
  244. package/dist/store/repositories/session-repository.d.ts +33 -0
  245. package/dist/store/repositories/session-repository.js +82 -0
  246. package/dist/store/repositories/todo-repository.d.ts +31 -0
  247. package/dist/store/repositories/todo-repository.js +77 -0
  248. package/dist/store/repositories/tracker-repository.d.ts +25 -0
  249. package/dist/store/repositories/tracker-repository.js +43 -0
  250. package/dist/store/repositories/vericify-repository.d.ts +32 -0
  251. package/dist/store/repositories/vericify-repository.js +58 -0
  252. package/dist/store/skills-install.d.ts +28 -0
  253. package/dist/store/skills-install.js +86 -0
  254. package/dist/store/state-reader.d.ts +49 -0
  255. package/dist/store/state-reader.js +111 -0
  256. package/dist/store/store-artifacts.d.ts +12 -0
  257. package/dist/store/store-artifacts.js +138 -0
  258. package/dist/store/store-snapshot.d.ts +19 -0
  259. package/dist/store/store-snapshot.js +140 -0
  260. package/dist/store/topology-bake.d.ts +15 -0
  261. package/dist/store/topology-bake.js +215 -0
  262. package/dist/store/types.d.ts +155 -0
  263. package/dist/store/types.js +35 -0
  264. package/dist/store/workspace-snapshot.d.ts +26 -0
  265. package/dist/store/workspace-snapshot.js +107 -0
  266. package/dist/store/write-queue.d.ts +7 -0
  267. package/dist/store/write-queue.js +26 -0
  268. package/dist/todo-state.d.ts +41 -0
  269. package/dist/todo-state.js +399 -0
  270. package/dist/tools-agent.d.ts +7 -0
  271. package/dist/tools-agent.js +1542 -0
  272. package/dist/tools-discovery.d.ts +6 -0
  273. package/dist/tools-discovery.js +178 -0
  274. package/dist/tools-drift.d.ts +13 -0
  275. package/dist/tools-drift.js +357 -0
  276. package/dist/tools-files.d.ts +6 -0
  277. package/dist/tools-files.js +679 -0
  278. package/dist/tools-framework.d.ts +7 -0
  279. package/dist/tools-framework.js +1414 -0
  280. package/dist/tools-git.d.ts +6 -0
  281. package/dist/tools-git.js +183 -0
  282. package/dist/tools-handoff.d.ts +32 -0
  283. package/dist/tools-handoff.js +489 -0
  284. package/dist/tools-lifecycle.d.ts +6 -0
  285. package/dist/tools-lifecycle.js +205 -0
  286. package/dist/tools-memory.d.ts +6 -0
  287. package/dist/tools-memory.js +260 -0
  288. package/dist/tools-scheduler.d.ts +6 -0
  289. package/dist/tools-scheduler.js +228 -0
  290. package/dist/tools-skills.d.ts +3 -0
  291. package/dist/tools-skills.js +104 -0
  292. package/dist/tools-todo.d.ts +6 -0
  293. package/dist/tools-todo.js +154 -0
  294. package/dist/tools.d.ts +9 -0
  295. package/dist/tools.js +33 -0
  296. package/dist/tracker-adapters.d.ts +74 -0
  297. package/dist/tracker-adapters.js +776 -0
  298. package/dist/tracker-sync.d.ts +10 -0
  299. package/dist/tracker-sync.js +84 -0
  300. package/dist/tui/agent-runner.d.ts +137 -0
  301. package/dist/tui/agent-runner.js +466 -0
  302. package/dist/tui/agent-worker.d.ts +10 -0
  303. package/dist/tui/agent-worker.js +347 -0
  304. package/dist/tui/chat.d.ts +84 -0
  305. package/dist/tui/chat.js +368 -0
  306. package/dist/tui/commands.d.ts +57 -0
  307. package/dist/tui/commands.js +432 -0
  308. package/dist/tui/dashboard.d.ts +24 -0
  309. package/dist/tui/dashboard.js +110 -0
  310. package/dist/tui/index.d.ts +114 -0
  311. package/dist/tui/index.js +1059 -0
  312. package/dist/tui/input.d.ts +49 -0
  313. package/dist/tui/input.js +336 -0
  314. package/dist/tui/layout.d.ts +116 -0
  315. package/dist/tui/layout.js +367 -0
  316. package/dist/tui/ollama.d.ts +116 -0
  317. package/dist/tui/ollama.js +192 -0
  318. package/dist/tui/openai-compatible.d.ts +63 -0
  319. package/dist/tui/openai-compatible.js +370 -0
  320. package/dist/tui/provider-discovery.d.ts +59 -0
  321. package/dist/tui/provider-discovery.js +530 -0
  322. package/dist/tui/renderer.d.ts +166 -0
  323. package/dist/tui/renderer.js +304 -0
  324. package/dist/tui/tabs.d.ts +70 -0
  325. package/dist/tui/tabs.js +208 -0
  326. package/dist/tui/telemetry.d.ts +56 -0
  327. package/dist/tui/telemetry.js +106 -0
  328. package/dist/vericify-bridge.d.ts +146 -0
  329. package/dist/vericify-bridge.js +571 -0
  330. package/dist/vericify-context.d.ts +10 -0
  331. package/dist/vericify-context.js +72 -0
  332. package/dist/workspace-manager.d.ts +107 -0
  333. package/dist/workspace-manager.js +636 -0
  334. package/package.json +83 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Semantic cache — snapshot, persist, and diff agent-state documents
3
+ * using MinHash signatures for approximate similarity.
4
+ *
5
+ * Flow:
6
+ * 1. takeSnapshot() — hash + sign every tracked file, persist to .tmp/cache/
7
+ * 2. computeSemanticDelta() — compare two snapshots, emit per-file + per-section deltas
8
+ * 3. checkDriftBudget() — gate: is the delta within acceptable bounds?
9
+ *
10
+ * Integration points:
11
+ * • scan_workspace_delta (coarse gate) runs first, flags changed files
12
+ * • semantic cache runs only on files flagged changed
13
+ * • drift report feeds skeptic/ops via status events
14
+ */
15
+ export interface MinHashParams {
16
+ num_permutations: number;
17
+ shingle_size: number;
18
+ seed: number;
19
+ }
20
+ export interface FileSignature {
21
+ content_hash: string;
22
+ size: number;
23
+ signature: number[];
24
+ sections: SectionSignature[];
25
+ }
26
+ export interface SectionSignature {
27
+ heading: string;
28
+ line_start: number;
29
+ line_end: number;
30
+ content_hash: string;
31
+ signature: number[];
32
+ }
33
+ export interface SemanticSnapshot {
34
+ version: 1;
35
+ snapshot_id: string;
36
+ timestamp: string;
37
+ minhash_params: MinHashParams;
38
+ tracked_dirs: string[];
39
+ file_count: number;
40
+ total_size: number;
41
+ files: Record<string, FileSignature>;
42
+ }
43
+ export type FileChangeStatus = "unchanged" | "modified" | "added" | "deleted";
44
+ export interface SectionChange {
45
+ heading: string;
46
+ status: FileChangeStatus;
47
+ similarity: number;
48
+ diff_summary?: string;
49
+ }
50
+ export interface FileDelta {
51
+ status: FileChangeStatus;
52
+ file_similarity: number;
53
+ size_before: number;
54
+ size_after: number;
55
+ growth_pct: number;
56
+ section_changes: SectionChange[];
57
+ }
58
+ export interface DriftBudgetConfig {
59
+ max_growth_pct: number;
60
+ max_churn_pct: number;
61
+ max_new_files: number;
62
+ max_deleted_files: number;
63
+ }
64
+ export interface DriftBudgetResult {
65
+ passed: boolean;
66
+ actual_growth_pct: number;
67
+ actual_churn_pct: number;
68
+ new_files: number;
69
+ deleted_files: number;
70
+ violations: string[];
71
+ }
72
+ export interface SemanticDelta {
73
+ version: 1;
74
+ before_snapshot: string;
75
+ after_snapshot: string;
76
+ timestamp: string;
77
+ summary: {
78
+ unchanged_files: number;
79
+ modified_files: number;
80
+ added_files: number;
81
+ deleted_files: number;
82
+ total_section_changes: number;
83
+ };
84
+ drift_budget?: DriftBudgetResult;
85
+ files: Record<string, FileDelta>;
86
+ }
87
+ export interface TakeSnapshotInput {
88
+ snapshot_id: string;
89
+ tracked_dirs?: string[];
90
+ shingle_size?: number;
91
+ num_permutations?: number;
92
+ seed?: number;
93
+ /** Only snapshot these specific files (overrides tracked_dirs scan). */
94
+ files?: string[];
95
+ }
96
+ /**
97
+ * Snapshot current state of all tracked files into semantic cache.
98
+ * Computes content hashes + MinHash signatures at file and section level.
99
+ */
100
+ export declare function takeSnapshot(input: TakeSnapshotInput): SemanticSnapshot;
101
+ export declare function loadSnapshot(snapshotId: string): SemanticSnapshot | undefined;
102
+ export declare function listSnapshots(): string[];
103
+ export interface ComputeDeltaInput {
104
+ before: string | SemanticSnapshot;
105
+ after: string | SemanticSnapshot;
106
+ /** Include surgical token diff for modified sections (more expensive). */
107
+ include_diffs?: boolean;
108
+ /** Drift budget config. */
109
+ drift_budget?: DriftBudgetConfig;
110
+ }
111
+ /**
112
+ * Compare two snapshots and produce a semantic delta.
113
+ * For markdown files: section-level alignment via DP.
114
+ * For all files: file-level MinHash similarity.
115
+ */
116
+ export declare function computeSemanticDelta(input: ComputeDeltaInput): SemanticDelta;
117
+ /**
118
+ * Pre-cycle: take a "before" snapshot.
119
+ * Returns the snapshot ID for use in post-cycle comparison.
120
+ */
121
+ export declare function preCycleSnapshot(cycleId: string, trackedDirs?: string[]): SemanticSnapshot;
122
+ /**
123
+ * Post-cycle: take an "after" snapshot and compute the delta.
124
+ */
125
+ export declare function postCycleSnapshot(cycleId: string, trackedDirs?: string[], driftBudget?: DriftBudgetConfig, includeDiffs?: boolean): {
126
+ snapshot: SemanticSnapshot;
127
+ delta: SemanticDelta;
128
+ };
129
+ export interface RewriteTarget {
130
+ file: string;
131
+ type: "full" | "section";
132
+ /** For section targets: heading text for ast-grep/heading search. */
133
+ heading?: string;
134
+ /** Line range (0-based) of the affected section. */
135
+ line_start?: number;
136
+ line_end?: number;
137
+ /** Similarity to old version. */
138
+ similarity: number;
139
+ }
140
+ /**
141
+ * Extract rewrite targets from a semantic delta.
142
+ * Returns only modified or added targets — nothing for unchanged/deleted.
143
+ * For code files: full-file target (use ast-grep node targeting externally).
144
+ * For markdown: section-level targets with heading/line ranges.
145
+ */
146
+ export declare function extractRewriteTargets(delta: SemanticDelta): RewriteTarget[];
147
+ //# sourceMappingURL=semantic-cache.d.ts.map
@@ -0,0 +1,552 @@
1
+ /**
2
+ * Semantic cache — snapshot, persist, and diff agent-state documents
3
+ * using MinHash signatures for approximate similarity.
4
+ *
5
+ * Flow:
6
+ * 1. takeSnapshot() — hash + sign every tracked file, persist to .tmp/cache/
7
+ * 2. computeSemanticDelta() — compare two snapshots, emit per-file + per-section deltas
8
+ * 3. checkDriftBudget() — gate: is the delta within acceptable bounds?
9
+ *
10
+ * Integration points:
11
+ * • scan_workspace_delta (coarse gate) runs first, flags changed files
12
+ * • semantic cache runs only on files flagged changed
13
+ * • drift report feeds skeptic/ops via status events
14
+ */
15
+ import { createHash } from "node:crypto";
16
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
17
+ import { resolve } from "node:path";
18
+ import { MinHash, getShingles, splitMarkdownSections, surgicalTokenDiff, renderDiffSummary, } from "./semantic-hash.js";
19
+ import { WORKSPACE_ROOT, safeRead } from "./helpers.js";
20
+ import { isReadError, normalizeRelPath } from "./shared.js";
21
+ // ────────────────────────────────────────────────────────────────────
22
+ // Constants
23
+ // ────────────────────────────────────────────────────────────────────
24
+ const CACHE_DIR = ".tmp/cache/semantic";
25
+ const DEFAULT_SHINGLE_SIZE = 3;
26
+ const DEFAULT_NUM_PERMUTATIONS = 128;
27
+ const DEFAULT_SEED = 42;
28
+ const DEFAULT_SIMILARITY_THRESHOLD = 0.4;
29
+ /** Tracked directories (workspace-relative). */
30
+ const DEFAULT_TRACKED_DIRS = ["agent-state", "global-state", "engineering-state", "venture-state"];
31
+ /** File extensions to track for semantic cache. */
32
+ const TRACKED_EXTENSIONS = new Set([".md", ".json", ".yaml", ".yml", ".txt"]);
33
+ /** Max file size for semantic hashing (skip huge files). */
34
+ const MAX_FILE_SIZE = 512 * 1024; // 512 KB
35
+ // ────────────────────────────────────────────────────────────────────
36
+ // Helpers
37
+ // ────────────────────────────────────────────────────────────────────
38
+ function contentHash(content) {
39
+ return createHash("sha256").update(content).digest("hex");
40
+ }
41
+ function cacheDir() {
42
+ const dir = resolve(WORKSPACE_ROOT, CACHE_DIR);
43
+ if (!existsSync(dir))
44
+ mkdirSync(dir, { recursive: true });
45
+ return dir;
46
+ }
47
+ function snapshotPath(snapshotId) {
48
+ return resolve(cacheDir(), `${snapshotId}.json`);
49
+ }
50
+ function isMarkdown(path) {
51
+ return path.endsWith(".md");
52
+ }
53
+ function isTrackedFile(name) {
54
+ const dot = name.lastIndexOf(".");
55
+ if (dot <= 0)
56
+ return false;
57
+ return TRACKED_EXTENSIONS.has(name.slice(dot).toLowerCase());
58
+ }
59
+ /**
60
+ * Recursively collect tracked files from given directories.
61
+ * Returns workspace-relative paths.
62
+ */
63
+ function collectTrackedFiles(dirs, maxDepth = 4) {
64
+ const files = [];
65
+ function walk(absDir, relDir, depth) {
66
+ if (depth > maxDepth || !existsSync(absDir))
67
+ return;
68
+ let entries;
69
+ try {
70
+ entries = readdirSync(absDir, { withFileTypes: true });
71
+ }
72
+ catch {
73
+ return;
74
+ }
75
+ for (const entry of entries) {
76
+ if (entry.name.startsWith("."))
77
+ continue;
78
+ const entryAbs = resolve(absDir, entry.name);
79
+ const entryRel = relDir ? `${relDir}/${entry.name}` : entry.name;
80
+ if (entry.isDirectory()) {
81
+ // Skip known junk dirs
82
+ if (["node_modules", "dist", ".git", "HANDOFF_HISTORY"].includes(entry.name))
83
+ continue;
84
+ walk(entryAbs, entryRel, depth + 1);
85
+ }
86
+ else if (entry.isFile() && isTrackedFile(entry.name)) {
87
+ try {
88
+ const stat = readFileSync(entryAbs);
89
+ if (stat.length <= MAX_FILE_SIZE) {
90
+ files.push(entryRel);
91
+ }
92
+ }
93
+ catch {
94
+ // skip unreadable
95
+ }
96
+ }
97
+ }
98
+ }
99
+ for (const dir of dirs) {
100
+ const absDir = resolve(WORKSPACE_ROOT, dir);
101
+ walk(absDir, dir, 0);
102
+ }
103
+ return files.sort();
104
+ }
105
+ /**
106
+ * Snapshot current state of all tracked files into semantic cache.
107
+ * Computes content hashes + MinHash signatures at file and section level.
108
+ */
109
+ export function takeSnapshot(input) {
110
+ const shingleSize = input.shingle_size ?? DEFAULT_SHINGLE_SIZE;
111
+ const numPerms = input.num_permutations ?? DEFAULT_NUM_PERMUTATIONS;
112
+ const seed = input.seed ?? DEFAULT_SEED;
113
+ const trackedDirs = input.tracked_dirs ?? DEFAULT_TRACKED_DIRS;
114
+ const mh = new MinHash(numPerms, seed);
115
+ // Collect files
116
+ const filePaths = input.files ?? collectTrackedFiles(trackedDirs);
117
+ const fileSignatures = {};
118
+ let totalSize = 0;
119
+ for (const relPath of filePaths) {
120
+ const raw = safeRead(relPath);
121
+ if (isReadError(raw))
122
+ continue;
123
+ const hash = contentHash(raw);
124
+ const size = Buffer.byteLength(raw, "utf-8");
125
+ totalSize += size;
126
+ // File-level signature
127
+ const fileShingles = getShingles(raw, shingleSize);
128
+ const fileSig = mh.computeSignature(fileShingles);
129
+ // Section-level signatures (markdown only)
130
+ const sections = [];
131
+ if (isMarkdown(relPath)) {
132
+ const mdSections = splitMarkdownSections(raw);
133
+ for (const sec of mdSections) {
134
+ const secShingles = getShingles(sec.content, shingleSize);
135
+ sections.push({
136
+ heading: sec.heading,
137
+ line_start: sec.lineStart,
138
+ line_end: sec.lineEnd,
139
+ content_hash: contentHash(sec.content),
140
+ signature: mh.computeSignature(secShingles),
141
+ });
142
+ }
143
+ }
144
+ fileSignatures[normalizeRelPath(relPath)] = {
145
+ content_hash: hash,
146
+ size,
147
+ signature: fileSig,
148
+ sections,
149
+ };
150
+ }
151
+ const snapshot = {
152
+ version: 1,
153
+ snapshot_id: input.snapshot_id,
154
+ timestamp: new Date().toISOString(),
155
+ minhash_params: {
156
+ num_permutations: numPerms,
157
+ shingle_size: shingleSize,
158
+ seed,
159
+ },
160
+ tracked_dirs: trackedDirs,
161
+ file_count: Object.keys(fileSignatures).length,
162
+ total_size: totalSize,
163
+ files: fileSignatures,
164
+ };
165
+ // Persist
166
+ const outPath = snapshotPath(input.snapshot_id);
167
+ writeFileSync(outPath, JSON.stringify(snapshot, null, 2), "utf-8");
168
+ return snapshot;
169
+ }
170
+ // ────────────────────────────────────────────────────────────────────
171
+ // Core: Load Snapshot
172
+ // ────────────────────────────────────────────────────────────────────
173
+ export function loadSnapshot(snapshotId) {
174
+ const path = snapshotPath(snapshotId);
175
+ if (!existsSync(path))
176
+ return undefined;
177
+ try {
178
+ const raw = readFileSync(path, "utf-8");
179
+ const parsed = JSON.parse(raw);
180
+ if (parsed.version !== 1)
181
+ return undefined;
182
+ return parsed;
183
+ }
184
+ catch {
185
+ return undefined;
186
+ }
187
+ }
188
+ export function listSnapshots() {
189
+ const dir = cacheDir();
190
+ try {
191
+ return readdirSync(dir)
192
+ .filter((f) => f.endsWith(".json"))
193
+ .map((f) => f.replace(/\.json$/, ""))
194
+ .sort();
195
+ }
196
+ catch {
197
+ return [];
198
+ }
199
+ }
200
+ /**
201
+ * Compare two snapshots and produce a semantic delta.
202
+ * For markdown files: section-level alignment via DP.
203
+ * For all files: file-level MinHash similarity.
204
+ */
205
+ export function computeSemanticDelta(input) {
206
+ const before = typeof input.before === "string"
207
+ ? loadSnapshot(input.before)
208
+ : input.before;
209
+ const after = typeof input.after === "string" ? loadSnapshot(input.after) : input.after;
210
+ if (!before || !after) {
211
+ throw new Error(`Missing snapshot: before=${typeof input.before === "string" ? input.before : "inline"}, after=${typeof input.after === "string" ? input.after : "inline"}`);
212
+ }
213
+ // Verify MinHash params match (otherwise signatures are incomparable)
214
+ const paramMatch = before.minhash_params.seed === after.minhash_params.seed &&
215
+ before.minhash_params.num_permutations ===
216
+ after.minhash_params.num_permutations &&
217
+ before.minhash_params.shingle_size === after.minhash_params.shingle_size;
218
+ if (!paramMatch) {
219
+ throw new Error("MinHash parameters differ between snapshots — signatures are not comparable. " +
220
+ "Use the same seed/permutations/shingle_size for both.");
221
+ }
222
+ const mh = new MinHash(before.minhash_params.num_permutations, before.minhash_params.seed);
223
+ const allPaths = new Set([
224
+ ...Object.keys(before.files),
225
+ ...Object.keys(after.files),
226
+ ]);
227
+ const fileDelta = {};
228
+ let unchangedCount = 0;
229
+ let modifiedCount = 0;
230
+ let addedCount = 0;
231
+ let deletedCount = 0;
232
+ let totalSectionChanges = 0;
233
+ for (const path of allPaths) {
234
+ const beforeFile = before.files[path];
235
+ const afterFile = after.files[path];
236
+ if (!beforeFile && afterFile) {
237
+ // Added
238
+ addedCount++;
239
+ fileDelta[path] = {
240
+ status: "added",
241
+ file_similarity: 0,
242
+ size_before: 0,
243
+ size_after: afterFile.size,
244
+ growth_pct: 100,
245
+ section_changes: afterFile.sections.map((s) => ({
246
+ heading: s.heading,
247
+ status: "added",
248
+ similarity: 0,
249
+ })),
250
+ };
251
+ totalSectionChanges += afterFile.sections.length;
252
+ continue;
253
+ }
254
+ if (beforeFile && !afterFile) {
255
+ // Deleted
256
+ deletedCount++;
257
+ fileDelta[path] = {
258
+ status: "deleted",
259
+ file_similarity: 0,
260
+ size_before: beforeFile.size,
261
+ size_after: 0,
262
+ growth_pct: -100,
263
+ section_changes: beforeFile.sections.map((s) => ({
264
+ heading: s.heading,
265
+ status: "deleted",
266
+ similarity: 0,
267
+ })),
268
+ };
269
+ totalSectionChanges += beforeFile.sections.length;
270
+ continue;
271
+ }
272
+ // Both exist — compare
273
+ if (beforeFile.content_hash === afterFile.content_hash) {
274
+ // Exact match
275
+ unchangedCount++;
276
+ fileDelta[path] = {
277
+ status: "unchanged",
278
+ file_similarity: 1.0,
279
+ size_before: beforeFile.size,
280
+ size_after: afterFile.size,
281
+ growth_pct: 0,
282
+ section_changes: [],
283
+ };
284
+ continue;
285
+ }
286
+ // Modified — compute similarity
287
+ modifiedCount++;
288
+ const fileSim = mh.estimateSimilarity(beforeFile.signature, afterFile.signature);
289
+ const growthPct = beforeFile.size > 0
290
+ ? ((afterFile.size - beforeFile.size) / beforeFile.size) * 100
291
+ : 100;
292
+ // Section-level alignment for markdown files
293
+ const sectionChanges = [];
294
+ if (beforeFile.sections.length > 0 ||
295
+ afterFile.sections.length > 0) {
296
+ // Reconstruct MarkdownSection structures from stored signatures
297
+ // for alignment. We need the content for surgical diff though,
298
+ // so read the actual files if diffs are requested.
299
+ const beforeSections = beforeFile.sections.map((s) => ({
300
+ heading: s.heading,
301
+ lineStart: s.line_start,
302
+ lineEnd: s.line_end,
303
+ content: "", // placeholder — content not stored in cache
304
+ }));
305
+ const afterSections = afterFile.sections.map((s) => ({
306
+ heading: s.heading,
307
+ lineStart: s.line_start,
308
+ lineEnd: s.line_end,
309
+ content: "",
310
+ }));
311
+ // Use stored signatures for alignment instead of recomputing
312
+ // Build a custom alignment from section content hashes
313
+ const bSigs = beforeFile.sections;
314
+ const aSigs = afterFile.sections;
315
+ // Similarity matrix from pre-computed signatures
316
+ const simMatrix = Array.from({ length: bSigs.length }, () => new Array(aSigs.length).fill(0));
317
+ for (let i = 0; i < bSigs.length; i++) {
318
+ for (let j = 0; j < aSigs.length; j++) {
319
+ simMatrix[i][j] = mh.estimateSimilarity(bSigs[i].signature, aSigs[j].signature);
320
+ }
321
+ }
322
+ // DP alignment
323
+ const n = bSigs.length;
324
+ const m = aSigs.length;
325
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
326
+ for (let i = 1; i <= n; i++) {
327
+ for (let j = 1; j <= m; j++) {
328
+ if (simMatrix[i - 1][j - 1] > DEFAULT_SIMILARITY_THRESHOLD) {
329
+ dp[i][j] = 1 + dp[i - 1][j - 1];
330
+ }
331
+ else {
332
+ dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
333
+ }
334
+ }
335
+ }
336
+ // Backtrack
337
+ let ii = n;
338
+ let jj = m;
339
+ const aligned = [];
340
+ while (ii > 0 || jj > 0) {
341
+ if (ii > 0 &&
342
+ jj > 0 &&
343
+ simMatrix[ii - 1][jj - 1] > DEFAULT_SIMILARITY_THRESHOLD) {
344
+ const sim = simMatrix[ii - 1][jj - 1];
345
+ const isExact = bSigs[ii - 1].content_hash === aSigs[jj - 1].content_hash;
346
+ aligned.push({
347
+ status: isExact ? "unchanged" : "modified",
348
+ leftIdx: ii - 1,
349
+ rightIdx: jj - 1,
350
+ similarity: sim,
351
+ });
352
+ ii--;
353
+ jj--;
354
+ }
355
+ else if (jj > 0 &&
356
+ (ii === 0 || dp[ii][jj - 1] >= dp[ii - 1][jj])) {
357
+ aligned.push({
358
+ status: "added",
359
+ leftIdx: -1,
360
+ rightIdx: jj - 1,
361
+ similarity: 0,
362
+ });
363
+ jj--;
364
+ }
365
+ else if (ii > 0) {
366
+ aligned.push({
367
+ status: "deleted",
368
+ leftIdx: ii - 1,
369
+ rightIdx: -1,
370
+ similarity: 0,
371
+ });
372
+ ii--;
373
+ }
374
+ }
375
+ aligned.reverse();
376
+ // Build section changes
377
+ for (const entry of aligned) {
378
+ const heading = entry.rightIdx >= 0
379
+ ? aSigs[entry.rightIdx].heading
380
+ : bSigs[entry.leftIdx].heading;
381
+ const change = {
382
+ heading,
383
+ status: entry.status,
384
+ similarity: entry.similarity,
385
+ };
386
+ // Surgical diff for modified sections (if requested and content available)
387
+ if (input.include_diffs && entry.status === "modified") {
388
+ // Read actual file content for surgical diff
389
+ const beforeContent = safeRead(path);
390
+ const afterContent = safeRead(path);
391
+ if (!isReadError(beforeContent) && !isReadError(afterContent)) {
392
+ const bSections = splitMarkdownSections(beforeContent);
393
+ const aSections = splitMarkdownSections(afterContent);
394
+ const bSec = bSections[entry.leftIdx];
395
+ const aSec = aSections[entry.rightIdx];
396
+ if (bSec && aSec) {
397
+ const ops = surgicalTokenDiff(bSec.content, aSec.content);
398
+ change.diff_summary = renderDiffSummary(ops).slice(0, 2000);
399
+ }
400
+ }
401
+ }
402
+ sectionChanges.push(change);
403
+ if (entry.status !== "unchanged")
404
+ totalSectionChanges++;
405
+ }
406
+ }
407
+ fileDelta[path] = {
408
+ status: "modified",
409
+ file_similarity: fileSim,
410
+ size_before: beforeFile.size,
411
+ size_after: afterFile.size,
412
+ growth_pct: Math.round(growthPct * 100) / 100,
413
+ section_changes: sectionChanges,
414
+ };
415
+ }
416
+ // Drift budget
417
+ let driftBudget;
418
+ if (input.drift_budget) {
419
+ driftBudget = checkDriftBudget({
420
+ before_total_size: before.total_size,
421
+ after_total_size: after.total_size,
422
+ modified_count: modifiedCount,
423
+ total_file_count: allPaths.size,
424
+ added_count: addedCount,
425
+ deleted_count: deletedCount,
426
+ }, input.drift_budget);
427
+ }
428
+ return {
429
+ version: 1,
430
+ before_snapshot: before.snapshot_id,
431
+ after_snapshot: after.snapshot_id,
432
+ timestamp: new Date().toISOString(),
433
+ summary: {
434
+ unchanged_files: unchangedCount,
435
+ modified_files: modifiedCount,
436
+ added_files: addedCount,
437
+ deleted_files: deletedCount,
438
+ total_section_changes: totalSectionChanges,
439
+ },
440
+ drift_budget: driftBudget,
441
+ files: fileDelta,
442
+ };
443
+ }
444
+ const DEFAULT_DRIFT_BUDGET = {
445
+ max_growth_pct: 25,
446
+ max_churn_pct: 40,
447
+ max_new_files: 10,
448
+ max_deleted_files: 5,
449
+ };
450
+ function checkDriftBudget(metrics, config = DEFAULT_DRIFT_BUDGET) {
451
+ const growthPct = metrics.before_total_size > 0
452
+ ? ((metrics.after_total_size - metrics.before_total_size) /
453
+ metrics.before_total_size) *
454
+ 100
455
+ : metrics.after_total_size > 0
456
+ ? 100
457
+ : 0;
458
+ const churnPct = metrics.total_file_count > 0
459
+ ? (metrics.modified_count / metrics.total_file_count) * 100
460
+ : 0;
461
+ const violations = [];
462
+ if (Math.abs(growthPct) > config.max_growth_pct) {
463
+ violations.push(`Size growth ${growthPct.toFixed(1)}% exceeds ±${config.max_growth_pct}% limit`);
464
+ }
465
+ if (churnPct > config.max_churn_pct) {
466
+ violations.push(`Churn ${churnPct.toFixed(1)}% exceeds ${config.max_churn_pct}% limit`);
467
+ }
468
+ if (metrics.added_count > config.max_new_files) {
469
+ violations.push(`${metrics.added_count} new files exceeds limit of ${config.max_new_files}`);
470
+ }
471
+ if (metrics.deleted_count > config.max_deleted_files) {
472
+ violations.push(`${metrics.deleted_count} deleted files exceeds limit of ${config.max_deleted_files}`);
473
+ }
474
+ return {
475
+ passed: violations.length === 0,
476
+ actual_growth_pct: Math.round(growthPct * 100) / 100,
477
+ actual_churn_pct: Math.round(churnPct * 100) / 100,
478
+ new_files: metrics.added_count,
479
+ deleted_files: metrics.deleted_count,
480
+ violations,
481
+ };
482
+ }
483
+ // ────────────────────────────────────────────────────────────────────
484
+ // Convenience: cycle wrapper
485
+ // ────────────────────────────────────────────────────────────────────
486
+ /**
487
+ * Pre-cycle: take a "before" snapshot.
488
+ * Returns the snapshot ID for use in post-cycle comparison.
489
+ */
490
+ export function preCycleSnapshot(cycleId, trackedDirs) {
491
+ return takeSnapshot({
492
+ snapshot_id: `${cycleId}_pre`,
493
+ tracked_dirs: trackedDirs,
494
+ });
495
+ }
496
+ /**
497
+ * Post-cycle: take an "after" snapshot and compute the delta.
498
+ */
499
+ export function postCycleSnapshot(cycleId, trackedDirs, driftBudget, includeDiffs = false) {
500
+ const afterSnap = takeSnapshot({
501
+ snapshot_id: `${cycleId}_post`,
502
+ tracked_dirs: trackedDirs,
503
+ });
504
+ const delta = computeSemanticDelta({
505
+ before: `${cycleId}_pre`,
506
+ after: afterSnap,
507
+ include_diffs: includeDiffs,
508
+ drift_budget: driftBudget ?? DEFAULT_DRIFT_BUDGET,
509
+ });
510
+ return { snapshot: afterSnap, delta };
511
+ }
512
+ /**
513
+ * Extract rewrite targets from a semantic delta.
514
+ * Returns only modified or added targets — nothing for unchanged/deleted.
515
+ * For code files: full-file target (use ast-grep node targeting externally).
516
+ * For markdown: section-level targets with heading/line ranges.
517
+ */
518
+ export function extractRewriteTargets(delta) {
519
+ const targets = [];
520
+ for (const [path, fileDelta] of Object.entries(delta.files)) {
521
+ if (fileDelta.status === "unchanged" || fileDelta.status === "deleted") {
522
+ continue;
523
+ }
524
+ if (fileDelta.status === "added") {
525
+ targets.push({ file: path, type: "full", similarity: 0 });
526
+ continue;
527
+ }
528
+ // Modified
529
+ if (fileDelta.section_changes.length === 0) {
530
+ // Non-markdown or no section data: full-file target
531
+ targets.push({
532
+ file: path,
533
+ type: "full",
534
+ similarity: fileDelta.file_similarity,
535
+ });
536
+ continue;
537
+ }
538
+ // Section-level targets for markdown
539
+ for (const sec of fileDelta.section_changes) {
540
+ if (sec.status === "unchanged")
541
+ continue;
542
+ targets.push({
543
+ file: path,
544
+ type: "section",
545
+ heading: sec.heading,
546
+ similarity: sec.similarity,
547
+ });
548
+ }
549
+ }
550
+ return targets;
551
+ }
552
+ //# sourceMappingURL=semantic-cache.js.map