@selvakumaresra/specship 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/agents/specship-explorer.md +29 -0
  5. package/commands/cg-drifted.md +23 -0
  6. package/commands/cg-explore.md +13 -0
  7. package/commands/cg-fix.md +21 -0
  8. package/commands/cg-impact.md +13 -0
  9. package/commands/cg-implement.md +23 -0
  10. package/commands/cg-relink.md +21 -0
  11. package/commands/cg-spec.md +19 -0
  12. package/commands/cg-sync.md +8 -0
  13. package/commands/cg-trace.md +13 -0
  14. package/dist/bin/node-version-check.d.ts +37 -0
  15. package/dist/bin/node-version-check.d.ts.map +1 -0
  16. package/dist/bin/node-version-check.js +79 -0
  17. package/dist/bin/node-version-check.js.map +1 -0
  18. package/dist/bin/specship.d.ts +25 -0
  19. package/dist/bin/specship.d.ts.map +1 -0
  20. package/dist/bin/specship.js +2018 -0
  21. package/dist/bin/specship.js.map +1 -0
  22. package/dist/bin/uninstall.d.ts +13 -0
  23. package/dist/bin/uninstall.d.ts.map +1 -0
  24. package/dist/bin/uninstall.js +35 -0
  25. package/dist/bin/uninstall.js.map +1 -0
  26. package/dist/context/formatter.d.ts +30 -0
  27. package/dist/context/formatter.d.ts.map +1 -0
  28. package/dist/context/formatter.js +263 -0
  29. package/dist/context/formatter.js.map +1 -0
  30. package/dist/context/index.d.ts +119 -0
  31. package/dist/context/index.d.ts.map +1 -0
  32. package/dist/context/index.js +1289 -0
  33. package/dist/context/index.js.map +1 -0
  34. package/dist/context/markers.d.ts +19 -0
  35. package/dist/context/markers.d.ts.map +1 -0
  36. package/dist/context/markers.js +22 -0
  37. package/dist/context/markers.js.map +1 -0
  38. package/dist/db/index.d.ts +101 -0
  39. package/dist/db/index.d.ts.map +1 -0
  40. package/dist/db/index.js +276 -0
  41. package/dist/db/index.js.map +1 -0
  42. package/dist/db/migrations.d.ts +44 -0
  43. package/dist/db/migrations.d.ts.map +1 -0
  44. package/dist/db/migrations.js +427 -0
  45. package/dist/db/migrations.js.map +1 -0
  46. package/dist/db/queries.d.ts +357 -0
  47. package/dist/db/queries.d.ts.map +1 -0
  48. package/dist/db/queries.js +1504 -0
  49. package/dist/db/queries.js.map +1 -0
  50. package/dist/db/schema.sql +410 -0
  51. package/dist/db/spec-queries.d.ts +101 -0
  52. package/dist/db/spec-queries.d.ts.map +1 -0
  53. package/dist/db/spec-queries.js +675 -0
  54. package/dist/db/spec-queries.js.map +1 -0
  55. package/dist/db/sqlite-adapter.d.ts +65 -0
  56. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  57. package/dist/db/sqlite-adapter.js +214 -0
  58. package/dist/db/sqlite-adapter.js.map +1 -0
  59. package/dist/directory.d.ts +57 -0
  60. package/dist/directory.d.ts.map +1 -0
  61. package/dist/directory.js +253 -0
  62. package/dist/directory.js.map +1 -0
  63. package/dist/errors.d.ts +136 -0
  64. package/dist/errors.d.ts.map +1 -0
  65. package/dist/errors.js +219 -0
  66. package/dist/errors.js.map +1 -0
  67. package/dist/extraction/dfm-extractor.d.ts +31 -0
  68. package/dist/extraction/dfm-extractor.d.ts.map +1 -0
  69. package/dist/extraction/dfm-extractor.js +151 -0
  70. package/dist/extraction/dfm-extractor.js.map +1 -0
  71. package/dist/extraction/generated-detection.d.ts +30 -0
  72. package/dist/extraction/generated-detection.d.ts.map +1 -0
  73. package/dist/extraction/generated-detection.js +80 -0
  74. package/dist/extraction/generated-detection.js.map +1 -0
  75. package/dist/extraction/grammars.d.ts +100 -0
  76. package/dist/extraction/grammars.d.ts.map +1 -0
  77. package/dist/extraction/grammars.js +426 -0
  78. package/dist/extraction/grammars.js.map +1 -0
  79. package/dist/extraction/index.d.ts +138 -0
  80. package/dist/extraction/index.d.ts.map +1 -0
  81. package/dist/extraction/index.js +1394 -0
  82. package/dist/extraction/index.js.map +1 -0
  83. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  84. package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  85. package/dist/extraction/languages/c-cpp.js +171 -0
  86. package/dist/extraction/languages/c-cpp.js.map +1 -0
  87. package/dist/extraction/languages/csharp.d.ts +3 -0
  88. package/dist/extraction/languages/csharp.d.ts.map +1 -0
  89. package/dist/extraction/languages/csharp.js +73 -0
  90. package/dist/extraction/languages/csharp.js.map +1 -0
  91. package/dist/extraction/languages/dart.d.ts +3 -0
  92. package/dist/extraction/languages/dart.d.ts.map +1 -0
  93. package/dist/extraction/languages/dart.js +192 -0
  94. package/dist/extraction/languages/dart.js.map +1 -0
  95. package/dist/extraction/languages/go.d.ts +3 -0
  96. package/dist/extraction/languages/go.d.ts.map +1 -0
  97. package/dist/extraction/languages/go.js +74 -0
  98. package/dist/extraction/languages/go.js.map +1 -0
  99. package/dist/extraction/languages/index.d.ts +10 -0
  100. package/dist/extraction/languages/index.d.ts.map +1 -0
  101. package/dist/extraction/languages/index.js +51 -0
  102. package/dist/extraction/languages/index.js.map +1 -0
  103. package/dist/extraction/languages/java.d.ts +3 -0
  104. package/dist/extraction/languages/java.d.ts.map +1 -0
  105. package/dist/extraction/languages/java.js +70 -0
  106. package/dist/extraction/languages/java.js.map +1 -0
  107. package/dist/extraction/languages/javascript.d.ts +3 -0
  108. package/dist/extraction/languages/javascript.d.ts.map +1 -0
  109. package/dist/extraction/languages/javascript.js +90 -0
  110. package/dist/extraction/languages/javascript.js.map +1 -0
  111. package/dist/extraction/languages/kotlin.d.ts +3 -0
  112. package/dist/extraction/languages/kotlin.d.ts.map +1 -0
  113. package/dist/extraction/languages/kotlin.js +259 -0
  114. package/dist/extraction/languages/kotlin.js.map +1 -0
  115. package/dist/extraction/languages/lua.d.ts +3 -0
  116. package/dist/extraction/languages/lua.d.ts.map +1 -0
  117. package/dist/extraction/languages/lua.js +150 -0
  118. package/dist/extraction/languages/lua.js.map +1 -0
  119. package/dist/extraction/languages/luau.d.ts +3 -0
  120. package/dist/extraction/languages/luau.d.ts.map +1 -0
  121. package/dist/extraction/languages/luau.js +37 -0
  122. package/dist/extraction/languages/luau.js.map +1 -0
  123. package/dist/extraction/languages/objc.d.ts +3 -0
  124. package/dist/extraction/languages/objc.d.ts.map +1 -0
  125. package/dist/extraction/languages/objc.js +133 -0
  126. package/dist/extraction/languages/objc.js.map +1 -0
  127. package/dist/extraction/languages/pascal.d.ts +3 -0
  128. package/dist/extraction/languages/pascal.d.ts.map +1 -0
  129. package/dist/extraction/languages/pascal.js +66 -0
  130. package/dist/extraction/languages/pascal.js.map +1 -0
  131. package/dist/extraction/languages/php.d.ts +3 -0
  132. package/dist/extraction/languages/php.d.ts.map +1 -0
  133. package/dist/extraction/languages/php.js +107 -0
  134. package/dist/extraction/languages/php.js.map +1 -0
  135. package/dist/extraction/languages/python.d.ts +3 -0
  136. package/dist/extraction/languages/python.d.ts.map +1 -0
  137. package/dist/extraction/languages/python.js +56 -0
  138. package/dist/extraction/languages/python.js.map +1 -0
  139. package/dist/extraction/languages/ruby.d.ts +3 -0
  140. package/dist/extraction/languages/ruby.d.ts.map +1 -0
  141. package/dist/extraction/languages/ruby.js +114 -0
  142. package/dist/extraction/languages/ruby.js.map +1 -0
  143. package/dist/extraction/languages/rust.d.ts +3 -0
  144. package/dist/extraction/languages/rust.d.ts.map +1 -0
  145. package/dist/extraction/languages/rust.js +109 -0
  146. package/dist/extraction/languages/rust.js.map +1 -0
  147. package/dist/extraction/languages/scala.d.ts +3 -0
  148. package/dist/extraction/languages/scala.d.ts.map +1 -0
  149. package/dist/extraction/languages/scala.js +139 -0
  150. package/dist/extraction/languages/scala.js.map +1 -0
  151. package/dist/extraction/languages/swift.d.ts +3 -0
  152. package/dist/extraction/languages/swift.d.ts.map +1 -0
  153. package/dist/extraction/languages/swift.js +91 -0
  154. package/dist/extraction/languages/swift.js.map +1 -0
  155. package/dist/extraction/languages/typescript.d.ts +3 -0
  156. package/dist/extraction/languages/typescript.d.ts.map +1 -0
  157. package/dist/extraction/languages/typescript.js +129 -0
  158. package/dist/extraction/languages/typescript.js.map +1 -0
  159. package/dist/extraction/liquid-extractor.d.ts +52 -0
  160. package/dist/extraction/liquid-extractor.d.ts.map +1 -0
  161. package/dist/extraction/liquid-extractor.js +313 -0
  162. package/dist/extraction/liquid-extractor.js.map +1 -0
  163. package/dist/extraction/mybatis-extractor.d.ts +48 -0
  164. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  165. package/dist/extraction/mybatis-extractor.js +198 -0
  166. package/dist/extraction/mybatis-extractor.js.map +1 -0
  167. package/dist/extraction/parse-worker.d.ts +8 -0
  168. package/dist/extraction/parse-worker.d.ts.map +1 -0
  169. package/dist/extraction/parse-worker.js +94 -0
  170. package/dist/extraction/parse-worker.js.map +1 -0
  171. package/dist/extraction/specs/markdown-spec-extractor.d.ts +59 -0
  172. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -0
  173. package/dist/extraction/specs/markdown-spec-extractor.js +327 -0
  174. package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -0
  175. package/dist/extraction/specs/types.d.ts +39 -0
  176. package/dist/extraction/specs/types.d.ts.map +1 -0
  177. package/dist/extraction/specs/types.js +8 -0
  178. package/dist/extraction/specs/types.js.map +1 -0
  179. package/dist/extraction/svelte-extractor.d.ts +56 -0
  180. package/dist/extraction/svelte-extractor.d.ts.map +1 -0
  181. package/dist/extraction/svelte-extractor.js +272 -0
  182. package/dist/extraction/svelte-extractor.js.map +1 -0
  183. package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
  184. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  185. package/dist/extraction/tree-sitter-helpers.js +103 -0
  186. package/dist/extraction/tree-sitter-helpers.js.map +1 -0
  187. package/dist/extraction/tree-sitter-types.d.ts +193 -0
  188. package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  189. package/dist/extraction/tree-sitter-types.js +10 -0
  190. package/dist/extraction/tree-sitter-types.js.map +1 -0
  191. package/dist/extraction/tree-sitter.d.ts +317 -0
  192. package/dist/extraction/tree-sitter.d.ts.map +1 -0
  193. package/dist/extraction/tree-sitter.js +3092 -0
  194. package/dist/extraction/tree-sitter.js.map +1 -0
  195. package/dist/extraction/vue-extractor.d.ts +51 -0
  196. package/dist/extraction/vue-extractor.d.ts.map +1 -0
  197. package/dist/extraction/vue-extractor.js +251 -0
  198. package/dist/extraction/vue-extractor.js.map +1 -0
  199. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  200. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  201. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  202. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  203. package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  204. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  205. package/dist/extraction/wasm-runtime-flags.js +106 -0
  206. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  207. package/dist/graph/index.d.ts +8 -0
  208. package/dist/graph/index.d.ts.map +1 -0
  209. package/dist/graph/index.js +13 -0
  210. package/dist/graph/index.js.map +1 -0
  211. package/dist/graph/queries.d.ts +106 -0
  212. package/dist/graph/queries.d.ts.map +1 -0
  213. package/dist/graph/queries.js +366 -0
  214. package/dist/graph/queries.js.map +1 -0
  215. package/dist/graph/traversal.d.ts +127 -0
  216. package/dist/graph/traversal.d.ts.map +1 -0
  217. package/dist/graph/traversal.js +531 -0
  218. package/dist/graph/traversal.js.map +1 -0
  219. package/dist/index.d.ts +551 -0
  220. package/dist/index.d.ts.map +1 -0
  221. package/dist/index.js +1165 -0
  222. package/dist/index.js.map +1 -0
  223. package/dist/installer/config-writer.d.ts +28 -0
  224. package/dist/installer/config-writer.d.ts.map +1 -0
  225. package/dist/installer/config-writer.js +91 -0
  226. package/dist/installer/config-writer.js.map +1 -0
  227. package/dist/installer/index.d.ts +87 -0
  228. package/dist/installer/index.d.ts.map +1 -0
  229. package/dist/installer/index.js +409 -0
  230. package/dist/installer/index.js.map +1 -0
  231. package/dist/installer/instructions-template.d.ts +18 -0
  232. package/dist/installer/instructions-template.d.ts.map +1 -0
  233. package/dist/installer/instructions-template.js +21 -0
  234. package/dist/installer/instructions-template.js.map +1 -0
  235. package/dist/installer/targets/claude.d.ts +88 -0
  236. package/dist/installer/targets/claude.d.ts.map +1 -0
  237. package/dist/installer/targets/claude.js +582 -0
  238. package/dist/installer/targets/claude.js.map +1 -0
  239. package/dist/installer/targets/registry.d.ts +19 -0
  240. package/dist/installer/targets/registry.d.ts.map +1 -0
  241. package/dist/installer/targets/registry.js +31 -0
  242. package/dist/installer/targets/registry.js.map +1 -0
  243. package/dist/installer/targets/shared.d.ts +62 -0
  244. package/dist/installer/targets/shared.d.ts.map +1 -0
  245. package/dist/installer/targets/shared.js +207 -0
  246. package/dist/installer/targets/shared.js.map +1 -0
  247. package/dist/installer/targets/types.d.ts +76 -0
  248. package/dist/installer/targets/types.d.ts.map +1 -0
  249. package/dist/installer/targets/types.js +12 -0
  250. package/dist/installer/targets/types.js.map +1 -0
  251. package/dist/isolation/worktree.d.ts +65 -0
  252. package/dist/isolation/worktree.d.ts.map +1 -0
  253. package/dist/isolation/worktree.js +231 -0
  254. package/dist/isolation/worktree.js.map +1 -0
  255. package/dist/mcp/daemon-paths.d.ts +46 -0
  256. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  257. package/dist/mcp/daemon-paths.js +125 -0
  258. package/dist/mcp/daemon-paths.js.map +1 -0
  259. package/dist/mcp/daemon.d.ts +161 -0
  260. package/dist/mcp/daemon.d.ts.map +1 -0
  261. package/dist/mcp/daemon.js +403 -0
  262. package/dist/mcp/daemon.js.map +1 -0
  263. package/dist/mcp/engine.d.ts +105 -0
  264. package/dist/mcp/engine.d.ts.map +1 -0
  265. package/dist/mcp/engine.js +270 -0
  266. package/dist/mcp/engine.js.map +1 -0
  267. package/dist/mcp/index.d.ts +112 -0
  268. package/dist/mcp/index.d.ts.map +1 -0
  269. package/dist/mcp/index.js +477 -0
  270. package/dist/mcp/index.js.map +1 -0
  271. package/dist/mcp/proxy.d.ts +81 -0
  272. package/dist/mcp/proxy.d.ts.map +1 -0
  273. package/dist/mcp/proxy.js +510 -0
  274. package/dist/mcp/proxy.js.map +1 -0
  275. package/dist/mcp/server-instructions.d.ts +18 -0
  276. package/dist/mcp/server-instructions.d.ts.map +1 -0
  277. package/dist/mcp/server-instructions.js +77 -0
  278. package/dist/mcp/server-instructions.js.map +1 -0
  279. package/dist/mcp/session.d.ts +77 -0
  280. package/dist/mcp/session.d.ts.map +1 -0
  281. package/dist/mcp/session.js +294 -0
  282. package/dist/mcp/session.js.map +1 -0
  283. package/dist/mcp/spec-tools.d.ts +39 -0
  284. package/dist/mcp/spec-tools.d.ts.map +1 -0
  285. package/dist/mcp/spec-tools.js +326 -0
  286. package/dist/mcp/spec-tools.js.map +1 -0
  287. package/dist/mcp/tools.d.ts +404 -0
  288. package/dist/mcp/tools.d.ts.map +1 -0
  289. package/dist/mcp/tools.js +3066 -0
  290. package/dist/mcp/tools.js.map +1 -0
  291. package/dist/mcp/transport.d.ts +188 -0
  292. package/dist/mcp/transport.d.ts.map +1 -0
  293. package/dist/mcp/transport.js +343 -0
  294. package/dist/mcp/transport.js.map +1 -0
  295. package/dist/mcp/version.d.ts +19 -0
  296. package/dist/mcp/version.d.ts.map +1 -0
  297. package/dist/mcp/version.js +71 -0
  298. package/dist/mcp/version.js.map +1 -0
  299. package/dist/resolution/callback-synthesizer.d.ts +10 -0
  300. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  301. package/dist/resolution/callback-synthesizer.js +1300 -0
  302. package/dist/resolution/callback-synthesizer.js.map +1 -0
  303. package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  304. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  305. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  306. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  307. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  308. package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  309. package/dist/resolution/frameworks/csharp.js +241 -0
  310. package/dist/resolution/frameworks/csharp.js.map +1 -0
  311. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  312. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  313. package/dist/resolution/frameworks/drupal.js +367 -0
  314. package/dist/resolution/frameworks/drupal.js.map +1 -0
  315. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  316. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  317. package/dist/resolution/frameworks/expo-modules.js +143 -0
  318. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  319. package/dist/resolution/frameworks/express.d.ts +8 -0
  320. package/dist/resolution/frameworks/express.d.ts.map +1 -0
  321. package/dist/resolution/frameworks/express.js +308 -0
  322. package/dist/resolution/frameworks/express.js.map +1 -0
  323. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  324. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  325. package/dist/resolution/frameworks/fabric.js +354 -0
  326. package/dist/resolution/frameworks/fabric.js.map +1 -0
  327. package/dist/resolution/frameworks/go.d.ts +8 -0
  328. package/dist/resolution/frameworks/go.d.ts.map +1 -0
  329. package/dist/resolution/frameworks/go.js +161 -0
  330. package/dist/resolution/frameworks/go.js.map +1 -0
  331. package/dist/resolution/frameworks/index.d.ts +48 -0
  332. package/dist/resolution/frameworks/index.d.ts.map +1 -0
  333. package/dist/resolution/frameworks/index.js +161 -0
  334. package/dist/resolution/frameworks/index.js.map +1 -0
  335. package/dist/resolution/frameworks/java.d.ts +8 -0
  336. package/dist/resolution/frameworks/java.d.ts.map +1 -0
  337. package/dist/resolution/frameworks/java.js +504 -0
  338. package/dist/resolution/frameworks/java.js.map +1 -0
  339. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  340. package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  341. package/dist/resolution/frameworks/laravel.js +257 -0
  342. package/dist/resolution/frameworks/laravel.js.map +1 -0
  343. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  344. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  345. package/dist/resolution/frameworks/nestjs.js +698 -0
  346. package/dist/resolution/frameworks/nestjs.js.map +1 -0
  347. package/dist/resolution/frameworks/play.d.ts +19 -0
  348. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  349. package/dist/resolution/frameworks/play.js +111 -0
  350. package/dist/resolution/frameworks/play.js.map +1 -0
  351. package/dist/resolution/frameworks/python.d.ts +10 -0
  352. package/dist/resolution/frameworks/python.d.ts.map +1 -0
  353. package/dist/resolution/frameworks/python.js +396 -0
  354. package/dist/resolution/frameworks/python.js.map +1 -0
  355. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  356. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  357. package/dist/resolution/frameworks/react-native.js +360 -0
  358. package/dist/resolution/frameworks/react-native.js.map +1 -0
  359. package/dist/resolution/frameworks/react.d.ts +8 -0
  360. package/dist/resolution/frameworks/react.d.ts.map +1 -0
  361. package/dist/resolution/frameworks/react.js +365 -0
  362. package/dist/resolution/frameworks/react.js.map +1 -0
  363. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  364. package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  365. package/dist/resolution/frameworks/ruby.js +302 -0
  366. package/dist/resolution/frameworks/ruby.js.map +1 -0
  367. package/dist/resolution/frameworks/rust.d.ts +8 -0
  368. package/dist/resolution/frameworks/rust.d.ts.map +1 -0
  369. package/dist/resolution/frameworks/rust.js +304 -0
  370. package/dist/resolution/frameworks/rust.js.map +1 -0
  371. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  372. package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  373. package/dist/resolution/frameworks/svelte.js +249 -0
  374. package/dist/resolution/frameworks/svelte.js.map +1 -0
  375. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  376. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  377. package/dist/resolution/frameworks/swift-objc.js +252 -0
  378. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  379. package/dist/resolution/frameworks/swift.d.ts +10 -0
  380. package/dist/resolution/frameworks/swift.d.ts.map +1 -0
  381. package/dist/resolution/frameworks/swift.js +400 -0
  382. package/dist/resolution/frameworks/swift.js.map +1 -0
  383. package/dist/resolution/frameworks/vue.d.ts +9 -0
  384. package/dist/resolution/frameworks/vue.d.ts.map +1 -0
  385. package/dist/resolution/frameworks/vue.js +306 -0
  386. package/dist/resolution/frameworks/vue.js.map +1 -0
  387. package/dist/resolution/go-module.d.ts +26 -0
  388. package/dist/resolution/go-module.d.ts.map +1 -0
  389. package/dist/resolution/go-module.js +78 -0
  390. package/dist/resolution/go-module.js.map +1 -0
  391. package/dist/resolution/import-resolver.d.ts +68 -0
  392. package/dist/resolution/import-resolver.d.ts.map +1 -0
  393. package/dist/resolution/import-resolver.js +1275 -0
  394. package/dist/resolution/import-resolver.js.map +1 -0
  395. package/dist/resolution/index.d.ts +117 -0
  396. package/dist/resolution/index.d.ts.map +1 -0
  397. package/dist/resolution/index.js +895 -0
  398. package/dist/resolution/index.js.map +1 -0
  399. package/dist/resolution/lru-cache.d.ts +24 -0
  400. package/dist/resolution/lru-cache.d.ts.map +1 -0
  401. package/dist/resolution/lru-cache.js +62 -0
  402. package/dist/resolution/lru-cache.js.map +1 -0
  403. package/dist/resolution/name-matcher.d.ts +32 -0
  404. package/dist/resolution/name-matcher.d.ts.map +1 -0
  405. package/dist/resolution/name-matcher.js +596 -0
  406. package/dist/resolution/name-matcher.js.map +1 -0
  407. package/dist/resolution/path-aliases.d.ts +68 -0
  408. package/dist/resolution/path-aliases.d.ts.map +1 -0
  409. package/dist/resolution/path-aliases.js +238 -0
  410. package/dist/resolution/path-aliases.js.map +1 -0
  411. package/dist/resolution/spec-link-resolver.d.ts +103 -0
  412. package/dist/resolution/spec-link-resolver.d.ts.map +1 -0
  413. package/dist/resolution/spec-link-resolver.js +259 -0
  414. package/dist/resolution/spec-link-resolver.js.map +1 -0
  415. package/dist/resolution/strip-comments.d.ts +27 -0
  416. package/dist/resolution/strip-comments.d.ts.map +1 -0
  417. package/dist/resolution/strip-comments.js +441 -0
  418. package/dist/resolution/strip-comments.js.map +1 -0
  419. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  420. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  421. package/dist/resolution/swift-objc-bridge.js +256 -0
  422. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  423. package/dist/resolution/types.d.ts +216 -0
  424. package/dist/resolution/types.d.ts.map +1 -0
  425. package/dist/resolution/types.js +8 -0
  426. package/dist/resolution/types.js.map +1 -0
  427. package/dist/resolution/workspace-packages.d.ts +48 -0
  428. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  429. package/dist/resolution/workspace-packages.js +208 -0
  430. package/dist/resolution/workspace-packages.js.map +1 -0
  431. package/dist/search/query-parser.d.ts +57 -0
  432. package/dist/search/query-parser.d.ts.map +1 -0
  433. package/dist/search/query-parser.js +177 -0
  434. package/dist/search/query-parser.js.map +1 -0
  435. package/dist/search/query-utils.d.ts +71 -0
  436. package/dist/search/query-utils.d.ts.map +1 -0
  437. package/dist/search/query-utils.js +380 -0
  438. package/dist/search/query-utils.js.map +1 -0
  439. package/dist/server/cli.js +152 -0
  440. package/dist/server/index.js +12 -0
  441. package/dist/server/ingest/index.js +18 -0
  442. package/dist/server/ingest/ingestor.js +406 -0
  443. package/dist/server/ingest/parser.js +104 -0
  444. package/dist/server/ingest/pricing.js +78 -0
  445. package/dist/server/ingest/types.js +9 -0
  446. package/dist/server/ingest/watcher.js +77 -0
  447. package/dist/server/package.json +3 -0
  448. package/dist/server/project-registry.js +101 -0
  449. package/dist/server/routes/claude.js +480 -0
  450. package/dist/server/routes/graph.js +149 -0
  451. package/dist/server/routes/memory.js +272 -0
  452. package/dist/server/routes/projects.js +197 -0
  453. package/dist/server/routes/spec.js +105 -0
  454. package/dist/server/routes/status.js +35 -0
  455. package/dist/server/routes/workflow.js +184 -0
  456. package/dist/server/server.js +202 -0
  457. package/dist/sync/git-hooks.d.ts +45 -0
  458. package/dist/sync/git-hooks.d.ts.map +1 -0
  459. package/dist/sync/git-hooks.js +225 -0
  460. package/dist/sync/git-hooks.js.map +1 -0
  461. package/dist/sync/index.d.ts +19 -0
  462. package/dist/sync/index.d.ts.map +1 -0
  463. package/dist/sync/index.js +35 -0
  464. package/dist/sync/index.js.map +1 -0
  465. package/dist/sync/watch-policy.d.ts +48 -0
  466. package/dist/sync/watch-policy.d.ts.map +1 -0
  467. package/dist/sync/watch-policy.js +124 -0
  468. package/dist/sync/watch-policy.js.map +1 -0
  469. package/dist/sync/watcher.d.ts +283 -0
  470. package/dist/sync/watcher.d.ts.map +1 -0
  471. package/dist/sync/watcher.js +606 -0
  472. package/dist/sync/watcher.js.map +1 -0
  473. package/dist/sync/worktree.d.ts +54 -0
  474. package/dist/sync/worktree.d.ts.map +1 -0
  475. package/dist/sync/worktree.js +137 -0
  476. package/dist/sync/worktree.js.map +1 -0
  477. package/dist/types.d.ts +623 -0
  478. package/dist/types.d.ts.map +1 -0
  479. package/dist/types.js +108 -0
  480. package/dist/types.js.map +1 -0
  481. package/dist/ui/glyphs.d.ts +42 -0
  482. package/dist/ui/glyphs.d.ts.map +1 -0
  483. package/dist/ui/glyphs.js +78 -0
  484. package/dist/ui/glyphs.js.map +1 -0
  485. package/dist/ui/shimmer-progress.d.ts +11 -0
  486. package/dist/ui/shimmer-progress.d.ts.map +1 -0
  487. package/dist/ui/shimmer-progress.js +90 -0
  488. package/dist/ui/shimmer-progress.js.map +1 -0
  489. package/dist/ui/shimmer-worker.d.ts +2 -0
  490. package/dist/ui/shimmer-worker.d.ts.map +1 -0
  491. package/dist/ui/shimmer-worker.js +118 -0
  492. package/dist/ui/shimmer-worker.js.map +1 -0
  493. package/dist/ui/types.d.ts +17 -0
  494. package/dist/ui/types.d.ts.map +1 -0
  495. package/dist/ui/types.js +3 -0
  496. package/dist/ui/types.js.map +1 -0
  497. package/dist/utils.d.ts +205 -0
  498. package/dist/utils.d.ts.map +1 -0
  499. package/dist/utils.js +549 -0
  500. package/dist/utils.js.map +1 -0
  501. package/dist/web/chunk-2YZXEHZ2.js +1 -0
  502. package/dist/web/chunk-3GIC555L.js +18 -0
  503. package/dist/web/chunk-3IIIGRMT.js +1 -0
  504. package/dist/web/chunk-47QYKLE5.js +1 -0
  505. package/dist/web/chunk-4LHBWWP7.js +1 -0
  506. package/dist/web/chunk-4OAZLD5W.js +1 -0
  507. package/dist/web/chunk-5OQKAJAE.js +1 -0
  508. package/dist/web/chunk-7B525GKQ.js +1 -0
  509. package/dist/web/chunk-BPDXCOOZ.js +1 -0
  510. package/dist/web/chunk-DT37HTZB.js +1 -0
  511. package/dist/web/chunk-EIMUHJND.js +1 -0
  512. package/dist/web/chunk-FTESTUEO.js +1 -0
  513. package/dist/web/chunk-GLJZV6MU.js +1 -0
  514. package/dist/web/chunk-I7LS67U5.js +1 -0
  515. package/dist/web/chunk-L4TVIPSR.js +1 -0
  516. package/dist/web/chunk-MASCULC2.js +1 -0
  517. package/dist/web/chunk-MW7ICSRM.js +1 -0
  518. package/dist/web/chunk-OI5VP2A3.js +1 -0
  519. package/dist/web/chunk-RA6EBF6I.js +1 -0
  520. package/dist/web/chunk-RP3WU5Y6.js +1 -0
  521. package/dist/web/chunk-RQDRMTXN.js +1 -0
  522. package/dist/web/chunk-TQMT6UDU.js +1 -0
  523. package/dist/web/chunk-U7IYOV7T.js +1 -0
  524. package/dist/web/chunk-UE227MWF.js +1 -0
  525. package/dist/web/chunk-WV573J4K.js +1 -0
  526. package/dist/web/chunk-WVCKOJZL.js +4 -0
  527. package/dist/web/chunk-XZKLVPHE.js +1 -0
  528. package/dist/web/chunk-ZABKKHJ3.js +1 -0
  529. package/dist/web/favicon-16.png +0 -0
  530. package/dist/web/favicon-180.png +0 -0
  531. package/dist/web/favicon-32.png +0 -0
  532. package/dist/web/favicon-512.png +0 -0
  533. package/dist/web/favicon-small.svg +15 -0
  534. package/dist/web/favicon.ico +0 -0
  535. package/dist/web/favicon.svg +20 -0
  536. package/dist/web/index.html +145 -0
  537. package/dist/web/main-RI5CO5Z4.js +1 -0
  538. package/dist/web/styles-CYN7IKT4.css +1 -0
  539. package/dist/workflows/condition-evaluator.d.ts +75 -0
  540. package/dist/workflows/condition-evaluator.d.ts.map +1 -0
  541. package/dist/workflows/condition-evaluator.js +282 -0
  542. package/dist/workflows/condition-evaluator.js.map +1 -0
  543. package/dist/workflows/defaults/index.d.ts +26 -0
  544. package/dist/workflows/defaults/index.d.ts.map +1 -0
  545. package/dist/workflows/defaults/index.js +94 -0
  546. package/dist/workflows/defaults/index.js.map +1 -0
  547. package/dist/workflows/defaults/spec-fix.yaml +110 -0
  548. package/dist/workflows/defaults/spec-implement.yaml +150 -0
  549. package/dist/workflows/defaults/spec-relink.yaml +81 -0
  550. package/dist/workflows/defaults/spec-verify.yaml +51 -0
  551. package/dist/workflows/discovery.d.ts +46 -0
  552. package/dist/workflows/discovery.d.ts.map +1 -0
  553. package/dist/workflows/discovery.js +193 -0
  554. package/dist/workflows/discovery.js.map +1 -0
  555. package/dist/workflows/executor.d.ts +83 -0
  556. package/dist/workflows/executor.d.ts.map +1 -0
  557. package/dist/workflows/executor.js +623 -0
  558. package/dist/workflows/executor.js.map +1 -0
  559. package/dist/workflows/runners/approval.d.ts +18 -0
  560. package/dist/workflows/runners/approval.d.ts.map +1 -0
  561. package/dist/workflows/runners/approval.js +34 -0
  562. package/dist/workflows/runners/approval.js.map +1 -0
  563. package/dist/workflows/runners/bash.d.ts +13 -0
  564. package/dist/workflows/runners/bash.d.ts.map +1 -0
  565. package/dist/workflows/runners/bash.js +143 -0
  566. package/dist/workflows/runners/bash.js.map +1 -0
  567. package/dist/workflows/runners/cancel.d.ts +10 -0
  568. package/dist/workflows/runners/cancel.d.ts.map +1 -0
  569. package/dist/workflows/runners/cancel.js +19 -0
  570. package/dist/workflows/runners/cancel.js.map +1 -0
  571. package/dist/workflows/runners/prompt.d.ts +28 -0
  572. package/dist/workflows/runners/prompt.d.ts.map +1 -0
  573. package/dist/workflows/runners/prompt.js +212 -0
  574. package/dist/workflows/runners/prompt.js.map +1 -0
  575. package/dist/workflows/runners/script.d.ts +17 -0
  576. package/dist/workflows/runners/script.d.ts.map +1 -0
  577. package/dist/workflows/runners/script.js +155 -0
  578. package/dist/workflows/runners/script.js.map +1 -0
  579. package/dist/workflows/runners/types.d.ts +51 -0
  580. package/dist/workflows/runners/types.d.ts.map +1 -0
  581. package/dist/workflows/runners/types.js +13 -0
  582. package/dist/workflows/runners/types.js.map +1 -0
  583. package/dist/workflows/schemas/workflow.d.ts +166 -0
  584. package/dist/workflows/schemas/workflow.d.ts.map +1 -0
  585. package/dist/workflows/schemas/workflow.js +437 -0
  586. package/dist/workflows/schemas/workflow.js.map +1 -0
  587. package/hooks/hooks.json +27 -0
  588. package/package.json +67 -0
  589. package/scripts/add-lang/bench.sh +60 -0
  590. package/scripts/add-lang/check-grammar.mjs +75 -0
  591. package/scripts/add-lang/dump-ast.mjs +103 -0
  592. package/scripts/add-lang/verify-extraction.mjs +70 -0
  593. package/scripts/agent-eval/arms-F.sh +21 -0
  594. package/scripts/agent-eval/arms-matrix.sh +37 -0
  595. package/scripts/agent-eval/audit.sh +68 -0
  596. package/scripts/agent-eval/bench-readme.sh +28 -0
  597. package/scripts/agent-eval/bench-why-repo.sh +22 -0
  598. package/scripts/agent-eval/block-read-hook.sh +19 -0
  599. package/scripts/agent-eval/hook-settings.json +15 -0
  600. package/scripts/agent-eval/itrun.sh +120 -0
  601. package/scripts/agent-eval/parse-arms.mjs +116 -0
  602. package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
  603. package/scripts/agent-eval/parse-run.mjs +45 -0
  604. package/scripts/agent-eval/parse-session.mjs +93 -0
  605. package/scripts/agent-eval/probe-context.mjs +21 -0
  606. package/scripts/agent-eval/probe-explore.mjs +40 -0
  607. package/scripts/agent-eval/probe-node.mjs +20 -0
  608. package/scripts/agent-eval/probe-sweep.mjs +119 -0
  609. package/scripts/agent-eval/probe-trace.mjs +20 -0
  610. package/scripts/agent-eval/run-agent.sh +34 -0
  611. package/scripts/agent-eval/run-all.sh +67 -0
  612. package/scripts/agent-eval/run-arms.sh +56 -0
  613. package/scripts/agent-eval/seq-matrix.mjs +137 -0
  614. package/scripts/build-bundle.sh +118 -0
  615. package/scripts/build-server-bundle.mjs +80 -0
  616. package/scripts/build-web-bundle.mjs +66 -0
  617. package/scripts/extract-release-notes.mjs +130 -0
  618. package/scripts/local-install.sh +41 -0
  619. package/scripts/npm-sdk.js +75 -0
  620. package/scripts/npm-shim.js +246 -0
  621. package/scripts/offline-install.ps1 +148 -0
  622. package/scripts/offline-install.sh +136 -0
  623. package/scripts/pack-npm.sh +119 -0
  624. package/scripts/prepare-release.mjs +270 -0
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ // Analyze the tool-surface ablation (/tmp/arms/<repo>/<arm>-r<n>.jsonl).
3
+ // Compares arms A–E on trace adoption, Read/Grep fallback, specship payload,
4
+ // round-trips, and duration — averaged across runs per arm.
5
+ //
6
+ // The decisive signal is READS: if removing a tool raises Reads on a question
7
+ // class, that tool was load-bearing for it (not redundant). If removing it
8
+ // changes nothing, it was redundant.
9
+ //
10
+ // A control all tools no steering (baseline)
11
+ // B steer all tools trace-first (adoption)
12
+ // C no-explore hide explore trace-first (is explore redundant?)
13
+ // D trace-centric hide explore+context trace-first (is the survey pair redundant?)
14
+ // E control-probe hide explore+context trace-first (NON-flow Q — should degrade)
15
+ //
16
+ // Usage: node scripts/agent-eval/parse-arms.mjs [/tmp/arms]
17
+ import { readFileSync, readdirSync, existsSync, statSync } from 'fs';
18
+ import { join } from 'path';
19
+
20
+ const ROOT = process.argv[2] || '/tmp/arms';
21
+ const cgShort = (n) => n.replace('mcp__specship__specship_', '').replace('mcp__specship__', '');
22
+
23
+ function parse(file) {
24
+ if (!existsSync(file)) return null;
25
+ const lines = readFileSync(file, 'utf8').split('\n').filter(Boolean);
26
+ const calls = []; let result = null, initCg = 0;
27
+ for (const l of lines) {
28
+ let ev; try { ev = JSON.parse(l); } catch { continue; }
29
+ if (ev.type === 'system' && ev.subtype === 'init') initCg = (ev.tools || []).filter(t => /specship/.test(t)).length;
30
+ if (ev.type === 'assistant') for (const b of (ev.message?.content || [])) if (b.type === 'tool_use')
31
+ calls.push({ id: b.id, name: b.name, out: 0 });
32
+ if (ev.type === 'user') for (const b of (ev.message?.content || [])) if (b.type === 'tool_result') {
33
+ const c = b.content;
34
+ const txt = typeof c === 'string' ? c : Array.isArray(c) ? c.map(x => x?.text || '').join('') : '';
35
+ const call = calls.find(k => k.id === b.tool_use_id); if (call) call.out = txt.length;
36
+ }
37
+ if (ev.type === 'result') result = ev;
38
+ }
39
+ const cg = calls.filter(c => c.name.includes('specship'));
40
+ return {
41
+ initCg,
42
+ reads: calls.filter(c => c.name === 'Read').length,
43
+ greps: calls.filter(c => c.name === 'Grep').length + calls.filter(c => c.name === 'Glob').length,
44
+ cgCalls: cg.length,
45
+ cgSeq: cg.map(c => cgShort(c.name)),
46
+ cgOut: cg.reduce((s, c) => s + c.out, 0),
47
+ traceUsed: cg.some(c => c.name.includes('trace')),
48
+ turns: result?.num_turns ?? null,
49
+ dur: result?.duration_ms ? Math.round(result.duration_ms / 1000) : null,
50
+ cost: result?.total_cost_usd || 0,
51
+ ok: result?.subtype === 'success',
52
+ };
53
+ }
54
+
55
+ // repo -> arm -> [runs]
56
+ const data = {};
57
+ if (!existsSync(ROOT)) { console.error(`no ${ROOT}`); process.exit(1); }
58
+ for (const repo of readdirSync(ROOT)) {
59
+ const rdir = join(ROOT, repo);
60
+ if (!statSync(rdir).isDirectory()) continue;
61
+ for (const f of readdirSync(rdir)) {
62
+ const m = f.match(/^([A-I])-r(\d+)\.jsonl$/); if (!m) continue;
63
+ const p = parse(join(rdir, f)); if (!p || !p.ok) continue;
64
+ (((data[repo] ??= {})[m[1]]) ??= []).push(p);
65
+ }
66
+ }
67
+
68
+ const avg = (a, f) => a.length ? a.reduce((s, x) => s + (f(x) || 0), 0) / a.length : 0;
69
+ const k = (n) => (n / 1000).toFixed(1);
70
+ const pad = (s, n) => String(s).padEnd(n);
71
+ const ARMS = ['A', 'H', 'I', 'B', 'F', 'G', 'C', 'D', 'E'];
72
+ const LABEL = { A: 'A all/none(old)', H: 'H body-trace/none', I: 'I bodytrace+dest', B: 'B all/steer(thin)', F: 'F all/steer(body)', G: 'G ported(noprompt)', C: 'C no-explore', D: 'D trace-centric', E: 'E nonflow-probe' };
73
+
74
+ // ---- per repo × arm ----
75
+ console.log('\n=== PER REPO × ARM (avg over runs) ===');
76
+ console.log(pad('repo', 22), pad('arm', 16), 'tools', 'trace', pad('reads', 6), pad('cgOutK', 7), pad('turns', 6), 'dur');
77
+ for (const repo of Object.keys(data).sort()) {
78
+ for (const arm of ARMS) {
79
+ const runs = data[repo][arm]; if (!runs?.length) continue;
80
+ console.log(
81
+ pad(repo, 22), pad(LABEL[arm], 16),
82
+ pad(runs[0].initCg, 5),
83
+ pad(runs.filter(r => r.traceUsed).length + '/' + runs.length, 5),
84
+ pad(avg(runs, r => r.reads).toFixed(1), 6),
85
+ pad(k(avg(runs, r => r.cgOut)), 7),
86
+ pad(avg(runs, r => r.turns).toFixed(1), 6),
87
+ avg(runs, r => r.dur).toFixed(0) + 's',
88
+ );
89
+ }
90
+ }
91
+
92
+ // ---- aggregate per arm (flow arms A–D over the flow repos; E shown apart) ----
93
+ console.log('\n=== AGGREGATE PER ARM (mean across repos) ===');
94
+ console.log(pad('arm', 16), pad('adoption', 9), pad('reads', 7), pad('greps', 7), pad('cgOutK', 8), pad('turns', 7), pad('dur', 6), 'cost');
95
+ for (const arm of ARMS) {
96
+ const all = [];
97
+ for (const repo of Object.keys(data)) for (const r of (data[repo][arm] || [])) all.push({ ...r, repo });
98
+ if (!all.length) continue;
99
+ const repos = new Set(all.map(r => r.repo)).size;
100
+ const adopt = all.filter(r => r.traceUsed).length;
101
+ console.log(
102
+ pad(LABEL[arm], 16),
103
+ pad(`${adopt}/${all.length}`, 9),
104
+ pad(avg(all, r => r.reads).toFixed(2), 7),
105
+ pad(avg(all, r => r.greps).toFixed(2), 7),
106
+ pad(k(avg(all, r => r.cgOut)), 8),
107
+ pad(avg(all, r => r.turns).toFixed(1), 7),
108
+ pad(avg(all, r => r.dur).toFixed(0) + 's', 6),
109
+ '$' + avg(all, r => r.cost).toFixed(3),
110
+ ` (${repos} repos)`,
111
+ );
112
+ }
113
+
114
+ console.log('\nRead the signal: B vs A = does steering alone fix adoption + cut payload.');
115
+ console.log('C vs B = is explore redundant (reads should NOT jump). D vs C = is context redundant.');
116
+ console.log('E = non-flow under trace-centric; reads SHOULD jump (proves survey tools are load-bearing).');
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ // Aggregate the README A/B (bench-readme.sh output): per repo, median of N runs
3
+ // per arm → time, tool calls, tokens, cost, and % saved. Plus an average row.
4
+ //
5
+ // Tokens = SUM of per-turn assistant `usage` (input + output + cache read +
6
+ // cache creation) — the cumulative "total tokens processed". NOTE: `result.usage`
7
+ // is last-turn-only in current Claude Code, so it under-counts badly; don't use it.
8
+ // `total_cost_usd` and `duration_ms` are already cumulative.
9
+ //
10
+ // Usage: node parse-bench-readme.mjs [/tmp/ab-readme]
11
+ import { readFileSync, existsSync, readdirSync } from 'fs';
12
+ import { join } from 'path';
13
+ const ROOT = process.argv[2] || '/tmp/ab-readme';
14
+ const REPOS = ['vscode', 'excalidraw', 'django', 'tokio', 'okhttp', 'gin', 'alamofire'];
15
+
16
+ function parse(file) {
17
+ if (!existsSync(file)) return null;
18
+ const L = readFileSync(file, 'utf8').split('\n').filter(Boolean);
19
+ let tools = 0, reads = 0, grep = 0, cg = 0, tokens = 0, r = null, raced = false;
20
+ for (const l of L) { let e; try { e = JSON.parse(l); } catch { continue; }
21
+ if (e.type === 'assistant') {
22
+ const u = e.message?.usage;
23
+ if (u) tokens += (u.input_tokens || 0) + (u.output_tokens || 0) + (u.cache_read_input_tokens || 0) + (u.cache_creation_input_tokens || 0);
24
+ for (const b of (e.message?.content || [])) if (b.type === 'tool_use') {
25
+ const n = b.name;
26
+ if (n === 'ToolSearch') continue;
27
+ tools++;
28
+ if (n === 'Read') reads++;
29
+ else if (n === 'Grep' || n === 'Glob') grep++;
30
+ else if (/specship/.test(n)) cg++;
31
+ }
32
+ }
33
+ // MCP cold-start race: the headless agent fired before `specship serve --mcp`
34
+ // finished registering its tools, so early calls returned "No such tool
35
+ // available" and the agent floundered into grep/Read. That measures SpecShip's
36
+ // startup latency, NOT its steady-state value — flag the run so the aggregate
37
+ // can exclude it (an artifact of headless first-turn timing, not the tool).
38
+ if (e.type === 'user') for (const b of (Array.isArray(e.message?.content) ? e.message.content : [])) {
39
+ if (b.type === 'tool_result') {
40
+ const t = Array.isArray(b.content) ? b.content.map(c => c.text || '').join('') : (b.content || '');
41
+ if (/No such tool available/.test(t)) raced = true;
42
+ }
43
+ }
44
+ if (e.type === 'result') r = e;
45
+ }
46
+ if (!r || r.subtype !== 'success') return null;
47
+ return { dur: r.duration_ms / 1000, tools, reads, grep, cg, tokens, cost: r.total_cost_usd || 0, raced };
48
+ }
49
+ const median = (arr) => { const v = [...arr].sort((a, b) => a - b); const n = v.length; return n === 0 ? 0 : n % 2 ? v[(n - 1) / 2] : (v[n / 2 - 1] + v[n / 2]) / 2; };
50
+ const fmtTime = (s) => s >= 60 ? `${Math.floor(s / 60)}m ${Math.round(s % 60)}s` : `${Math.round(s)}s`;
51
+ const fmtTok = (t) => t >= 1e6 ? `${(t / 1e6).toFixed(1)}M` : `${Math.round(t / 1000)}k`;
52
+ const pct = (w, wo) => wo > 0 ? Math.round((1 - w / wo) * 100) : 0;
53
+
54
+ console.log('repo n(w/wo) time WITH→WITHOUT tools W→WO tokens W→WO (saved) cost W→WO (saved)');
55
+ const savings = { cost: [], tokens: [], time: [], tools: [] };
56
+ for (const repo of REPOS) {
57
+ const dir = join(ROOT, repo);
58
+ const runDirs = existsSync(dir) ? readdirSync(dir).filter(d => /^run\d+$/.test(d)) : [];
59
+ // Exclude MCP-cold-start-raced WITH runs by default — they measure a startup
60
+ // race, not steady-state value. `CG_INCLUDE_RACED=1` keeps them (to see the raw
61
+ // distribution). The WITHOUT arm has no MCP, so it's never raced.
62
+ const includeRaced = process.env.CG_INCLUDE_RACED === '1';
63
+ const W = [], WO = []; let racedExcluded = 0;
64
+ for (const rd of runDirs) {
65
+ const w = parse(join(dir, rd, 'run-headless-with.jsonl'));
66
+ if (w) { if (w.raced && !includeRaced) racedExcluded++; else W.push(w); }
67
+ const wo = parse(join(dir, rd, 'run-headless-without.jsonl')); if (wo) WO.push(wo);
68
+ }
69
+ if (!W.length || !WO.length) { console.log(`${repo.padEnd(11)} (incomplete: w=${W.length} wo=${WO.length})`); continue; }
70
+ const m = (arr, k) => median(arr.map(x => x[k]));
71
+ const wT = m(W, 'dur'), woT = m(WO, 'dur'), wTok = m(W, 'tokens'), woTok = m(WO, 'tokens');
72
+ const wC = m(W, 'cost'), woC = m(WO, 'cost'), wTl = m(W, 'tools'), woTl = m(WO, 'tools');
73
+ savings.time.push(pct(wT, woT)); savings.tokens.push(pct(wTok, woTok)); savings.cost.push(pct(wC, woC)); savings.tools.push(pct(wTl, woTl));
74
+ console.log(
75
+ `${repo.padEnd(11)} ${W.length}/${WO.length} ` +
76
+ `${(fmtTime(wT) + '→' + fmtTime(woT)).padEnd(22)}` +
77
+ `${(Math.round(wTl) + '→' + Math.round(woTl)).padEnd(12)}` +
78
+ `${(fmtTok(wTok) + '→' + fmtTok(woTok) + ' (' + pct(wTok, woTok) + '%)').padEnd(24)}` +
79
+ `$${wC.toFixed(2)}→$${woC.toFixed(2)} (${pct(wC, woC)}%)` +
80
+ (racedExcluded ? ` [${racedExcluded} raced run${racedExcluded === 1 ? '' : 's'} excluded]` : '')
81
+ );
82
+ }
83
+ const avg = (a) => a.length ? Math.round(a.reduce((s, x) => s + x, 0) / a.length) : 0;
84
+ console.log(`\nAVERAGE saved: cost ${avg(savings.cost)}% · tokens ${avg(savings.tokens)}% · time ${avg(savings.time)}% · tool calls ${avg(savings.tools)}%`);
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ // Parse a Claude Code stream-json run log: tool-call sequence + token usage.
3
+ import { readFileSync } from 'fs';
4
+ const file = process.argv[2];
5
+ const lines = readFileSync(file, 'utf8').split('\n').filter(Boolean);
6
+
7
+ const toolCalls = [];
8
+ let result = null;
9
+ let initTools = null;
10
+
11
+ for (const line of lines) {
12
+ let ev;
13
+ try { ev = JSON.parse(line); } catch { continue; }
14
+ if (ev.type === 'system' && ev.subtype === 'init') {
15
+ initTools = (ev.tools || []).filter(t => /specship/.test(t));
16
+ }
17
+ if (ev.type === 'assistant' && ev.message?.content) {
18
+ for (const block of ev.message.content) {
19
+ if (block.type === 'tool_use') {
20
+ let detail = '';
21
+ if (block.name === 'Task') detail = ` [subagent_type=${block.input?.subagent_type ?? '?'}] ${(block.input?.description ?? '').slice(0,40)}`;
22
+ else if (/specship/.test(block.name)) detail = ` ${JSON.stringify(block.input?.query ?? block.input?.task ?? block.input?.symbol ?? '').slice(0,60)}`;
23
+ else if (block.name === 'Bash') detail = ` ${(block.input?.command ?? '').slice(0,50)}`;
24
+ else if (block.name === 'Read') detail = ` ${(block.input?.file_path ?? '').split('/').slice(-1)[0]}`;
25
+ toolCalls.push(`${block.name}${detail}`);
26
+ }
27
+ }
28
+ }
29
+ if (ev.type === 'result') result = ev;
30
+ }
31
+
32
+ console.log(`\n=== ${file.split('/').pop()} ===`);
33
+ console.log(`specship tools exposed: ${initTools ? initTools.length : '?'}`);
34
+ console.log(`\nTool calls (${toolCalls.length}):`);
35
+ const counts = {};
36
+ for (const tc of toolCalls) { const n = tc.split(' ')[0]; counts[n] = (counts[n]||0)+1; }
37
+ console.log(' by type:', JSON.stringify(counts));
38
+ toolCalls.forEach((tc, i) => console.log(` ${i+1}. ${tc}`));
39
+
40
+ if (result) {
41
+ const u = result.usage || {};
42
+ const totalIn = (u.input_tokens||0) + (u.cache_read_input_tokens||0) + (u.cache_creation_input_tokens||0);
43
+ console.log(`\nResult: ${result.subtype} | duration ${(result.duration_ms/1000).toFixed(0)}s | turns ${result.num_turns}`);
44
+ console.log(` tokens: in=${totalIn} out=${u.output_tokens||0} | cost $${(result.total_cost_usd||0).toFixed(3)}`);
45
+ }
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ // Parse the newest Claude Code session log for a project + its subagent logs,
3
+ // and report the tool-call breakdown (main + subagents). Works for interactive
4
+ // runs (driven via itrun.sh) — Claude Code writes full transcripts to
5
+ // ~/.claude/projects/<escaped-cwd>/<session>.jsonl with subagents/ alongside.
6
+ import { readFileSync, readdirSync, statSync, existsSync, realpathSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+
10
+ const projectArg = process.argv[2];
11
+ if (!projectArg) { console.error('usage: parse-session.mjs <project-dir>'); process.exit(1); }
12
+
13
+ // Claude Code escapes the (real) cwd by replacing every "/" with "-".
14
+ const real = realpathSync(projectArg);
15
+ const escaped = real.replace(/\//g, '-');
16
+ const projDir = join(homedir(), '.claude', 'projects', escaped);
17
+ if (!existsSync(projDir)) { console.error('no session logs at', projDir); process.exit(1); }
18
+
19
+ // Newest top-level session .jsonl
20
+ const sessions = readdirSync(projDir)
21
+ .filter(f => f.endsWith('.jsonl'))
22
+ .map(f => ({ f, m: statSync(join(projDir, f)).mtimeMs }))
23
+ .sort((a, b) => b.m - a.m);
24
+ if (sessions.length === 0) { console.error('no .jsonl sessions in', projDir); process.exit(1); }
25
+ const sessionId = sessions[0].f.replace('.jsonl', '');
26
+
27
+ function tally(file) {
28
+ const counts = {};
29
+ for (const line of readFileSync(file, 'utf8').split('\n')) {
30
+ if (!line) continue;
31
+ let ev; try { ev = JSON.parse(line); } catch { continue; }
32
+ const content = ev.message?.content;
33
+ if (!Array.isArray(content)) continue;
34
+ for (const b of content) {
35
+ if (b.type === 'tool_use') counts[b.name] = (counts[b.name] || 0) + 1;
36
+ }
37
+ }
38
+ return counts;
39
+ }
40
+
41
+ // Sum token usage from a transcript. The TUI's "Done (…Xk tokens…)" line only
42
+ // covers a subagent's throughput; this works for main-thread runs too and is
43
+ // consistent across both paths. `gen` = output, `fresh` = uncached input
44
+ // (input + cache_creation), `cached` = cache reads (≈free), `total` = all.
45
+ function sumTokens(file) {
46
+ const t = { gen: 0, fresh: 0, cached: 0 };
47
+ for (const line of readFileSync(file, 'utf8').split('\n')) {
48
+ if (!line) continue;
49
+ let ev; try { ev = JSON.parse(line); } catch { continue; }
50
+ const u = ev.message?.usage;
51
+ if (!u) continue;
52
+ t.gen += u.output_tokens || 0;
53
+ t.fresh += (u.input_tokens || 0) + (u.cache_creation_input_tokens || 0);
54
+ t.cached += u.cache_read_input_tokens || 0;
55
+ }
56
+ return t;
57
+ }
58
+
59
+ const mainCounts = tally(join(projDir, sessionId + '.jsonl'));
60
+
61
+ // Subagent transcripts live under <session>/subagents/*.jsonl
62
+ const subDir = join(projDir, sessionId, 'subagents');
63
+ const subCounts = {};
64
+ let subAgentFiles = 0;
65
+ if (existsSync(subDir)) {
66
+ for (const f of readdirSync(subDir).filter(f => f.endsWith('.jsonl'))) {
67
+ subAgentFiles++;
68
+ const c = tally(join(subDir, f));
69
+ for (const [k, v] of Object.entries(c)) subCounts[k] = (subCounts[k] || 0) + v;
70
+ }
71
+ }
72
+
73
+ const fmt = (counts) => Object.entries(counts).sort((a, b) => b[1] - a[1])
74
+ .map(([k, v]) => ` ${String(v).padStart(3)} ${k}`).join('\n') || ' (none)';
75
+
76
+ console.log(`session: ${sessionId}`);
77
+ console.log(`\nMAIN thread tools:\n${fmt(mainCounts)}`);
78
+ console.log(`\nSUBAGENT tools (${subAgentFiles} subagent transcript${subAgentFiles === 1 ? '' : 's'}):\n${fmt(subCounts)}`);
79
+
80
+ const explore = subCounts['mcp__specship__specship_explore'] || mainCounts['mcp__specship__specship_explore'] || 0;
81
+ const reads = (subCounts['Read'] || 0) + (mainCounts['Read'] || 0);
82
+ const greps = (subCounts['Grep'] || 0) + (mainCounts['Grep'] || 0) + (subCounts['Bash'] || 0) + (mainCounts['Bash'] || 0);
83
+ console.log(`\nVERDICT: specship_explore used ${explore}x | Read ${reads} | Grep/Bash ${greps}`);
84
+
85
+ // Token totals (main + subagents), consistent across main-thread and subagent runs.
86
+ const tok = { gen: 0, fresh: 0, cached: 0 };
87
+ const addTok = (t) => { tok.gen += t.gen; tok.fresh += t.fresh; tok.cached += t.cached; };
88
+ addTok(sumTokens(join(projDir, sessionId + '.jsonl')));
89
+ if (existsSync(subDir)) {
90
+ for (const f of readdirSync(subDir).filter(f => f.endsWith('.jsonl'))) addTok(sumTokens(join(subDir, f)));
91
+ }
92
+ const k = (n) => (n / 1000).toFixed(1) + 'k';
93
+ console.log(`TOKENS: gen ${k(tok.gen)} | fresh-in ${k(tok.fresh)} | cached-in ${k(tok.cached)} | billable≈ ${k(tok.gen + tok.fresh)}`);
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ // Probe specship_context (with call-paths) against an index using the built dist.
3
+ // Usage: node probe-context.mjs <repo-with-.specship> <task words...>
4
+ import { pathToFileURL } from 'node:url';
5
+ import { resolve } from 'node:path';
6
+
7
+ const [, , repo, ...taskParts] = process.argv;
8
+ const task = taskParts.join(' ');
9
+ if (!repo || !task) { console.error('usage: probe-context.mjs <repo> <task...>'); process.exit(1); }
10
+
11
+ const load = async (rel) => import(pathToFileURL(resolve(rel)).href);
12
+ const idx = await load('dist/index.js');
13
+ const tools = await load('dist/mcp/tools.js');
14
+ const SpecShip = idx.default?.default ?? idx.default ?? idx.SpecShip;
15
+ const ToolHandler = tools.ToolHandler ?? tools.default?.ToolHandler;
16
+
17
+ const cg = SpecShip.openSync(repo);
18
+ const h = new ToolHandler(cg);
19
+ const res = await h.execute('specship_context', { task });
20
+ console.log(res.content?.[0]?.text ?? '(no text)');
21
+ try { cg.close?.(); } catch {}
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ // One-shot probe: run handleExplore against an existing index using the built
3
+ // dist, print the output + a few stats. Lets us verify explore's coverage fix
4
+ // without a full agent run. Usage: node probe-explore.mjs <repo-with-.specship> "<query>"
5
+ import { pathToFileURL } from 'node:url';
6
+ import { resolve } from 'node:path';
7
+
8
+ const [, , repo, query] = process.argv;
9
+ if (!repo || !query) {
10
+ console.error('usage: probe-explore.mjs <repo> "<query>"');
11
+ process.exit(1);
12
+ }
13
+
14
+ const load = async (rel) => import(pathToFileURL(resolve(rel)).href);
15
+ const idx = await load('dist/index.js');
16
+ const tools = await load('dist/mcp/tools.js');
17
+
18
+ // esModuleInterop: dynamic import of CJS yields { default: module.exports, ...named }
19
+ const SpecShip = idx.default?.default ?? idx.default ?? idx.SpecShip;
20
+ const ToolHandler = tools.ToolHandler ?? tools.default?.ToolHandler;
21
+
22
+ if (typeof SpecShip?.openSync !== 'function') {
23
+ console.error('could not resolve SpecShip.openSync; index keys:', Object.keys(idx), 'default keys:', idx.default && Object.keys(idx.default));
24
+ process.exit(2);
25
+ }
26
+ if (typeof ToolHandler !== 'function') {
27
+ console.error('could not resolve ToolHandler; tools keys:', Object.keys(tools));
28
+ process.exit(2);
29
+ }
30
+
31
+ const cg = SpecShip.openSync(repo);
32
+ const h = new ToolHandler(cg);
33
+ const res = await h.execute('specship_explore', { query });
34
+ const text = res.content?.[0]?.text ?? '(no text)';
35
+ console.log(text);
36
+ console.error('\n--- PROBE STATS ---');
37
+ console.error('output chars:', text.length);
38
+ console.error('triggerRender body present (-> setState({})):', /triggerRender[\s\S]{0,400}setState\(\{\}\)/.test(text));
39
+ console.error('App.tsx in source section:', /#### .*App\.tsx —/.test(text));
40
+ try { cg.close?.(); } catch {}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // Probe specship_node (with trail) against an index using the built dist.
3
+ // Usage: node probe-node.mjs <repo-with-.specship> <symbol> [code]
4
+ import { pathToFileURL } from 'node:url';
5
+ import { resolve } from 'node:path';
6
+
7
+ const [, , repo, symbol, code] = process.argv;
8
+ if (!repo || !symbol) { console.error('usage: probe-node.mjs <repo> <symbol> [code]'); process.exit(1); }
9
+
10
+ const load = async (rel) => import(pathToFileURL(resolve(rel)).href);
11
+ const idx = await load('dist/index.js');
12
+ const tools = await load('dist/mcp/tools.js');
13
+ const SpecShip = idx.default?.default ?? idx.default ?? idx.SpecShip;
14
+ const ToolHandler = tools.ToolHandler ?? tools.default?.ToolHandler;
15
+
16
+ const cg = SpecShip.openSync(repo);
17
+ const h = new ToolHandler(cg);
18
+ const res = await h.execute('specship_node', { symbol, includeCode: code === 'code' });
19
+ console.log(res.content?.[0]?.text ?? '(no text)');
20
+ try { cg.close?.(); } catch {}
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ // probe-sweep — direct MCP test across N repos × N tools, no claude needed.
3
+ //
4
+ // Measures response characteristics (size, sections present, signals fired)
5
+ // for each (repo, query) pair against the built dist/. Sub-second per probe;
6
+ // the full sweep below runs in ~10-30s vs hours for a real claude audit.
7
+ //
8
+ // Use this to iterate on backend changes rapidly: change tools.ts /
9
+ // context-builder, npm run build, re-run probe-sweep, compare. Once a
10
+ // change looks good on probe metrics, run a focused claude audit for the
11
+ // few repos that matter to confirm end-to-end cost behavior.
12
+ //
13
+ // Usage: node scripts/agent-eval/probe-sweep.mjs [--tool=context|explore|trace] [--repos=a,b,c]
14
+ import { pathToFileURL } from 'node:url';
15
+ import { resolve } from 'node:path';
16
+
17
+ const args = Object.fromEntries(
18
+ process.argv.slice(2).map(a => a.startsWith('--') ? a.slice(2).split('=') : [a, true])
19
+ );
20
+ const TOOL = args.tool ?? 'context';
21
+
22
+ const load = (rel) => import(pathToFileURL(resolve(rel)).href);
23
+ const idx = await load('dist/index.js');
24
+ const tools = await load('dist/mcp/tools.js');
25
+ const SpecShip = idx.default?.default ?? idx.default ?? idx.SpecShip;
26
+ const ToolHandler = tools.ToolHandler ?? tools.default?.ToolHandler;
27
+
28
+ // Each entry: repo, query, optional 2nd arg for trace (from, to).
29
+ // The query is the same prompt used in the real claude audits, so probe
30
+ // output is directly comparable to the agent's would-be input.
31
+ const SWEEP = [
32
+ // Small realworld template repos (the loss cases from the cross-language sweep)
33
+ { id: 'gin-rw', repo: '/tmp/specship-corpus/gin-realworld', q: 'How does this Gin app route a request through its middleware chain to a handler?' },
34
+ { id: 'go-mux', repo: '/tmp/specship-corpus/go-mux', q: 'How does this gorilla/mux app route a request to its handler?' },
35
+ { id: 'fastapi-rw', repo: '/tmp/specship-corpus/fastapi-realworld', q: 'How does FastAPI route a request through its dependencies to a handler?' },
36
+ { id: 'spring-pc', repo: '/tmp/specship-corpus/spring-petclinic', q: 'How does Spring route an HTTP request to a controller method?' },
37
+ { id: 'axum-rw', repo: '/tmp/specship-corpus/rust-axum-realworld', q: 'How does Axum route a request to its handler in this app?' },
38
+ { id: 'express-rw', repo: '/tmp/specship-corpus/express-realworld', q: 'How does this Express app route a request through middleware to a handler?' },
39
+ { id: 'kotlin-pc', repo: '/tmp/specship-corpus/kotlin-petclinic', q: 'How does the Kotlin Spring app route an HTTP request to its handler?' },
40
+ { id: 'flask-mb', repo: '/tmp/specship-corpus/flask-microblog', q: 'How does this Flask app route a request to a view function?' },
41
+ { id: 'vapor-tpl', repo: '/tmp/specship-corpus/vapor-template', q: 'How does Vapor route an HTTP request to its handler?' },
42
+ { id: 'cpp-leveldb', repo: '/tmp/specship-corpus/cpp-leveldb', q: 'How does LevelDB handle a Put operation through to disk?' },
43
+ { id: 'lualine', repo: '/tmp/specship-corpus/lualine.nvim', q: 'How does lualine assemble and render the statusline?' },
44
+ { id: 'drupal-admin', repo: '/tmp/specship-corpus/drupal-admintoolbar', q: 'How does the Drupal admin toolbar module render its toolbar?' },
45
+ { id: 'svelte-rw', repo: '/tmp/specship-corpus/svelte-realworld', q: 'How does this SvelteKit app route a request to a handler?' },
46
+ { id: 'react-rw', repo: '/tmp/specship-corpus/react-realworld', q: 'How does this React app fetch and display articles?' },
47
+ { id: 'rails-rw', repo: '/tmp/specship-corpus/rails-realworld', q: 'How does Rails route a request to a controller action?' },
48
+ { id: 'flask-rest', repo: '/tmp/specship-corpus/flask-restful-realworld', q: 'How does Flask-RESTful route a request to a resource method?' },
49
+ { id: 'laravel-rw', repo: '/tmp/specship-corpus/laravel-realworld', q: 'How does Laravel route a request to the controller method?' },
50
+ { id: 'aspnet-rw', repo: '/tmp/specship-corpus/aspnet-realworld', q: 'How does ASP.NET route a request to the controller action?' },
51
+ // The iter7 wins/ties (to make sure we don't regress)
52
+ { id: 'cobra', repo: '/tmp/specship-corpus/cobra', q: 'How does cobra parse commands and flags?' },
53
+ { id: 'sinatra', repo: '/tmp/specship-corpus/sinatra', q: 'How does sinatra route a request to its handler?' },
54
+ { id: 'slim', repo: '/tmp/specship-corpus/slim', q: 'How does slim route a request and apply middleware?' },
55
+ ];
56
+
57
+ // Detect signals in response text — these are the levers we've added that
58
+ // otherwise only show up via "agent ran X more tool calls" downstream.
59
+ const detect = (text) => ({
60
+ hasEntryPoints: /^### Entry Points/m.test(text),
61
+ hasRelatedSymbols: /^### Related Symbols/m.test(text),
62
+ hasFlowTrace: /^## Inline flow trace/m.test(text),
63
+ hasRouteManifest: /^## Routing manifest/m.test(text),
64
+ hasTopHandler: /^### Top handler file/m.test(text),
65
+ hasSmallRepoTail: /This project is small/.test(text),
66
+ });
67
+
68
+ const filterRepos = args.repos ? new Set(String(args.repos).split(',')) : null;
69
+ const subjects = SWEEP.filter(s => !filterRepos || filterRepos.has(s.id));
70
+
71
+ const t0 = Date.now();
72
+ const rows = [];
73
+ for (const s of subjects) {
74
+ try {
75
+ const cg = SpecShip.openSync(s.repo);
76
+ const handler = new ToolHandler(cg);
77
+ const t1 = Date.now();
78
+ const res = await handler.execute('specship_' + TOOL,
79
+ TOOL === 'context' ? { task: s.q } :
80
+ TOOL === 'explore' ? { query: s.q } : { from: 'main', to: 'main' });
81
+ const text = res.content?.[0]?.text ?? '';
82
+ const signals = detect(text);
83
+ rows.push({
84
+ id: s.id,
85
+ ms: Date.now() - t1,
86
+ chars: text.length,
87
+ lines: text.split('\n').length,
88
+ ...signals,
89
+ });
90
+ try { cg.close?.(); } catch {}
91
+ } catch (e) {
92
+ rows.push({ id: s.id, error: String(e).slice(0, 80) });
93
+ }
94
+ }
95
+
96
+ // Pretty-print as a compact table.
97
+ const fmt = (r) =>
98
+ r.error
99
+ ? ` ${r.id.padEnd(13)} ERROR: ${r.error}`
100
+ : ` ${r.id.padEnd(13)} ${String(r.chars).padStart(6)}c ${String(r.lines).padStart(4)}L ${String(r.ms).padStart(4)}ms` +
101
+ ` ${r.hasEntryPoints ? 'EP ' : ' '}` +
102
+ `${r.hasFlowTrace ? 'TRC ' : ' '}` +
103
+ `${r.hasRouteManifest ? 'MAN ' : ' '}` +
104
+ `${r.hasTopHandler ? 'HND ' : ' '}` +
105
+ `${r.hasSmallRepoTail ? 'TAIL' : ' '}`;
106
+ console.log(`=== probe-sweep tool=${TOOL} n=${subjects.length} (${Date.now() - t0}ms total) ===`);
107
+ console.log(' id chars lines ms signals');
108
+ console.log(' ' + '-'.repeat(56));
109
+ for (const r of rows) console.log(fmt(r));
110
+
111
+ // Sum + medians for the size pillar
112
+ const sizes = rows.filter(r => !r.error).map(r => r.chars);
113
+ sizes.sort((a, b) => a - b);
114
+ const median = sizes[Math.floor(sizes.length / 2)];
115
+ const sum = sizes.reduce((a, b) => a + b, 0);
116
+ console.log(` ${'-'.repeat(64)}`);
117
+ console.log(` median=${median}c total=${sum}c ` +
118
+ `manifest=${rows.filter(r => r.hasRouteManifest).length}/${rows.filter(r => !r.error).length} ` +
119
+ `top-handler=${rows.filter(r => r.hasTopHandler).length}/${rows.filter(r => !r.error).length}`);
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // Probe specship_trace against an index using the built dist.
3
+ // Usage: node probe-trace.mjs <repo-with-.specship> <from> <to>
4
+ import { pathToFileURL } from 'node:url';
5
+ import { resolve } from 'node:path';
6
+
7
+ const [, , repo, from, to] = process.argv;
8
+ if (!repo || !from || !to) { console.error('usage: probe-trace.mjs <repo> <from> <to>'); process.exit(1); }
9
+
10
+ const load = async (rel) => import(pathToFileURL(resolve(rel)).href);
11
+ const idx = await load('dist/index.js');
12
+ const tools = await load('dist/mcp/tools.js');
13
+ const SpecShip = idx.default?.default ?? idx.default ?? idx.SpecShip;
14
+ const ToolHandler = tools.ToolHandler ?? tools.default?.ToolHandler;
15
+
16
+ const cg = SpecShip.openSync(repo);
17
+ const h = new ToolHandler(cg);
18
+ const res = await h.execute('specship_trace', { from, to });
19
+ console.log(res.content?.[0]?.text ?? '(no text)');
20
+ try { cg.close?.(); } catch {}
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ # Headless Claude Code run against a repo with specship MCP, capturing the
3
+ # full stream-json so we can see tool calls + token usage. Complements the
4
+ # interactive itrun.sh: headless gives a clean per-tool breakdown + exact
5
+ # tokens/cost, but defaults to the general-purpose subagent (not Explore).
6
+ # To force the Explore path, ask for it in the prompt.
7
+ #
8
+ # Usage: run-agent.sh <repo-path> <label> "<prompt>"
9
+ # Env: AGENT_EVAL_OUT (default /tmp/agent-eval), CG_BIN (specship dist binary)
10
+ set -uo pipefail
11
+
12
+ REPO="$1"; LABEL="$2"; PROMPT="$3"
13
+ CG_BIN="${CG_BIN:-$(command -v specship || echo /usr/local/bin/specship)}"
14
+ OUT_DIR="${AGENT_EVAL_OUT:-/tmp/agent-eval}"; mkdir -p "$OUT_DIR"
15
+ OUT="$OUT_DIR/run-${LABEL}.jsonl"
16
+
17
+ MCP_CONFIG=$(cat <<JSON
18
+ {"mcpServers":{"specship":{"command":"${CG_BIN}","args":["serve","--mcp","--path","${REPO}"]}}}
19
+ JSON
20
+ )
21
+
22
+ echo "→ running [$LABEL] in $REPO"
23
+ cd "$REPO" || exit 1
24
+
25
+ claude -p "$PROMPT" \
26
+ --output-format stream-json --verbose \
27
+ --permission-mode bypassPermissions \
28
+ --model opus \
29
+ --max-budget-usd 2 \
30
+ --strict-mcp-config --mcp-config "$MCP_CONFIG" \
31
+ > "$OUT" 2>"$OUT_DIR/run-${LABEL}.err"
32
+
33
+ echo "exit: $? | wrote $OUT ($(wc -l < "$OUT") lines)"
34
+ node "$(cd "$(dirname "$0")" && pwd)/parse-run.mjs" "$OUT" 2>/dev/null || true