@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
@@ -0,0 +1,257 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Refactor Difficulty — curvature x friction over WARP facts
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { AggregateResult, QueryResultV1 } from "@git-stunts/git-warp";
6
+ import type { WarpContext } from "./context.js";
7
+ import { observeGraph } from "./context.js";
8
+ import { symbolTimeline, type SymbolVersion } from "./symbol-timeline.js";
9
+ import { countSymbolReferencesFromGraph } from "./warp-reference-count.js";
10
+
11
+ const CHANGE_EDGE_LABELS = ["adds", "changes", "removes"] as const;
12
+
13
+ export type RefactorDifficultyRisk = "low" | "medium" | "high";
14
+
15
+ export type RefactorDifficultyRecommendation =
16
+ | "refactor_freely"
17
+ | "refactor_with_tests"
18
+ | "plan_before_refactor";
19
+
20
+ export interface RefactorDifficultyOptions {
21
+ readonly symbol: string;
22
+ readonly path?: string | undefined;
23
+ readonly limit?: number | undefined;
24
+ }
25
+
26
+ export interface RefactorDifficultyAxis {
27
+ readonly score: number;
28
+ }
29
+
30
+ export interface RefactorDifficultyCurvature extends RefactorDifficultyAxis {
31
+ readonly changeCount: number;
32
+ readonly signatureChangeCount: number;
33
+ }
34
+
35
+ export interface RefactorDifficultyFriction extends RefactorDifficultyAxis {
36
+ readonly referenceCount: number;
37
+ readonly referencingFiles: readonly string[];
38
+ }
39
+
40
+ export interface RefactorDifficultyEntry {
41
+ readonly symbol: string;
42
+ readonly filePath: string;
43
+ readonly kind: string;
44
+ readonly score: number;
45
+ readonly risk: RefactorDifficultyRisk;
46
+ readonly recommendation: RefactorDifficultyRecommendation;
47
+ readonly curvature: RefactorDifficultyCurvature;
48
+ readonly friction: RefactorDifficultyFriction;
49
+ }
50
+
51
+ export interface RefactorDifficultyResult {
52
+ readonly symbol: string;
53
+ readonly path?: string | undefined;
54
+ readonly entries: readonly RefactorDifficultyEntry[];
55
+ readonly total: number;
56
+ readonly summary: string;
57
+ }
58
+
59
+ interface SymbolCandidate {
60
+ readonly id: string;
61
+ readonly symbol: string;
62
+ readonly filePath: string;
63
+ readonly kind: string;
64
+ }
65
+
66
+ export async function refactorDifficultyFromGraph(
67
+ ctx: WarpContext,
68
+ options: RefactorDifficultyOptions,
69
+ ): Promise<RefactorDifficultyResult> {
70
+ const symbol = options.symbol.trim();
71
+ if (symbol.length === 0) {
72
+ throw new Error("refactorDifficultyFromGraph: symbol must be non-empty");
73
+ }
74
+
75
+ const pathFilter = normalizeOptionalPath(options.path);
76
+ const limit = options.limit ?? 20;
77
+ const candidates = await findSymbolCandidates(ctx, symbol, pathFilter);
78
+ const entries = await Promise.all(
79
+ candidates.map((candidate) => scoreCandidate(ctx, candidate)),
80
+ );
81
+
82
+ const sorted = entries.sort(compareDifficultyEntries).slice(0, limit);
83
+ const top = sorted[0];
84
+ const summary = top === undefined
85
+ ? `No indexed symbols matched ${symbol}.`
86
+ : `${String(entries.length)} symbol matches. Highest difficulty: ${top.symbol} in ${top.filePath} (${String(top.score)}).`;
87
+
88
+ return {
89
+ symbol,
90
+ ...(pathFilter !== undefined ? { path: pathFilter } : {}),
91
+ entries: sorted,
92
+ total: entries.length,
93
+ summary,
94
+ };
95
+ }
96
+
97
+ async function findSymbolCandidates(
98
+ ctx: WarpContext,
99
+ symbol: string,
100
+ pathFilter: string | undefined,
101
+ ): Promise<SymbolCandidate[]> {
102
+ const obs = await observeGraph(ctx, {
103
+ match: "sym:*",
104
+ expose: ["name", "kind", "filePath"],
105
+ });
106
+
107
+ const result = await obs.query()
108
+ .match("sym:*")
109
+ .where((node) => {
110
+ const parsed = parseSymId(node.id);
111
+ if (parsed === null) return false;
112
+ if (!matchesPathFilter(parsed.filePath, pathFilter)) return false;
113
+
114
+ const propName = typeof node.props["name"] === "string" ? node.props["name"] : "";
115
+ return parsed.symbol === symbol || propName === symbol;
116
+ })
117
+ .select(["id", "props"])
118
+ .run() as QueryResultV1;
119
+
120
+ const candidates: SymbolCandidate[] = [];
121
+ for (const node of result.nodes) {
122
+ if (node.id === undefined) continue;
123
+ const parsed = parseSymId(node.id);
124
+ if (parsed === null) continue;
125
+
126
+ candidates.push({
127
+ id: node.id,
128
+ symbol: parsed.symbol,
129
+ filePath: parsed.filePath,
130
+ kind: typeof node.props?.["kind"] === "string" ? node.props["kind"] : "unknown",
131
+ });
132
+ }
133
+ return candidates;
134
+ }
135
+
136
+ async function scoreCandidate(
137
+ ctx: WarpContext,
138
+ candidate: SymbolCandidate,
139
+ ): Promise<RefactorDifficultyEntry> {
140
+ const [changeCount, timeline, references] = await Promise.all([
141
+ countSymbolTouches(ctx, candidate.id),
142
+ symbolTimeline(ctx, candidate.symbol, candidate.filePath),
143
+ countSymbolReferencesFromGraph(ctx, candidate.symbol, candidate.filePath),
144
+ ]);
145
+
146
+ const signatureChangeCount = countSignatureChanges(timeline.versions);
147
+ const curvatureScore = changeCount + signatureChangeCount;
148
+ const frictionScore = references.referenceCount;
149
+ const score = curvatureScore * frictionScore;
150
+
151
+ return {
152
+ symbol: candidate.symbol,
153
+ filePath: candidate.filePath,
154
+ kind: candidate.kind,
155
+ score,
156
+ risk: riskForScore(score),
157
+ recommendation: recommendationForScore(score),
158
+ curvature: {
159
+ changeCount,
160
+ signatureChangeCount,
161
+ score: curvatureScore,
162
+ },
163
+ friction: {
164
+ referenceCount: references.referenceCount,
165
+ referencingFiles: references.referencingFiles,
166
+ score: frictionScore,
167
+ },
168
+ };
169
+ }
170
+
171
+ async function countSymbolTouches(
172
+ ctx: WarpContext,
173
+ symId: string,
174
+ ): Promise<number> {
175
+ const obs = await observeGraph(ctx, {
176
+ match: ["commit:*", "sym:*"],
177
+ expose: ["tick"],
178
+ });
179
+
180
+ const counts = await Promise.all(CHANGE_EDGE_LABELS.map(async (label): Promise<number> => {
181
+ const result = await obs.query()
182
+ .match("commit:*")
183
+ .where((node) => node.edgesOut.some((edge) => edge.label === label && edge.to === symId))
184
+ .aggregate({ count: true })
185
+ .run() as AggregateResult;
186
+ return result.count ?? 0;
187
+ }));
188
+
189
+ return counts.reduce((sum, count) => sum + count, 0);
190
+ }
191
+
192
+ function countSignatureChanges(versions: readonly SymbolVersion[]): number {
193
+ let lastSignature: string | undefined;
194
+ let changes = 0;
195
+
196
+ for (const version of versions) {
197
+ if (version.signature === undefined) continue;
198
+ if (lastSignature === undefined) {
199
+ lastSignature = version.signature;
200
+ continue;
201
+ }
202
+ if (version.signature !== lastSignature) {
203
+ changes++;
204
+ lastSignature = version.signature;
205
+ }
206
+ }
207
+
208
+ return changes;
209
+ }
210
+
211
+ function riskForScore(score: number): RefactorDifficultyRisk {
212
+ if (score >= 12) return "high";
213
+ if (score >= 4) return "medium";
214
+ return "low";
215
+ }
216
+
217
+ function recommendationForScore(score: number): RefactorDifficultyRecommendation {
218
+ if (score >= 12) return "plan_before_refactor";
219
+ if (score >= 4) return "refactor_with_tests";
220
+ return "refactor_freely";
221
+ }
222
+
223
+ function compareDifficultyEntries(
224
+ left: RefactorDifficultyEntry,
225
+ right: RefactorDifficultyEntry,
226
+ ): number {
227
+ return right.score - left.score ||
228
+ right.curvature.score - left.curvature.score ||
229
+ right.friction.score - left.friction.score ||
230
+ left.filePath.localeCompare(right.filePath) ||
231
+ left.symbol.localeCompare(right.symbol);
232
+ }
233
+
234
+ function parseSymId(symId: string): { filePath: string; symbol: string } | null {
235
+ if (!symId.startsWith("sym:")) return null;
236
+
237
+ const withoutPrefix = symId.slice("sym:".length);
238
+ const lastColon = withoutPrefix.lastIndexOf(":");
239
+ if (lastColon === -1) return null;
240
+
241
+ return {
242
+ filePath: withoutPrefix.slice(0, lastColon),
243
+ symbol: withoutPrefix.slice(lastColon + 1),
244
+ };
245
+ }
246
+
247
+ function normalizeOptionalPath(path: string | undefined): string | undefined {
248
+ if (path === undefined) return undefined;
249
+ const trimmed = path.trim();
250
+ return trimmed.length > 0 ? trimmed : undefined;
251
+ }
252
+
253
+ function matchesPathFilter(filePath: string, pathFilter: string | undefined): boolean {
254
+ return pathFilter === undefined ||
255
+ filePath === pathFilter ||
256
+ filePath.startsWith(`${pathFilter}/`);
257
+ }
@@ -0,0 +1,77 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Symbol reference queries — find what depends on a symbol via the WARP graph
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { QueryResultV1 } from "@git-stunts/git-warp";
6
+ import type { WarpContext } from "./context.js";
7
+ import { observeGraph } from "./context.js";
8
+
9
+ export interface SymbolReference {
10
+ readonly filePath: string;
11
+ readonly importedName: string;
12
+ readonly localName: string;
13
+ }
14
+
15
+ /**
16
+ * Find all files that reference a symbol, by querying the WARP graph's
17
+ * cross-file import resolution edges.
18
+ *
19
+ * Uses traverse.bfs for edge discovery (substrate-side) and QueryBuilder
20
+ * for batch prop reads. No getEdges() — never assumes all edges fit in
21
+ * memory.
22
+ *
23
+ * For named symbols: finds import_specifier/export_specifier nodes that
24
+ * have a `references` edge pointing at `sym:<filePath>:<symbolName>`.
25
+ *
26
+ * For namespace imports ("*"): finds namespace_import nodes that have a
27
+ * `references` edge pointing at `file:<filePath>`.
28
+ */
29
+ export async function referencesForSymbol(
30
+ ctx: WarpContext,
31
+ symbolName: string,
32
+ filePath: string,
33
+ ): Promise<SymbolReference[]> {
34
+ const obs = await observeGraph(ctx, { match: ["ast:*", "file:*", "sym:*"] });
35
+
36
+ // Determine the target node ID
37
+ const targetId = symbolName === "*"
38
+ ? `file:${filePath}`
39
+ : `sym:${filePath}:${symbolName}`;
40
+
41
+ // Guard: target must exist for traverse to work.
42
+ const targetExists = await obs.hasNode(targetId);
43
+ if (!targetExists) return [];
44
+
45
+ // Traverse: find AST nodes with incoming `references` edges to the target.
46
+ const referrerIds = await obs.traverse.bfs(targetId, {
47
+ dir: "in",
48
+ labelFilter: "references",
49
+ maxDepth: 1,
50
+ });
51
+
52
+ const astReferrerIds = referrerIds.filter((id) => id.startsWith("ast:"));
53
+ if (astReferrerIds.length === 0) return [];
54
+
55
+ // Batch prop read for all referencing nodes.
56
+ const propsResult = await obs.query()
57
+ .match(astReferrerIds)
58
+ .select(["id", "props"])
59
+ .run() as QueryResultV1;
60
+
61
+ const results: SymbolReference[] = [];
62
+
63
+ for (const node of propsResult.nodes) {
64
+ if (node.id === undefined) continue;
65
+ const props = node.props ?? {};
66
+
67
+ const importedName = typeof props["importedName"] === "string" ? props["importedName"] : symbolName;
68
+ const localName = typeof props["localName"] === "string" ? props["localName"] : importedName;
69
+ const nodeFilePath = typeof props["filePath"] === "string" ? props["filePath"] : null;
70
+
71
+ if (nodeFilePath !== null) {
72
+ results.push({ filePath: nodeFilePath, importedName, localName });
73
+ }
74
+ }
75
+
76
+ return results;
77
+ }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Stale Docs Checker — cross-references doc symbol mentions against
3
+ * the WARP graph to detect documentation that may be outdated.
4
+ *
5
+ * Walks markdown for backtick-quoted identifiers and code block
6
+ * contents. For each referenced symbol, queries the WARP graph to
7
+ * determine whether the symbol changed after the doc was last modified.
8
+ *
9
+ * Also detects version number drift between package.json and CHANGELOG.
10
+ */
11
+
12
+ import type { WarpContext } from "./context.js";
13
+ import { symbolTimeline } from "./symbol-timeline.js";
14
+ import { observeGraph } from "./context.js";
15
+
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Types
19
+ // ---------------------------------------------------------------------------
20
+
21
+ /** A symbol in a doc that is stale relative to the WARP graph. */
22
+ export interface StaleSymbolEntry {
23
+ readonly symbol: string;
24
+ readonly changeKind: "changed" | "removed";
25
+ readonly lastChangeSha: string;
26
+ }
27
+
28
+ /** Result of checking a single doc for staleness. */
29
+ export interface StaleDocReport {
30
+ readonly docPath: string;
31
+ /** Symbols referenced in the doc that changed after the doc was last modified. */
32
+ readonly staleSymbols: readonly StaleSymbolEntry[];
33
+ /** Symbols referenced in the doc that do not exist in the WARP graph. */
34
+ readonly unknownSymbols: readonly string[];
35
+ }
36
+
37
+ /** Result of checking version drift between package.json and CHANGELOG. */
38
+ export interface VersionDriftReport {
39
+ readonly drifted: boolean;
40
+ readonly packageVersion: string;
41
+ readonly changelogVersion: string | null;
42
+ }
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // Symbol extraction
46
+ // ---------------------------------------------------------------------------
47
+
48
+ /** Match single-backtick content that looks like an identifier (no spaces, no dots). */
49
+ const INLINE_CODE_RE = /`([A-Za-z_$][A-Za-z0-9_$]*)`/g;
50
+
51
+ /**
52
+ * Match identifiers inside fenced code blocks.
53
+ * We look for function/class/const/let/var/type/interface/import declarations
54
+ * and bare identifiers that look like symbol names.
55
+ */
56
+ const CODE_BLOCK_RE = /```[\s\S]*?```/g;
57
+
58
+ /**
59
+ * Inside code blocks, match identifiers from destructured imports/exports
60
+ * and direct declarations.
61
+ */
62
+ const CODE_BLOCK_DECL_RE =
63
+ /(?:import|export|function|class|const|let|var|type|interface)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
64
+
65
+ /**
66
+ * Match identifiers inside braces of import/export destructuring.
67
+ * e.g. import { evaluatePolicy, runCheck } from '...'
68
+ */
69
+ const DESTRUCTURE_RE = /(?:import|export)\s+\{([^}]+)\}/g;
70
+ const DESTRUCTURE_IDENT_RE = /([A-Za-z_$][A-Za-z0-9_$]*)/g;
71
+
72
+ /**
73
+ * Extract symbol name references from markdown content.
74
+ *
75
+ * Sources:
76
+ * 1. Backtick-quoted identifiers (single backtick, must be valid JS/TS identifier)
77
+ * 2. Declaration identifiers inside fenced code blocks
78
+ *
79
+ * Returns a deduplicated array of symbol names.
80
+ */
81
+ export function extractDocSymbolReferences(markdown: string): string[] {
82
+ const symbols = new Set<string>();
83
+
84
+ // 1. Inline backtick identifiers
85
+ let match: RegExpExecArray | null;
86
+ while ((match = INLINE_CODE_RE.exec(markdown)) !== null) {
87
+ if (match[1] !== undefined) symbols.add(match[1]);
88
+ }
89
+
90
+ // 2. Identifiers inside fenced code blocks
91
+ for (const blockMatch of markdown.matchAll(CODE_BLOCK_RE)) {
92
+ const block = blockMatch[0];
93
+
94
+ // Direct declarations: function foo, class Bar, etc.
95
+ while ((match = CODE_BLOCK_DECL_RE.exec(block)) !== null) {
96
+ if (match[1] !== undefined) symbols.add(match[1]);
97
+ }
98
+
99
+ // Destructured imports/exports: import { foo, bar } from ...
100
+ for (const destructMatch of block.matchAll(DESTRUCTURE_RE)) {
101
+ const inner = destructMatch[1];
102
+ if (inner === undefined) continue;
103
+ let identMatch: RegExpExecArray | null;
104
+ while ((identMatch = DESTRUCTURE_IDENT_RE.exec(inner)) !== null) {
105
+ // Skip "as" keyword in "foo as bar" patterns — keep both identifiers
106
+ const identifier = identMatch[1];
107
+ if (identifier !== undefined && identifier !== "as") {
108
+ symbols.add(identifier);
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ return [...symbols];
115
+ }
116
+
117
+ // ---------------------------------------------------------------------------
118
+ // Stale doc check
119
+ // ---------------------------------------------------------------------------
120
+
121
+ /**
122
+ * Resolve the tick (lamport clock) for a given commit SHA.
123
+ * Returns null if the commit is not in the graph.
124
+ */
125
+ async function getCommitTick(
126
+ ctx: WarpContext,
127
+ sha: string,
128
+ ): Promise<number | null> {
129
+ const obs = await observeGraph(ctx, { match: "commit:*", expose: ["sha", "tick"] });
130
+ const props = await obs.getNodeProps(`commit:${sha}`);
131
+ return typeof props?.["tick"] === "number" ? props["tick"] : null;
132
+ }
133
+
134
+ /**
135
+ * Check a markdown document for stale symbol references.
136
+ *
137
+ * @param ctx - WARP context
138
+ * @param docPath - relative path of the doc (for the report)
139
+ * @param docCommitSha - SHA of the commit when the doc was last modified
140
+ * @param docContent - raw markdown content of the doc
141
+ */
142
+ export async function checkStaleDocs(
143
+ ctx: WarpContext,
144
+ docPath: string,
145
+ docCommitSha: string,
146
+ docContent: string,
147
+ ): Promise<StaleDocReport> {
148
+ const symbolNames = extractDocSymbolReferences(docContent);
149
+ const docTick = await getCommitTick(ctx, docCommitSha);
150
+
151
+ const staleSymbols: StaleSymbolEntry[] = [];
152
+ const unknownSymbols: string[] = [];
153
+
154
+ for (const symbolName of symbolNames) {
155
+ const timeline = await symbolTimeline(ctx, symbolName);
156
+
157
+ if (timeline.versions.length === 0) {
158
+ unknownSymbols.push(symbolName);
159
+ continue;
160
+ }
161
+
162
+ // If we cannot resolve the doc commit tick, we cannot compare —
163
+ // treat the doc as fresh (conservative).
164
+ if (docTick === null) continue;
165
+
166
+ // Check if any version has a tick after the doc's commit tick.
167
+ // symbolTimeline returns versions in tick order with accurate
168
+ // per-commit data (unlike commitsForSymbol which returns HEAD
169
+ // signature for all entries).
170
+ for (const version of timeline.versions) {
171
+ if (version.tick > docTick) {
172
+ if (version.changeKind === "changed" || version.changeKind === "removed") {
173
+ staleSymbols.push({
174
+ symbol: symbolName,
175
+ changeKind: version.changeKind,
176
+ lastChangeSha: version.sha,
177
+ });
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ return { docPath, staleSymbols, unknownSymbols };
185
+ }
186
+
187
+ // ---------------------------------------------------------------------------
188
+ // Version drift check
189
+ // ---------------------------------------------------------------------------
190
+
191
+ /** Match the first semver-looking heading in a CHANGELOG. */
192
+ const CHANGELOG_VERSION_RE = /^##\s+\[?v?(\d+\.\d+\.\d+(?:-[A-Za-z0-9.]+)?)\]?/m;
193
+
194
+ /**
195
+ * Check whether the latest version in a CHANGELOG matches
196
+ * the version in package.json.
197
+ */
198
+ export function checkVersionDrift(
199
+ packageVersion: string,
200
+ changelogContent: string,
201
+ ): VersionDriftReport {
202
+ const match = CHANGELOG_VERSION_RE.exec(changelogContent);
203
+ const changelogVersion = match?.[1] ?? null;
204
+
205
+ return {
206
+ drifted: changelogVersion !== packageVersion,
207
+ packageVersion,
208
+ changelogVersion,
209
+ };
210
+ }
@@ -0,0 +1,97 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Structural Drift Detection — verify doc claims against reality
3
+ // ---------------------------------------------------------------------------
4
+
5
+ /** Result of checking a single drift rule. */
6
+ export interface DriftResult {
7
+ readonly drifted: boolean;
8
+ readonly docPath: string;
9
+ readonly claim: string;
10
+ readonly expected: string;
11
+ readonly actual: string;
12
+ }
13
+
14
+ /** Options for numeric claim checking. */
15
+ export interface NumericClaimOptions {
16
+ readonly docPath: string;
17
+ /** The text containing the numeric claim (e.g., "12 MCP tools"). */
18
+ readonly claim: string;
19
+ /** Regex with a capture group for the number. */
20
+ readonly pattern: RegExp;
21
+ /** The actual count from reality. */
22
+ readonly actual: number;
23
+ }
24
+
25
+ /**
26
+ * Check whether a numeric claim in a doc matches reality.
27
+ *
28
+ * Parses the claim text with the given pattern to extract the stated
29
+ * number, then compares against the actual count.
30
+ */
31
+ export function checkNumericClaim(options: NumericClaimOptions): DriftResult {
32
+ const { docPath, claim, pattern, actual } = options;
33
+ const match = pattern.exec(claim);
34
+
35
+ if (match?.[1] === undefined) {
36
+ return {
37
+ drifted: true,
38
+ docPath,
39
+ claim,
40
+ expected: "no match",
41
+ actual: String(actual),
42
+ };
43
+ }
44
+
45
+ const stated = parseInt(match[1], 10);
46
+ return {
47
+ drifted: stated !== actual,
48
+ docPath,
49
+ claim,
50
+ expected: match[1],
51
+ actual: String(actual),
52
+ };
53
+ }
54
+
55
+ /** Result of checking a pattern prohibition. */
56
+ export interface PatternProhibitionResult {
57
+ readonly drifted: boolean;
58
+ readonly docPath: string;
59
+ readonly rule: string;
60
+ readonly violations: readonly string[];
61
+ }
62
+
63
+ /** Options for pattern prohibition checking. */
64
+ export interface PatternProhibitionOptions {
65
+ readonly docPath: string;
66
+ /** Human-readable description of the rule (e.g., "no getNodes calls in src/"). */
67
+ readonly rule: string;
68
+ /** Regex to search for in file contents. */
69
+ readonly pattern: RegExp;
70
+ /** Map of file path → content to check. */
71
+ readonly files: Readonly<Record<string, string>>;
72
+ }
73
+
74
+ /**
75
+ * Check whether a prohibited pattern appears in any of the given files.
76
+ *
77
+ * Returns the list of files that violate the prohibition.
78
+ */
79
+ export function checkPatternProhibition(
80
+ options: PatternProhibitionOptions,
81
+ ): PatternProhibitionResult {
82
+ const { docPath, rule, pattern, files } = options;
83
+ const violations: string[] = [];
84
+
85
+ for (const [filePath, content] of Object.entries(files)) {
86
+ if (pattern.test(content)) {
87
+ violations.push(filePath);
88
+ }
89
+ }
90
+
91
+ return {
92
+ drifted: violations.length > 0,
93
+ docPath,
94
+ rule,
95
+ violations,
96
+ };
97
+ }