@flyingrobots/graft 0.6.1 → 0.7.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 (561) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/README.md +1 -1
  3. package/dist/adapters/json-text-decoder.d.ts +3 -0
  4. package/dist/adapters/json-text-decoder.d.ts.map +1 -0
  5. package/dist/adapters/json-text-decoder.js +12 -0
  6. package/dist/adapters/json-text-decoder.js.map +1 -0
  7. package/dist/adapters/node-paths.d.ts +3 -0
  8. package/dist/adapters/node-paths.d.ts.map +1 -0
  9. package/dist/adapters/node-paths.js +29 -0
  10. package/dist/adapters/node-paths.js.map +1 -0
  11. package/dist/adapters/repo-paths.d.ts.map +1 -1
  12. package/dist/adapters/repo-paths.js +40 -5
  13. package/dist/adapters/repo-paths.js.map +1 -1
  14. package/dist/api/tool-bridge.d.ts +1 -1
  15. package/dist/api/tool-bridge.d.ts.map +1 -1
  16. package/dist/api/tool-bridge.js +1 -1
  17. package/dist/api/tool-bridge.js.map +1 -1
  18. package/dist/cli/cli-error.d.ts.map +1 -1
  19. package/dist/cli/cli-error.js +47 -10
  20. package/dist/cli/cli-error.js.map +1 -1
  21. package/dist/cli/command-parser.d.ts +12 -3
  22. package/dist/cli/command-parser.d.ts.map +1 -1
  23. package/dist/cli/command-parser.js +161 -2
  24. package/dist/cli/command-parser.js.map +1 -1
  25. package/dist/cli/daemon-status-model.d.ts +87 -0
  26. package/dist/cli/daemon-status-model.d.ts.map +1 -0
  27. package/dist/cli/daemon-status-model.js +142 -0
  28. package/dist/cli/daemon-status-model.js.map +1 -0
  29. package/dist/cli/daemon-status-render.d.ts +3 -0
  30. package/dist/cli/daemon-status-render.d.ts.map +1 -0
  31. package/dist/cli/daemon-status-render.js +100 -0
  32. package/dist/cli/daemon-status-render.js.map +1 -0
  33. package/dist/cli/daemon-status.d.ts +7 -0
  34. package/dist/cli/daemon-status.d.ts.map +1 -0
  35. package/dist/cli/daemon-status.js +79 -0
  36. package/dist/cli/daemon-status.js.map +1 -0
  37. package/dist/cli/git-graft-enhance-model.d.ts +67 -0
  38. package/dist/cli/git-graft-enhance-model.d.ts.map +1 -0
  39. package/dist/cli/git-graft-enhance-model.js +55 -0
  40. package/dist/cli/git-graft-enhance-model.js.map +1 -0
  41. package/dist/cli/git-graft-enhance-render.d.ts +3 -0
  42. package/dist/cli/git-graft-enhance-render.d.ts.map +1 -0
  43. package/dist/cli/git-graft-enhance-render.js +29 -0
  44. package/dist/cli/git-graft-enhance-render.js.map +1 -0
  45. package/dist/cli/git-graft-enhance.d.ts +14 -0
  46. package/dist/cli/git-graft-enhance.d.ts.map +1 -0
  47. package/dist/cli/git-graft-enhance.js +29 -0
  48. package/dist/cli/git-graft-enhance.js.map +1 -0
  49. package/dist/cli/index-cmd.d.ts.map +1 -1
  50. package/dist/cli/index-cmd.js +18 -21
  51. package/dist/cli/index-cmd.js.map +1 -1
  52. package/dist/cli/index-model.d.ts +5 -9
  53. package/dist/cli/index-model.d.ts.map +1 -1
  54. package/dist/cli/index-model.js +20 -18
  55. package/dist/cli/index-model.js.map +1 -1
  56. package/dist/cli/init-client-config.d.ts +12 -7
  57. package/dist/cli/init-client-config.d.ts.map +1 -1
  58. package/dist/cli/init-client-config.js +105 -43
  59. package/dist/cli/init-client-config.js.map +1 -1
  60. package/dist/cli/init-model.d.ts +9 -2
  61. package/dist/cli/init-model.d.ts.map +1 -1
  62. package/dist/cli/init-model.js +52 -4
  63. package/dist/cli/init-model.js.map +1 -1
  64. package/dist/cli/init-render.d.ts.map +1 -1
  65. package/dist/cli/init-render.js +2 -2
  66. package/dist/cli/init-render.js.map +1 -1
  67. package/dist/cli/init.d.ts.map +1 -1
  68. package/dist/cli/init.js +11 -9
  69. package/dist/cli/init.js.map +1 -1
  70. package/dist/cli/json-document.d.ts +5 -0
  71. package/dist/cli/json-document.d.ts.map +1 -1
  72. package/dist/cli/json-document.js +9 -0
  73. package/dist/cli/json-document.js.map +1 -1
  74. package/dist/cli/main.d.ts +7 -0
  75. package/dist/cli/main.d.ts.map +1 -1
  76. package/dist/cli/main.js +49 -7
  77. package/dist/cli/main.js.map +1 -1
  78. package/dist/cli/migrate-local-history.d.ts.map +1 -1
  79. package/dist/cli/migrate-local-history.js +3 -2
  80. package/dist/cli/migrate-local-history.js.map +1 -1
  81. package/dist/cli/peer-command.d.ts +1 -1
  82. package/dist/cli/peer-command.d.ts.map +1 -1
  83. package/dist/cli/peer-command.js +1 -1
  84. package/dist/cli/peer-command.js.map +1 -1
  85. package/dist/contracts/capabilities.d.ts +5 -5
  86. package/dist/contracts/capabilities.d.ts.map +1 -1
  87. package/dist/contracts/capabilities.js +89 -0
  88. package/dist/contracts/capabilities.js.map +1 -1
  89. package/dist/contracts/causal-ontology.d.ts +17 -17
  90. package/dist/contracts/json-object.d.ts +0 -1
  91. package/dist/contracts/json-object.d.ts.map +1 -1
  92. package/dist/contracts/json-object.js +0 -10
  93. package/dist/contracts/json-object.js.map +1 -1
  94. package/dist/contracts/output-schema-cli.d.ts +277 -25
  95. package/dist/contracts/output-schema-cli.d.ts.map +1 -1
  96. package/dist/contracts/output-schema-cli.js +35 -3
  97. package/dist/contracts/output-schema-cli.js.map +1 -1
  98. package/dist/contracts/output-schema-fragments.d.ts +212 -87
  99. package/dist/contracts/output-schema-fragments.d.ts.map +1 -1
  100. package/dist/contracts/output-schema-fragments.js +49 -2
  101. package/dist/contracts/output-schema-fragments.js.map +1 -1
  102. package/dist/contracts/output-schema-mcp.d.ts +372 -47
  103. package/dist/contracts/output-schema-mcp.d.ts.map +1 -1
  104. package/dist/contracts/output-schema-mcp.js +217 -1
  105. package/dist/contracts/output-schema-mcp.js.map +1 -1
  106. package/dist/contracts/output-schema-meta.d.ts +2 -2
  107. package/dist/contracts/output-schema-meta.d.ts.map +1 -1
  108. package/dist/contracts/output-schemas.d.ts +7 -7
  109. package/dist/contracts/output-schemas.d.ts.map +1 -1
  110. package/dist/contracts/output-schemas.js +294 -6
  111. package/dist/contracts/output-schemas.js.map +1 -1
  112. package/dist/git/diff.d.ts +11 -0
  113. package/dist/git/diff.d.ts.map +1 -1
  114. package/dist/git/diff.js +50 -6
  115. package/dist/git/diff.js.map +1 -1
  116. package/dist/mcp/burden.d.ts.map +1 -1
  117. package/dist/mcp/burden.js +9 -0
  118. package/dist/mcp/burden.js.map +1 -1
  119. package/dist/mcp/context.d.ts +3 -2
  120. package/dist/mcp/context.d.ts.map +1 -1
  121. package/dist/mcp/context.js +2 -37
  122. package/dist/mcp/context.js.map +1 -1
  123. package/dist/mcp/daemon-server.d.ts +2 -0
  124. package/dist/mcp/daemon-server.d.ts.map +1 -1
  125. package/dist/mcp/daemon-server.js +6 -1
  126. package/dist/mcp/daemon-server.js.map +1 -1
  127. package/dist/mcp/daemon-session-host.d.ts +1 -0
  128. package/dist/mcp/daemon-session-host.d.ts.map +1 -1
  129. package/dist/mcp/daemon-session-host.js +3 -0
  130. package/dist/mcp/daemon-session-host.js.map +1 -1
  131. package/dist/mcp/daemon-stdio-bridge.d.ts +1 -0
  132. package/dist/mcp/daemon-stdio-bridge.d.ts.map +1 -1
  133. package/dist/mcp/daemon-stdio-bridge.js +1 -0
  134. package/dist/mcp/daemon-stdio-bridge.js.map +1 -1
  135. package/dist/mcp/monitor-tick-job.d.ts +1 -0
  136. package/dist/mcp/monitor-tick-job.d.ts.map +1 -1
  137. package/dist/mcp/monitor-tick-job.js +84 -29
  138. package/dist/mcp/monitor-tick-job.js.map +1 -1
  139. package/dist/mcp/monitor-types.d.ts +1 -1
  140. package/dist/mcp/monitor-types.d.ts.map +1 -1
  141. package/dist/mcp/persisted-local-history-graph.d.ts +2 -2
  142. package/dist/mcp/persisted-local-history-graph.d.ts.map +1 -1
  143. package/dist/mcp/persisted-local-history-graph.js +3 -2
  144. package/dist/mcp/persisted-local-history-graph.js.map +1 -1
  145. package/dist/mcp/persisted-local-history.d.ts +5 -5
  146. package/dist/mcp/persisted-local-history.js +2 -2
  147. package/dist/mcp/persisted-local-history.js.map +1 -1
  148. package/dist/mcp/persistent-monitor-runtime.d.ts +1 -0
  149. package/dist/mcp/persistent-monitor-runtime.d.ts.map +1 -1
  150. package/dist/mcp/persistent-monitor-runtime.js +35 -0
  151. package/dist/mcp/persistent-monitor-runtime.js.map +1 -1
  152. package/dist/mcp/repo-tool-worker-context.d.ts.map +1 -1
  153. package/dist/mcp/repo-tool-worker-context.js +5 -2
  154. package/dist/mcp/repo-tool-worker-context.js.map +1 -1
  155. package/dist/mcp/server-context.d.ts.map +1 -1
  156. package/dist/mcp/server-context.js +13 -0
  157. package/dist/mcp/server-context.js.map +1 -1
  158. package/dist/mcp/server-tool-access.d.ts +1 -1
  159. package/dist/mcp/server-tool-access.d.ts.map +1 -1
  160. package/dist/mcp/server-tool-access.js +3 -1
  161. package/dist/mcp/server-tool-access.js.map +1 -1
  162. package/dist/mcp/server.d.ts +3 -0
  163. package/dist/mcp/server.d.ts.map +1 -1
  164. package/dist/mcp/server.js +5 -3
  165. package/dist/mcp/server.js.map +1 -1
  166. package/dist/mcp/tool-registry.d.ts.map +1 -1
  167. package/dist/mcp/tool-registry.js +18 -0
  168. package/dist/mcp/tool-registry.js.map +1 -1
  169. package/dist/mcp/tools/code-find.d.ts.map +1 -1
  170. package/dist/mcp/tools/code-find.js +20 -0
  171. package/dist/mcp/tools/code-find.js.map +1 -1
  172. package/dist/mcp/tools/code-show.d.ts.map +1 -1
  173. package/dist/mcp/tools/code-show.js +24 -0
  174. package/dist/mcp/tools/code-show.js.map +1 -1
  175. package/dist/mcp/tools/diagnostic-models.d.ts +2 -0
  176. package/dist/mcp/tools/diagnostic-models.d.ts.map +1 -1
  177. package/dist/mcp/tools/doctor.d.ts.map +1 -1
  178. package/dist/mcp/tools/doctor.js +18 -1
  179. package/dist/mcp/tools/doctor.js.map +1 -1
  180. package/dist/mcp/tools/export-surface-diff.d.ts +3 -0
  181. package/dist/mcp/tools/export-surface-diff.d.ts.map +1 -0
  182. package/dist/mcp/tools/export-surface-diff.js +24 -0
  183. package/dist/mcp/tools/export-surface-diff.js.map +1 -0
  184. package/dist/mcp/tools/file-outline.js +1 -1
  185. package/dist/mcp/tools/file-outline.js.map +1 -1
  186. package/dist/mcp/tools/graft-edit.d.ts +3 -0
  187. package/dist/mcp/tools/graft-edit.d.ts.map +1 -0
  188. package/dist/mcp/tools/graft-edit.js +192 -0
  189. package/dist/mcp/tools/graft-edit.js.map +1 -0
  190. package/dist/mcp/tools/knowledge-map.d.ts +3 -0
  191. package/dist/mcp/tools/knowledge-map.d.ts.map +1 -0
  192. package/dist/mcp/tools/knowledge-map.js +31 -0
  193. package/dist/mcp/tools/knowledge-map.js.map +1 -0
  194. package/dist/mcp/tools/monitor-nudge.d.ts +3 -0
  195. package/dist/mcp/tools/monitor-nudge.d.ts.map +1 -0
  196. package/dist/mcp/tools/monitor-nudge.js +17 -0
  197. package/dist/mcp/tools/monitor-nudge.js.map +1 -0
  198. package/dist/mcp/tools/precision-warp.d.ts +3 -3
  199. package/dist/mcp/tools/precision-warp.d.ts.map +1 -1
  200. package/dist/mcp/tools/precision-warp.js +24 -15
  201. package/dist/mcp/tools/precision-warp.js.map +1 -1
  202. package/dist/mcp/tools/refactor-difficulty.d.ts +3 -0
  203. package/dist/mcp/tools/refactor-difficulty.d.ts.map +1 -0
  204. package/dist/mcp/tools/refactor-difficulty.js +36 -0
  205. package/dist/mcp/tools/refactor-difficulty.js.map +1 -0
  206. package/dist/mcp/tools/safe-read.js +2 -2
  207. package/dist/mcp/tools/safe-read.js.map +1 -1
  208. package/dist/mcp/tools/structural-blame.d.ts +3 -0
  209. package/dist/mcp/tools/structural-blame.d.ts.map +1 -0
  210. package/dist/mcp/tools/structural-blame.js +44 -0
  211. package/dist/mcp/tools/structural-blame.js.map +1 -0
  212. package/dist/mcp/tools/structural-churn.d.ts +3 -0
  213. package/dist/mcp/tools/structural-churn.d.ts.map +1 -0
  214. package/dist/mcp/tools/structural-churn.js +28 -0
  215. package/dist/mcp/tools/structural-churn.js.map +1 -0
  216. package/dist/mcp/tools/structural-log.d.ts +3 -0
  217. package/dist/mcp/tools/structural-log.d.ts.map +1 -0
  218. package/dist/mcp/tools/structural-log.js +38 -0
  219. package/dist/mcp/tools/structural-log.js.map +1 -0
  220. package/dist/mcp/tools/structural-review.d.ts +3 -0
  221. package/dist/mcp/tools/structural-review.d.ts.map +1 -0
  222. package/dist/mcp/tools/structural-review.js +55 -0
  223. package/dist/mcp/tools/structural-review.js.map +1 -0
  224. package/dist/mcp/warp-pool.d.ts +4 -4
  225. package/dist/mcp/warp-pool.d.ts.map +1 -1
  226. package/dist/mcp/warp-pool.js.map +1 -1
  227. package/dist/mcp/workspace-router-model.d.ts +2 -2
  228. package/dist/mcp/workspace-router-model.d.ts.map +1 -1
  229. package/dist/mcp/workspace-router-runtime.d.ts +3 -3
  230. package/dist/mcp/workspace-router-runtime.d.ts.map +1 -1
  231. package/dist/mcp/workspace-router-runtime.js +4 -1
  232. package/dist/mcp/workspace-router-runtime.js.map +1 -1
  233. package/dist/mcp/workspace-router.d.ts +3 -2
  234. package/dist/mcp/workspace-router.d.ts.map +1 -1
  235. package/dist/mcp/workspace-router.js +6 -0
  236. package/dist/mcp/workspace-router.js.map +1 -1
  237. package/dist/operations/adaptive-projection.d.ts +22 -0
  238. package/dist/operations/adaptive-projection.d.ts.map +1 -0
  239. package/dist/operations/adaptive-projection.js +36 -0
  240. package/dist/operations/adaptive-projection.js.map +1 -0
  241. package/dist/operations/agent-handoff.d.ts +25 -0
  242. package/dist/operations/agent-handoff.d.ts.map +1 -0
  243. package/dist/operations/agent-handoff.js +36 -0
  244. package/dist/operations/agent-handoff.js.map +1 -0
  245. package/dist/operations/capture-range.d.ts +33 -0
  246. package/dist/operations/capture-range.d.ts.map +1 -0
  247. package/dist/operations/capture-range.js +45 -0
  248. package/dist/operations/capture-range.js.map +1 -0
  249. package/dist/operations/conversation-primer.d.ts +27 -0
  250. package/dist/operations/conversation-primer.d.ts.map +1 -0
  251. package/dist/operations/conversation-primer.js +52 -0
  252. package/dist/operations/conversation-primer.js.map +1 -0
  253. package/dist/operations/cross-session-resume.d.ts +28 -0
  254. package/dist/operations/cross-session-resume.d.ts.map +1 -0
  255. package/dist/operations/cross-session-resume.js +79 -0
  256. package/dist/operations/cross-session-resume.js.map +1 -0
  257. package/dist/operations/deterministic-replay.d.ts +39 -0
  258. package/dist/operations/deterministic-replay.d.ts.map +1 -0
  259. package/dist/operations/deterministic-replay.js +90 -0
  260. package/dist/operations/deterministic-replay.js.map +1 -0
  261. package/dist/operations/export-surface-diff.d.ts +36 -0
  262. package/dist/operations/export-surface-diff.d.ts.map +1 -0
  263. package/dist/operations/export-surface-diff.js +298 -0
  264. package/dist/operations/export-surface-diff.js.map +1 -0
  265. package/dist/operations/footprint-parallelism.d.ts +25 -0
  266. package/dist/operations/footprint-parallelism.d.ts.map +1 -0
  267. package/dist/operations/footprint-parallelism.js +79 -0
  268. package/dist/operations/footprint-parallelism.js.map +1 -0
  269. package/dist/operations/graft-diff.d.ts.map +1 -1
  270. package/dist/operations/graft-diff.js +14 -7
  271. package/dist/operations/graft-diff.js.map +1 -1
  272. package/dist/operations/horizon-of-readability.d.ts +23 -0
  273. package/dist/operations/horizon-of-readability.d.ts.map +1 -0
  274. package/dist/operations/horizon-of-readability.js +39 -0
  275. package/dist/operations/horizon-of-readability.js.map +1 -0
  276. package/dist/operations/import-reference-impact.d.ts +13 -0
  277. package/dist/operations/import-reference-impact.d.ts.map +1 -0
  278. package/dist/operations/import-reference-impact.js +101 -0
  279. package/dist/operations/import-reference-impact.js.map +1 -0
  280. package/dist/operations/knowledge-map.d.ts +30 -0
  281. package/dist/operations/knowledge-map.d.ts.map +1 -0
  282. package/dist/operations/knowledge-map.js +64 -0
  283. package/dist/operations/knowledge-map.js.map +1 -0
  284. package/dist/operations/observation-cache.d.ts +8 -2
  285. package/dist/operations/observation-cache.d.ts.map +1 -1
  286. package/dist/operations/observation-cache.js +17 -5
  287. package/dist/operations/observation-cache.js.map +1 -1
  288. package/dist/operations/projection-safety.d.ts +31 -0
  289. package/dist/operations/projection-safety.d.ts.map +1 -0
  290. package/dist/operations/projection-safety.js +77 -0
  291. package/dist/operations/projection-safety.js.map +1 -0
  292. package/dist/operations/repo-workspace.js +3 -3
  293. package/dist/operations/repo-workspace.js.map +1 -1
  294. package/dist/operations/semantic-drift.d.ts +27 -0
  295. package/dist/operations/semantic-drift.d.ts.map +1 -0
  296. package/dist/operations/semantic-drift.js +46 -0
  297. package/dist/operations/semantic-drift.js.map +1 -0
  298. package/dist/operations/session-filtration.d.ts +36 -0
  299. package/dist/operations/session-filtration.d.ts.map +1 -0
  300. package/dist/operations/session-filtration.js +48 -0
  301. package/dist/operations/session-filtration.js.map +1 -0
  302. package/dist/operations/session-replay.d.ts +17 -0
  303. package/dist/operations/session-replay.d.ts.map +1 -0
  304. package/dist/operations/session-replay.js +59 -0
  305. package/dist/operations/session-replay.js.map +1 -0
  306. package/dist/operations/sludge-detector.d.ts +45 -0
  307. package/dist/operations/sludge-detector.d.ts.map +1 -0
  308. package/dist/operations/sludge-detector.js +278 -0
  309. package/dist/operations/sludge-detector.js.map +1 -0
  310. package/dist/operations/structural-blame.d.ts +67 -0
  311. package/dist/operations/structural-blame.d.ts.map +1 -0
  312. package/dist/operations/structural-blame.js +111 -0
  313. package/dist/operations/structural-blame.js.map +1 -0
  314. package/dist/operations/structural-review.d.ts +47 -0
  315. package/dist/operations/structural-review.d.ts.map +1 -0
  316. package/dist/operations/structural-review.js +225 -0
  317. package/dist/operations/structural-review.js.map +1 -0
  318. package/dist/operations/teaching-hints.d.ts +18 -0
  319. package/dist/operations/teaching-hints.d.ts.map +1 -0
  320. package/dist/operations/teaching-hints.js +35 -0
  321. package/dist/operations/teaching-hints.js.map +1 -0
  322. package/dist/parser/diff.d.ts +2 -0
  323. package/dist/parser/diff.d.ts.map +1 -1
  324. package/dist/parser/diff.js +7 -0
  325. package/dist/parser/diff.js.map +1 -1
  326. package/dist/ports/paths.d.ts +17 -0
  327. package/dist/ports/paths.d.ts.map +1 -0
  328. package/dist/ports/{warp.js → paths.js} +2 -2
  329. package/dist/ports/paths.js.map +1 -0
  330. package/dist/warp/ast-emitter.d.ts +28 -0
  331. package/dist/warp/ast-emitter.d.ts.map +1 -0
  332. package/dist/warp/ast-emitter.js +90 -0
  333. package/dist/warp/ast-emitter.js.map +1 -0
  334. package/dist/warp/ast-import-resolver.d.ts +13 -0
  335. package/dist/warp/ast-import-resolver.d.ts.map +1 -0
  336. package/dist/warp/ast-import-resolver.js +259 -0
  337. package/dist/warp/ast-import-resolver.js.map +1 -0
  338. package/dist/warp/commit-meta.d.ts +8 -0
  339. package/dist/warp/commit-meta.d.ts.map +1 -0
  340. package/dist/warp/commit-meta.js +13 -0
  341. package/dist/warp/commit-meta.js.map +1 -0
  342. package/dist/warp/context.d.ts +10 -0
  343. package/dist/warp/context.d.ts.map +1 -0
  344. package/dist/warp/context.js +26 -0
  345. package/dist/warp/context.js.map +1 -0
  346. package/dist/warp/dead-symbols.d.ts +40 -0
  347. package/dist/warp/dead-symbols.d.ts.map +1 -0
  348. package/dist/warp/dead-symbols.js +127 -0
  349. package/dist/warp/dead-symbols.js.map +1 -0
  350. package/dist/warp/drift-sentinel.d.ts +30 -0
  351. package/dist/warp/drift-sentinel.d.ts.map +1 -0
  352. package/dist/warp/drift-sentinel.js +65 -0
  353. package/dist/warp/drift-sentinel.js.map +1 -0
  354. package/dist/warp/index-head.d.ts +32 -0
  355. package/dist/warp/index-head.d.ts.map +1 -0
  356. package/dist/warp/index-head.js +245 -0
  357. package/dist/warp/index-head.js.map +1 -0
  358. package/dist/warp/observers.d.ts +6 -6
  359. package/dist/warp/observers.d.ts.map +1 -1
  360. package/dist/warp/observers.js +5 -4
  361. package/dist/warp/observers.js.map +1 -1
  362. package/dist/warp/open.d.ts +5 -4
  363. package/dist/warp/open.d.ts.map +1 -1
  364. package/dist/warp/open.js +24 -49
  365. package/dist/warp/open.js.map +1 -1
  366. package/dist/warp/outline-diff-trailer.d.ts +26 -0
  367. package/dist/warp/outline-diff-trailer.d.ts.map +1 -0
  368. package/dist/warp/outline-diff-trailer.js +68 -0
  369. package/dist/warp/outline-diff-trailer.js.map +1 -0
  370. package/dist/warp/refactor-difficulty.d.ts +38 -0
  371. package/dist/warp/refactor-difficulty.d.ts.map +1 -0
  372. package/dist/warp/refactor-difficulty.js +169 -0
  373. package/dist/warp/refactor-difficulty.js.map +1 -0
  374. package/dist/warp/references.d.ts +22 -0
  375. package/dist/warp/references.d.ts.map +1 -0
  376. package/dist/warp/references.js +57 -0
  377. package/dist/warp/references.js.map +1 -0
  378. package/dist/warp/stale-docs.d.ts +56 -0
  379. package/dist/warp/stale-docs.d.ts.map +1 -0
  380. package/dist/warp/stale-docs.js +149 -0
  381. package/dist/warp/stale-docs.js.map +1 -0
  382. package/dist/warp/structural-drift-detection.d.ts +49 -0
  383. package/dist/warp/structural-drift-detection.d.ts.map +1 -0
  384. package/dist/warp/structural-drift-detection.js +51 -0
  385. package/dist/warp/structural-drift-detection.js.map +1 -0
  386. package/dist/warp/structural-queries.d.ts +49 -0
  387. package/dist/warp/structural-queries.d.ts.map +1 -0
  388. package/dist/warp/structural-queries.js +175 -0
  389. package/dist/warp/structural-queries.js.map +1 -0
  390. package/dist/warp/symbol-timeline.d.ts +34 -0
  391. package/dist/warp/symbol-timeline.d.ts.map +1 -0
  392. package/dist/warp/symbol-timeline.js +127 -0
  393. package/dist/warp/symbol-timeline.js.map +1 -0
  394. package/dist/warp/traverse-hydrate.d.ts +23 -0
  395. package/dist/warp/traverse-hydrate.d.ts.map +1 -0
  396. package/dist/warp/traverse-hydrate.js +39 -0
  397. package/dist/warp/traverse-hydrate.js.map +1 -0
  398. package/dist/warp/warp-reference-count.d.ts +19 -0
  399. package/dist/warp/warp-reference-count.d.ts.map +1 -0
  400. package/dist/warp/warp-reference-count.js +32 -0
  401. package/dist/warp/warp-reference-count.js.map +1 -0
  402. package/dist/warp/warp-structural-blame.d.ts +20 -0
  403. package/dist/warp/warp-structural-blame.d.ts.map +1 -0
  404. package/dist/warp/warp-structural-blame.js +43 -0
  405. package/dist/warp/warp-structural-blame.js.map +1 -0
  406. package/dist/warp/warp-structural-churn.d.ts +30 -0
  407. package/dist/warp/warp-structural-churn.d.ts.map +1 -0
  408. package/dist/warp/warp-structural-churn.js +213 -0
  409. package/dist/warp/warp-structural-churn.js.map +1 -0
  410. package/dist/warp/warp-structural-log.d.ts +35 -0
  411. package/dist/warp/warp-structural-log.d.ts.map +1 -0
  412. package/dist/warp/warp-structural-log.js +104 -0
  413. package/dist/warp/warp-structural-log.js.map +1 -0
  414. package/docs/CLI.md +68 -4
  415. package/docs/MCP.md +23 -0
  416. package/docs/SETUP.md +101 -20
  417. package/package.json +5 -3
  418. package/src/adapters/json-text-decoder.ts +11 -0
  419. package/src/adapters/node-paths.ts +35 -0
  420. package/src/adapters/repo-paths.ts +45 -4
  421. package/src/api/tool-bridge.ts +2 -1
  422. package/src/cli/cli-error.ts +49 -10
  423. package/src/cli/command-parser.ts +185 -3
  424. package/src/cli/daemon-status-model.ts +238 -0
  425. package/src/cli/daemon-status-render.ts +102 -0
  426. package/src/cli/daemon-status.ts +100 -0
  427. package/src/cli/git-graft-enhance-model.ts +131 -0
  428. package/src/cli/git-graft-enhance-render.ts +33 -0
  429. package/src/cli/git-graft-enhance.ts +54 -0
  430. package/src/cli/index-cmd.ts +18 -22
  431. package/src/cli/index-model.ts +21 -22
  432. package/src/cli/init-client-config.ts +167 -38
  433. package/src/cli/init-model.ts +57 -2
  434. package/src/cli/init-render.ts +2 -2
  435. package/src/cli/init.ts +11 -9
  436. package/src/cli/json-document.ts +11 -0
  437. package/src/cli/main.ts +53 -6
  438. package/src/cli/migrate-local-history.ts +3 -2
  439. package/src/cli/peer-command.ts +2 -1
  440. package/src/contracts/capabilities.ts +90 -0
  441. package/src/contracts/json-object.ts +1 -11
  442. package/src/contracts/output-schema-cli.ts +36 -3
  443. package/src/contracts/output-schema-fragments.ts +52 -2
  444. package/src/contracts/output-schema-mcp.ts +219 -0
  445. package/src/contracts/output-schemas.ts +300 -6
  446. package/src/git/diff.ts +61 -0
  447. package/src/mcp/burden.ts +9 -0
  448. package/src/mcp/context.ts +5 -42
  449. package/src/mcp/daemon-server.ts +8 -1
  450. package/src/mcp/daemon-session-host.ts +4 -0
  451. package/src/mcp/daemon-stdio-bridge.ts +2 -0
  452. package/src/mcp/monitor-tick-job.ts +90 -39
  453. package/src/mcp/monitor-types.ts +1 -1
  454. package/src/mcp/persisted-local-history-graph.ts +5 -4
  455. package/src/mcp/persisted-local-history.ts +2 -2
  456. package/src/mcp/persistent-monitor-runtime.ts +37 -0
  457. package/src/mcp/repo-tool-worker-context.ts +5 -2
  458. package/src/mcp/server-context.ts +15 -2
  459. package/src/mcp/server-tool-access.ts +4 -1
  460. package/src/mcp/server.ts +8 -3
  461. package/src/mcp/tool-registry.ts +18 -0
  462. package/src/mcp/tools/code-find.ts +23 -0
  463. package/src/mcp/tools/code-show.ts +27 -0
  464. package/src/mcp/tools/diagnostic-models.ts +2 -0
  465. package/src/mcp/tools/doctor.ts +18 -1
  466. package/src/mcp/tools/export-surface-diff.ts +26 -0
  467. package/src/mcp/tools/file-outline.ts +1 -1
  468. package/src/mcp/tools/graft-edit.ts +276 -0
  469. package/src/mcp/tools/knowledge-map.ts +34 -0
  470. package/src/mcp/tools/monitor-nudge.ts +19 -0
  471. package/src/mcp/tools/precision-warp.ts +27 -16
  472. package/src/mcp/tools/refactor-difficulty.ts +42 -0
  473. package/src/mcp/tools/safe-read.ts +2 -2
  474. package/src/mcp/tools/structural-blame.ts +55 -0
  475. package/src/mcp/tools/structural-churn.ts +28 -0
  476. package/src/mcp/tools/structural-log.ts +41 -0
  477. package/src/mcp/tools/structural-review.ts +63 -0
  478. package/src/mcp/warp-pool.ts +6 -6
  479. package/src/mcp/workspace-router-model.ts +2 -2
  480. package/src/mcp/workspace-router-runtime.ts +11 -8
  481. package/src/mcp/workspace-router.ts +9 -2
  482. package/src/operations/adaptive-projection.ts +54 -0
  483. package/src/operations/agent-handoff.ts +59 -0
  484. package/src/operations/capture-range.ts +64 -0
  485. package/src/operations/conversation-primer.ts +82 -0
  486. package/src/operations/cross-session-resume.ts +104 -0
  487. package/src/operations/deterministic-replay.ts +143 -0
  488. package/src/operations/export-surface-diff.ts +355 -0
  489. package/src/operations/footprint-parallelism.ts +98 -0
  490. package/src/operations/graft-diff.ts +14 -7
  491. package/src/operations/horizon-of-readability.ts +60 -0
  492. package/src/operations/import-reference-impact.ts +143 -0
  493. package/src/operations/knowledge-map.ts +96 -0
  494. package/src/operations/observation-cache.ts +20 -4
  495. package/src/operations/projection-safety.ts +111 -0
  496. package/src/operations/repo-workspace.ts +3 -3
  497. package/src/operations/semantic-drift.ts +70 -0
  498. package/src/operations/session-filtration.ts +76 -0
  499. package/src/operations/session-replay.ts +73 -0
  500. package/src/operations/sludge-detector.ts +356 -0
  501. package/src/operations/structural-blame.ts +197 -0
  502. package/src/operations/structural-review.ts +317 -0
  503. package/src/operations/teaching-hints.ts +52 -0
  504. package/src/parser/diff.ts +7 -0
  505. package/src/ports/paths.ts +22 -0
  506. package/src/warp/ast-emitter.ts +133 -0
  507. package/src/warp/ast-import-resolver.ts +333 -0
  508. package/src/warp/commit-meta.ts +19 -0
  509. package/src/warp/context.ts +48 -0
  510. package/src/warp/dead-symbols.ts +174 -0
  511. package/src/warp/drift-sentinel.ts +101 -0
  512. package/src/warp/index-head.ts +348 -0
  513. package/src/warp/observers.ts +8 -7
  514. package/src/warp/open.ts +40 -66
  515. package/src/warp/outline-diff-trailer.ts +100 -0
  516. package/src/warp/plumbing.d.ts +11 -2
  517. package/src/warp/refactor-difficulty.ts +257 -0
  518. package/src/warp/references.ts +77 -0
  519. package/src/warp/stale-docs.ts +210 -0
  520. package/src/warp/structural-drift-detection.ts +97 -0
  521. package/src/warp/structural-queries.ts +258 -0
  522. package/src/warp/symbol-timeline.ts +209 -0
  523. package/src/warp/traverse-hydrate.ts +61 -0
  524. package/src/warp/warp-reference-count.ts +47 -0
  525. package/src/warp/warp-structural-blame.ts +65 -0
  526. package/src/warp/warp-structural-churn.ts +309 -0
  527. package/src/warp/warp-structural-log.ts +149 -0
  528. package/dist/ports/warp.d.ts +0 -45
  529. package/dist/ports/warp.d.ts.map +0 -1
  530. package/dist/ports/warp.js.map +0 -1
  531. package/dist/warp/identity-resolver.d.ts +0 -14
  532. package/dist/warp/identity-resolver.d.ts.map +0 -1
  533. package/dist/warp/identity-resolver.js +0 -31
  534. package/dist/warp/identity-resolver.js.map +0 -1
  535. package/dist/warp/indexer-git.d.ts +0 -22
  536. package/dist/warp/indexer-git.d.ts.map +0 -1
  537. package/dist/warp/indexer-git.js +0 -148
  538. package/dist/warp/indexer-git.js.map +0 -1
  539. package/dist/warp/indexer-graph.d.ts +0 -17
  540. package/dist/warp/indexer-graph.d.ts.map +0 -1
  541. package/dist/warp/indexer-graph.js +0 -179
  542. package/dist/warp/indexer-graph.js.map +0 -1
  543. package/dist/warp/indexer-model.d.ts +0 -51
  544. package/dist/warp/indexer-model.d.ts.map +0 -1
  545. package/dist/warp/indexer-model.js +0 -21
  546. package/dist/warp/indexer-model.js.map +0 -1
  547. package/dist/warp/indexer.d.ts +0 -9
  548. package/dist/warp/indexer.d.ts.map +0 -1
  549. package/dist/warp/indexer.js +0 -112
  550. package/dist/warp/indexer.js.map +0 -1
  551. package/dist/warp/symbol-identity.d.ts +0 -11
  552. package/dist/warp/symbol-identity.d.ts.map +0 -1
  553. package/dist/warp/symbol-identity.js +0 -67
  554. package/dist/warp/symbol-identity.js.map +0 -1
  555. package/src/ports/warp.ts +0 -55
  556. package/src/warp/identity-resolver.ts +0 -35
  557. package/src/warp/indexer-git.ts +0 -182
  558. package/src/warp/indexer-graph.ts +0 -276
  559. package/src/warp/indexer-model.ts +0 -69
  560. package/src/warp/indexer.ts +0 -186
  561. package/src/warp/symbol-identity.ts +0 -100
@@ -1,22 +1,22 @@
1
- import type { WarpHandle } from "../ports/warp.js";
1
+ import type WarpApp from "@git-stunts/git-warp";
2
2
  import { DEFAULT_WARP_WRITER_ID } from "../warp/writer-id.js";
3
3
 
4
4
  export interface WarpPool {
5
- getOrOpen(repoId: string, worktreeRoot: string, writerId?: string): Promise<WarpHandle>;
5
+ getOrOpen(repoId: string, worktreeRoot: string, writerId?: string): Promise<WarpApp>;
6
6
  size(): number;
7
7
  }
8
8
 
9
9
  export class InMemoryWarpPool implements WarpPool {
10
- private readonly opened = new Map<string, Map<string, Promise<WarpHandle>>>();
10
+ private readonly opened = new Map<string, Map<string, Promise<WarpApp>>>();
11
11
 
12
- constructor(private readonly openWarp: (worktreeRoot: string, writerId: string) => Promise<WarpHandle>) {}
12
+ constructor(private readonly openWarp: (worktreeRoot: string, writerId: string) => Promise<WarpApp>) {}
13
13
 
14
- getOrOpen(repoId: string, worktreeRoot: string, writerId: string = DEFAULT_WARP_WRITER_ID): Promise<WarpHandle> {
14
+ getOrOpen(repoId: string, worktreeRoot: string, writerId: string = DEFAULT_WARP_WRITER_ID): Promise<WarpApp> {
15
15
  const repoHandles = this.opened.get(repoId);
16
16
  const cached = repoHandles?.get(writerId);
17
17
  if (cached !== undefined) return cached;
18
18
 
19
- const nextRepoHandles = repoHandles ?? new Map<string, Promise<WarpHandle>>();
19
+ const nextRepoHandles = repoHandles ?? new Map<string, Promise<WarpApp>>();
20
20
  const opened = this.openWarp(worktreeRoot, writerId).catch((error: unknown) => {
21
21
  const current = this.opened.get(repoId);
22
22
  current?.delete(writerId);
@@ -4,7 +4,7 @@ import type { RepoStateTracker } from "./repo-state.js";
4
4
  import type { RuntimeCausalContext } from "./runtime-causal-context.js";
5
5
  import type { PersistedLocalHistorySummary } from "./persisted-local-history.js";
6
6
  import type { GovernorTracker } from "../session/tracker.js";
7
- import type { WarpHandle } from "../ports/warp.js";
7
+ import type { WarpContext } from "../warp/context.js";
8
8
 
9
9
  export type WorkspaceMode = "repo_local" | "daemon";
10
10
  export type WorkspaceBindState = "bound" | "unbound";
@@ -89,7 +89,7 @@ export interface WorkspaceExecutionContext {
89
89
  readonly metrics: Metrics;
90
90
  readonly graftDir: string;
91
91
  readonly repoState: RepoStateTracker;
92
- readonly getWarp: () => Promise<WarpHandle>;
92
+ readonly getWarp: () => Promise<WarpContext>;
93
93
  }
94
94
 
95
95
  export interface ResolvedWorkspace {
@@ -2,7 +2,7 @@ import * as path from "node:path";
2
2
  import { createRepoPathResolver } from "../adapters/repo-paths.js";
3
3
  import type { FileSystem } from "../ports/filesystem.js";
4
4
  import type { GitClient } from "../ports/git.js";
5
- import type { WarpHandle } from "../ports/warp.js";
5
+ import type { WarpContext } from "../warp/context.js";
6
6
  import { DEFAULT_WARP_WRITER_ID } from "../warp/writer-id.js";
7
7
  import { GovernorTracker } from "../session/tracker.js";
8
8
  import { ObservationCache } from "./cache.js";
@@ -48,7 +48,7 @@ export interface BoundWorkspace {
48
48
  readonly warpWriterId: string;
49
49
  readonly transportSessionId: string;
50
50
  readonly slice: WorkspaceSlice;
51
- readonly getWarp: () => Promise<WarpHandle>;
51
+ readonly getWarp: () => Promise<WarpContext>;
52
52
  }
53
53
 
54
54
  export function createWorkspaceSlice(input: {
@@ -94,11 +94,14 @@ export async function createBoundWorkspace(input: {
94
94
  transportSessionId: input.transportSessionId,
95
95
  warpWriterId: input.warpWriterId ?? DEFAULT_WARP_WRITER_ID,
96
96
  slice: input.slice,
97
- getWarp: () => input.warpPool.getOrOpen(
98
- input.resolved.repoId,
99
- input.resolved.worktreeRoot,
100
- input.warpWriterId ?? DEFAULT_WARP_WRITER_ID,
101
- ),
97
+ getWarp: async () => ({
98
+ app: await input.warpPool.getOrOpen(
99
+ input.resolved.repoId,
100
+ input.resolved.worktreeRoot,
101
+ input.warpWriterId ?? DEFAULT_WARP_WRITER_ID,
102
+ ),
103
+ strandId: null,
104
+ }),
102
105
  };
103
106
  }
104
107
 
@@ -193,7 +196,7 @@ export async function resolveCheckoutBoundaryHookEvent(input: {
193
196
 
194
197
  export async function buildPersistedLocalHistoryGraphContext(
195
198
  worktreeRoot: string,
196
- getWarp: () => Promise<WarpHandle>,
199
+ getWarp: () => Promise<WarpContext>,
197
200
  ): Promise<PersistedLocalHistoryGraphContext | null> {
198
201
  try {
199
202
  return {
@@ -37,7 +37,7 @@ import {
37
37
  import { resolveWorkspaceRequest, stableWorkspaceId } from "./workspace-router-resolution.js";
38
38
  import type { FileSystem } from "../ports/filesystem.js";
39
39
  import type { GitClient } from "../ports/git.js";
40
- import type { WarpHandle } from "../ports/warp.js";
40
+ import type { WarpContext } from "../warp/context.js";
41
41
  import type { JsonObject } from "../contracts/json-object.js";
42
42
  import type { WarpPool } from "./warp-pool.js";
43
43
  import { DEFAULT_WARP_WRITER_ID } from "../warp/writer-id.js";
@@ -87,6 +87,7 @@ interface WorkspaceRouterOptions {
87
87
  readonly authorizationPolicy?: WorkspaceAuthorizationPolicy | undefined;
88
88
  readonly sharedAttachPolicy?: WorkspaceSharedAttachPolicy | undefined;
89
89
  readonly persistedLocalHistory: PersistedLocalHistoryStore;
90
+ readonly persistedLocalHistoryGraph?: boolean;
90
91
  }
91
92
 
92
93
  export class WorkspaceRouter {
@@ -197,7 +198,7 @@ export class WorkspaceRouter {
197
198
  return this.requireBinding().resolvePath;
198
199
  }
199
200
 
200
- getWarp(): Promise<WarpHandle> {
201
+ getWarp(): Promise<WarpContext> {
201
202
  return this.requireBinding().getWarp();
202
203
  }
203
204
 
@@ -670,12 +671,18 @@ export class WorkspaceRouter {
670
671
  private async buildPersistedLocalHistoryGraphContext(
671
672
  binding: BoundWorkspace,
672
673
  ): Promise<PersistedLocalHistoryGraphContext | null> {
674
+ if (this.options.persistedLocalHistoryGraph === false) {
675
+ return null;
676
+ }
673
677
  return buildPersistedLocalHistoryGraphContext(binding.worktreeRoot, binding.getWarp);
674
678
  }
675
679
 
676
680
  private async buildPersistedLocalHistoryGraphContextFromExecution(
677
681
  execution: WorkspaceExecutionContext,
678
682
  ): Promise<PersistedLocalHistoryGraphContext | null> {
683
+ if (this.options.persistedLocalHistoryGraph === false) {
684
+ return null;
685
+ }
679
686
  return buildPersistedLocalHistoryGraphContext(execution.worktreeRoot, execution.getWarp);
680
687
  }
681
688
  }
@@ -0,0 +1,54 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Adaptive Projection Selection — structural auto-selection
3
+ // ---------------------------------------------------------------------------
4
+
5
+ /** Structural metrics for projection selection. */
6
+ export interface ProjectionCandidate {
7
+ readonly fileLines: number;
8
+ readonly fileBytes: number;
9
+ readonly symbolCount: number;
10
+ readonly outlineCompressionRatio: number;
11
+ readonly targetSymbol?: string;
12
+ }
13
+
14
+ /** Selected projection with reasoning. */
15
+ export interface ProjectionSelection {
16
+ readonly projection: "outline" | "content" | "range";
17
+ readonly reason: string;
18
+ }
19
+
20
+ const SMALL_FILE_THRESHOLD = 50;
21
+ const HORIZON_RATIO = 0.7;
22
+
23
+ /**
24
+ * Select the optimal projection based on structural metrics.
25
+ *
26
+ * - Dense large files → outline (saves the most context)
27
+ * - Small or irreducibly complex files → content (outline doesn't help)
28
+ * - Targeted symbol investigation → range (surgical read)
29
+ */
30
+ export function selectProjection(candidate: ProjectionCandidate): ProjectionSelection {
31
+ // If a specific symbol is targeted, use range
32
+ if (candidate.targetSymbol !== undefined) {
33
+ return {
34
+ projection: "range",
35
+ reason: `Targeted read for symbol "${candidate.targetSymbol}" — range is most efficient.`,
36
+ };
37
+ }
38
+
39
+ // Small files or high compression ratio → content
40
+ if (candidate.fileLines <= SMALL_FILE_THRESHOLD || candidate.outlineCompressionRatio >= HORIZON_RATIO) {
41
+ return {
42
+ projection: "content",
43
+ reason: candidate.fileLines <= SMALL_FILE_THRESHOLD
44
+ ? `Small file (${String(candidate.fileLines)} lines) — content fits easily.`
45
+ : `Outline is ${String(Math.round(candidate.outlineCompressionRatio * 100))}% of content — outline provides negligible savings.`,
46
+ };
47
+ }
48
+
49
+ // Default: outline for larger files with good compression
50
+ return {
51
+ projection: "outline",
52
+ reason: `${String(candidate.fileLines)} lines, ${String(candidate.symbolCount)} symbols, ${String(Math.round(candidate.outlineCompressionRatio * 100))}% compression — outline is efficient.`,
53
+ };
54
+ }
@@ -0,0 +1,59 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Agent Handoff Protocol — structured session transfer
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { ObservationCache } from "./observation-cache.js";
6
+
7
+ /** The structured handoff payload. */
8
+ export interface HandoffPayload {
9
+ readonly sessionId: string;
10
+ readonly filesRead: readonly string[];
11
+ readonly symbolsInspected: readonly string[];
12
+ readonly observations: number;
13
+ readonly budgetConsumed: string;
14
+ }
15
+
16
+ /** Options for building a handoff. */
17
+ export interface HandoffOptions {
18
+ readonly cache: ObservationCache;
19
+ readonly sessionId: string;
20
+ readonly budgetTotal?: number;
21
+ readonly budgetConsumed?: number;
22
+ }
23
+
24
+ /**
25
+ * Build a structured handoff payload from the current session state.
26
+ *
27
+ * Projects the observation cache into a portable JSON payload that
28
+ * a receiving agent can use to understand what the departing agent
29
+ * knew and where it left off.
30
+ */
31
+ export function buildHandoff(options: HandoffOptions): HandoffPayload {
32
+ const { cache, sessionId } = options;
33
+
34
+ const filesRead: string[] = [];
35
+ const symbolsInspected: string[] = [];
36
+ let observationCount = 0;
37
+
38
+ for (const [filePath, observation] of cache.allEntries()) {
39
+ filesRead.push(filePath);
40
+ for (const entry of observation.outline) {
41
+ symbolsInspected.push(entry.name);
42
+ }
43
+ observationCount++;
44
+ }
45
+
46
+ let budgetStr = "unknown";
47
+ if (options.budgetTotal !== undefined && options.budgetConsumed !== undefined && options.budgetTotal > 0) {
48
+ const pct = Math.round((options.budgetConsumed / options.budgetTotal) * 100);
49
+ budgetStr = `${String(pct)}%`;
50
+ }
51
+
52
+ return {
53
+ sessionId,
54
+ filesRead,
55
+ symbolsInspected,
56
+ observations: observationCount,
57
+ budgetConsumed: budgetStr,
58
+ };
59
+ }
@@ -0,0 +1,64 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Capture Range — opaque handles for run_capture output
3
+ // ---------------------------------------------------------------------------
4
+
5
+
6
+
7
+ interface CaptureEntry {
8
+ readonly sessionId: string;
9
+ readonly content: string;
10
+ readonly lines: readonly string[];
11
+ }
12
+
13
+ /** Result of a range retrieval. */
14
+ export type CaptureRangeResult =
15
+ | { readonly ok: true; readonly lines: readonly string[]; readonly totalLines: number }
16
+ | { readonly ok: false; readonly error: string };
17
+
18
+ /**
19
+ * Registry of opaque capture handles.
20
+ *
21
+ * Maps UUIDs to capture content. Handles are session-scoped — a
22
+ * handle from one session is rejected in another.
23
+ */
24
+ export class CaptureHandleRegistry {
25
+ private nextId = 0;
26
+ private readonly entries = new Map<string, CaptureEntry>();
27
+
28
+ /**
29
+ * Register capture content and return an opaque handle.
30
+ */
31
+ register(sessionId: string, content: string): string {
32
+ const handle = `capture-${String(++this.nextId)}`;
33
+ const lines = content.split("\n").filter(
34
+ (line, index, arr) => index < arr.length - 1 || line.length > 0,
35
+ );
36
+ this.entries.set(handle, { sessionId, content, lines });
37
+ return handle;
38
+ }
39
+
40
+ /**
41
+ * Retrieve a line range from a capture handle.
42
+ *
43
+ * @param handle - The opaque handle from register()
44
+ * @param sessionId - The requesting session (must match the registering session)
45
+ * @param start - 1-based start line (inclusive)
46
+ * @param end - 1-based end line (inclusive)
47
+ */
48
+ getRange(handle: string, sessionId: string, start: number, end: number): CaptureRangeResult {
49
+ const entry = this.entries.get(handle);
50
+ if (entry === undefined) {
51
+ return { ok: false, error: "Capture handle not found" };
52
+ }
53
+ if (entry.sessionId !== sessionId) {
54
+ return { ok: false, error: "Capture handle belongs to a different session" };
55
+ }
56
+
57
+ const totalLines = entry.lines.length;
58
+ const clampedStart = Math.max(1, start);
59
+ const clampedEnd = Math.min(totalLines, end);
60
+ const lines = entry.lines.slice(clampedStart - 1, clampedEnd);
61
+
62
+ return { ok: true, lines, totalLines };
63
+ }
64
+ }
@@ -0,0 +1,82 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Conversation Primer — auto-orient agent at session start via graft_map
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { GitClient } from "../ports/git.js";
6
+ import type { FileSystem } from "../ports/filesystem.js";
7
+ import type { PathOps } from "../ports/paths.js";
8
+
9
+ /** Result of building a conversation primer. */
10
+ export interface ConversationPrimerResult {
11
+ readonly scope: string;
12
+ readonly files: readonly string[];
13
+ readonly truncated: boolean;
14
+ readonly totalFiles: number;
15
+ }
16
+
17
+ /** Options for building a primer. */
18
+ export interface ConversationPrimerOptions {
19
+ readonly cwd: string;
20
+ readonly git: GitClient;
21
+ readonly fs: FileSystem;
22
+ readonly pathOps: PathOps;
23
+ readonly scope?: string;
24
+ readonly maxFiles?: number;
25
+ }
26
+
27
+ /** Common source directory names, in priority order. */
28
+ const COMMON_SCOPES = ["src", "lib", "app", "packages"];
29
+
30
+ async function isDirectory(fileSystem: FileSystem, dirPath: string): Promise<boolean> {
31
+ try {
32
+ await fileSystem.readdir(dirPath);
33
+ return true;
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Build a conversation primer for the given project.
41
+ *
42
+ * Auto-detects the best scope (src/, lib/, etc.) or uses an explicit
43
+ * scope. Returns a list of tracked files, truncated if beyond maxFiles.
44
+ */
45
+ export async function buildConversationPrimer(
46
+ options: ConversationPrimerOptions,
47
+ ): Promise<ConversationPrimerResult> {
48
+ const { cwd, git, fs: fileSystem, pathOps, maxFiles = 50 } = options;
49
+
50
+ // Detect scope
51
+ let scope = options.scope ?? ".";
52
+ if (options.scope === undefined) {
53
+ for (const candidate of COMMON_SCOPES) {
54
+ const candidatePath = pathOps.join(cwd, candidate);
55
+ if (await isDirectory(fileSystem, candidatePath)) {
56
+ scope = candidate;
57
+ break;
58
+ }
59
+ }
60
+ }
61
+
62
+ // List tracked files via git ls-files (allowed by plumbing)
63
+ const lsResult = await git.run({
64
+ cwd,
65
+ args: ["ls-files", "--", scope],
66
+ });
67
+
68
+ const allFiles = lsResult.stdout
69
+ .split("\n")
70
+ .map((f) => f.trim())
71
+ .filter((f) => f.length > 0);
72
+
73
+ const truncated = allFiles.length > maxFiles;
74
+ const files = truncated ? allFiles.slice(0, maxFiles) : allFiles;
75
+
76
+ return {
77
+ scope,
78
+ files,
79
+ truncated,
80
+ totalFiles: allFiles.length,
81
+ };
82
+ }
@@ -0,0 +1,104 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cross-session resume — structural diff from saved HEAD to current HEAD
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { GitClient } from "../ports/git.js";
6
+
7
+ /** A file that changed between saved HEAD and current HEAD. */
8
+ export interface ResumeChangedFile {
9
+ readonly path: string;
10
+ readonly status: "added" | "modified" | "deleted" | "renamed";
11
+ }
12
+
13
+ /** Result of attempting to resume from a saved session state. */
14
+ export interface SessionResumeResult {
15
+ readonly resumable: boolean;
16
+ readonly currentHead: string;
17
+ readonly savedHead: string;
18
+ readonly changedFiles: readonly ResumeChangedFile[];
19
+ readonly commitsBehind: number;
20
+ readonly error?: string;
21
+ }
22
+
23
+ export interface SessionResumeOptions {
24
+ readonly cwd: string;
25
+ readonly savedHeadSha: string;
26
+ readonly git: GitClient;
27
+ }
28
+
29
+ /**
30
+ * Build a structural resume from a saved HEAD to current HEAD.
31
+ *
32
+ * Uses plumbing-safe git commands (diff-tree, rev-list, log) to
33
+ * find changed files and count commits between two points.
34
+ */
35
+ export async function buildSessionResume(
36
+ options: SessionResumeOptions,
37
+ ): Promise<SessionResumeResult> {
38
+ const { cwd, savedHeadSha, git } = options;
39
+
40
+ const headResult = await git.run({ cwd, args: ["rev-parse", "HEAD"] });
41
+ const currentHead = headResult.stdout.trim();
42
+ if (headResult.status !== 0 || currentHead.length === 0) {
43
+ return {
44
+ resumable: false, currentHead: "", savedHead: savedHeadSha,
45
+ changedFiles: [], commitsBehind: 0,
46
+ error: "Cannot resolve current HEAD",
47
+ };
48
+ }
49
+
50
+ // Check if saved HEAD exists in the repo
51
+ const verifyResult = await git.run({ cwd, args: ["cat-file", "-t", savedHeadSha] });
52
+ if (verifyResult.stdout.trim() !== "commit") {
53
+ return {
54
+ resumable: false, currentHead, savedHead: savedHeadSha,
55
+ changedFiles: [], commitsBehind: 0,
56
+ error: "Saved HEAD SHA not found in repository",
57
+ };
58
+ }
59
+
60
+ if (currentHead === savedHeadSha) {
61
+ return {
62
+ resumable: true, currentHead, savedHead: savedHeadSha,
63
+ changedFiles: [], commitsBehind: 0,
64
+ };
65
+ }
66
+
67
+ // Use diff-tree (plumbing-safe) with -r for recursive
68
+ const diffResult = await git.run({
69
+ cwd,
70
+ args: ["diff-tree", "-r", "--name-status", "--no-commit-id", savedHeadSha, currentHead],
71
+ });
72
+ const changedFiles: ResumeChangedFile[] = [];
73
+ const diffOutput = diffResult.stdout.trim();
74
+
75
+ if (diffOutput.length > 0) {
76
+ for (const line of diffOutput.split("\n")) {
77
+ const parts = line.split("\t");
78
+ if (parts.length < 2) continue;
79
+ const statusChar = (parts[0] ?? "").charAt(0);
80
+ const filePath = parts[parts.length - 1] ?? "";
81
+
82
+ let status: ResumeChangedFile["status"];
83
+ switch (statusChar) {
84
+ case "A": status = "added"; break;
85
+ case "D": status = "deleted"; break;
86
+ case "R": status = "renamed"; break;
87
+ default: status = "modified"; break;
88
+ }
89
+ changedFiles.push({ path: filePath, status });
90
+ }
91
+ }
92
+
93
+ // Count commits
94
+ const countResult = await git.run({
95
+ cwd,
96
+ args: ["rev-list", "--count", `${savedHeadSha}..${currentHead}`],
97
+ });
98
+ const commitsBehind = parseInt(countResult.stdout.trim(), 10) || 0;
99
+
100
+ return {
101
+ resumable: true, currentHead, savedHead: savedHeadSha,
102
+ changedFiles, commitsBehind,
103
+ };
104
+ }
@@ -0,0 +1,143 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Deterministic Scenario Replay — re-drive sessions for CI regression
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { FileSystem } from "../ports/filesystem.js";
6
+
7
+ /** A recorded tool call with its expected result. */
8
+ export interface RecordedToolCall {
9
+ readonly tool: string;
10
+ readonly args: Readonly<Record<string, unknown>>;
11
+ readonly expectedResult: Readonly<Record<string, unknown>>;
12
+ }
13
+
14
+ /** A replay scenario: filesystem snapshot + recorded calls. */
15
+ interface _ReplayScenario {
16
+ readonly files: Readonly<Record<string, string>>;
17
+ readonly calls: readonly RecordedToolCall[];
18
+ }
19
+
20
+ /** A single mismatch between expected and actual. */
21
+ export interface ReplayFailure {
22
+ readonly index: number;
23
+ readonly tool: string;
24
+ readonly expected: Readonly<Record<string, unknown>>;
25
+ readonly actual: Readonly<Record<string, unknown>>;
26
+ }
27
+
28
+ /** Result of replaying a scenario. */
29
+ export interface ReplayResult {
30
+ readonly passed: boolean;
31
+ readonly total: number;
32
+ readonly matched: number;
33
+ readonly mismatched: number;
34
+ readonly failures: readonly ReplayFailure[];
35
+ }
36
+
37
+ /** Handler that executes a tool call and returns the result. */
38
+ export type ToolCallHandler = (
39
+ tool: string,
40
+ args: Readonly<Record<string, unknown>>,
41
+ ) => Promise<Readonly<Record<string, unknown>>>;
42
+
43
+ /**
44
+ * Create a mock FileSystem from a snapshot map.
45
+ *
46
+ * Keys are file paths, values are file contents. Provides readFile,
47
+ * readdir, stat, and other FileSystem methods backed by the map.
48
+ */
49
+ export function createSnapshotFs(
50
+ files: Readonly<Record<string, string>>,
51
+ ): FileSystem {
52
+ const fileMap = new Map(Object.entries(files));
53
+
54
+ return {
55
+ readFile(path: string, _encoding?: string): Promise<string> {
56
+ const content = fileMap.get(path);
57
+ if (content === undefined) {
58
+ return Promise.reject(new Error(`File not found in snapshot: ${path}`));
59
+ }
60
+ return Promise.resolve(content);
61
+ },
62
+
63
+ readFileSync(path: string): string {
64
+ const content = fileMap.get(path);
65
+ if (content === undefined) {
66
+ throw new Error(`File not found in snapshot: ${path}`);
67
+ }
68
+ return content;
69
+ },
70
+
71
+ readdir(dirPath: string): Promise<string[]> {
72
+ const prefix = dirPath.endsWith("/") ? dirPath : `${dirPath}/`;
73
+ const entries = new Set<string>();
74
+ for (const key of fileMap.keys()) {
75
+ if (key.startsWith(prefix)) {
76
+ const rest = key.slice(prefix.length);
77
+ const firstSegment = rest.split("/")[0];
78
+ if (firstSegment !== undefined && firstSegment.length > 0) {
79
+ entries.add(firstSegment);
80
+ }
81
+ }
82
+ }
83
+ return Promise.resolve([...entries].sort());
84
+ },
85
+
86
+ writeFile(): Promise<void> {
87
+ return Promise.resolve();
88
+ },
89
+
90
+ appendFile(): Promise<void> {
91
+ return Promise.resolve();
92
+ },
93
+
94
+ mkdir(): Promise<void> {
95
+ return Promise.resolve();
96
+ },
97
+
98
+ stat(path: string): Promise<{ size: number }> {
99
+ const content = fileMap.get(path);
100
+ return Promise.resolve({ size: content?.length ?? 0 });
101
+ },
102
+ } as unknown as FileSystem;
103
+ }
104
+
105
+ /**
106
+ * Replay a sequence of recorded tool calls against a handler.
107
+ *
108
+ * Compares each actual result to the expected result from the
109
+ * recording. Returns pass/fail with details on mismatches.
110
+ */
111
+ export async function replayToolCalls(
112
+ calls: readonly RecordedToolCall[],
113
+ handler: ToolCallHandler,
114
+ ): Promise<ReplayResult> {
115
+ const failures: ReplayFailure[] = [];
116
+ let matched = 0;
117
+
118
+ for (let i = 0; i < calls.length; i++) {
119
+ const call = calls[i] ?? { tool: "", args: {}, expectedResult: {} };
120
+ const actual = await handler(call.tool, call.args);
121
+ const expectedJson = JSON.stringify(call.expectedResult);
122
+ const actualJson = JSON.stringify(actual);
123
+
124
+ if (expectedJson === actualJson) {
125
+ matched++;
126
+ } else {
127
+ failures.push({
128
+ index: i,
129
+ tool: call.tool,
130
+ expected: call.expectedResult,
131
+ actual,
132
+ });
133
+ }
134
+ }
135
+
136
+ return {
137
+ passed: failures.length === 0,
138
+ total: calls.length,
139
+ matched,
140
+ mismatched: failures.length,
141
+ failures,
142
+ };
143
+ }