@flyingrobots/graft 0.6.0 → 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 (563) hide show
  1. package/ADVANCED_GUIDE.md +52 -0
  2. package/CHANGELOG.md +142 -0
  3. package/GUIDE.md +53 -0
  4. package/README.md +1 -1
  5. package/dist/adapters/json-text-decoder.d.ts +3 -0
  6. package/dist/adapters/json-text-decoder.d.ts.map +1 -0
  7. package/dist/adapters/json-text-decoder.js +12 -0
  8. package/dist/adapters/json-text-decoder.js.map +1 -0
  9. package/dist/adapters/node-paths.d.ts +3 -0
  10. package/dist/adapters/node-paths.d.ts.map +1 -0
  11. package/dist/adapters/node-paths.js +29 -0
  12. package/dist/adapters/node-paths.js.map +1 -0
  13. package/dist/adapters/repo-paths.d.ts.map +1 -1
  14. package/dist/adapters/repo-paths.js +40 -5
  15. package/dist/adapters/repo-paths.js.map +1 -1
  16. package/dist/api/tool-bridge.d.ts +1 -1
  17. package/dist/api/tool-bridge.d.ts.map +1 -1
  18. package/dist/api/tool-bridge.js +1 -1
  19. package/dist/api/tool-bridge.js.map +1 -1
  20. package/dist/cli/cli-error.d.ts.map +1 -1
  21. package/dist/cli/cli-error.js +47 -10
  22. package/dist/cli/cli-error.js.map +1 -1
  23. package/dist/cli/command-parser.d.ts +12 -3
  24. package/dist/cli/command-parser.d.ts.map +1 -1
  25. package/dist/cli/command-parser.js +161 -2
  26. package/dist/cli/command-parser.js.map +1 -1
  27. package/dist/cli/daemon-status-model.d.ts +87 -0
  28. package/dist/cli/daemon-status-model.d.ts.map +1 -0
  29. package/dist/cli/daemon-status-model.js +142 -0
  30. package/dist/cli/daemon-status-model.js.map +1 -0
  31. package/dist/cli/daemon-status-render.d.ts +3 -0
  32. package/dist/cli/daemon-status-render.d.ts.map +1 -0
  33. package/dist/cli/daemon-status-render.js +100 -0
  34. package/dist/cli/daemon-status-render.js.map +1 -0
  35. package/dist/cli/daemon-status.d.ts +7 -0
  36. package/dist/cli/daemon-status.d.ts.map +1 -0
  37. package/dist/cli/daemon-status.js +79 -0
  38. package/dist/cli/daemon-status.js.map +1 -0
  39. package/dist/cli/git-graft-enhance-model.d.ts +67 -0
  40. package/dist/cli/git-graft-enhance-model.d.ts.map +1 -0
  41. package/dist/cli/git-graft-enhance-model.js +55 -0
  42. package/dist/cli/git-graft-enhance-model.js.map +1 -0
  43. package/dist/cli/git-graft-enhance-render.d.ts +3 -0
  44. package/dist/cli/git-graft-enhance-render.d.ts.map +1 -0
  45. package/dist/cli/git-graft-enhance-render.js +29 -0
  46. package/dist/cli/git-graft-enhance-render.js.map +1 -0
  47. package/dist/cli/git-graft-enhance.d.ts +14 -0
  48. package/dist/cli/git-graft-enhance.d.ts.map +1 -0
  49. package/dist/cli/git-graft-enhance.js +29 -0
  50. package/dist/cli/git-graft-enhance.js.map +1 -0
  51. package/dist/cli/index-cmd.d.ts.map +1 -1
  52. package/dist/cli/index-cmd.js +18 -21
  53. package/dist/cli/index-cmd.js.map +1 -1
  54. package/dist/cli/index-model.d.ts +5 -9
  55. package/dist/cli/index-model.d.ts.map +1 -1
  56. package/dist/cli/index-model.js +20 -18
  57. package/dist/cli/index-model.js.map +1 -1
  58. package/dist/cli/init-client-config.d.ts +12 -7
  59. package/dist/cli/init-client-config.d.ts.map +1 -1
  60. package/dist/cli/init-client-config.js +105 -43
  61. package/dist/cli/init-client-config.js.map +1 -1
  62. package/dist/cli/init-model.d.ts +9 -2
  63. package/dist/cli/init-model.d.ts.map +1 -1
  64. package/dist/cli/init-model.js +52 -4
  65. package/dist/cli/init-model.js.map +1 -1
  66. package/dist/cli/init-render.d.ts.map +1 -1
  67. package/dist/cli/init-render.js +2 -2
  68. package/dist/cli/init-render.js.map +1 -1
  69. package/dist/cli/init.d.ts.map +1 -1
  70. package/dist/cli/init.js +11 -9
  71. package/dist/cli/init.js.map +1 -1
  72. package/dist/cli/json-document.d.ts +5 -0
  73. package/dist/cli/json-document.d.ts.map +1 -1
  74. package/dist/cli/json-document.js +9 -0
  75. package/dist/cli/json-document.js.map +1 -1
  76. package/dist/cli/main.d.ts +7 -0
  77. package/dist/cli/main.d.ts.map +1 -1
  78. package/dist/cli/main.js +49 -7
  79. package/dist/cli/main.js.map +1 -1
  80. package/dist/cli/migrate-local-history.d.ts.map +1 -1
  81. package/dist/cli/migrate-local-history.js +3 -2
  82. package/dist/cli/migrate-local-history.js.map +1 -1
  83. package/dist/cli/peer-command.d.ts +1 -1
  84. package/dist/cli/peer-command.d.ts.map +1 -1
  85. package/dist/cli/peer-command.js +1 -1
  86. package/dist/cli/peer-command.js.map +1 -1
  87. package/dist/contracts/capabilities.d.ts +5 -5
  88. package/dist/contracts/capabilities.d.ts.map +1 -1
  89. package/dist/contracts/capabilities.js +89 -0
  90. package/dist/contracts/capabilities.js.map +1 -1
  91. package/dist/contracts/causal-ontology.d.ts +17 -17
  92. package/dist/contracts/json-object.d.ts +0 -1
  93. package/dist/contracts/json-object.d.ts.map +1 -1
  94. package/dist/contracts/json-object.js +0 -10
  95. package/dist/contracts/json-object.js.map +1 -1
  96. package/dist/contracts/output-schema-cli.d.ts +277 -25
  97. package/dist/contracts/output-schema-cli.d.ts.map +1 -1
  98. package/dist/contracts/output-schema-cli.js +35 -3
  99. package/dist/contracts/output-schema-cli.js.map +1 -1
  100. package/dist/contracts/output-schema-fragments.d.ts +212 -87
  101. package/dist/contracts/output-schema-fragments.d.ts.map +1 -1
  102. package/dist/contracts/output-schema-fragments.js +49 -2
  103. package/dist/contracts/output-schema-fragments.js.map +1 -1
  104. package/dist/contracts/output-schema-mcp.d.ts +372 -47
  105. package/dist/contracts/output-schema-mcp.d.ts.map +1 -1
  106. package/dist/contracts/output-schema-mcp.js +217 -1
  107. package/dist/contracts/output-schema-mcp.js.map +1 -1
  108. package/dist/contracts/output-schema-meta.d.ts +2 -2
  109. package/dist/contracts/output-schema-meta.d.ts.map +1 -1
  110. package/dist/contracts/output-schemas.d.ts +7 -7
  111. package/dist/contracts/output-schemas.d.ts.map +1 -1
  112. package/dist/contracts/output-schemas.js +294 -6
  113. package/dist/contracts/output-schemas.js.map +1 -1
  114. package/dist/git/diff.d.ts +11 -0
  115. package/dist/git/diff.d.ts.map +1 -1
  116. package/dist/git/diff.js +50 -6
  117. package/dist/git/diff.js.map +1 -1
  118. package/dist/mcp/burden.d.ts.map +1 -1
  119. package/dist/mcp/burden.js +9 -0
  120. package/dist/mcp/burden.js.map +1 -1
  121. package/dist/mcp/context.d.ts +3 -2
  122. package/dist/mcp/context.d.ts.map +1 -1
  123. package/dist/mcp/context.js +2 -37
  124. package/dist/mcp/context.js.map +1 -1
  125. package/dist/mcp/daemon-server.d.ts +2 -0
  126. package/dist/mcp/daemon-server.d.ts.map +1 -1
  127. package/dist/mcp/daemon-server.js +6 -1
  128. package/dist/mcp/daemon-server.js.map +1 -1
  129. package/dist/mcp/daemon-session-host.d.ts +1 -0
  130. package/dist/mcp/daemon-session-host.d.ts.map +1 -1
  131. package/dist/mcp/daemon-session-host.js +3 -0
  132. package/dist/mcp/daemon-session-host.js.map +1 -1
  133. package/dist/mcp/daemon-stdio-bridge.d.ts +1 -0
  134. package/dist/mcp/daemon-stdio-bridge.d.ts.map +1 -1
  135. package/dist/mcp/daemon-stdio-bridge.js +1 -0
  136. package/dist/mcp/daemon-stdio-bridge.js.map +1 -1
  137. package/dist/mcp/monitor-tick-job.d.ts +1 -0
  138. package/dist/mcp/monitor-tick-job.d.ts.map +1 -1
  139. package/dist/mcp/monitor-tick-job.js +84 -29
  140. package/dist/mcp/monitor-tick-job.js.map +1 -1
  141. package/dist/mcp/monitor-types.d.ts +1 -1
  142. package/dist/mcp/monitor-types.d.ts.map +1 -1
  143. package/dist/mcp/persisted-local-history-graph.d.ts +2 -2
  144. package/dist/mcp/persisted-local-history-graph.d.ts.map +1 -1
  145. package/dist/mcp/persisted-local-history-graph.js +3 -2
  146. package/dist/mcp/persisted-local-history-graph.js.map +1 -1
  147. package/dist/mcp/persisted-local-history.d.ts +5 -5
  148. package/dist/mcp/persisted-local-history.js +2 -2
  149. package/dist/mcp/persisted-local-history.js.map +1 -1
  150. package/dist/mcp/persistent-monitor-runtime.d.ts +1 -0
  151. package/dist/mcp/persistent-monitor-runtime.d.ts.map +1 -1
  152. package/dist/mcp/persistent-monitor-runtime.js +35 -0
  153. package/dist/mcp/persistent-monitor-runtime.js.map +1 -1
  154. package/dist/mcp/repo-tool-worker-context.d.ts.map +1 -1
  155. package/dist/mcp/repo-tool-worker-context.js +5 -2
  156. package/dist/mcp/repo-tool-worker-context.js.map +1 -1
  157. package/dist/mcp/server-context.d.ts.map +1 -1
  158. package/dist/mcp/server-context.js +13 -0
  159. package/dist/mcp/server-context.js.map +1 -1
  160. package/dist/mcp/server-tool-access.d.ts +1 -1
  161. package/dist/mcp/server-tool-access.d.ts.map +1 -1
  162. package/dist/mcp/server-tool-access.js +3 -1
  163. package/dist/mcp/server-tool-access.js.map +1 -1
  164. package/dist/mcp/server.d.ts +3 -0
  165. package/dist/mcp/server.d.ts.map +1 -1
  166. package/dist/mcp/server.js +5 -3
  167. package/dist/mcp/server.js.map +1 -1
  168. package/dist/mcp/tool-registry.d.ts.map +1 -1
  169. package/dist/mcp/tool-registry.js +18 -0
  170. package/dist/mcp/tool-registry.js.map +1 -1
  171. package/dist/mcp/tools/code-find.d.ts.map +1 -1
  172. package/dist/mcp/tools/code-find.js +20 -0
  173. package/dist/mcp/tools/code-find.js.map +1 -1
  174. package/dist/mcp/tools/code-show.d.ts.map +1 -1
  175. package/dist/mcp/tools/code-show.js +24 -0
  176. package/dist/mcp/tools/code-show.js.map +1 -1
  177. package/dist/mcp/tools/diagnostic-models.d.ts +2 -0
  178. package/dist/mcp/tools/diagnostic-models.d.ts.map +1 -1
  179. package/dist/mcp/tools/doctor.d.ts.map +1 -1
  180. package/dist/mcp/tools/doctor.js +18 -1
  181. package/dist/mcp/tools/doctor.js.map +1 -1
  182. package/dist/mcp/tools/export-surface-diff.d.ts +3 -0
  183. package/dist/mcp/tools/export-surface-diff.d.ts.map +1 -0
  184. package/dist/mcp/tools/export-surface-diff.js +24 -0
  185. package/dist/mcp/tools/export-surface-diff.js.map +1 -0
  186. package/dist/mcp/tools/file-outline.js +1 -1
  187. package/dist/mcp/tools/file-outline.js.map +1 -1
  188. package/dist/mcp/tools/graft-edit.d.ts +3 -0
  189. package/dist/mcp/tools/graft-edit.d.ts.map +1 -0
  190. package/dist/mcp/tools/graft-edit.js +192 -0
  191. package/dist/mcp/tools/graft-edit.js.map +1 -0
  192. package/dist/mcp/tools/knowledge-map.d.ts +3 -0
  193. package/dist/mcp/tools/knowledge-map.d.ts.map +1 -0
  194. package/dist/mcp/tools/knowledge-map.js +31 -0
  195. package/dist/mcp/tools/knowledge-map.js.map +1 -0
  196. package/dist/mcp/tools/monitor-nudge.d.ts +3 -0
  197. package/dist/mcp/tools/monitor-nudge.d.ts.map +1 -0
  198. package/dist/mcp/tools/monitor-nudge.js +17 -0
  199. package/dist/mcp/tools/monitor-nudge.js.map +1 -0
  200. package/dist/mcp/tools/precision-warp.d.ts +3 -3
  201. package/dist/mcp/tools/precision-warp.d.ts.map +1 -1
  202. package/dist/mcp/tools/precision-warp.js +24 -15
  203. package/dist/mcp/tools/precision-warp.js.map +1 -1
  204. package/dist/mcp/tools/refactor-difficulty.d.ts +3 -0
  205. package/dist/mcp/tools/refactor-difficulty.d.ts.map +1 -0
  206. package/dist/mcp/tools/refactor-difficulty.js +36 -0
  207. package/dist/mcp/tools/refactor-difficulty.js.map +1 -0
  208. package/dist/mcp/tools/safe-read.js +2 -2
  209. package/dist/mcp/tools/safe-read.js.map +1 -1
  210. package/dist/mcp/tools/structural-blame.d.ts +3 -0
  211. package/dist/mcp/tools/structural-blame.d.ts.map +1 -0
  212. package/dist/mcp/tools/structural-blame.js +44 -0
  213. package/dist/mcp/tools/structural-blame.js.map +1 -0
  214. package/dist/mcp/tools/structural-churn.d.ts +3 -0
  215. package/dist/mcp/tools/structural-churn.d.ts.map +1 -0
  216. package/dist/mcp/tools/structural-churn.js +28 -0
  217. package/dist/mcp/tools/structural-churn.js.map +1 -0
  218. package/dist/mcp/tools/structural-log.d.ts +3 -0
  219. package/dist/mcp/tools/structural-log.d.ts.map +1 -0
  220. package/dist/mcp/tools/structural-log.js +38 -0
  221. package/dist/mcp/tools/structural-log.js.map +1 -0
  222. package/dist/mcp/tools/structural-review.d.ts +3 -0
  223. package/dist/mcp/tools/structural-review.d.ts.map +1 -0
  224. package/dist/mcp/tools/structural-review.js +55 -0
  225. package/dist/mcp/tools/structural-review.js.map +1 -0
  226. package/dist/mcp/warp-pool.d.ts +4 -4
  227. package/dist/mcp/warp-pool.d.ts.map +1 -1
  228. package/dist/mcp/warp-pool.js.map +1 -1
  229. package/dist/mcp/workspace-router-model.d.ts +2 -2
  230. package/dist/mcp/workspace-router-model.d.ts.map +1 -1
  231. package/dist/mcp/workspace-router-runtime.d.ts +3 -3
  232. package/dist/mcp/workspace-router-runtime.d.ts.map +1 -1
  233. package/dist/mcp/workspace-router-runtime.js +4 -1
  234. package/dist/mcp/workspace-router-runtime.js.map +1 -1
  235. package/dist/mcp/workspace-router.d.ts +3 -2
  236. package/dist/mcp/workspace-router.d.ts.map +1 -1
  237. package/dist/mcp/workspace-router.js +6 -0
  238. package/dist/mcp/workspace-router.js.map +1 -1
  239. package/dist/operations/adaptive-projection.d.ts +22 -0
  240. package/dist/operations/adaptive-projection.d.ts.map +1 -0
  241. package/dist/operations/adaptive-projection.js +36 -0
  242. package/dist/operations/adaptive-projection.js.map +1 -0
  243. package/dist/operations/agent-handoff.d.ts +25 -0
  244. package/dist/operations/agent-handoff.d.ts.map +1 -0
  245. package/dist/operations/agent-handoff.js +36 -0
  246. package/dist/operations/agent-handoff.js.map +1 -0
  247. package/dist/operations/capture-range.d.ts +33 -0
  248. package/dist/operations/capture-range.d.ts.map +1 -0
  249. package/dist/operations/capture-range.js +45 -0
  250. package/dist/operations/capture-range.js.map +1 -0
  251. package/dist/operations/conversation-primer.d.ts +27 -0
  252. package/dist/operations/conversation-primer.d.ts.map +1 -0
  253. package/dist/operations/conversation-primer.js +52 -0
  254. package/dist/operations/conversation-primer.js.map +1 -0
  255. package/dist/operations/cross-session-resume.d.ts +28 -0
  256. package/dist/operations/cross-session-resume.d.ts.map +1 -0
  257. package/dist/operations/cross-session-resume.js +79 -0
  258. package/dist/operations/cross-session-resume.js.map +1 -0
  259. package/dist/operations/deterministic-replay.d.ts +39 -0
  260. package/dist/operations/deterministic-replay.d.ts.map +1 -0
  261. package/dist/operations/deterministic-replay.js +90 -0
  262. package/dist/operations/deterministic-replay.js.map +1 -0
  263. package/dist/operations/export-surface-diff.d.ts +36 -0
  264. package/dist/operations/export-surface-diff.d.ts.map +1 -0
  265. package/dist/operations/export-surface-diff.js +298 -0
  266. package/dist/operations/export-surface-diff.js.map +1 -0
  267. package/dist/operations/footprint-parallelism.d.ts +25 -0
  268. package/dist/operations/footprint-parallelism.d.ts.map +1 -0
  269. package/dist/operations/footprint-parallelism.js +79 -0
  270. package/dist/operations/footprint-parallelism.js.map +1 -0
  271. package/dist/operations/graft-diff.d.ts.map +1 -1
  272. package/dist/operations/graft-diff.js +14 -7
  273. package/dist/operations/graft-diff.js.map +1 -1
  274. package/dist/operations/horizon-of-readability.d.ts +23 -0
  275. package/dist/operations/horizon-of-readability.d.ts.map +1 -0
  276. package/dist/operations/horizon-of-readability.js +39 -0
  277. package/dist/operations/horizon-of-readability.js.map +1 -0
  278. package/dist/operations/import-reference-impact.d.ts +13 -0
  279. package/dist/operations/import-reference-impact.d.ts.map +1 -0
  280. package/dist/operations/import-reference-impact.js +101 -0
  281. package/dist/operations/import-reference-impact.js.map +1 -0
  282. package/dist/operations/knowledge-map.d.ts +30 -0
  283. package/dist/operations/knowledge-map.d.ts.map +1 -0
  284. package/dist/operations/knowledge-map.js +64 -0
  285. package/dist/operations/knowledge-map.js.map +1 -0
  286. package/dist/operations/observation-cache.d.ts +8 -2
  287. package/dist/operations/observation-cache.d.ts.map +1 -1
  288. package/dist/operations/observation-cache.js +17 -5
  289. package/dist/operations/observation-cache.js.map +1 -1
  290. package/dist/operations/projection-safety.d.ts +31 -0
  291. package/dist/operations/projection-safety.d.ts.map +1 -0
  292. package/dist/operations/projection-safety.js +77 -0
  293. package/dist/operations/projection-safety.js.map +1 -0
  294. package/dist/operations/repo-workspace.js +3 -3
  295. package/dist/operations/repo-workspace.js.map +1 -1
  296. package/dist/operations/semantic-drift.d.ts +27 -0
  297. package/dist/operations/semantic-drift.d.ts.map +1 -0
  298. package/dist/operations/semantic-drift.js +46 -0
  299. package/dist/operations/semantic-drift.js.map +1 -0
  300. package/dist/operations/session-filtration.d.ts +36 -0
  301. package/dist/operations/session-filtration.d.ts.map +1 -0
  302. package/dist/operations/session-filtration.js +48 -0
  303. package/dist/operations/session-filtration.js.map +1 -0
  304. package/dist/operations/session-replay.d.ts +17 -0
  305. package/dist/operations/session-replay.d.ts.map +1 -0
  306. package/dist/operations/session-replay.js +59 -0
  307. package/dist/operations/session-replay.js.map +1 -0
  308. package/dist/operations/sludge-detector.d.ts +45 -0
  309. package/dist/operations/sludge-detector.d.ts.map +1 -0
  310. package/dist/operations/sludge-detector.js +278 -0
  311. package/dist/operations/sludge-detector.js.map +1 -0
  312. package/dist/operations/structural-blame.d.ts +67 -0
  313. package/dist/operations/structural-blame.d.ts.map +1 -0
  314. package/dist/operations/structural-blame.js +111 -0
  315. package/dist/operations/structural-blame.js.map +1 -0
  316. package/dist/operations/structural-review.d.ts +47 -0
  317. package/dist/operations/structural-review.d.ts.map +1 -0
  318. package/dist/operations/structural-review.js +225 -0
  319. package/dist/operations/structural-review.js.map +1 -0
  320. package/dist/operations/teaching-hints.d.ts +18 -0
  321. package/dist/operations/teaching-hints.d.ts.map +1 -0
  322. package/dist/operations/teaching-hints.js +35 -0
  323. package/dist/operations/teaching-hints.js.map +1 -0
  324. package/dist/parser/diff.d.ts +2 -0
  325. package/dist/parser/diff.d.ts.map +1 -1
  326. package/dist/parser/diff.js +7 -0
  327. package/dist/parser/diff.js.map +1 -1
  328. package/dist/ports/paths.d.ts +17 -0
  329. package/dist/ports/paths.d.ts.map +1 -0
  330. package/dist/ports/{warp.js → paths.js} +2 -2
  331. package/dist/ports/paths.js.map +1 -0
  332. package/dist/warp/ast-emitter.d.ts +28 -0
  333. package/dist/warp/ast-emitter.d.ts.map +1 -0
  334. package/dist/warp/ast-emitter.js +90 -0
  335. package/dist/warp/ast-emitter.js.map +1 -0
  336. package/dist/warp/ast-import-resolver.d.ts +13 -0
  337. package/dist/warp/ast-import-resolver.d.ts.map +1 -0
  338. package/dist/warp/ast-import-resolver.js +259 -0
  339. package/dist/warp/ast-import-resolver.js.map +1 -0
  340. package/dist/warp/commit-meta.d.ts +8 -0
  341. package/dist/warp/commit-meta.d.ts.map +1 -0
  342. package/dist/warp/commit-meta.js +13 -0
  343. package/dist/warp/commit-meta.js.map +1 -0
  344. package/dist/warp/context.d.ts +10 -0
  345. package/dist/warp/context.d.ts.map +1 -0
  346. package/dist/warp/context.js +26 -0
  347. package/dist/warp/context.js.map +1 -0
  348. package/dist/warp/dead-symbols.d.ts +40 -0
  349. package/dist/warp/dead-symbols.d.ts.map +1 -0
  350. package/dist/warp/dead-symbols.js +127 -0
  351. package/dist/warp/dead-symbols.js.map +1 -0
  352. package/dist/warp/drift-sentinel.d.ts +30 -0
  353. package/dist/warp/drift-sentinel.d.ts.map +1 -0
  354. package/dist/warp/drift-sentinel.js +65 -0
  355. package/dist/warp/drift-sentinel.js.map +1 -0
  356. package/dist/warp/index-head.d.ts +32 -0
  357. package/dist/warp/index-head.d.ts.map +1 -0
  358. package/dist/warp/index-head.js +245 -0
  359. package/dist/warp/index-head.js.map +1 -0
  360. package/dist/warp/observers.d.ts +6 -6
  361. package/dist/warp/observers.d.ts.map +1 -1
  362. package/dist/warp/observers.js +5 -4
  363. package/dist/warp/observers.js.map +1 -1
  364. package/dist/warp/open.d.ts +5 -4
  365. package/dist/warp/open.d.ts.map +1 -1
  366. package/dist/warp/open.js +24 -49
  367. package/dist/warp/open.js.map +1 -1
  368. package/dist/warp/outline-diff-trailer.d.ts +26 -0
  369. package/dist/warp/outline-diff-trailer.d.ts.map +1 -0
  370. package/dist/warp/outline-diff-trailer.js +68 -0
  371. package/dist/warp/outline-diff-trailer.js.map +1 -0
  372. package/dist/warp/refactor-difficulty.d.ts +38 -0
  373. package/dist/warp/refactor-difficulty.d.ts.map +1 -0
  374. package/dist/warp/refactor-difficulty.js +169 -0
  375. package/dist/warp/refactor-difficulty.js.map +1 -0
  376. package/dist/warp/references.d.ts +22 -0
  377. package/dist/warp/references.d.ts.map +1 -0
  378. package/dist/warp/references.js +57 -0
  379. package/dist/warp/references.js.map +1 -0
  380. package/dist/warp/stale-docs.d.ts +56 -0
  381. package/dist/warp/stale-docs.d.ts.map +1 -0
  382. package/dist/warp/stale-docs.js +149 -0
  383. package/dist/warp/stale-docs.js.map +1 -0
  384. package/dist/warp/structural-drift-detection.d.ts +49 -0
  385. package/dist/warp/structural-drift-detection.d.ts.map +1 -0
  386. package/dist/warp/structural-drift-detection.js +51 -0
  387. package/dist/warp/structural-drift-detection.js.map +1 -0
  388. package/dist/warp/structural-queries.d.ts +49 -0
  389. package/dist/warp/structural-queries.d.ts.map +1 -0
  390. package/dist/warp/structural-queries.js +175 -0
  391. package/dist/warp/structural-queries.js.map +1 -0
  392. package/dist/warp/symbol-timeline.d.ts +34 -0
  393. package/dist/warp/symbol-timeline.d.ts.map +1 -0
  394. package/dist/warp/symbol-timeline.js +127 -0
  395. package/dist/warp/symbol-timeline.js.map +1 -0
  396. package/dist/warp/traverse-hydrate.d.ts +23 -0
  397. package/dist/warp/traverse-hydrate.d.ts.map +1 -0
  398. package/dist/warp/traverse-hydrate.js +39 -0
  399. package/dist/warp/traverse-hydrate.js.map +1 -0
  400. package/dist/warp/warp-reference-count.d.ts +19 -0
  401. package/dist/warp/warp-reference-count.d.ts.map +1 -0
  402. package/dist/warp/warp-reference-count.js +32 -0
  403. package/dist/warp/warp-reference-count.js.map +1 -0
  404. package/dist/warp/warp-structural-blame.d.ts +20 -0
  405. package/dist/warp/warp-structural-blame.d.ts.map +1 -0
  406. package/dist/warp/warp-structural-blame.js +43 -0
  407. package/dist/warp/warp-structural-blame.js.map +1 -0
  408. package/dist/warp/warp-structural-churn.d.ts +30 -0
  409. package/dist/warp/warp-structural-churn.d.ts.map +1 -0
  410. package/dist/warp/warp-structural-churn.js +213 -0
  411. package/dist/warp/warp-structural-churn.js.map +1 -0
  412. package/dist/warp/warp-structural-log.d.ts +35 -0
  413. package/dist/warp/warp-structural-log.d.ts.map +1 -0
  414. package/dist/warp/warp-structural-log.js +104 -0
  415. package/dist/warp/warp-structural-log.js.map +1 -0
  416. package/docs/CLI.md +68 -4
  417. package/docs/MCP.md +23 -0
  418. package/docs/SETUP.md +779 -0
  419. package/package.json +10 -7
  420. package/src/adapters/json-text-decoder.ts +11 -0
  421. package/src/adapters/node-paths.ts +35 -0
  422. package/src/adapters/repo-paths.ts +45 -4
  423. package/src/api/tool-bridge.ts +2 -1
  424. package/src/cli/cli-error.ts +49 -10
  425. package/src/cli/command-parser.ts +185 -3
  426. package/src/cli/daemon-status-model.ts +238 -0
  427. package/src/cli/daemon-status-render.ts +102 -0
  428. package/src/cli/daemon-status.ts +100 -0
  429. package/src/cli/git-graft-enhance-model.ts +131 -0
  430. package/src/cli/git-graft-enhance-render.ts +33 -0
  431. package/src/cli/git-graft-enhance.ts +54 -0
  432. package/src/cli/index-cmd.ts +18 -22
  433. package/src/cli/index-model.ts +21 -22
  434. package/src/cli/init-client-config.ts +167 -38
  435. package/src/cli/init-model.ts +57 -2
  436. package/src/cli/init-render.ts +2 -2
  437. package/src/cli/init.ts +11 -9
  438. package/src/cli/json-document.ts +11 -0
  439. package/src/cli/main.ts +53 -6
  440. package/src/cli/migrate-local-history.ts +3 -2
  441. package/src/cli/peer-command.ts +2 -1
  442. package/src/contracts/capabilities.ts +90 -0
  443. package/src/contracts/json-object.ts +1 -11
  444. package/src/contracts/output-schema-cli.ts +36 -3
  445. package/src/contracts/output-schema-fragments.ts +52 -2
  446. package/src/contracts/output-schema-mcp.ts +219 -0
  447. package/src/contracts/output-schemas.ts +300 -6
  448. package/src/git/diff.ts +61 -0
  449. package/src/mcp/burden.ts +9 -0
  450. package/src/mcp/context.ts +5 -42
  451. package/src/mcp/daemon-server.ts +8 -1
  452. package/src/mcp/daemon-session-host.ts +4 -0
  453. package/src/mcp/daemon-stdio-bridge.ts +2 -0
  454. package/src/mcp/monitor-tick-job.ts +90 -39
  455. package/src/mcp/monitor-types.ts +1 -1
  456. package/src/mcp/persisted-local-history-graph.ts +5 -4
  457. package/src/mcp/persisted-local-history.ts +2 -2
  458. package/src/mcp/persistent-monitor-runtime.ts +37 -0
  459. package/src/mcp/repo-tool-worker-context.ts +5 -2
  460. package/src/mcp/server-context.ts +15 -2
  461. package/src/mcp/server-tool-access.ts +4 -1
  462. package/src/mcp/server.ts +8 -3
  463. package/src/mcp/tool-registry.ts +18 -0
  464. package/src/mcp/tools/code-find.ts +23 -0
  465. package/src/mcp/tools/code-show.ts +27 -0
  466. package/src/mcp/tools/diagnostic-models.ts +2 -0
  467. package/src/mcp/tools/doctor.ts +18 -1
  468. package/src/mcp/tools/export-surface-diff.ts +26 -0
  469. package/src/mcp/tools/file-outline.ts +1 -1
  470. package/src/mcp/tools/graft-edit.ts +276 -0
  471. package/src/mcp/tools/knowledge-map.ts +34 -0
  472. package/src/mcp/tools/monitor-nudge.ts +19 -0
  473. package/src/mcp/tools/precision-warp.ts +27 -16
  474. package/src/mcp/tools/refactor-difficulty.ts +42 -0
  475. package/src/mcp/tools/safe-read.ts +2 -2
  476. package/src/mcp/tools/structural-blame.ts +55 -0
  477. package/src/mcp/tools/structural-churn.ts +28 -0
  478. package/src/mcp/tools/structural-log.ts +41 -0
  479. package/src/mcp/tools/structural-review.ts +63 -0
  480. package/src/mcp/warp-pool.ts +6 -6
  481. package/src/mcp/workspace-router-model.ts +2 -2
  482. package/src/mcp/workspace-router-runtime.ts +11 -8
  483. package/src/mcp/workspace-router.ts +9 -2
  484. package/src/operations/adaptive-projection.ts +54 -0
  485. package/src/operations/agent-handoff.ts +59 -0
  486. package/src/operations/capture-range.ts +64 -0
  487. package/src/operations/conversation-primer.ts +82 -0
  488. package/src/operations/cross-session-resume.ts +104 -0
  489. package/src/operations/deterministic-replay.ts +143 -0
  490. package/src/operations/export-surface-diff.ts +355 -0
  491. package/src/operations/footprint-parallelism.ts +98 -0
  492. package/src/operations/graft-diff.ts +14 -7
  493. package/src/operations/horizon-of-readability.ts +60 -0
  494. package/src/operations/import-reference-impact.ts +143 -0
  495. package/src/operations/knowledge-map.ts +96 -0
  496. package/src/operations/observation-cache.ts +20 -4
  497. package/src/operations/projection-safety.ts +111 -0
  498. package/src/operations/repo-workspace.ts +3 -3
  499. package/src/operations/semantic-drift.ts +70 -0
  500. package/src/operations/session-filtration.ts +76 -0
  501. package/src/operations/session-replay.ts +73 -0
  502. package/src/operations/sludge-detector.ts +356 -0
  503. package/src/operations/structural-blame.ts +197 -0
  504. package/src/operations/structural-review.ts +317 -0
  505. package/src/operations/teaching-hints.ts +52 -0
  506. package/src/parser/diff.ts +7 -0
  507. package/src/ports/paths.ts +22 -0
  508. package/src/warp/ast-emitter.ts +133 -0
  509. package/src/warp/ast-import-resolver.ts +333 -0
  510. package/src/warp/commit-meta.ts +19 -0
  511. package/src/warp/context.ts +48 -0
  512. package/src/warp/dead-symbols.ts +174 -0
  513. package/src/warp/drift-sentinel.ts +101 -0
  514. package/src/warp/index-head.ts +348 -0
  515. package/src/warp/observers.ts +8 -7
  516. package/src/warp/open.ts +40 -66
  517. package/src/warp/outline-diff-trailer.ts +100 -0
  518. package/src/warp/plumbing.d.ts +11 -2
  519. package/src/warp/refactor-difficulty.ts +257 -0
  520. package/src/warp/references.ts +77 -0
  521. package/src/warp/stale-docs.ts +210 -0
  522. package/src/warp/structural-drift-detection.ts +97 -0
  523. package/src/warp/structural-queries.ts +258 -0
  524. package/src/warp/symbol-timeline.ts +209 -0
  525. package/src/warp/traverse-hydrate.ts +61 -0
  526. package/src/warp/warp-reference-count.ts +47 -0
  527. package/src/warp/warp-structural-blame.ts +65 -0
  528. package/src/warp/warp-structural-churn.ts +309 -0
  529. package/src/warp/warp-structural-log.ts +149 -0
  530. package/dist/ports/warp.d.ts +0 -45
  531. package/dist/ports/warp.d.ts.map +0 -1
  532. package/dist/ports/warp.js.map +0 -1
  533. package/dist/warp/identity-resolver.d.ts +0 -14
  534. package/dist/warp/identity-resolver.d.ts.map +0 -1
  535. package/dist/warp/identity-resolver.js +0 -31
  536. package/dist/warp/identity-resolver.js.map +0 -1
  537. package/dist/warp/indexer-git.d.ts +0 -22
  538. package/dist/warp/indexer-git.d.ts.map +0 -1
  539. package/dist/warp/indexer-git.js +0 -148
  540. package/dist/warp/indexer-git.js.map +0 -1
  541. package/dist/warp/indexer-graph.d.ts +0 -17
  542. package/dist/warp/indexer-graph.d.ts.map +0 -1
  543. package/dist/warp/indexer-graph.js +0 -179
  544. package/dist/warp/indexer-graph.js.map +0 -1
  545. package/dist/warp/indexer-model.d.ts +0 -51
  546. package/dist/warp/indexer-model.d.ts.map +0 -1
  547. package/dist/warp/indexer-model.js +0 -21
  548. package/dist/warp/indexer-model.js.map +0 -1
  549. package/dist/warp/indexer.d.ts +0 -9
  550. package/dist/warp/indexer.d.ts.map +0 -1
  551. package/dist/warp/indexer.js +0 -112
  552. package/dist/warp/indexer.js.map +0 -1
  553. package/dist/warp/symbol-identity.d.ts +0 -11
  554. package/dist/warp/symbol-identity.d.ts.map +0 -1
  555. package/dist/warp/symbol-identity.js +0 -67
  556. package/dist/warp/symbol-identity.js.map +0 -1
  557. package/src/ports/warp.ts +0 -55
  558. package/src/warp/identity-resolver.ts +0 -35
  559. package/src/warp/indexer-git.ts +0 -182
  560. package/src/warp/indexer-graph.ts +0 -276
  561. package/src/warp/indexer-model.ts +0 -69
  562. package/src/warp/indexer.ts +0 -186
  563. package/src/warp/symbol-identity.ts +0 -100
package/src/git/diff.ts CHANGED
@@ -48,6 +48,67 @@ async function objectExists(ref: string, filePath: string, cwd: string, gitClien
48
48
  * Throws GitError for invalid refs or non-git directories.
49
49
  * Returns empty array only when there are genuinely no changes.
50
50
  */
51
+
52
+ export type ChangedFileStatus = "added" | "modified" | "deleted" | "renamed";
53
+
54
+ export interface ChangedFile {
55
+ readonly path: string;
56
+ readonly status: ChangedFileStatus;
57
+ readonly oldPath?: string;
58
+ }
59
+
60
+ const STATUS_MAP: Record<string, ChangedFileStatus> = {
61
+ A: "added",
62
+ M: "modified",
63
+ D: "deleted",
64
+ R: "renamed",
65
+ };
66
+
67
+ function parseNameStatus(output: string): ChangedFile[] {
68
+ if (output === "") return [];
69
+ const lines = output.split("\n");
70
+ const result: ChangedFile[] = [];
71
+ for (const line of lines) {
72
+ const statusCode = line[0];
73
+ if (statusCode === undefined) continue;
74
+ const baseStatus = statusCode === "R" || statusCode === "C" ? statusCode : statusCode;
75
+ const status = STATUS_MAP[baseStatus] ?? "modified";
76
+ const parts = line.split("\t");
77
+ if (statusCode === "R" || statusCode === "C") {
78
+ const oldPath = parts[1];
79
+ const newPath = parts[2];
80
+ if (oldPath !== undefined && newPath !== undefined) {
81
+ result.push({ path: newPath, status, oldPath });
82
+ }
83
+ } else {
84
+ const filePath = parts[1];
85
+ if (filePath !== undefined) {
86
+ result.push({ path: filePath, status });
87
+ }
88
+ }
89
+ }
90
+ return result;
91
+ }
92
+
93
+ /**
94
+ * List files changed between two refs with rename detection.
95
+ * Returns structured data including status and old path for renames.
96
+ */
97
+ export async function getChangedFilesWithStatus(opts: ChangedFilesOptions): Promise<ChangedFile[]> {
98
+ const base = opts.base ?? "HEAD";
99
+ const args = opts.head !== undefined
100
+ ? ["diff-tree", "--no-commit-id", "--name-status", "-M", "-r", base, opts.head]
101
+ : ["diff-index", "--name-status", "-M", base, "--"];
102
+
103
+ try {
104
+ const output = (await git(opts.git, args, opts.cwd)).trim();
105
+ return parseNameStatus(output);
106
+ } catch (err: unknown) {
107
+ const msg = err instanceof Error ? err.message : String(err);
108
+ throw new GitError(`git diff failed: ${msg}`);
109
+ }
110
+ }
111
+
51
112
  export async function getChangedFiles(opts: ChangedFilesOptions): Promise<string[]> {
52
113
  const base = opts.base ?? "HEAD";
53
114
  const args = opts.head !== undefined
package/src/mcp/burden.ts CHANGED
@@ -15,6 +15,7 @@ const ZERO_BUCKET: BurdenBucket = Object.freeze({ calls: 0, bytesReturned: 0 });
15
15
 
16
16
  const TOOL_BURDEN_KIND: Record<McpToolName, BurdenKind> = {
17
17
  safe_read: "read",
18
+ graft_edit: "state",
18
19
  file_outline: "read",
19
20
  read_range: "read",
20
21
  changed_since: "read",
@@ -31,6 +32,7 @@ const TOOL_BURDEN_KIND: Record<McpToolName, BurdenKind> = {
31
32
  monitor_start: "diagnostic",
32
33
  monitor_pause: "diagnostic",
33
34
  monitor_resume: "diagnostic",
35
+ monitor_nudge: "diagnostic",
34
36
  monitor_stop: "diagnostic",
35
37
  workspace_authorize: "diagnostic",
36
38
  workspace_authorizations: "diagnostic",
@@ -48,6 +50,13 @@ const TOOL_BURDEN_KIND: Record<McpToolName, BurdenKind> = {
48
50
  explain: "diagnostic",
49
51
  doctor: "diagnostic",
50
52
  stats: "diagnostic",
53
+ graft_churn: "search",
54
+ graft_exports: "search",
55
+ graft_log: "search",
56
+ graft_blame: "search",
57
+ graft_difficulty: "search",
58
+ graft_review: "search",
59
+ knowledge_map: "diagnostic",
51
60
  };
52
61
 
53
62
  export function emptyBurdenByKind(): BurdenByKind {
@@ -2,8 +2,7 @@
2
2
  // ToolContext — shared dependencies injected into every tool handler
3
3
  // ---------------------------------------------------------------------------
4
4
 
5
- import * as fs from "node:fs";
6
- import * as path from "node:path";
5
+ import { createRepoPathResolver } from "../adapters/repo-paths.js";
7
6
  import type { ObservationCache } from "./cache.js";
8
7
  import type { Metrics } from "./metrics.js";
9
8
  import type { GovernorTracker } from "../session/tracker.js";
@@ -12,7 +11,7 @@ import type { FileSystem } from "../ports/filesystem.js";
12
11
  import type { JsonCodec } from "../ports/codec.js";
13
12
  import type { ProcessRunner } from "../ports/process-runner.js";
14
13
  import type { GitClient } from "../ports/git.js";
15
- import type { WarpHandle } from "../ports/warp.js";
14
+ import type { WarpContext } from "../warp/context.js";
16
15
  import type { RepoObservation } from "./repo-state.js";
17
16
  import type { RunCaptureConfig } from "./run-capture-config.js";
18
17
  import type { RuntimeObservabilityState, ToolCallFootprintRegion } from "./runtime-observability.js";
@@ -81,7 +80,7 @@ export interface ToolContext {
81
80
  readonly regions?: readonly ToolCallFootprintRegion[];
82
81
  }): void;
83
82
  resolvePath(relative: string): string;
84
- getWarp(): Promise<WarpHandle>;
83
+ getWarp(): Promise<WarpContext>;
85
84
  getRepoState(): RepoObservation;
86
85
  getCausalContext(): RuntimeCausalContext;
87
86
  getWorkspaceOverlayFooting(): Promise<RuntimeWorkspaceOverlayFooting | null>;
@@ -100,6 +99,7 @@ export interface ToolContext {
100
99
  pauseMonitor(request: WorkspaceBindRequest): Promise<MonitorActionResult>;
101
100
  resumeMonitor(request: WorkspaceBindRequest): Promise<MonitorActionResult>;
102
101
  stopMonitor(request: WorkspaceBindRequest): Promise<MonitorActionResult>;
102
+ nudgeMonitor(request: WorkspaceBindRequest): Promise<MonitorActionResult>;
103
103
  listWorkspaceAuthorizations(): Promise<readonly AuthorizedWorkspaceView[]>;
104
104
  authorizeWorkspace(request: WorkspaceAuthorizeRequest): Promise<WorkspaceAuthorizeResult>;
105
105
  revokeWorkspace(request: WorkspaceBindRequest): Promise<WorkspaceRevokeResult>;
@@ -111,44 +111,7 @@ export interface ToolContext {
111
111
  * Symlinks are resolved before the confinement check to prevent escapes.
112
112
  */
113
113
  export function createPathResolver(projectRoot: string): (input: string) => string {
114
- const normalizedRoot = path.resolve(projectRoot);
115
-
116
- // Resolve the project root itself through symlinks for consistent comparison
117
- let realProjectRoot: string;
118
- try {
119
- realProjectRoot = fs.realpathSync(normalizedRoot);
120
- } catch {
121
- realProjectRoot = normalizedRoot;
122
- }
123
-
124
- return (input: string): string => {
125
- // Resolve: absolute paths are taken as-is, relative paths join to projectRoot
126
- const resolved = path.isAbsolute(input)
127
- ? path.resolve(input)
128
- : path.resolve(normalizedRoot, input);
129
-
130
- // Logical confinement check (catches ".." traversal without needing fs access)
131
- const logicalRel = path.relative(normalizedRoot, resolved);
132
- if (logicalRel.startsWith("..") || path.isAbsolute(logicalRel)) {
133
- throw new Error(`Path traversal blocked: ${input}`);
134
- }
135
-
136
- // Resolve symlinks before a second confinement check to prevent symlink escapes
137
- let real: string;
138
- try {
139
- real = fs.realpathSync(resolved);
140
- } catch {
141
- // Target doesn't exist yet — return the logical path (already passed confinement)
142
- return resolved;
143
- }
144
-
145
- // Symlink confinement check: the real path must be within the real project root
146
- const realRel = path.relative(realProjectRoot, real);
147
- if (realRel.startsWith("..") || path.isAbsolute(realRel)) {
148
- throw new Error(`Path traversal blocked: ${input}`);
149
- }
150
- return resolved;
151
- };
114
+ return createRepoPathResolver(projectRoot);
152
115
  }
153
116
 
154
117
  /**
@@ -34,6 +34,8 @@ export interface StartDaemonServerOptions {
34
34
  readonly env?: Readonly<Record<string, string | undefined>> | undefined;
35
35
  readonly runCapture?: Partial<RunCaptureConfig> | undefined;
36
36
  readonly runtimeObservability?: Partial<RuntimeObservabilityState> | undefined;
37
+ readonly workerPoolSize?: number | undefined;
38
+ readonly persistedLocalHistoryGraph?: boolean | undefined;
37
39
  }
38
40
 
39
41
  export interface GraftDaemonServer {
@@ -55,7 +57,9 @@ export async function startDaemonServer(options: StartDaemonServerOptions = {}):
55
57
  graftDir,
56
58
  });
57
59
  const daemonScheduler = new DaemonJobScheduler();
58
- const daemonWorkerPool = new ChildProcessDaemonWorkerPool();
60
+ const daemonWorkerPool = new ChildProcessDaemonWorkerPool({
61
+ ...(options.workerPoolSize !== undefined ? { size: options.workerPoolSize } : {}),
62
+ });
59
63
  const monitorRuntime = new PersistentMonitorRuntime({
60
64
  fs: nodeFs,
61
65
  codec: new CanonicalJsonCodec(),
@@ -103,6 +107,9 @@ export async function startDaemonServer(options: StartDaemonServerOptions = {}):
103
107
  ...(options.runtimeObservability !== undefined
104
108
  ? { runtimeObservability: options.runtimeObservability }
105
109
  : {}),
110
+ ...(options.persistedLocalHistoryGraph !== undefined
111
+ ? { persistedLocalHistoryGraph: options.persistedLocalHistoryGraph }
112
+ : {}),
106
113
  });
107
114
 
108
115
  const httpServer = http.createServer((req, res) => {
@@ -40,6 +40,7 @@ export interface CreateDaemonSessionHostOptions {
40
40
  readonly env?: Readonly<Record<string, string | undefined>> | undefined;
41
41
  readonly runCapture?: Partial<RunCaptureConfig> | undefined;
42
42
  readonly runtimeObservability?: Partial<RuntimeObservabilityState> | undefined;
43
+ readonly persistedLocalHistoryGraph?: boolean | undefined;
43
44
  }
44
45
 
45
46
  export interface DaemonSessionHost {
@@ -125,6 +126,9 @@ async function createDaemonSession(
125
126
  ...(options.runtimeObservability !== undefined
126
127
  ? { runtimeObservability: options.runtimeObservability }
127
128
  : {}),
129
+ ...(options.persistedLocalHistoryGraph !== undefined
130
+ ? { persistedLocalHistoryGraph: options.persistedLocalHistoryGraph }
131
+ : {}),
128
132
  });
129
133
  const session: DaemonSession = {
130
134
  id: newSessionId,
@@ -176,6 +176,7 @@ function internalErrorResponse(
176
176
 
177
177
  export interface StartDaemonBackedStdioBridgeOptions {
178
178
  socketPath?: string;
179
+ spawnIfMissing?: boolean;
179
180
  ensureReady?: ((options?: EnsureDaemonReadyOptions) => Promise<string>) | undefined;
180
181
  }
181
182
 
@@ -184,6 +185,7 @@ export async function startDaemonBackedStdioBridge(
184
185
  ): Promise<void> {
185
186
  const socketPath = await (options.ensureReady ?? ensureDaemonReady)({
186
187
  ...(options.socketPath !== undefined ? { socketPath: options.socketPath } : {}),
188
+ ...(options.spawnIfMissing !== undefined ? { spawnIfMissing: options.spawnIfMissing } : {}),
187
189
  });
188
190
  const stdioTransport = new StdioServerTransport();
189
191
  const daemonTransport = new StreamableHTTPClientTransport(
@@ -1,5 +1,6 @@
1
- import { indexCommits } from "../warp/indexer.js";
1
+ import { DEFAULT_INDEX_MAX_FILES_PER_CALL, indexHead } from "../warp/index-head.js";
2
2
  import { nodeGit } from "../adapters/node-git.js";
3
+ import { nodePathOps } from "../adapters/node-paths.js";
3
4
  import { openWarp } from "../warp/open.js";
4
5
 
5
6
  export interface MonitorTickWorkerJob {
@@ -7,6 +8,7 @@ export interface MonitorTickWorkerJob {
7
8
  readonly worktreeRoot: string;
8
9
  readonly writerId: string;
9
10
  readonly lastIndexedCommit: string | null;
11
+ readonly maxFilesPerBatch?: number | undefined;
10
12
  }
11
13
 
12
14
  export type MonitorTickWorkerResult =
@@ -26,8 +28,8 @@ export type MonitorTickWorkerResult =
26
28
  readonly backlogCommits: number;
27
29
  };
28
30
 
29
- async function readGit(cwd: string, args: readonly string[]): Promise<string | null> {
30
- const result = await nodeGit.run({ cwd, args });
31
+ async function readHeadCommit(cwd: string): Promise<string | null> {
32
+ const result = await nodeGit.run({ cwd, args: ["rev-parse", "--verify", "HEAD"] });
31
33
  if (result.error !== undefined || result.status !== 0) {
32
34
  return null;
33
35
  }
@@ -35,68 +37,117 @@ async function readGit(cwd: string, args: readonly string[]): Promise<string | n
35
37
  return trimmed.length === 0 ? null : trimmed;
36
38
  }
37
39
 
38
- async function readHeadCommit(cwd: string): Promise<string | null> {
39
- return readGit(cwd, ["rev-parse", "--verify", "HEAD"]);
40
+ function parseGitPathList(output: string): readonly string[] {
41
+ const seen = new Set<string>();
42
+ const paths: string[] = [];
43
+ for (const line of output.split("\n")) {
44
+ const filePath = line.trim();
45
+ if (filePath.length === 0 || seen.has(filePath)) continue;
46
+ seen.add(filePath);
47
+ paths.push(filePath);
48
+ }
49
+ return paths;
40
50
  }
41
51
 
42
- async function countPendingCommits(
43
- cwd: string,
44
- from: string | null,
45
- to: string | null,
46
- ): Promise<number> {
47
- if (to === null) return 0;
48
- const range = from === null ? to : `${from}..${to}`;
49
- const output = await readGit(cwd, ["rev-list", "--count", range]);
50
- if (output === null) return 0;
51
- const parsed = Number.parseInt(output, 10);
52
- return Number.isInteger(parsed) && parsed >= 0 ? parsed : 0;
52
+ async function listTrackedPaths(cwd: string): Promise<readonly string[]> {
53
+ const result = await nodeGit.run({ cwd, args: ["ls-files"] });
54
+ if (result.error !== undefined || result.status !== 0) {
55
+ throw result.error ?? new Error(result.stderr.trim() || `git ls-files exited with status ${String(result.status)}`);
56
+ }
57
+ return parseGitPathList(result.stdout);
58
+ }
59
+
60
+ async function listChangedPaths(cwd: string, base: string, head: string): Promise<readonly string[] | null> {
61
+ const result = await nodeGit.run({ cwd, args: ["diff", "--name-only", `${base}..${head}`] });
62
+ if (result.error !== undefined || result.status !== 0) {
63
+ return null;
64
+ }
65
+ return parseGitPathList(result.stdout);
66
+ }
67
+
68
+ async function monitorIndexPaths(input: {
69
+ readonly cwd: string;
70
+ readonly currentHead: string | null;
71
+ readonly lastIndexedCommit: string | null;
72
+ }): Promise<readonly string[]> {
73
+ if (input.currentHead === null) return [];
74
+ if (input.lastIndexedCommit !== null) {
75
+ const changedPaths = await listChangedPaths(input.cwd, input.lastIndexedCommit, input.currentHead);
76
+ if (changedPaths !== null) return changedPaths;
77
+ }
78
+ return listTrackedPaths(input.cwd);
79
+ }
80
+
81
+ function pathBatches(paths: readonly string[], size: number): readonly (readonly string[])[] {
82
+ const batches: (readonly string[])[] = [];
83
+ for (let index = 0; index < paths.length; index += size) {
84
+ batches.push(paths.slice(index, index + size));
85
+ }
86
+ return batches;
53
87
  }
54
88
 
55
89
  export async function runMonitorTickJob(job: MonitorTickWorkerJob): Promise<MonitorTickWorkerResult> {
56
90
  const headAtStart = await readHeadCommit(job.worktreeRoot);
57
91
 
92
+ // ── Tick ceiling: skip indexing when HEAD hasn't moved ───────────
93
+ // When HEAD equals the last indexed commit (including both null for
94
+ // empty repos), there is nothing to index. Short-circuit before
95
+ // opening WARP or calling indexCommits to keep idle ticks near-zero-cost.
96
+ if (headAtStart === job.lastIndexedCommit) {
97
+ return {
98
+ ok: true,
99
+ headAtStart,
100
+ currentHead: headAtStart,
101
+ lastIndexedCommit: job.lastIndexedCommit,
102
+ backlogCommits: 0,
103
+ commitsIndexed: 0,
104
+ patchesWritten: 0,
105
+ };
106
+ }
107
+
58
108
  try {
59
- const warp = await openWarp({
109
+ const app = await openWarp({
60
110
  cwd: job.worktreeRoot,
61
111
  writerId: job.writerId,
62
112
  });
63
- const result = await indexCommits(warp, {
113
+ const ctx = { app, strandId: null };
114
+ const paths = await monitorIndexPaths({
64
115
  cwd: job.worktreeRoot,
65
- git: nodeGit,
66
- ...(job.lastIndexedCommit !== null ? { from: job.lastIndexedCommit } : {}),
67
- ...(headAtStart !== null ? { to: headAtStart } : {}),
116
+ currentHead: headAtStart,
117
+ lastIndexedCommit: job.lastIndexedCommit,
68
118
  });
69
- if (!result.ok) {
70
- throw new Error(result.error);
119
+ let commitsIndexed = 0;
120
+ let patchesWritten = 0;
121
+ const maxFilesPerBatch = job.maxFilesPerBatch ?? DEFAULT_INDEX_MAX_FILES_PER_CALL;
122
+ for (const batch of pathBatches(paths, maxFilesPerBatch)) {
123
+ const result = await indexHead({
124
+ cwd: job.worktreeRoot,
125
+ git: nodeGit,
126
+ pathOps: nodePathOps,
127
+ ctx,
128
+ paths: batch,
129
+ maxFilesPerCall: maxFilesPerBatch,
130
+ });
131
+ commitsIndexed += result.filesIndexed;
132
+ patchesWritten += result.nodesEmitted;
71
133
  }
72
134
  const currentHead = await readHeadCommit(job.worktreeRoot);
73
- const lastIndexedCommit = headAtStart ?? job.lastIndexedCommit;
74
- const backlogCommits = await countPendingCommits(
75
- job.worktreeRoot,
76
- lastIndexedCommit,
77
- currentHead,
78
- );
79
135
  return {
80
136
  ok: true,
81
137
  headAtStart,
82
138
  currentHead,
83
- lastIndexedCommit,
84
- backlogCommits,
85
- commitsIndexed: result.commitsIndexed,
86
- patchesWritten: result.patchesWritten,
139
+ lastIndexedCommit: headAtStart,
140
+ backlogCommits: 0,
141
+ commitsIndexed,
142
+ patchesWritten,
87
143
  };
88
144
  } catch (error) {
89
145
  const currentHead = await readHeadCommit(job.worktreeRoot);
90
- const backlogCommits = await countPendingCommits(
91
- job.worktreeRoot,
92
- job.lastIndexedCommit,
93
- currentHead,
94
- );
95
146
  return {
96
147
  ok: false,
97
148
  error: error instanceof Error ? error.message : String(error),
98
149
  currentHead,
99
- backlogCommits,
150
+ backlogCommits: 0,
100
151
  };
101
152
  }
102
153
  }
@@ -18,7 +18,7 @@ export const DEFAULT_POLL_INTERVAL_MS = 5_000;
18
18
  export type MonitorLifecycleState = "running" | "paused" | "stopped";
19
19
  export type MonitorHealth = "ok" | "lagging" | "error" | "unauthorized" | "paused" | "stopped";
20
20
  export type MonitorWorkerKind = "git_poll_indexer";
21
- export type MonitorAction = "start" | "pause" | "resume" | "stop";
21
+ export type MonitorAction = "start" | "pause" | "resume" | "stop" | "nudge";
22
22
 
23
23
  // ── Persistence schemas ────────────────────────────────────────────
24
24
 
@@ -6,10 +6,11 @@ import type {
6
6
  CausalRegion,
7
7
  Evidence,
8
8
  } from "../contracts/causal-ontology.js";
9
- import type { WarpHandle } from "../ports/warp.js";
9
+ import type { WarpContext } from "../warp/context.js";
10
+ import { patchGraph } from "../warp/context.js";
10
11
  import type { RuntimeStagedTargetFullFile } from "./runtime-staged-target.js";
11
12
 
12
- export type PersistedLocalHistoryGraphWarp = Pick<WarpHandle, "hasNode" | "observer" | "patch">;
13
+ export type PersistedLocalHistoryGraphWarp = WarpContext;
13
14
 
14
15
  export interface PersistedLocalHistoryGraphContext {
15
16
  readonly warp: PersistedLocalHistoryGraphWarp;
@@ -161,10 +162,10 @@ async function commitAccumulator(
161
162
  const ids = [...accumulator.nodes.keys()];
162
163
  const existence = new Map<string, boolean>();
163
164
  for (const id of ids) {
164
- existence.set(id, await graph.warp.hasNode(id));
165
+ existence.set(id, await graph.warp.app.core().hasNode(id));
165
166
  }
166
167
 
167
- await graph.warp.patch((patch) => {
168
+ await patchGraph(graph.warp, (patch) => {
168
169
  for (const [id, props] of accumulator.nodes.entries()) {
169
170
  const exists = existence.get(id) ?? false;
170
171
  if (!exists) {
@@ -462,7 +462,7 @@ async function loadObservedLocalHistoryGraph(
462
462
  return null;
463
463
  }
464
464
 
465
- const observer = await graph.warp.observer({
465
+ const observer = await graph.warp.app.observer({
466
466
  match: [...LOCAL_HISTORY_GRAPH_MATCH],
467
467
  expose: [...LOCAL_HISTORY_GRAPH_EXPOSE],
468
468
  });
@@ -980,7 +980,7 @@ async function hasLocalHistoryEventNode(
980
980
  graph: PersistedLocalHistoryGraphContext,
981
981
  eventId: string,
982
982
  ): Promise<boolean> {
983
- return graph.warp.hasNode(`lh:event:${eventId}`);
983
+ return graph.warp.app.core().hasNode(`lh:event:${eventId}`);
984
984
  }
985
985
 
986
986
  export async function migrateLegacyPersistedLocalHistoryToGraph(input: {
@@ -200,6 +200,43 @@ export class PersistentMonitorRuntime {
200
200
  return this.transitionMonitor("stop", request, "stopped");
201
201
  }
202
202
 
203
+ async nudgeMonitor(request: WorkspaceBindRequest): Promise<MonitorActionResult> {
204
+ await this.ensureLoaded();
205
+ const resolved = await this.resolveAuthorizedRepo(request);
206
+ if ("errorCode" in resolved) {
207
+ return {
208
+ ok: false,
209
+ action: "nudge",
210
+ created: false,
211
+ changed: false,
212
+ errorCode: resolved.errorCode,
213
+ error: resolved.error,
214
+ };
215
+ }
216
+ const { repoId } = resolved;
217
+ const record = this.records.get(repoId);
218
+ if (record?.lifecycleState !== "running") {
219
+ return {
220
+ ok: false,
221
+ action: "nudge",
222
+ created: false,
223
+ changed: false,
224
+ errorCode: "not_running",
225
+ error: "Monitor is not running — start it first.",
226
+ };
227
+ }
228
+ // Fire an immediate tick without changing lifecycle state
229
+ await this.runTick(repoId).catch(() => undefined);
230
+ return {
231
+ ok: true,
232
+ action: "nudge" as MonitorAction,
233
+ created: false,
234
+ changed: false,
235
+ status: await this.getStatusByRepoId(repoId),
236
+ };
237
+ }
238
+
239
+
203
240
  // ── Private: lifecycle transitions ─────────────────────────────
204
241
 
205
242
  private async transitionMonitor(
@@ -118,8 +118,8 @@ export function buildRepoToolWorkerContext(
118
118
  // captures footprint via AsyncLocalStorage in the invocation engine.
119
119
  },
120
120
  resolvePath: createRepoPathResolver(job.projectRoot),
121
- getWarp() {
122
- return openWarp({ cwd: job.projectRoot, writerId: job.writerId });
121
+ async getWarp() {
122
+ return { app: await openWarp({ cwd: job.projectRoot, writerId: job.writerId }), strandId: null };
123
123
  },
124
124
  getRepoState() {
125
125
  return job.repoState;
@@ -179,6 +179,9 @@ export function buildRepoToolWorkerContext(
179
179
  resumeMonitor() {
180
180
  return unsupported("resumeMonitor");
181
181
  },
182
+ nudgeMonitor() {
183
+ return unsupported("nudgeMonitor");
184
+ },
182
185
  stopMonitor() {
183
186
  return unsupported("stopMonitor");
184
187
  },
@@ -3,7 +3,7 @@ import type { CanonicalJsonCodec } from "../adapters/canonical-json.js";
3
3
  import type { FileSystem } from "../ports/filesystem.js";
4
4
  import type { ProcessRunner } from "../ports/process-runner.js";
5
5
  import type { GitClient } from "../ports/git.js";
6
- import type { WarpHandle } from "../ports/warp.js";
6
+ import type { WarpContext } from "../warp/context.js";
7
7
  import type { ToolContext, ToolDefinition } from "./context.js";
8
8
  import type { McpToolResult } from "./receipt.js";
9
9
  import type { RunCaptureConfig } from "./run-capture-config.js";
@@ -92,7 +92,7 @@ export function buildToolContext(deps: ToolContextDeps): ToolContext {
92
92
  git: deps.git,
93
93
  runCapture: deps.runCapture,
94
94
  observability: deps.observability,
95
- getWarp(): Promise<WarpHandle> {
95
+ getWarp(): Promise<WarpContext> {
96
96
  return getActiveExecutionContext()?.getWarp() ?? workspaceRouter.getWarp();
97
97
  },
98
98
  getRepoState() {
@@ -195,6 +195,19 @@ export function buildToolContext(deps: ToolContextDeps): ToolContext {
195
195
  }
196
196
  return monitorRuntime.resumeMonitor(request);
197
197
  },
198
+ nudgeMonitor(request) {
199
+ if (monitorRuntime === null) {
200
+ return Promise.resolve({
201
+ ok: false,
202
+ action: "nudge",
203
+ created: false,
204
+ changed: false,
205
+ errorCode: "no_daemon",
206
+ error: "Monitor runtime is not available.",
207
+ });
208
+ }
209
+ return monitorRuntime.nudgeMonitor(request);
210
+ },
198
211
  stopMonitor(request) {
199
212
  if (monitorRuntime === null) {
200
213
  throw new Error("monitor_stop is only available in daemon mode");
@@ -1,5 +1,6 @@
1
1
  import type { McpToolResult } from "./receipt.js";
2
- import { parseJsonTextObject, type JsonObject } from "../contracts/json-object.js";
2
+ import type { JsonObject } from "../contracts/json-object.js";
3
+ import { parseJsonTextObject } from "../adapters/json-text-decoder.js";
3
4
  import { evaluateMcpPolicy } from "./policy.js";
4
5
  import { RefusedResult } from "../policy/types.js";
5
6
  import { OFFLOADED_DAEMON_REPO_TOOL_NAMES, type OffloadedRepoToolName } from "./repo-tool-job.js";
@@ -18,6 +19,7 @@ const daemonAlwaysAvailableTools = new Set<string>([
18
19
  "monitor_start",
19
20
  "monitor_pause",
20
21
  "monitor_resume",
22
+ "monitor_nudge",
21
23
  "monitor_stop",
22
24
  "workspace_authorize",
23
25
  "workspace_authorizations",
@@ -37,6 +39,7 @@ export const repoStateOptionalTools = new Set<string>([
37
39
  "monitor_start",
38
40
  "monitor_pause",
39
41
  "monitor_resume",
42
+ "monitor_nudge",
40
43
  "monitor_stop",
41
44
  "workspace_authorize",
42
45
  "workspace_authorizations",
package/src/mcp/server.ts CHANGED
@@ -10,6 +10,7 @@ import { CanonicalJsonCodec } from "../adapters/canonical-json.js";
10
10
  import { nodeProcessRunner } from "../adapters/node-process-runner.js";
11
11
  import type { ProcessRunner } from "../ports/process-runner.js";
12
12
  import { nodeGit } from "../adapters/node-git.js";
13
+ import type { GitClient } from "../ports/git.js";
13
14
  import { openWarp } from "../warp/open.js";
14
15
  import type { RunCaptureConfig } from "./run-capture-config.js";
15
16
  import { resolveRunCaptureConfig } from "./run-capture-config.js";
@@ -64,6 +65,8 @@ export interface CreateGraftServerOptions {
64
65
  daemonWorkerPool?: DaemonWorkerPool;
65
66
  daemonRuntime?: (() => DaemonRuntimeDescriptor) | undefined;
66
67
  processRunner?: ProcessRunner;
68
+ git?: GitClient;
69
+ persistedLocalHistoryGraph?: boolean;
67
70
  }
68
71
 
69
72
  export function createGraftServer(options: CreateGraftServerOptions = {}): GraftServer {
@@ -88,6 +91,7 @@ export function createGraftServer(options: CreateGraftServerOptions = {}): Graft
88
91
  ...(options.env !== undefined ? { env: options.env } : {}),
89
92
  ...(options.runtimeObservability !== undefined ? { overrides: options.runtimeObservability } : {}),
90
93
  });
94
+ const gitClient = options.git ?? nodeGit;
91
95
  const runtimeLogger = new RuntimeEventLogger({
92
96
  fs: nodeFs,
93
97
  codec,
@@ -107,7 +111,7 @@ export function createGraftServer(options: CreateGraftServerOptions = {}): Graft
107
111
  ? (options.daemonControlPlane ?? new DaemonControlPlane({
108
112
  fs: nodeFs,
109
113
  codec,
110
- git: nodeGit,
114
+ git: gitClient,
111
115
  graftDir,
112
116
  }))
113
117
  : null;
@@ -116,7 +120,7 @@ export function createGraftServer(options: CreateGraftServerOptions = {}): Graft
116
120
  : (options.monitorRuntime ?? new PersistentMonitorRuntime({
117
121
  fs: nodeFs,
118
122
  codec,
119
- git: nodeGit,
123
+ git: gitClient,
120
124
  graftDir,
121
125
  controlPlane: daemonControlPlane,
122
126
  scheduler: daemonScheduler,
@@ -139,7 +143,7 @@ export function createGraftServer(options: CreateGraftServerOptions = {}): Graft
139
143
  const workspaceRouter = new WorkspaceRouter({
140
144
  mode,
141
145
  fs: nodeFs,
142
- git: nodeGit,
146
+ git: gitClient,
143
147
  graftDir,
144
148
  ...(projectRoot !== undefined ? { projectRoot } : {}),
145
149
  warpPool,
@@ -148,6 +152,7 @@ export function createGraftServer(options: CreateGraftServerOptions = {}): Graft
148
152
  ...(daemonControlPlane !== null ? { authorizationPolicy: daemonControlPlane } : {}),
149
153
  ...(daemonControlPlane !== null ? { sharedAttachPolicy: daemonControlPlane } : {}),
150
154
  persistedLocalHistory,
155
+ persistedLocalHistoryGraph: options.persistedLocalHistoryGraph ?? true,
151
156
  });
152
157
  const daemonRepoOverview = daemonControlPlane !== null && monitorRuntime !== null
153
158
  ? new DaemonRepoOverview({