@harness-engineering/cli 1.13.0 → 1.14.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 (367) hide show
  1. package/dist/agents/skills/claude-code/add-harness-component/skill.yaml +1 -0
  2. package/dist/agents/skills/claude-code/align-documentation/skill.yaml +1 -0
  3. package/dist/agents/skills/claude-code/check-mechanical-constraints/skill.yaml +1 -0
  4. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +1 -0
  5. package/dist/agents/skills/claude-code/detect-doc-drift/skill.yaml +1 -0
  6. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +1 -0
  7. package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +1 -0
  8. package/dist/agents/skills/claude-code/harness-api-design/SKILL.md +304 -0
  9. package/dist/agents/skills/claude-code/harness-api-design/skill.yaml +74 -0
  10. package/dist/agents/skills/claude-code/harness-architecture-advisor/skill.yaml +1 -0
  11. package/dist/agents/skills/claude-code/harness-auth/SKILL.md +279 -0
  12. package/dist/agents/skills/claude-code/harness-auth/skill.yaml +81 -0
  13. package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +1 -0
  14. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +39 -0
  15. package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
  16. package/dist/agents/skills/claude-code/harness-caching/SKILL.md +309 -0
  17. package/dist/agents/skills/claude-code/harness-caching/skill.yaml +73 -0
  18. package/dist/agents/skills/claude-code/harness-chaos/SKILL.md +295 -0
  19. package/dist/agents/skills/claude-code/harness-chaos/skill.yaml +72 -0
  20. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +44 -0
  21. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +1 -0
  22. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +1 -0
  23. package/dist/agents/skills/claude-code/harness-compliance/SKILL.md +303 -0
  24. package/dist/agents/skills/claude-code/harness-compliance/skill.yaml +78 -0
  25. package/dist/agents/skills/claude-code/harness-containerization/SKILL.md +284 -0
  26. package/dist/agents/skills/claude-code/harness-containerization/skill.yaml +80 -0
  27. package/dist/agents/skills/claude-code/harness-data-pipeline/SKILL.md +274 -0
  28. package/dist/agents/skills/claude-code/harness-data-pipeline/skill.yaml +81 -0
  29. package/dist/agents/skills/claude-code/harness-data-validation/SKILL.md +343 -0
  30. package/dist/agents/skills/claude-code/harness-data-validation/skill.yaml +75 -0
  31. package/dist/agents/skills/claude-code/harness-database/SKILL.md +258 -0
  32. package/dist/agents/skills/claude-code/harness-database/skill.yaml +80 -0
  33. package/dist/agents/skills/claude-code/harness-debugging/skill.yaml +1 -0
  34. package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -0
  35. package/dist/agents/skills/claude-code/harness-deployment/SKILL.md +255 -0
  36. package/dist/agents/skills/claude-code/harness-deployment/skill.yaml +77 -0
  37. package/dist/agents/skills/claude-code/harness-design/skill.yaml +1 -0
  38. package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +1 -0
  39. package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +1 -0
  40. package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +1 -0
  41. package/dist/agents/skills/claude-code/harness-diagnostics/skill.yaml +1 -0
  42. package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +1 -0
  43. package/dist/agents/skills/claude-code/harness-dx/SKILL.md +276 -0
  44. package/dist/agents/skills/claude-code/harness-dx/skill.yaml +76 -0
  45. package/dist/agents/skills/claude-code/harness-e2e/SKILL.md +245 -0
  46. package/dist/agents/skills/claude-code/harness-e2e/skill.yaml +78 -0
  47. package/dist/agents/skills/claude-code/harness-event-driven/SKILL.md +280 -0
  48. package/dist/agents/skills/claude-code/harness-event-driven/skill.yaml +77 -0
  49. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +44 -0
  50. package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
  51. package/dist/agents/skills/claude-code/harness-feature-flags/SKILL.md +287 -0
  52. package/dist/agents/skills/claude-code/harness-feature-flags/skill.yaml +74 -0
  53. package/dist/agents/skills/claude-code/harness-git-workflow/skill.yaml +1 -0
  54. package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -0
  55. package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +1 -0
  56. package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +1 -0
  57. package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +1 -0
  58. package/dist/agents/skills/claude-code/harness-impact-analysis/skill.yaml +1 -0
  59. package/dist/agents/skills/claude-code/harness-incident-response/SKILL.md +223 -0
  60. package/dist/agents/skills/claude-code/harness-incident-response/skill.yaml +78 -0
  61. package/dist/agents/skills/claude-code/harness-infrastructure-as-code/SKILL.md +279 -0
  62. package/dist/agents/skills/claude-code/harness-infrastructure-as-code/skill.yaml +80 -0
  63. package/dist/agents/skills/claude-code/harness-integration-test/SKILL.md +271 -0
  64. package/dist/agents/skills/claude-code/harness-integration-test/skill.yaml +73 -0
  65. package/dist/agents/skills/claude-code/harness-integrity/skill.yaml +1 -0
  66. package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -0
  67. package/dist/agents/skills/claude-code/harness-load-testing/SKILL.md +274 -0
  68. package/dist/agents/skills/claude-code/harness-load-testing/skill.yaml +79 -0
  69. package/dist/agents/skills/claude-code/harness-ml-ops/SKILL.md +341 -0
  70. package/dist/agents/skills/claude-code/harness-ml-ops/skill.yaml +79 -0
  71. package/dist/agents/skills/claude-code/harness-mobile-patterns/SKILL.md +326 -0
  72. package/dist/agents/skills/claude-code/harness-mobile-patterns/skill.yaml +82 -0
  73. package/dist/agents/skills/claude-code/harness-mutation-test/SKILL.md +251 -0
  74. package/dist/agents/skills/claude-code/harness-mutation-test/skill.yaml +70 -0
  75. package/dist/agents/skills/claude-code/harness-observability/SKILL.md +283 -0
  76. package/dist/agents/skills/claude-code/harness-observability/skill.yaml +78 -0
  77. package/dist/agents/skills/claude-code/harness-onboarding/skill.yaml +1 -0
  78. package/dist/agents/skills/claude-code/harness-parallel-agents/skill.yaml +1 -0
  79. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +1 -0
  80. package/dist/agents/skills/claude-code/harness-perf-tdd/skill.yaml +1 -0
  81. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +39 -0
  82. package/dist/agents/skills/claude-code/harness-planning/skill.yaml +1 -0
  83. package/dist/agents/skills/claude-code/harness-pre-commit-review/skill.yaml +1 -0
  84. package/dist/agents/skills/claude-code/harness-product-spec/SKILL.md +285 -0
  85. package/dist/agents/skills/claude-code/harness-product-spec/skill.yaml +72 -0
  86. package/dist/agents/skills/claude-code/harness-property-test/SKILL.md +281 -0
  87. package/dist/agents/skills/claude-code/harness-property-test/skill.yaml +71 -0
  88. package/dist/agents/skills/claude-code/harness-refactoring/skill.yaml +1 -0
  89. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +3 -3
  90. package/dist/agents/skills/claude-code/harness-release-readiness/skill.yaml +1 -0
  91. package/dist/agents/skills/claude-code/harness-resilience/SKILL.md +255 -0
  92. package/dist/agents/skills/claude-code/harness-resilience/skill.yaml +76 -0
  93. package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +1 -0
  94. package/dist/agents/skills/claude-code/harness-secrets/SKILL.md +293 -0
  95. package/dist/agents/skills/claude-code/harness-secrets/skill.yaml +76 -0
  96. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +1 -0
  97. package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -0
  98. package/dist/agents/skills/claude-code/harness-skill-authoring/skill.yaml +1 -0
  99. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +1 -0
  100. package/dist/agents/skills/claude-code/harness-sql-review/SKILL.md +315 -0
  101. package/dist/agents/skills/claude-code/harness-sql-review/skill.yaml +74 -0
  102. package/dist/agents/skills/claude-code/harness-state-management/skill.yaml +1 -0
  103. package/dist/agents/skills/claude-code/harness-tdd/skill.yaml +1 -0
  104. package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +1 -0
  105. package/dist/agents/skills/claude-code/harness-test-data/SKILL.md +268 -0
  106. package/dist/agents/skills/claude-code/harness-test-data/skill.yaml +74 -0
  107. package/dist/agents/skills/claude-code/harness-ux-copy/SKILL.md +271 -0
  108. package/dist/agents/skills/claude-code/harness-ux-copy/skill.yaml +77 -0
  109. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +35 -0
  110. package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
  111. package/dist/agents/skills/claude-code/harness-verify/skill.yaml +1 -0
  112. package/dist/agents/skills/claude-code/harness-visual-regression/SKILL.md +257 -0
  113. package/dist/agents/skills/claude-code/harness-visual-regression/skill.yaml +74 -0
  114. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +11 -3
  115. package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
  116. package/dist/agents/skills/claude-code/validate-context-engineering/skill.yaml +1 -0
  117. package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +1 -0
  118. package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +1 -0
  119. package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +1 -0
  120. package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +1 -0
  121. package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +1 -0
  122. package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +1 -0
  123. package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +1 -0
  124. package/dist/agents/skills/gemini-cli/harness-api-design/SKILL.md +304 -0
  125. package/dist/agents/skills/gemini-cli/harness-api-design/skill.yaml +74 -0
  126. package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +1 -0
  127. package/dist/agents/skills/gemini-cli/harness-auth/SKILL.md +279 -0
  128. package/dist/agents/skills/gemini-cli/harness-auth/skill.yaml +81 -0
  129. package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +1 -0
  130. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +39 -0
  131. package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
  132. package/dist/agents/skills/gemini-cli/harness-caching/SKILL.md +309 -0
  133. package/dist/agents/skills/gemini-cli/harness-caching/skill.yaml +73 -0
  134. package/dist/agents/skills/gemini-cli/harness-chaos/SKILL.md +295 -0
  135. package/dist/agents/skills/gemini-cli/harness-chaos/skill.yaml +72 -0
  136. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +44 -0
  137. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +1 -0
  138. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +1 -0
  139. package/dist/agents/skills/gemini-cli/harness-compliance/SKILL.md +303 -0
  140. package/dist/agents/skills/gemini-cli/harness-compliance/skill.yaml +78 -0
  141. package/dist/agents/skills/gemini-cli/harness-containerization/SKILL.md +284 -0
  142. package/dist/agents/skills/gemini-cli/harness-containerization/skill.yaml +80 -0
  143. package/dist/agents/skills/gemini-cli/harness-data-pipeline/SKILL.md +274 -0
  144. package/dist/agents/skills/gemini-cli/harness-data-pipeline/skill.yaml +81 -0
  145. package/dist/agents/skills/gemini-cli/harness-data-validation/SKILL.md +343 -0
  146. package/dist/agents/skills/gemini-cli/harness-data-validation/skill.yaml +75 -0
  147. package/dist/agents/skills/gemini-cli/harness-database/SKILL.md +258 -0
  148. package/dist/agents/skills/gemini-cli/harness-database/skill.yaml +80 -0
  149. package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +1 -0
  150. package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -0
  151. package/dist/agents/skills/gemini-cli/harness-deployment/SKILL.md +255 -0
  152. package/dist/agents/skills/gemini-cli/harness-deployment/skill.yaml +77 -0
  153. package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +1 -0
  154. package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +1 -0
  155. package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +1 -0
  156. package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +1 -0
  157. package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +1 -0
  158. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +1 -0
  159. package/dist/agents/skills/gemini-cli/harness-dx/SKILL.md +276 -0
  160. package/dist/agents/skills/gemini-cli/harness-dx/skill.yaml +76 -0
  161. package/dist/agents/skills/gemini-cli/harness-e2e/SKILL.md +245 -0
  162. package/dist/agents/skills/gemini-cli/harness-e2e/skill.yaml +78 -0
  163. package/dist/agents/skills/gemini-cli/harness-event-driven/SKILL.md +280 -0
  164. package/dist/agents/skills/gemini-cli/harness-event-driven/skill.yaml +77 -0
  165. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +44 -0
  166. package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +1 -0
  167. package/dist/agents/skills/gemini-cli/harness-feature-flags/SKILL.md +287 -0
  168. package/dist/agents/skills/gemini-cli/harness-feature-flags/skill.yaml +74 -0
  169. package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +1 -0
  170. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -0
  171. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +1 -0
  172. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +1 -0
  173. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +1 -0
  174. package/dist/agents/skills/gemini-cli/harness-impact-analysis/skill.yaml +1 -0
  175. package/dist/agents/skills/gemini-cli/harness-incident-response/SKILL.md +223 -0
  176. package/dist/agents/skills/gemini-cli/harness-incident-response/skill.yaml +78 -0
  177. package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/SKILL.md +279 -0
  178. package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/skill.yaml +80 -0
  179. package/dist/agents/skills/gemini-cli/harness-integration-test/SKILL.md +271 -0
  180. package/dist/agents/skills/gemini-cli/harness-integration-test/skill.yaml +73 -0
  181. package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +1 -0
  182. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -0
  183. package/dist/agents/skills/gemini-cli/harness-load-testing/SKILL.md +274 -0
  184. package/dist/agents/skills/gemini-cli/harness-load-testing/skill.yaml +79 -0
  185. package/dist/agents/skills/gemini-cli/harness-ml-ops/SKILL.md +341 -0
  186. package/dist/agents/skills/gemini-cli/harness-ml-ops/skill.yaml +79 -0
  187. package/dist/agents/skills/gemini-cli/harness-mobile-patterns/SKILL.md +326 -0
  188. package/dist/agents/skills/gemini-cli/harness-mobile-patterns/skill.yaml +82 -0
  189. package/dist/agents/skills/gemini-cli/harness-mutation-test/SKILL.md +251 -0
  190. package/dist/agents/skills/gemini-cli/harness-mutation-test/skill.yaml +70 -0
  191. package/dist/agents/skills/gemini-cli/harness-observability/SKILL.md +283 -0
  192. package/dist/agents/skills/gemini-cli/harness-observability/skill.yaml +78 -0
  193. package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +1 -0
  194. package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +1 -0
  195. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +1 -0
  196. package/dist/agents/skills/gemini-cli/harness-perf-tdd/skill.yaml +1 -0
  197. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +39 -0
  198. package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +1 -0
  199. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +1 -0
  200. package/dist/agents/skills/gemini-cli/harness-product-spec/SKILL.md +285 -0
  201. package/dist/agents/skills/gemini-cli/harness-product-spec/skill.yaml +72 -0
  202. package/dist/agents/skills/gemini-cli/harness-property-test/SKILL.md +281 -0
  203. package/dist/agents/skills/gemini-cli/harness-property-test/skill.yaml +71 -0
  204. package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +1 -0
  205. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +3 -3
  206. package/dist/agents/skills/gemini-cli/harness-release-readiness/skill.yaml +1 -0
  207. package/dist/agents/skills/gemini-cli/harness-resilience/SKILL.md +255 -0
  208. package/dist/agents/skills/gemini-cli/harness-resilience/skill.yaml +76 -0
  209. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +1 -0
  210. package/dist/agents/skills/gemini-cli/harness-secrets/SKILL.md +293 -0
  211. package/dist/agents/skills/gemini-cli/harness-secrets/skill.yaml +76 -0
  212. package/dist/agents/skills/gemini-cli/harness-security-review/SKILL.md +240 -0
  213. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +1 -0
  214. package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -0
  215. package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +1 -0
  216. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +1 -0
  217. package/dist/agents/skills/gemini-cli/harness-sql-review/SKILL.md +315 -0
  218. package/dist/agents/skills/gemini-cli/harness-sql-review/skill.yaml +74 -0
  219. package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +1 -0
  220. package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +1 -0
  221. package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +1 -0
  222. package/dist/agents/skills/gemini-cli/harness-test-data/SKILL.md +268 -0
  223. package/dist/agents/skills/gemini-cli/harness-test-data/skill.yaml +74 -0
  224. package/dist/agents/skills/gemini-cli/harness-ux-copy/SKILL.md +271 -0
  225. package/dist/agents/skills/gemini-cli/harness-ux-copy/skill.yaml +77 -0
  226. package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +35 -0
  227. package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +1 -0
  228. package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +1 -0
  229. package/dist/agents/skills/gemini-cli/harness-visual-regression/SKILL.md +257 -0
  230. package/dist/agents/skills/gemini-cli/harness-visual-regression/skill.yaml +74 -0
  231. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +11 -3
  232. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
  233. package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +1 -0
  234. package/dist/agents-md-YTYQDA3P.js +8 -0
  235. package/dist/{architecture-ESOOE26S.js → architecture-JQZYM4US.js} +4 -4
  236. package/dist/bin/harness-mcp.js +16 -15
  237. package/dist/bin/harness.js +31 -30
  238. package/dist/{check-phase-gate-S2MZKLFQ.js → check-phase-gate-L3RADYWO.js} +4 -3
  239. package/dist/{chunk-WPPDRIJL.js → chunk-3C2MLBPJ.js} +4 -4
  240. package/dist/chunk-6KTUUFRN.js +217 -0
  241. package/dist/{chunk-MI5XJQDY.js → chunk-7IP4JIFL.js} +24 -10
  242. package/dist/{chunk-C2ERUR3L.js → chunk-7MJAPE3Z.js} +165 -49
  243. package/dist/{chunk-KELT6K6M.js → chunk-ABQHQ6I5.js} +1861 -1418
  244. package/dist/{chunk-L2KLU56K.js → chunk-AOZRDOIP.js} +2 -2
  245. package/dist/{chunk-QPEH2QPG.js → chunk-DBSOCI3G.js} +53 -54
  246. package/dist/{chunk-MHBMTPW7.js → chunk-ERS5EVUZ.js} +9 -0
  247. package/dist/{chunk-JSTQ3AWB.js → chunk-FIAPHX37.js} +1 -1
  248. package/dist/{chunk-2YPZKGAG.js → chunk-FTMXDOR6.js} +1 -1
  249. package/dist/{chunk-72GHBOL2.js → chunk-GZKSBLQL.js} +1 -1
  250. package/dist/{chunk-K6XAPGML.js → chunk-H7Y5CKTM.js} +1 -1
  251. package/dist/{chunk-HD4IBGLA.js → chunk-N5G5QMS3.js} +24 -1
  252. package/dist/{chunk-LD3DKUK5.js → chunk-NLVUVUGD.js} +1 -1
  253. package/dist/{chunk-3KOLLWWE.js → chunk-O5OJVPL6.js} +26 -211
  254. package/dist/{chunk-NKDM3FMH.js → chunk-OD3S2NHN.js} +1 -1
  255. package/dist/{chunk-5VY23YK3.js → chunk-OSXBPAMK.js} +2 -2
  256. package/dist/{chunk-MACVXDZK.js → chunk-OXLLOSSR.js} +45 -47
  257. package/dist/{chunk-GNGELAXY.js → chunk-RCWZBSK5.js} +2 -2
  258. package/dist/{chunk-PSNN4LWX.js → chunk-S2FXOWOR.js} +3 -3
  259. package/dist/{chunk-VUCPTQ6G.js → chunk-SD3SQOZ2.js} +1 -1
  260. package/dist/{chunk-7PZWR4LI.js → chunk-TPOTOBR7.js} +9 -9
  261. package/dist/{chunk-RZSUJBZZ.js → chunk-XKECDXJS.js} +452 -353
  262. package/dist/{chunk-VRFZWGMS.js → chunk-XYLGHKG6.js} +5 -1
  263. package/dist/{chunk-6N4R6FVX.js → chunk-YBJ262QL.js} +1 -1
  264. package/dist/{chunk-2VU4MFM3.js → chunk-YPYGXRDR.js} +7 -7
  265. package/dist/{chunk-Q6AB7W5Z.js → chunk-YQ6KC6TE.js} +1 -1
  266. package/dist/{chunk-7KQSUZVG.js → chunk-YZD2MRNQ.js} +1528 -1010
  267. package/dist/ci-workflow-EQZFVX3P.js +8 -0
  268. package/dist/{create-skill-WPXHSLX2.js → create-skill-XSWHMSM5.js} +2 -2
  269. package/dist/{dist-M6BQODWC.js → dist-B26DFXMP.js} +573 -480
  270. package/dist/{dist-L7LAAQAS.js → dist-DZ63LLUD.js} +1 -1
  271. package/dist/{dist-WF4C7A4A.js → dist-HWXF2C3R.js} +18 -2
  272. package/dist/{dist-D4RYGUZE.js → dist-USY2C5JL.js} +3 -1
  273. package/dist/{docs-BPYCN2DR.js → docs-7ECGYMAV.js} +5 -3
  274. package/dist/engine-EG4EH4IX.js +8 -0
  275. package/dist/{entropy-4VDVV5CR.js → entropy-5USWKLVS.js} +3 -3
  276. package/dist/{feedback-63QB5RCA.js → feedback-UTBXZZHF.js} +1 -1
  277. package/dist/{generate-agent-definitions-QABOJG56.js → generate-agent-definitions-3PM5EU7V.js} +5 -5
  278. package/dist/{glob-helper-5OHBUQAI.js → glob-helper-R5FXNUPS.js} +1 -1
  279. package/dist/{graph-loader-KO4GJ5N2.js → graph-loader-2M2HXDQI.js} +1 -1
  280. package/dist/index.d.ts +183 -17
  281. package/dist/index.js +32 -30
  282. package/dist/loader-ZPALXIVR.js +10 -0
  283. package/dist/mcp-362EZHF4.js +35 -0
  284. package/dist/{performance-26BH47O4.js → performance-OQAFMJUD.js} +3 -3
  285. package/dist/{review-pipeline-GHR3WFBI.js → review-pipeline-C4GCFVGP.js} +1 -1
  286. package/dist/runtime-7YLVK453.js +9 -0
  287. package/dist/{security-UQFUZXEN.js → security-PZOX7AQS.js} +1 -1
  288. package/dist/skill-executor-XZLYZYAK.js +8 -0
  289. package/dist/templates/axum/Cargo.toml.hbs +8 -0
  290. package/dist/templates/axum/src/main.rs +12 -0
  291. package/dist/templates/axum/template.json +16 -0
  292. package/dist/templates/django/manage.py.hbs +19 -0
  293. package/dist/templates/django/requirements.txt.hbs +1 -0
  294. package/dist/templates/django/src/settings.py.hbs +44 -0
  295. package/dist/templates/django/src/urls.py +6 -0
  296. package/dist/templates/django/src/wsgi.py.hbs +9 -0
  297. package/dist/templates/django/template.json +21 -0
  298. package/dist/templates/express/package.json.hbs +15 -0
  299. package/dist/templates/express/src/app.ts +12 -0
  300. package/dist/templates/express/src/lib/.gitkeep +0 -0
  301. package/dist/templates/express/template.json +16 -0
  302. package/dist/templates/fastapi/requirements.txt.hbs +2 -0
  303. package/dist/templates/fastapi/src/main.py +8 -0
  304. package/dist/templates/fastapi/template.json +20 -0
  305. package/dist/templates/gin/go.mod.hbs +5 -0
  306. package/dist/templates/gin/main.go +15 -0
  307. package/dist/templates/gin/template.json +19 -0
  308. package/dist/templates/go-base/.golangci.yml +16 -0
  309. package/dist/templates/go-base/AGENTS.md.hbs +35 -0
  310. package/dist/templates/go-base/go.mod.hbs +3 -0
  311. package/dist/templates/go-base/harness.config.json.hbs +17 -0
  312. package/dist/templates/go-base/main.go +7 -0
  313. package/dist/templates/go-base/template.json +14 -0
  314. package/dist/templates/java-base/AGENTS.md.hbs +35 -0
  315. package/dist/templates/java-base/checkstyle.xml +20 -0
  316. package/dist/templates/java-base/harness.config.json.hbs +16 -0
  317. package/dist/templates/java-base/pom.xml.hbs +39 -0
  318. package/dist/templates/java-base/src/main/java/App.java.hbs +5 -0
  319. package/dist/templates/java-base/template.json +13 -0
  320. package/dist/templates/nestjs/nest-cli.json +5 -0
  321. package/dist/templates/nestjs/package.json.hbs +18 -0
  322. package/dist/templates/nestjs/src/app.module.ts +8 -0
  323. package/dist/templates/nestjs/src/lib/.gitkeep +0 -0
  324. package/dist/templates/nestjs/src/main.ts +11 -0
  325. package/dist/templates/nestjs/template.json +16 -0
  326. package/dist/templates/nextjs/template.json +15 -1
  327. package/dist/templates/python-base/.python-version +1 -0
  328. package/dist/templates/python-base/AGENTS.md.hbs +32 -0
  329. package/dist/templates/python-base/harness.config.json.hbs +16 -0
  330. package/dist/templates/python-base/pyproject.toml.hbs +18 -0
  331. package/dist/templates/python-base/ruff.toml +5 -0
  332. package/dist/templates/python-base/src/__init__.py +0 -0
  333. package/dist/templates/python-base/template.json +13 -0
  334. package/dist/templates/react-vite/index.html +12 -0
  335. package/dist/templates/react-vite/package.json.hbs +18 -0
  336. package/dist/templates/react-vite/src/App.tsx +7 -0
  337. package/dist/templates/react-vite/src/lib/.gitkeep +0 -0
  338. package/dist/templates/react-vite/src/main.tsx +9 -0
  339. package/dist/templates/react-vite/template.json +19 -0
  340. package/dist/templates/react-vite/vite.config.ts +6 -0
  341. package/dist/templates/rust-base/AGENTS.md.hbs +35 -0
  342. package/dist/templates/rust-base/Cargo.toml.hbs +6 -0
  343. package/dist/templates/rust-base/clippy.toml +2 -0
  344. package/dist/templates/rust-base/harness.config.json.hbs +17 -0
  345. package/dist/templates/rust-base/src/main.rs +3 -0
  346. package/dist/templates/rust-base/template.json +14 -0
  347. package/dist/templates/spring-boot/pom.xml.hbs +50 -0
  348. package/dist/templates/spring-boot/src/main/java/Application.java.hbs +19 -0
  349. package/dist/templates/spring-boot/template.json +15 -0
  350. package/dist/templates/vue/index.html +12 -0
  351. package/dist/templates/vue/package.json.hbs +16 -0
  352. package/dist/templates/vue/src/App.vue +7 -0
  353. package/dist/templates/vue/src/lib/.gitkeep +0 -0
  354. package/dist/templates/vue/src/main.ts +4 -0
  355. package/dist/templates/vue/template.json +19 -0
  356. package/dist/templates/vue/vite.config.ts +6 -0
  357. package/dist/{validate-N7QJOKFZ.js → validate-FD3Z6VJD.js} +4 -4
  358. package/dist/validate-cross-check-WNJM6H2D.js +8 -0
  359. package/package.json +6 -6
  360. package/dist/agents-md-P2RHSUV7.js +0 -8
  361. package/dist/ci-workflow-4NYBUG6R.js +0 -8
  362. package/dist/engine-LXLIWQQ3.js +0 -8
  363. package/dist/loader-Z2IT7QX3.js +0 -10
  364. package/dist/mcp-KQHEL5IF.js +0 -34
  365. package/dist/runtime-PDWD7UIK.js +0 -9
  366. package/dist/skill-executor-RG45LUO5.js +0 -8
  367. package/dist/validate-cross-check-EDQ5QGTM.js +0 -8
@@ -361,6 +361,53 @@ var VectorStore = class _VectorStore {
361
361
  return store;
362
362
  }
363
363
  };
364
+ function edgeKey(e) {
365
+ return `${e.from}|${e.to}|${e.type}`;
366
+ }
367
+ function addEdge(state, edge) {
368
+ const key = edgeKey(edge);
369
+ if (!state.edgeSet.has(key)) {
370
+ state.edgeSet.add(key);
371
+ state.resultEdges.push(edge);
372
+ }
373
+ }
374
+ function shouldPruneNode(neighbor, pruneObservability, params) {
375
+ if (pruneObservability && OBSERVABILITY_TYPES.has(neighbor.type)) return true;
376
+ if (params.includeTypes && !params.includeTypes.includes(neighbor.type)) return true;
377
+ if (params.excludeTypes && params.excludeTypes.includes(neighbor.type)) return true;
378
+ return false;
379
+ }
380
+ function isEdgeExcluded(edge, params) {
381
+ return !!(params.includeEdges && !params.includeEdges.includes(edge.type));
382
+ }
383
+ function processNeighbor(store, edge, neighborId, nextDepth, queue, state, pruneObservability, params) {
384
+ if (isEdgeExcluded(edge, params)) return;
385
+ if (state.visited.has(neighborId)) {
386
+ addEdge(state, edge);
387
+ return;
388
+ }
389
+ const neighbor = store.getNode(neighborId);
390
+ if (!neighbor) return;
391
+ state.visited.add(neighborId);
392
+ if (shouldPruneNode(neighbor, pruneObservability, params)) {
393
+ state.pruned++;
394
+ return;
395
+ }
396
+ state.resultNodeMap.set(neighborId, neighbor);
397
+ addEdge(state, edge);
398
+ queue.push({ id: neighborId, depth: nextDepth });
399
+ }
400
+ function addCrossEdges(store, state) {
401
+ const resultNodeIds = new Set(state.resultNodeMap.keys());
402
+ for (const nodeId of resultNodeIds) {
403
+ const outEdges = store.getEdges({ from: nodeId });
404
+ for (const edge of outEdges) {
405
+ if (resultNodeIds.has(edge.to)) {
406
+ addEdge(state, edge);
407
+ }
408
+ }
409
+ }
410
+ }
364
411
  var ContextQL = class {
365
412
  store;
366
413
  constructor(store) {
@@ -370,89 +417,69 @@ var ContextQL = class {
370
417
  const maxDepth = params.maxDepth ?? 3;
371
418
  const bidirectional = params.bidirectional ?? false;
372
419
  const pruneObservability = params.pruneObservability ?? true;
373
- const visited = /* @__PURE__ */ new Set();
374
- const resultNodeMap = /* @__PURE__ */ new Map();
375
- const resultEdges = [];
376
- const edgeSet = /* @__PURE__ */ new Set();
377
- let pruned = 0;
378
- let depthReached = 0;
379
- const edgeKey = (e) => `${e.from}|${e.to}|${e.type}`;
380
- const addEdge = (edge) => {
381
- const key = edgeKey(edge);
382
- if (!edgeSet.has(key)) {
383
- edgeSet.add(key);
384
- resultEdges.push(edge);
385
- }
420
+ const state = {
421
+ visited: /* @__PURE__ */ new Set(),
422
+ resultNodeMap: /* @__PURE__ */ new Map(),
423
+ resultEdges: [],
424
+ edgeSet: /* @__PURE__ */ new Set(),
425
+ pruned: 0,
426
+ depthReached: 0
386
427
  };
387
428
  const queue = [];
388
- for (const rootId of params.rootNodeIds) {
429
+ this.seedRootNodes(params.rootNodeIds, state, queue);
430
+ this.runBFS(queue, maxDepth, bidirectional, pruneObservability, params, state);
431
+ addCrossEdges(this.store, state);
432
+ return {
433
+ nodes: Array.from(state.resultNodeMap.values()),
434
+ edges: state.resultEdges,
435
+ stats: {
436
+ totalTraversed: state.visited.size,
437
+ totalReturned: state.resultNodeMap.size,
438
+ pruned: state.pruned,
439
+ depthReached: state.depthReached
440
+ }
441
+ };
442
+ }
443
+ seedRootNodes(rootNodeIds, state, queue) {
444
+ for (const rootId of rootNodeIds) {
389
445
  const node = this.store.getNode(rootId);
390
446
  if (node) {
391
- visited.add(rootId);
392
- resultNodeMap.set(rootId, node);
447
+ state.visited.add(rootId);
448
+ state.resultNodeMap.set(rootId, node);
393
449
  queue.push({ id: rootId, depth: 0 });
394
450
  }
395
451
  }
452
+ }
453
+ runBFS(queue, maxDepth, bidirectional, pruneObservability, params, state) {
396
454
  let head = 0;
397
455
  while (head < queue.length) {
398
456
  const entry = queue[head++];
399
457
  const { id: currentId, depth } = entry;
400
458
  if (depth >= maxDepth) continue;
401
459
  const nextDepth = depth + 1;
402
- if (nextDepth > depthReached) depthReached = nextDepth;
403
- const outEdges = this.store.getEdges({ from: currentId });
404
- const inEdges = bidirectional ? this.store.getEdges({ to: currentId }) : [];
405
- const allEdges = [
406
- ...outEdges.map((e) => ({ edge: e, neighborId: e.to })),
407
- ...inEdges.map((e) => ({ edge: e, neighborId: e.from }))
408
- ];
460
+ if (nextDepth > state.depthReached) state.depthReached = nextDepth;
461
+ const allEdges = this.gatherEdges(currentId, bidirectional);
409
462
  for (const { edge, neighborId } of allEdges) {
410
- if (params.includeEdges && !params.includeEdges.includes(edge.type)) {
411
- continue;
412
- }
413
- if (visited.has(neighborId)) {
414
- addEdge(edge);
415
- continue;
416
- }
417
- const neighbor = this.store.getNode(neighborId);
418
- if (!neighbor) continue;
419
- visited.add(neighborId);
420
- if (pruneObservability && OBSERVABILITY_TYPES.has(neighbor.type)) {
421
- pruned++;
422
- continue;
423
- }
424
- if (params.includeTypes && !params.includeTypes.includes(neighbor.type)) {
425
- pruned++;
426
- continue;
427
- }
428
- if (params.excludeTypes && params.excludeTypes.includes(neighbor.type)) {
429
- pruned++;
430
- continue;
431
- }
432
- resultNodeMap.set(neighborId, neighbor);
433
- addEdge(edge);
434
- queue.push({ id: neighborId, depth: nextDepth });
435
- }
436
- }
437
- const resultNodeIds = new Set(resultNodeMap.keys());
438
- for (const nodeId of resultNodeIds) {
439
- const outEdges = this.store.getEdges({ from: nodeId });
440
- for (const edge of outEdges) {
441
- if (resultNodeIds.has(edge.to)) {
442
- addEdge(edge);
443
- }
463
+ processNeighbor(
464
+ this.store,
465
+ edge,
466
+ neighborId,
467
+ nextDepth,
468
+ queue,
469
+ state,
470
+ pruneObservability,
471
+ params
472
+ );
444
473
  }
445
474
  }
446
- return {
447
- nodes: Array.from(resultNodeMap.values()),
448
- edges: resultEdges,
449
- stats: {
450
- totalTraversed: visited.size,
451
- totalReturned: resultNodeMap.size,
452
- pruned,
453
- depthReached
454
- }
455
- };
475
+ }
476
+ gatherEdges(nodeId, bidirectional) {
477
+ const outEdges = this.store.getEdges({ from: nodeId });
478
+ const inEdges = bidirectional ? this.store.getEdges({ to: nodeId }) : [];
479
+ return [
480
+ ...outEdges.map((e) => ({ edge: e, neighborId: e.to })),
481
+ ...inEdges.map((e) => ({ edge: e, neighborId: e.from }))
482
+ ];
456
483
  }
457
484
  };
458
485
  function project(nodes, spec) {
@@ -497,6 +524,15 @@ function groupNodesByImpact(nodes, excludeId) {
497
524
  }
498
525
  return { tests, docs, code, other };
499
526
  }
527
+ var SKIP_METHOD_NAMES = /* @__PURE__ */ new Set(["constructor", "if", "for", "while", "switch"]);
528
+ function countBraces(line) {
529
+ let net = 0;
530
+ for (const ch of line) {
531
+ if (ch === "{") net++;
532
+ else if (ch === "}") net--;
533
+ }
534
+ return net;
535
+ }
500
536
  var CodeIngestor = class {
501
537
  constructor(store) {
502
538
  this.store = store;
@@ -511,41 +547,9 @@ var CodeIngestor = class {
511
547
  const fileContents = /* @__PURE__ */ new Map();
512
548
  for (const filePath of files) {
513
549
  try {
514
- const relativePath = path.relative(rootDir, filePath).replace(/\\/g, "/");
515
- const content = await fs.readFile(filePath, "utf-8");
516
- const stat2 = await fs.stat(filePath);
517
- const fileId = `file:${relativePath}`;
518
- fileContents.set(relativePath, content);
519
- const fileNode = {
520
- id: fileId,
521
- type: "file",
522
- name: path.basename(filePath),
523
- path: relativePath,
524
- metadata: { language: this.detectLanguage(filePath) },
525
- lastModified: stat2.mtime.toISOString()
526
- };
527
- this.store.addNode(fileNode);
528
- nodesAdded++;
529
- const symbols = this.extractSymbols(content, fileId, relativePath);
530
- for (const { node, edge } of symbols) {
531
- this.store.addNode(node);
532
- this.store.addEdge(edge);
533
- nodesAdded++;
534
- edgesAdded++;
535
- if (node.type === "function" || node.type === "method") {
536
- let files2 = nameToFiles.get(node.name);
537
- if (!files2) {
538
- files2 = /* @__PURE__ */ new Set();
539
- nameToFiles.set(node.name, files2);
540
- }
541
- files2.add(relativePath);
542
- }
543
- }
544
- const imports = await this.extractImports(content, fileId, relativePath, rootDir);
545
- for (const edge of imports) {
546
- this.store.addEdge(edge);
547
- edgesAdded++;
548
- }
550
+ const result = await this.processFile(filePath, rootDir, nameToFiles, fileContents);
551
+ nodesAdded += result.nodesAdded;
552
+ edgesAdded += result.edgesAdded;
549
553
  } catch (err) {
550
554
  errors.push(`${filePath}: ${err instanceof Error ? err.message : String(err)}`);
551
555
  }
@@ -564,6 +568,48 @@ var CodeIngestor = class {
564
568
  durationMs: Date.now() - start
565
569
  };
566
570
  }
571
+ async processFile(filePath, rootDir, nameToFiles, fileContents) {
572
+ let nodesAdded = 0;
573
+ let edgesAdded = 0;
574
+ const relativePath = path.relative(rootDir, filePath).replace(/\\/g, "/");
575
+ const content = await fs.readFile(filePath, "utf-8");
576
+ const stat2 = await fs.stat(filePath);
577
+ const fileId = `file:${relativePath}`;
578
+ fileContents.set(relativePath, content);
579
+ const fileNode = {
580
+ id: fileId,
581
+ type: "file",
582
+ name: path.basename(filePath),
583
+ path: relativePath,
584
+ metadata: { language: this.detectLanguage(filePath) },
585
+ lastModified: stat2.mtime.toISOString()
586
+ };
587
+ this.store.addNode(fileNode);
588
+ nodesAdded++;
589
+ const symbols = this.extractSymbols(content, fileId, relativePath);
590
+ for (const { node, edge } of symbols) {
591
+ this.store.addNode(node);
592
+ this.store.addEdge(edge);
593
+ nodesAdded++;
594
+ edgesAdded++;
595
+ this.trackCallable(node, relativePath, nameToFiles);
596
+ }
597
+ const imports = await this.extractImports(content, fileId, relativePath, rootDir);
598
+ for (const edge of imports) {
599
+ this.store.addEdge(edge);
600
+ edgesAdded++;
601
+ }
602
+ return { nodesAdded, edgesAdded };
603
+ }
604
+ trackCallable(node, relativePath, nameToFiles) {
605
+ if (node.type !== "function" && node.type !== "method") return;
606
+ let files = nameToFiles.get(node.name);
607
+ if (!files) {
608
+ files = /* @__PURE__ */ new Set();
609
+ nameToFiles.set(node.name, files);
610
+ }
611
+ files.add(relativePath);
612
+ }
567
613
  async findSourceFiles(dir) {
568
614
  const results = [];
569
615
  const entries = await fs.readdir(dir, { withFileTypes: true });
@@ -580,149 +626,152 @@ var CodeIngestor = class {
580
626
  extractSymbols(content, fileId, relativePath) {
581
627
  const results = [];
582
628
  const lines = content.split("\n");
583
- let currentClassName = null;
584
- let currentClassId = null;
585
- let braceDepth = 0;
586
- let insideClass = false;
629
+ const ctx = { className: null, classId: null, insideClass: false, braceDepth: 0 };
587
630
  for (let i = 0; i < lines.length; i++) {
588
631
  const line = lines[i];
589
- const fnMatch = line.match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)/);
590
- if (fnMatch) {
591
- const name = fnMatch[1];
592
- const id = `function:${relativePath}:${name}`;
593
- const endLine = this.findClosingBrace(lines, i);
594
- results.push({
595
- node: {
596
- id,
597
- type: "function",
598
- name,
599
- path: relativePath,
600
- location: { fileId, startLine: i + 1, endLine },
601
- metadata: {
602
- exported: line.includes("export"),
603
- cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
604
- nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
605
- lineCount: endLine - i,
606
- parameterCount: this.countParameters(line)
607
- }
608
- },
609
- edge: { from: fileId, to: id, type: "contains" }
610
- });
611
- if (!insideClass) {
612
- currentClassName = null;
613
- currentClassId = null;
614
- }
615
- continue;
616
- }
617
- const classMatch = line.match(/(?:export\s+)?class\s+(\w+)/);
618
- if (classMatch) {
619
- const name = classMatch[1];
620
- const id = `class:${relativePath}:${name}`;
621
- const endLine = this.findClosingBrace(lines, i);
622
- results.push({
623
- node: {
624
- id,
625
- type: "class",
626
- name,
627
- path: relativePath,
628
- location: { fileId, startLine: i + 1, endLine },
629
- metadata: { exported: line.includes("export") }
630
- },
631
- edge: { from: fileId, to: id, type: "contains" }
632
- });
633
- currentClassName = name;
634
- currentClassId = id;
635
- insideClass = true;
636
- braceDepth = 0;
637
- for (const ch of line) {
638
- if (ch === "{") braceDepth++;
639
- if (ch === "}") braceDepth--;
640
- }
641
- continue;
642
- }
643
- const ifaceMatch = line.match(/(?:export\s+)?interface\s+(\w+)/);
644
- if (ifaceMatch) {
645
- const name = ifaceMatch[1];
646
- const id = `interface:${relativePath}:${name}`;
647
- const endLine = this.findClosingBrace(lines, i);
648
- results.push({
649
- node: {
650
- id,
651
- type: "interface",
652
- name,
653
- path: relativePath,
654
- location: { fileId, startLine: i + 1, endLine },
655
- metadata: { exported: line.includes("export") }
656
- },
657
- edge: { from: fileId, to: id, type: "contains" }
658
- });
659
- currentClassName = null;
660
- currentClassId = null;
661
- insideClass = false;
662
- continue;
663
- }
664
- if (insideClass) {
665
- for (const ch of line) {
666
- if (ch === "{") braceDepth++;
667
- if (ch === "}") braceDepth--;
668
- }
669
- if (braceDepth <= 0) {
670
- currentClassName = null;
671
- currentClassId = null;
672
- insideClass = false;
673
- continue;
674
- }
675
- }
676
- if (insideClass && currentClassName && currentClassId) {
677
- const methodMatch = line.match(
678
- /^\s+(?:(?:public|private|protected|readonly|static|abstract)\s+)*(?:async\s+)?(\w+)\s*\(/
679
- );
680
- if (methodMatch) {
681
- const methodName = methodMatch[1];
682
- if (methodName === "constructor" || methodName === "if" || methodName === "for" || methodName === "while" || methodName === "switch")
683
- continue;
684
- const id = `method:${relativePath}:${currentClassName}.${methodName}`;
685
- const endLine = this.findClosingBrace(lines, i);
686
- results.push({
687
- node: {
688
- id,
689
- type: "method",
690
- name: methodName,
691
- path: relativePath,
692
- location: { fileId, startLine: i + 1, endLine },
693
- metadata: {
694
- className: currentClassName,
695
- exported: false,
696
- cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
697
- nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
698
- lineCount: endLine - i,
699
- parameterCount: this.countParameters(line)
700
- }
701
- },
702
- edge: { from: currentClassId, to: id, type: "contains" }
703
- });
704
- }
705
- continue;
706
- }
707
- const varMatch = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)/);
708
- if (varMatch) {
709
- const name = varMatch[1];
710
- const id = `variable:${relativePath}:${name}`;
711
- results.push({
712
- node: {
713
- id,
714
- type: "variable",
715
- name,
716
- path: relativePath,
717
- location: { fileId, startLine: i + 1, endLine: i + 1 },
718
- metadata: { exported: line.includes("export") }
719
- },
720
- edge: { from: fileId, to: id, type: "contains" }
721
- });
722
- }
632
+ if (this.tryExtractFunction(line, lines, i, fileId, relativePath, ctx, results)) continue;
633
+ if (this.tryExtractClass(line, lines, i, fileId, relativePath, ctx, results)) continue;
634
+ if (this.tryExtractInterface(line, lines, i, fileId, relativePath, ctx, results)) continue;
635
+ if (this.updateClassContext(line, ctx)) continue;
636
+ if (this.tryExtractMethod(line, lines, i, fileId, relativePath, ctx, results)) continue;
637
+ if (ctx.insideClass) continue;
638
+ this.tryExtractVariable(line, i, fileId, relativePath, results);
723
639
  }
724
640
  return results;
725
641
  }
642
+ tryExtractFunction(line, lines, i, fileId, relativePath, ctx, results) {
643
+ const fnMatch = line.match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)/);
644
+ if (!fnMatch) return false;
645
+ const name = fnMatch[1];
646
+ const id = `function:${relativePath}:${name}`;
647
+ const endLine = this.findClosingBrace(lines, i);
648
+ results.push({
649
+ node: {
650
+ id,
651
+ type: "function",
652
+ name,
653
+ path: relativePath,
654
+ location: { fileId, startLine: i + 1, endLine },
655
+ metadata: {
656
+ exported: line.includes("export"),
657
+ cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
658
+ nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
659
+ lineCount: endLine - i,
660
+ parameterCount: this.countParameters(line)
661
+ }
662
+ },
663
+ edge: { from: fileId, to: id, type: "contains" }
664
+ });
665
+ if (!ctx.insideClass) {
666
+ ctx.className = null;
667
+ ctx.classId = null;
668
+ }
669
+ return true;
670
+ }
671
+ tryExtractClass(line, lines, i, fileId, relativePath, ctx, results) {
672
+ const classMatch = line.match(/(?:export\s+)?class\s+(\w+)/);
673
+ if (!classMatch) return false;
674
+ const name = classMatch[1];
675
+ const id = `class:${relativePath}:${name}`;
676
+ const endLine = this.findClosingBrace(lines, i);
677
+ results.push({
678
+ node: {
679
+ id,
680
+ type: "class",
681
+ name,
682
+ path: relativePath,
683
+ location: { fileId, startLine: i + 1, endLine },
684
+ metadata: { exported: line.includes("export") }
685
+ },
686
+ edge: { from: fileId, to: id, type: "contains" }
687
+ });
688
+ ctx.className = name;
689
+ ctx.classId = id;
690
+ ctx.insideClass = true;
691
+ ctx.braceDepth = countBraces(line);
692
+ return true;
693
+ }
694
+ tryExtractInterface(line, lines, i, fileId, relativePath, ctx, results) {
695
+ const ifaceMatch = line.match(/(?:export\s+)?interface\s+(\w+)/);
696
+ if (!ifaceMatch) return false;
697
+ const name = ifaceMatch[1];
698
+ const id = `interface:${relativePath}:${name}`;
699
+ const endLine = this.findClosingBrace(lines, i);
700
+ results.push({
701
+ node: {
702
+ id,
703
+ type: "interface",
704
+ name,
705
+ path: relativePath,
706
+ location: { fileId, startLine: i + 1, endLine },
707
+ metadata: { exported: line.includes("export") }
708
+ },
709
+ edge: { from: fileId, to: id, type: "contains" }
710
+ });
711
+ ctx.className = null;
712
+ ctx.classId = null;
713
+ ctx.insideClass = false;
714
+ return true;
715
+ }
716
+ /** Update brace tracking; returns true when line is consumed (class ended or tracked). */
717
+ updateClassContext(line, ctx) {
718
+ if (!ctx.insideClass) return false;
719
+ ctx.braceDepth += countBraces(line);
720
+ if (ctx.braceDepth <= 0) {
721
+ ctx.className = null;
722
+ ctx.classId = null;
723
+ ctx.insideClass = false;
724
+ return true;
725
+ }
726
+ return false;
727
+ }
728
+ tryExtractMethod(line, lines, i, fileId, relativePath, ctx, results) {
729
+ if (!ctx.insideClass || !ctx.className || !ctx.classId) return false;
730
+ const methodMatch = line.match(
731
+ /^\s+(?:(?:public|private|protected|readonly|static|abstract)\s+)*(?:async\s+)?(\w+)\s*\(/
732
+ );
733
+ if (!methodMatch) return false;
734
+ const methodName = methodMatch[1];
735
+ if (SKIP_METHOD_NAMES.has(methodName)) return false;
736
+ const id = `method:${relativePath}:${ctx.className}.${methodName}`;
737
+ const endLine = this.findClosingBrace(lines, i);
738
+ results.push({
739
+ node: {
740
+ id,
741
+ type: "method",
742
+ name: methodName,
743
+ path: relativePath,
744
+ location: { fileId, startLine: i + 1, endLine },
745
+ metadata: {
746
+ className: ctx.className,
747
+ exported: false,
748
+ cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
749
+ nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
750
+ lineCount: endLine - i,
751
+ parameterCount: this.countParameters(line)
752
+ }
753
+ },
754
+ edge: { from: ctx.classId, to: id, type: "contains" }
755
+ });
756
+ return true;
757
+ }
758
+ tryExtractVariable(line, i, fileId, relativePath, results) {
759
+ const varMatch = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)/);
760
+ if (!varMatch) return;
761
+ const name = varMatch[1];
762
+ const id = `variable:${relativePath}:${name}`;
763
+ results.push({
764
+ node: {
765
+ id,
766
+ type: "variable",
767
+ name,
768
+ path: relativePath,
769
+ location: { fileId, startLine: i + 1, endLine: i + 1 },
770
+ metadata: { exported: line.includes("export") }
771
+ },
772
+ edge: { from: fileId, to: id, type: "contains" }
773
+ });
774
+ }
726
775
  /**
727
776
  * Find the closing brace for a construct starting at the given line.
728
777
  * Uses a simple brace-counting heuristic. Returns 1-indexed line number.
@@ -1324,17 +1373,33 @@ var KnowledgeIngestor = class {
1324
1373
  }
1325
1374
  };
1326
1375
  var CODE_NODE_TYPES2 = ["file", "function", "class", "method", "interface", "variable"];
1376
+ var SANITIZE_RULES = [
1377
+ // Strip XML/HTML-like instruction tags that could be interpreted as system prompts
1378
+ {
1379
+ pattern: /<\/?(?:system|instruction|prompt|role|context|tool_call|function_call|assistant|human|user)[^>]*>/gi,
1380
+ replacement: ""
1381
+ },
1382
+ // Strip markdown-style system prompt markers (including trailing space)
1383
+ {
1384
+ pattern: /^#{1,3}\s*(?:system|instruction|prompt)\s*[::]\s*/gim,
1385
+ replacement: ""
1386
+ },
1387
+ // Strip common injection prefixes
1388
+ {
1389
+ pattern: /(?:ignore|disregard|forget)\s+(?:all\s+)?(?:previous|prior|above)\s+(?:instructions?|prompts?|context)/gi,
1390
+ replacement: "[filtered]"
1391
+ },
1392
+ // Strip "you are now" re-roling attempts (only when followed by AI/agent role words)
1393
+ {
1394
+ pattern: /you\s+are\s+now\s+(?:a\s+)?(?:helpful\s+)?(?:an?\s+)?(?:assistant|system|ai|bot|agent|tool)\b/gi,
1395
+ replacement: "[filtered]"
1396
+ }
1397
+ ];
1327
1398
  function sanitizeExternalText(text, maxLength = 2e3) {
1328
- let sanitized = text.replace(
1329
- /<\/?(?:system|instruction|prompt|role|context|tool_call|function_call|assistant|human|user)[^>]*>/gi,
1330
- ""
1331
- ).replace(/^#{1,3}\s*(?:system|instruction|prompt)\s*[::]\s*/gim, "").replace(
1332
- /(?:ignore|disregard|forget)\s+(?:all\s+)?(?:previous|prior|above)\s+(?:instructions?|prompts?|context)/gi,
1333
- "[filtered]"
1334
- ).replace(
1335
- /you\s+are\s+now\s+(?:a\s+)?(?:helpful\s+)?(?:an?\s+)?(?:assistant|system|ai|bot|agent|tool)\b/gi,
1336
- "[filtered]"
1337
- );
1399
+ let sanitized = text;
1400
+ for (const rule of SANITIZE_RULES) {
1401
+ sanitized = sanitized.replace(rule.pattern, rule.replacement);
1402
+ }
1338
1403
  if (sanitized.length > maxLength) {
1339
1404
  sanitized = sanitized.slice(0, maxLength) + "\u2026";
1340
1405
  }
@@ -1428,6 +1493,28 @@ var SyncManager = class {
1428
1493
  await fs3.writeFile(this.metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
1429
1494
  }
1430
1495
  };
1496
+ function buildIngestResult(nodesAdded, edgesAdded, errors, start) {
1497
+ return {
1498
+ nodesAdded,
1499
+ nodesUpdated: 0,
1500
+ edgesAdded,
1501
+ edgesUpdated: 0,
1502
+ errors,
1503
+ durationMs: Date.now() - start
1504
+ };
1505
+ }
1506
+ function buildJql(config) {
1507
+ const project2 = config.project;
1508
+ let jql = project2 ? `project=${project2}` : "";
1509
+ const filters = config.filters;
1510
+ if (filters?.status?.length) {
1511
+ jql += `${jql ? " AND " : ""}status IN (${filters.status.map((s) => `"${s}"`).join(",")})`;
1512
+ }
1513
+ if (filters?.labels?.length) {
1514
+ jql += `${jql ? " AND " : ""}labels IN (${filters.labels.map((l) => `"${l}"`).join(",")})`;
1515
+ }
1516
+ return jql;
1517
+ }
1431
1518
  var JiraConnector = class {
1432
1519
  name = "jira";
1433
1520
  source = "jira";
@@ -1437,105 +1524,81 @@ var JiraConnector = class {
1437
1524
  }
1438
1525
  async ingest(store, config) {
1439
1526
  const start = Date.now();
1440
- const errors = [];
1441
1527
  let nodesAdded = 0;
1442
1528
  let edgesAdded = 0;
1443
1529
  const apiKeyEnv = config.apiKeyEnv ?? "JIRA_API_KEY";
1444
1530
  const apiKey = process.env[apiKeyEnv];
1445
1531
  if (!apiKey) {
1446
- return {
1447
- nodesAdded: 0,
1448
- nodesUpdated: 0,
1449
- edgesAdded: 0,
1450
- edgesUpdated: 0,
1451
- errors: [`Missing API key: environment variable "${apiKeyEnv}" is not set`],
1452
- durationMs: Date.now() - start
1453
- };
1532
+ return buildIngestResult(
1533
+ 0,
1534
+ 0,
1535
+ [`Missing API key: environment variable "${apiKeyEnv}" is not set`],
1536
+ start
1537
+ );
1454
1538
  }
1455
1539
  const baseUrlEnv = config.baseUrlEnv ?? "JIRA_BASE_URL";
1456
1540
  const baseUrl = process.env[baseUrlEnv];
1457
1541
  if (!baseUrl) {
1458
- return {
1459
- nodesAdded: 0,
1460
- nodesUpdated: 0,
1461
- edgesAdded: 0,
1462
- edgesUpdated: 0,
1463
- errors: [`Missing base URL: environment variable "${baseUrlEnv}" is not set`],
1464
- durationMs: Date.now() - start
1465
- };
1466
- }
1467
- const project2 = config.project;
1468
- let jql = project2 ? `project=${project2}` : "";
1469
- const filters = config.filters;
1470
- if (filters?.status?.length) {
1471
- jql += `${jql ? " AND " : ""}status IN (${filters.status.map((s) => `"${s}"`).join(",")})`;
1472
- }
1473
- if (filters?.labels?.length) {
1474
- jql += `${jql ? " AND " : ""}labels IN (${filters.labels.map((l) => `"${l}"`).join(",")})`;
1542
+ return buildIngestResult(
1543
+ 0,
1544
+ 0,
1545
+ [`Missing base URL: environment variable "${baseUrlEnv}" is not set`],
1546
+ start
1547
+ );
1475
1548
  }
1549
+ const jql = buildJql(config);
1476
1550
  const headers = {
1477
1551
  Authorization: `Basic ${apiKey}`,
1478
1552
  "Content-Type": "application/json"
1479
1553
  };
1480
- let startAt = 0;
1481
- const maxResults = 50;
1482
- let total = Infinity;
1483
1554
  try {
1555
+ let startAt = 0;
1556
+ const maxResults = 50;
1557
+ let total = Infinity;
1484
1558
  while (startAt < total) {
1485
1559
  const url = `${baseUrl}/rest/api/2/search?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}`;
1486
1560
  const response = await this.httpClient(url, { headers });
1487
1561
  if (!response.ok) {
1488
- return {
1489
- nodesAdded,
1490
- nodesUpdated: 0,
1491
- edgesAdded,
1492
- edgesUpdated: 0,
1493
- errors: ["Jira API request failed"],
1494
- durationMs: Date.now() - start
1495
- };
1562
+ return buildIngestResult(nodesAdded, edgesAdded, ["Jira API request failed"], start);
1496
1563
  }
1497
1564
  const data = await response.json();
1498
1565
  total = data.total;
1499
1566
  for (const issue of data.issues) {
1500
- const nodeId = `issue:jira:${issue.key}`;
1501
- store.addNode({
1502
- id: nodeId,
1503
- type: "issue",
1504
- name: sanitizeExternalText(issue.fields.summary, 500),
1505
- metadata: {
1506
- key: issue.key,
1507
- status: issue.fields.status?.name,
1508
- priority: issue.fields.priority?.name,
1509
- assignee: issue.fields.assignee?.displayName,
1510
- labels: issue.fields.labels ?? []
1511
- }
1512
- });
1513
- nodesAdded++;
1514
- const searchText = sanitizeExternalText(
1515
- [issue.fields.summary, issue.fields.description ?? ""].join(" ")
1516
- );
1517
- edgesAdded += linkToCode(store, searchText, nodeId, "applies_to");
1567
+ const counts = this.processIssue(store, issue);
1568
+ nodesAdded += counts.nodesAdded;
1569
+ edgesAdded += counts.edgesAdded;
1518
1570
  }
1519
1571
  startAt += maxResults;
1520
1572
  }
1521
1573
  } catch (err) {
1522
- return {
1574
+ return buildIngestResult(
1523
1575
  nodesAdded,
1524
- nodesUpdated: 0,
1525
1576
  edgesAdded,
1526
- edgesUpdated: 0,
1527
- errors: [`Jira API error: ${err instanceof Error ? err.message : String(err)}`],
1528
- durationMs: Date.now() - start
1529
- };
1577
+ [`Jira API error: ${err instanceof Error ? err.message : String(err)}`],
1578
+ start
1579
+ );
1530
1580
  }
1531
- return {
1532
- nodesAdded,
1533
- nodesUpdated: 0,
1534
- edgesAdded,
1535
- edgesUpdated: 0,
1536
- errors,
1537
- durationMs: Date.now() - start
1538
- };
1581
+ return buildIngestResult(nodesAdded, edgesAdded, [], start);
1582
+ }
1583
+ processIssue(store, issue) {
1584
+ const nodeId = `issue:jira:${issue.key}`;
1585
+ store.addNode({
1586
+ id: nodeId,
1587
+ type: "issue",
1588
+ name: sanitizeExternalText(issue.fields.summary, 500),
1589
+ metadata: {
1590
+ key: issue.key,
1591
+ status: issue.fields.status?.name,
1592
+ priority: issue.fields.priority?.name,
1593
+ assignee: issue.fields.assignee?.displayName,
1594
+ labels: issue.fields.labels ?? []
1595
+ }
1596
+ });
1597
+ const searchText = sanitizeExternalText(
1598
+ [issue.fields.summary, issue.fields.description ?? ""].join(" ")
1599
+ );
1600
+ const edgesAdded = linkToCode(store, searchText, nodeId, "applies_to");
1601
+ return { nodesAdded: 1, edgesAdded };
1539
1602
  }
1540
1603
  };
1541
1604
  var SlackConnector = class {
@@ -1566,44 +1629,10 @@ var SlackConnector = class {
1566
1629
  const oldest = config.lookbackDays ? String(Math.floor((Date.now() - Number(config.lookbackDays) * 864e5) / 1e3)) : void 0;
1567
1630
  for (const channel of channels) {
1568
1631
  try {
1569
- let url = `https://slack.com/api/conversations.history?channel=${encodeURIComponent(channel)}`;
1570
- if (oldest) {
1571
- url += `&oldest=${oldest}`;
1572
- }
1573
- const response = await this.httpClient(url, {
1574
- headers: {
1575
- Authorization: `Bearer ${apiKey}`,
1576
- "Content-Type": "application/json"
1577
- }
1578
- });
1579
- if (!response.ok) {
1580
- errors.push(`Slack API request failed for channel ${channel}`);
1581
- continue;
1582
- }
1583
- const data = await response.json();
1584
- if (!data.ok) {
1585
- errors.push(`Slack API error for channel ${channel}`);
1586
- continue;
1587
- }
1588
- for (const message of data.messages) {
1589
- const nodeId = `conversation:slack:${channel}:${message.ts}`;
1590
- const sanitizedText = sanitizeExternalText(message.text);
1591
- const snippet = sanitizedText.length > 100 ? sanitizedText.slice(0, 100) : sanitizedText;
1592
- store.addNode({
1593
- id: nodeId,
1594
- type: "conversation",
1595
- name: snippet,
1596
- metadata: {
1597
- author: message.user,
1598
- channel,
1599
- timestamp: message.ts
1600
- }
1601
- });
1602
- nodesAdded++;
1603
- edgesAdded += linkToCode(store, sanitizedText, nodeId, "references", {
1604
- checkPaths: true
1605
- });
1606
- }
1632
+ const result = await this.processChannel(store, channel, apiKey, oldest);
1633
+ nodesAdded += result.nodesAdded;
1634
+ edgesAdded += result.edgesAdded;
1635
+ errors.push(...result.errors);
1607
1636
  } catch (err) {
1608
1637
  errors.push(
1609
1638
  `Slack API error for channel ${channel}: ${err instanceof Error ? err.message : String(err)}`
@@ -1619,6 +1648,52 @@ var SlackConnector = class {
1619
1648
  durationMs: Date.now() - start
1620
1649
  };
1621
1650
  }
1651
+ async processChannel(store, channel, apiKey, oldest) {
1652
+ const errors = [];
1653
+ let nodesAdded = 0;
1654
+ let edgesAdded = 0;
1655
+ let url = `https://slack.com/api/conversations.history?channel=${encodeURIComponent(channel)}`;
1656
+ if (oldest) {
1657
+ url += `&oldest=${oldest}`;
1658
+ }
1659
+ const response = await this.httpClient(url, {
1660
+ headers: {
1661
+ Authorization: `Bearer ${apiKey}`,
1662
+ "Content-Type": "application/json"
1663
+ }
1664
+ });
1665
+ if (!response.ok) {
1666
+ return {
1667
+ nodesAdded: 0,
1668
+ edgesAdded: 0,
1669
+ errors: [`Slack API request failed for channel ${channel}`]
1670
+ };
1671
+ }
1672
+ const data = await response.json();
1673
+ if (!data.ok) {
1674
+ return { nodesAdded: 0, edgesAdded: 0, errors: [`Slack API error for channel ${channel}`] };
1675
+ }
1676
+ for (const message of data.messages) {
1677
+ const nodeId = `conversation:slack:${channel}:${message.ts}`;
1678
+ const sanitizedText = sanitizeExternalText(message.text);
1679
+ const snippet = sanitizedText.length > 100 ? sanitizedText.slice(0, 100) : sanitizedText;
1680
+ store.addNode({
1681
+ id: nodeId,
1682
+ type: "conversation",
1683
+ name: snippet,
1684
+ metadata: {
1685
+ author: message.user,
1686
+ channel,
1687
+ timestamp: message.ts
1688
+ }
1689
+ });
1690
+ nodesAdded++;
1691
+ edgesAdded += linkToCode(store, sanitizedText, nodeId, "references", {
1692
+ checkPaths: true
1693
+ });
1694
+ }
1695
+ return { nodesAdded, edgesAdded, errors };
1696
+ }
1622
1697
  };
1623
1698
  var ConfluenceConnector = class {
1624
1699
  name = "confluence";
@@ -1648,36 +1723,10 @@ var ConfluenceConnector = class {
1648
1723
  const baseUrl = process.env[baseUrlEnv] ?? "";
1649
1724
  const spaceKey = config.spaceKey ?? "";
1650
1725
  try {
1651
- let nextUrl = `${baseUrl}/wiki/api/v2/pages?spaceKey=${encodeURIComponent(spaceKey)}&limit=25&body-format=storage`;
1652
- while (nextUrl) {
1653
- const response = await this.httpClient(nextUrl, {
1654
- headers: { Authorization: `Bearer ${apiKey}` }
1655
- });
1656
- if (!response.ok) {
1657
- errors.push(`Confluence API error: status ${response.status}`);
1658
- break;
1659
- }
1660
- const data = await response.json();
1661
- for (const page of data.results) {
1662
- const nodeId = `confluence:${page.id}`;
1663
- store.addNode({
1664
- id: nodeId,
1665
- type: "document",
1666
- name: sanitizeExternalText(page.title, 500),
1667
- metadata: {
1668
- source: "confluence",
1669
- spaceKey,
1670
- pageId: page.id,
1671
- status: page.status,
1672
- url: page._links?.webui ?? ""
1673
- }
1674
- });
1675
- nodesAdded++;
1676
- const text = sanitizeExternalText(`${page.title} ${page.body?.storage?.value ?? ""}`);
1677
- edgesAdded += linkToCode(store, text, nodeId, "documents");
1678
- }
1679
- nextUrl = data._links?.next ? `${baseUrl}${data._links.next}` : null;
1680
- }
1726
+ const result = await this.fetchAllPages(store, baseUrl, apiKey, spaceKey);
1727
+ nodesAdded = result.nodesAdded;
1728
+ edgesAdded = result.edgesAdded;
1729
+ errors.push(...result.errors);
1681
1730
  } catch (err) {
1682
1731
  errors.push(`Confluence fetch error: ${err instanceof Error ? err.message : String(err)}`);
1683
1732
  }
@@ -1690,6 +1739,47 @@ var ConfluenceConnector = class {
1690
1739
  durationMs: Date.now() - start
1691
1740
  };
1692
1741
  }
1742
+ async fetchAllPages(store, baseUrl, apiKey, spaceKey) {
1743
+ const errors = [];
1744
+ let nodesAdded = 0;
1745
+ let edgesAdded = 0;
1746
+ let nextUrl = `${baseUrl}/wiki/api/v2/pages?spaceKey=${encodeURIComponent(spaceKey)}&limit=25&body-format=storage`;
1747
+ while (nextUrl) {
1748
+ const response = await this.httpClient(nextUrl, {
1749
+ headers: { Authorization: `Bearer ${apiKey}` }
1750
+ });
1751
+ if (!response.ok) {
1752
+ errors.push(`Confluence API error: status ${response.status}`);
1753
+ break;
1754
+ }
1755
+ const data = await response.json();
1756
+ for (const page of data.results) {
1757
+ const counts = this.processPage(store, page, spaceKey);
1758
+ nodesAdded += counts.nodesAdded;
1759
+ edgesAdded += counts.edgesAdded;
1760
+ }
1761
+ nextUrl = data._links?.next ? `${baseUrl}${data._links.next}` : null;
1762
+ }
1763
+ return { nodesAdded, edgesAdded, errors };
1764
+ }
1765
+ processPage(store, page, spaceKey) {
1766
+ const nodeId = `confluence:${page.id}`;
1767
+ store.addNode({
1768
+ id: nodeId,
1769
+ type: "document",
1770
+ name: sanitizeExternalText(page.title, 500),
1771
+ metadata: {
1772
+ source: "confluence",
1773
+ spaceKey,
1774
+ pageId: page.id,
1775
+ status: page.status,
1776
+ url: page._links?.webui ?? ""
1777
+ }
1778
+ });
1779
+ const text = sanitizeExternalText(`${page.title} ${page.body?.storage?.value ?? ""}`);
1780
+ const edgesAdded = linkToCode(store, text, nodeId, "documents");
1781
+ return { nodesAdded: 1, edgesAdded };
1782
+ }
1693
1783
  };
1694
1784
  var CIConnector = class {
1695
1785
  name = "ci";
@@ -1976,22 +2066,25 @@ var GraphEntropyAdapter = class {
1976
2066
  * 3. Unreachable = code nodes NOT in visited set
1977
2067
  */
1978
2068
  computeDeadCodeData() {
1979
- const allFileNodes = this.store.findNodes({ type: "file" });
2069
+ const entryPoints = this.findEntryPoints();
2070
+ const visited = this.bfsFromEntryPoints(entryPoints);
2071
+ const unreachableNodes = this.collectUnreachableNodes(visited);
2072
+ return { reachableNodeIds: visited, unreachableNodes, entryPoints };
2073
+ }
2074
+ findEntryPoints() {
1980
2075
  const entryPoints = [];
1981
- for (const node of allFileNodes) {
1982
- if (node.name === "index.ts" || node.metadata?.entryPoint === true) {
1983
- entryPoints.push(node.id);
1984
- }
1985
- }
1986
2076
  for (const nodeType of CODE_NODE_TYPES3) {
1987
- if (nodeType === "file") continue;
1988
2077
  const nodes = this.store.findNodes({ type: nodeType });
1989
2078
  for (const node of nodes) {
1990
- if (node.metadata?.entryPoint === true) {
2079
+ const isIndexFile = nodeType === "file" && node.name === "index.ts";
2080
+ if (isIndexFile || node.metadata?.entryPoint === true) {
1991
2081
  entryPoints.push(node.id);
1992
2082
  }
1993
2083
  }
1994
2084
  }
2085
+ return entryPoints;
2086
+ }
2087
+ bfsFromEntryPoints(entryPoints) {
1995
2088
  const visited = /* @__PURE__ */ new Set();
1996
2089
  const queue = [...entryPoints];
1997
2090
  let head = 0;
@@ -1999,25 +2092,22 @@ var GraphEntropyAdapter = class {
1999
2092
  const nodeId = queue[head++];
2000
2093
  if (visited.has(nodeId)) continue;
2001
2094
  visited.add(nodeId);
2002
- const importEdges = this.store.getEdges({ from: nodeId, type: "imports" });
2003
- for (const edge of importEdges) {
2004
- if (!visited.has(edge.to)) {
2005
- queue.push(edge.to);
2006
- }
2007
- }
2008
- const callEdges = this.store.getEdges({ from: nodeId, type: "calls" });
2009
- for (const edge of callEdges) {
2010
- if (!visited.has(edge.to)) {
2011
- queue.push(edge.to);
2012
- }
2013
- }
2014
- const containsEdges = this.store.getEdges({ from: nodeId, type: "contains" });
2015
- for (const edge of containsEdges) {
2095
+ this.enqueueOutboundEdges(nodeId, visited, queue);
2096
+ }
2097
+ return visited;
2098
+ }
2099
+ enqueueOutboundEdges(nodeId, visited, queue) {
2100
+ const edgeTypes = ["imports", "calls", "contains"];
2101
+ for (const edgeType of edgeTypes) {
2102
+ const edges = this.store.getEdges({ from: nodeId, type: edgeType });
2103
+ for (const edge of edges) {
2016
2104
  if (!visited.has(edge.to)) {
2017
2105
  queue.push(edge.to);
2018
2106
  }
2019
2107
  }
2020
2108
  }
2109
+ }
2110
+ collectUnreachableNodes(visited) {
2021
2111
  const unreachableNodes = [];
2022
2112
  for (const nodeType of CODE_NODE_TYPES3) {
2023
2113
  const nodes = this.store.findNodes({ type: nodeType });
@@ -2032,11 +2122,7 @@ var GraphEntropyAdapter = class {
2032
2122
  }
2033
2123
  }
2034
2124
  }
2035
- return {
2036
- reachableNodeIds: visited,
2037
- unreachableNodes,
2038
- entryPoints
2039
- };
2125
+ return unreachableNodes;
2040
2126
  }
2041
2127
  /**
2042
2128
  * Count all nodes and edges by type.
@@ -2085,33 +2171,9 @@ var GraphComplexityAdapter = class {
2085
2171
  const hotspots = [];
2086
2172
  for (const fnNode of functionNodes) {
2087
2173
  const complexity = fnNode.metadata?.cyclomaticComplexity ?? 1;
2088
- const containsEdges = this.store.getEdges({ to: fnNode.id, type: "contains" });
2089
- let fileId;
2090
- for (const edge of containsEdges) {
2091
- const sourceNode = this.store.getNode(edge.from);
2092
- if (sourceNode?.type === "file") {
2093
- fileId = sourceNode.id;
2094
- break;
2095
- }
2096
- if (sourceNode?.type === "class") {
2097
- const classContainsEdges = this.store.getEdges({ to: sourceNode.id, type: "contains" });
2098
- for (const classEdge of classContainsEdges) {
2099
- const parentNode = this.store.getNode(classEdge.from);
2100
- if (parentNode?.type === "file") {
2101
- fileId = parentNode.id;
2102
- break;
2103
- }
2104
- }
2105
- if (fileId) break;
2106
- }
2107
- }
2174
+ const fileId = this.findContainingFileId(fnNode.id);
2108
2175
  if (!fileId) continue;
2109
- let changeFrequency = fileChangeFrequency.get(fileId);
2110
- if (changeFrequency === void 0) {
2111
- const referencesEdges = this.store.getEdges({ to: fileId, type: "references" });
2112
- changeFrequency = referencesEdges.length;
2113
- fileChangeFrequency.set(fileId, changeFrequency);
2114
- }
2176
+ const changeFrequency = this.getChangeFrequency(fileId, fileChangeFrequency);
2115
2177
  const hotspotScore = changeFrequency * complexity;
2116
2178
  const filePath = fnNode.path ?? fileId.replace(/^file:/, "");
2117
2179
  hotspots.push({
@@ -2129,6 +2191,39 @@ var GraphComplexityAdapter = class {
2129
2191
  );
2130
2192
  return { hotspots, percentile95Score };
2131
2193
  }
2194
+ /**
2195
+ * Walk the 'contains' edges to find the file node that contains a given function/method.
2196
+ * For methods, walks through the intermediate class node.
2197
+ */
2198
+ findContainingFileId(nodeId) {
2199
+ const containsEdges = this.store.getEdges({ to: nodeId, type: "contains" });
2200
+ for (const edge of containsEdges) {
2201
+ const sourceNode = this.store.getNode(edge.from);
2202
+ if (sourceNode?.type === "file") return sourceNode.id;
2203
+ if (sourceNode?.type === "class") {
2204
+ const fileId = this.findParentFileOfClass(sourceNode.id);
2205
+ if (fileId) return fileId;
2206
+ }
2207
+ }
2208
+ return void 0;
2209
+ }
2210
+ findParentFileOfClass(classNodeId) {
2211
+ const classContainsEdges = this.store.getEdges({ to: classNodeId, type: "contains" });
2212
+ for (const classEdge of classContainsEdges) {
2213
+ const parentNode = this.store.getNode(classEdge.from);
2214
+ if (parentNode?.type === "file") return parentNode.id;
2215
+ }
2216
+ return void 0;
2217
+ }
2218
+ getChangeFrequency(fileId, cache) {
2219
+ let freq = cache.get(fileId);
2220
+ if (freq === void 0) {
2221
+ const referencesEdges = this.store.getEdges({ to: fileId, type: "references" });
2222
+ freq = referencesEdges.length;
2223
+ cache.set(fileId, freq);
2224
+ }
2225
+ return freq;
2226
+ }
2132
2227
  computePercentile(descendingScores, percentile) {
2133
2228
  if (descendingScores.length === 0) return 0;
2134
2229
  const ascending = [...descendingScores].sort((a, b) => a - b);
@@ -2766,6 +2861,23 @@ var STOP_WORDS2 = /* @__PURE__ */ new Set([
2766
2861
  var PASCAL_OR_CAMEL_RE = /\b([A-Z][a-z]+[A-Za-z]*[a-z][A-Za-z]*|[a-z]+[A-Z][A-Za-z]*)\b/g;
2767
2862
  var FILE_PATH_RE = /(?:\.\/|[a-zA-Z0-9_-]+\/)[a-zA-Z0-9_\-./]+\.[a-zA-Z]{1,10}/g;
2768
2863
  var QUOTED_RE = /["']([^"']+)["']/g;
2864
+ function isSkippableWord(cleaned, allConsumed) {
2865
+ if (allConsumed.has(cleaned)) return true;
2866
+ const lower = cleaned.toLowerCase();
2867
+ if (STOP_WORDS2.has(lower)) return true;
2868
+ if (INTENT_KEYWORDS.has(lower)) return true;
2869
+ if (cleaned === cleaned.toUpperCase() && /^[A-Z]+$/.test(cleaned)) return true;
2870
+ return false;
2871
+ }
2872
+ function buildConsumedSet(quotedConsumed, casingConsumed, pathConsumed) {
2873
+ const quotedWords = /* @__PURE__ */ new Set();
2874
+ for (const q of quotedConsumed) {
2875
+ for (const w of q.split(/\s+/)) {
2876
+ if (w.length > 0) quotedWords.add(w);
2877
+ }
2878
+ }
2879
+ return /* @__PURE__ */ new Set([...quotedConsumed, ...quotedWords, ...casingConsumed, ...pathConsumed]);
2880
+ }
2769
2881
  var EntityExtractor = class {
2770
2882
  /**
2771
2883
  * Extract candidate entity mentions from a natural language query.
@@ -2806,27 +2918,12 @@ var EntityExtractor = class {
2806
2918
  add(path6);
2807
2919
  pathConsumed.add(path6);
2808
2920
  }
2809
- const quotedWords = /* @__PURE__ */ new Set();
2810
- for (const q of quotedConsumed) {
2811
- for (const w of q.split(/\s+/)) {
2812
- if (w.length > 0) quotedWords.add(w);
2813
- }
2814
- }
2815
- const allConsumed = /* @__PURE__ */ new Set([
2816
- ...quotedConsumed,
2817
- ...quotedWords,
2818
- ...casingConsumed,
2819
- ...pathConsumed
2820
- ]);
2921
+ const allConsumed = buildConsumedSet(quotedConsumed, casingConsumed, pathConsumed);
2821
2922
  const words = trimmed.split(/\s+/);
2822
2923
  for (const raw of words) {
2823
2924
  const cleaned = raw.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "");
2824
2925
  if (cleaned.length === 0) continue;
2825
- const lower = cleaned.toLowerCase();
2826
- if (allConsumed.has(cleaned)) continue;
2827
- if (STOP_WORDS2.has(lower)) continue;
2828
- if (INTENT_KEYWORDS.has(lower)) continue;
2829
- if (cleaned === cleaned.toUpperCase() && /^[A-Z]+$/.test(cleaned)) continue;
2926
+ if (isSkippableWord(cleaned, allConsumed)) continue;
2830
2927
  add(cleaned);
2831
2928
  }
2832
2929
  return result;
@@ -3141,14 +3238,20 @@ var Assembler = class {
3141
3238
  const fusion = this.getFusionLayer();
3142
3239
  const topResults = fusion.search(intent, 10);
3143
3240
  if (topResults.length === 0) {
3144
- return {
3145
- nodes: [],
3146
- edges: [],
3147
- tokenEstimate: 0,
3148
- intent,
3149
- truncated: false
3150
- };
3241
+ return { nodes: [], edges: [], tokenEstimate: 0, intent, truncated: false };
3151
3242
  }
3243
+ const { nodeMap, collectedEdges, nodeScores } = this.expandSearchResults(topResults);
3244
+ const sortedNodes = Array.from(nodeMap.values()).sort((a, b) => {
3245
+ return (nodeScores.get(b.id) ?? 0) - (nodeScores.get(a.id) ?? 0);
3246
+ });
3247
+ const { keptNodes, tokenEstimate, truncated } = this.truncateToFit(sortedNodes, tokenBudget);
3248
+ const keptNodeIds = new Set(keptNodes.map((n) => n.id));
3249
+ const keptEdges = collectedEdges.filter(
3250
+ (e) => keptNodeIds.has(e.from) && keptNodeIds.has(e.to)
3251
+ );
3252
+ return { nodes: keptNodes, edges: keptEdges, tokenEstimate, intent, truncated };
3253
+ }
3254
+ expandSearchResults(topResults) {
3152
3255
  const contextQL = new ContextQL(this.store);
3153
3256
  const nodeMap = /* @__PURE__ */ new Map();
3154
3257
  const edgeSet = /* @__PURE__ */ new Set();
@@ -3176,9 +3279,9 @@ var Assembler = class {
3176
3279
  }
3177
3280
  }
3178
3281
  }
3179
- const sortedNodes = Array.from(nodeMap.values()).sort((a, b) => {
3180
- return (nodeScores.get(b.id) ?? 0) - (nodeScores.get(a.id) ?? 0);
3181
- });
3282
+ return { nodeMap, collectedEdges, nodeScores };
3283
+ }
3284
+ truncateToFit(sortedNodes, tokenBudget) {
3182
3285
  let tokenEstimate = 0;
3183
3286
  const keptNodes = [];
3184
3287
  let truncated = false;
@@ -3191,17 +3294,7 @@ var Assembler = class {
3191
3294
  tokenEstimate += nodeTokens;
3192
3295
  keptNodes.push(node);
3193
3296
  }
3194
- const keptNodeIds = new Set(keptNodes.map((n) => n.id));
3195
- const keptEdges = collectedEdges.filter(
3196
- (e) => keptNodeIds.has(e.from) && keptNodeIds.has(e.to)
3197
- );
3198
- return {
3199
- nodes: keptNodes,
3200
- edges: keptEdges,
3201
- tokenEstimate,
3202
- intent,
3203
- truncated
3204
- };
3297
+ return { keptNodes, tokenEstimate, truncated };
3205
3298
  }
3206
3299
  /**
3207
3300
  * Compute a token budget allocation across node types.
@@ -3370,8 +3463,8 @@ var GraphConstraintAdapter = class {
3370
3463
  const { edges } = this.computeDependencyGraph();
3371
3464
  const violations = [];
3372
3465
  for (const edge of edges) {
3373
- const fromRelative = relative2(rootDir, edge.from);
3374
- const toRelative = relative2(rootDir, edge.to);
3466
+ const fromRelative = relative2(rootDir, edge.from).replaceAll("\\", "/");
3467
+ const toRelative = relative2(rootDir, edge.to).replaceAll("\\", "/");
3375
3468
  const fromLayer = this.resolveLayer(fromRelative, layers);
3376
3469
  const toLayer = this.resolveLayer(toRelative, layers);
3377
3470
  if (!fromLayer || !toLayer) continue;