@planu/cli 1.3.0 → 1.5.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 (282) hide show
  1. package/dist/config/license-plans.json +18 -1
  2. package/dist/engine/audit-trail/formatter.d.ts +13 -0
  3. package/dist/engine/audit-trail/formatter.d.ts.map +1 -0
  4. package/dist/engine/audit-trail/formatter.js +43 -0
  5. package/dist/engine/audit-trail/formatter.js.map +1 -0
  6. package/dist/engine/audit-trail/hasher.d.ts +18 -0
  7. package/dist/engine/audit-trail/hasher.d.ts.map +1 -0
  8. package/dist/engine/audit-trail/hasher.js +46 -0
  9. package/dist/engine/audit-trail/hasher.js.map +1 -0
  10. package/dist/engine/audit-trail/index.d.ts +2 -0
  11. package/dist/engine/audit-trail/index.d.ts.map +1 -1
  12. package/dist/engine/audit-trail/index.js +4 -1
  13. package/dist/engine/audit-trail/index.js.map +1 -1
  14. package/dist/engine/auto-promoter.d.ts +14 -0
  15. package/dist/engine/auto-promoter.d.ts.map +1 -0
  16. package/dist/engine/auto-promoter.js +40 -0
  17. package/dist/engine/auto-promoter.js.map +1 -0
  18. package/dist/engine/compliance-test-generator/control-mapper.d.ts +4 -0
  19. package/dist/engine/compliance-test-generator/control-mapper.d.ts.map +1 -0
  20. package/dist/engine/compliance-test-generator/control-mapper.js +41 -0
  21. package/dist/engine/compliance-test-generator/control-mapper.js.map +1 -0
  22. package/dist/engine/compliance-test-generator/frameworks/iso42001.d.ts +3 -0
  23. package/dist/engine/compliance-test-generator/frameworks/iso42001.d.ts.map +1 -0
  24. package/dist/engine/compliance-test-generator/frameworks/iso42001.js +55 -0
  25. package/dist/engine/compliance-test-generator/frameworks/iso42001.js.map +1 -0
  26. package/dist/engine/compliance-test-generator/frameworks/pci-dss.d.ts +3 -0
  27. package/dist/engine/compliance-test-generator/frameworks/pci-dss.d.ts.map +1 -0
  28. package/dist/engine/compliance-test-generator/frameworks/pci-dss.js +55 -0
  29. package/dist/engine/compliance-test-generator/frameworks/pci-dss.js.map +1 -0
  30. package/dist/engine/compliance-test-generator/frameworks/soc2.d.ts +3 -0
  31. package/dist/engine/compliance-test-generator/frameworks/soc2.d.ts.map +1 -0
  32. package/dist/engine/compliance-test-generator/frameworks/soc2.js +47 -0
  33. package/dist/engine/compliance-test-generator/frameworks/soc2.js.map +1 -0
  34. package/dist/engine/compliance-test-generator/index.d.ts +3 -0
  35. package/dist/engine/compliance-test-generator/index.d.ts.map +1 -0
  36. package/dist/engine/compliance-test-generator/index.js +64 -0
  37. package/dist/engine/compliance-test-generator/index.js.map +1 -0
  38. package/dist/engine/compliance-test-generator/test-formatter.d.ts +6 -0
  39. package/dist/engine/compliance-test-generator/test-formatter.d.ts.map +1 -0
  40. package/dist/engine/compliance-test-generator/test-formatter.js +33 -0
  41. package/dist/engine/compliance-test-generator/test-formatter.js.map +1 -0
  42. package/dist/engine/cost-guardrails.d.ts +11 -0
  43. package/dist/engine/cost-guardrails.d.ts.map +1 -0
  44. package/dist/engine/cost-guardrails.js +39 -0
  45. package/dist/engine/cost-guardrails.js.map +1 -0
  46. package/dist/engine/doc-compliance-checker.d.ts +23 -0
  47. package/dist/engine/doc-compliance-checker.d.ts.map +1 -0
  48. package/dist/engine/doc-compliance-checker.js +168 -0
  49. package/dist/engine/doc-compliance-checker.js.map +1 -0
  50. package/dist/engine/dogfood-analyzer.d.ts +6 -0
  51. package/dist/engine/dogfood-analyzer.d.ts.map +1 -0
  52. package/dist/engine/dogfood-analyzer.js +59 -0
  53. package/dist/engine/dogfood-analyzer.js.map +1 -0
  54. package/dist/engine/drift-watcher/criteria-checker.d.ts +16 -0
  55. package/dist/engine/drift-watcher/criteria-checker.d.ts.map +1 -0
  56. package/dist/engine/drift-watcher/criteria-checker.js +81 -0
  57. package/dist/engine/drift-watcher/criteria-checker.js.map +1 -0
  58. package/dist/engine/drift-watcher/file-watcher.d.ts +8 -0
  59. package/dist/engine/drift-watcher/file-watcher.d.ts.map +1 -0
  60. package/dist/engine/drift-watcher/file-watcher.js +24 -0
  61. package/dist/engine/drift-watcher/file-watcher.js.map +1 -0
  62. package/dist/engine/drift-watcher/index.d.ts +19 -0
  63. package/dist/engine/drift-watcher/index.d.ts.map +1 -0
  64. package/dist/engine/drift-watcher/index.js +70 -0
  65. package/dist/engine/drift-watcher/index.js.map +1 -0
  66. package/dist/engine/mcp-gateway/gateway-registry.d.ts +19 -0
  67. package/dist/engine/mcp-gateway/gateway-registry.d.ts.map +1 -0
  68. package/dist/engine/mcp-gateway/gateway-registry.js +33 -0
  69. package/dist/engine/mcp-gateway/gateway-registry.js.map +1 -0
  70. package/dist/engine/mcp-gateway/gateway-scanner.d.ts +17 -0
  71. package/dist/engine/mcp-gateway/gateway-scanner.d.ts.map +1 -0
  72. package/dist/engine/mcp-gateway/gateway-scanner.js +62 -0
  73. package/dist/engine/mcp-gateway/gateway-scanner.js.map +1 -0
  74. package/dist/engine/mcp-gateway/index.d.ts +3 -0
  75. package/dist/engine/mcp-gateway/index.d.ts.map +1 -0
  76. package/dist/engine/mcp-gateway/index.js +4 -0
  77. package/dist/engine/mcp-gateway/index.js.map +1 -0
  78. package/dist/engine/multi-repo/companion-spec-builder.d.ts +9 -0
  79. package/dist/engine/multi-repo/companion-spec-builder.d.ts.map +1 -0
  80. package/dist/engine/multi-repo/companion-spec-builder.js +22 -0
  81. package/dist/engine/multi-repo/companion-spec-builder.js.map +1 -0
  82. package/dist/engine/multi-repo/consumer-scanner.d.ts +12 -0
  83. package/dist/engine/multi-repo/consumer-scanner.d.ts.map +1 -0
  84. package/dist/engine/multi-repo/consumer-scanner.js +48 -0
  85. package/dist/engine/multi-repo/consumer-scanner.js.map +1 -0
  86. package/dist/engine/multi-repo/index.d.ts +4 -0
  87. package/dist/engine/multi-repo/index.d.ts.map +1 -0
  88. package/dist/engine/multi-repo/index.js +5 -0
  89. package/dist/engine/multi-repo/index.js.map +1 -0
  90. package/dist/engine/multi-repo/refactor-tracker.d.ts +7 -0
  91. package/dist/engine/multi-repo/refactor-tracker.d.ts.map +1 -0
  92. package/dist/engine/multi-repo/refactor-tracker.js +22 -0
  93. package/dist/engine/multi-repo/refactor-tracker.js.map +1 -0
  94. package/dist/engine/skill-generator/sections-docs.d.ts +13 -0
  95. package/dist/engine/skill-generator/sections-docs.d.ts.map +1 -0
  96. package/dist/engine/skill-generator/sections-docs.js +59 -0
  97. package/dist/engine/skill-generator/sections-docs.js.map +1 -0
  98. package/dist/engine/skill-generator/skills-content.d.ts +1 -1
  99. package/dist/engine/skill-generator/skills-content.d.ts.map +1 -1
  100. package/dist/engine/skill-generator/skills-content.js +3 -2
  101. package/dist/engine/skill-generator/skills-content.js.map +1 -1
  102. package/dist/engine/skill-generator/skills.d.ts +1 -0
  103. package/dist/engine/skill-generator/skills.d.ts.map +1 -1
  104. package/dist/engine/skill-generator/skills.js +1 -0
  105. package/dist/engine/skill-generator/skills.js.map +1 -1
  106. package/dist/engine/skill-generator.d.ts.map +1 -1
  107. package/dist/engine/skill-generator.js +21 -2
  108. package/dist/engine/skill-generator.js.map +1 -1
  109. package/dist/engine/web-fetcher/docs-intelligence.d.ts +8 -0
  110. package/dist/engine/web-fetcher/docs-intelligence.d.ts.map +1 -0
  111. package/dist/engine/web-fetcher/docs-intelligence.js +154 -0
  112. package/dist/engine/web-fetcher/docs-intelligence.js.map +1 -0
  113. package/dist/engine/web-fetcher/registry-auto-discovery.d.ts +20 -0
  114. package/dist/engine/web-fetcher/registry-auto-discovery.d.ts.map +1 -0
  115. package/dist/engine/web-fetcher/registry-auto-discovery.js +184 -0
  116. package/dist/engine/web-fetcher/registry-auto-discovery.js.map +1 -0
  117. package/dist/engine/web-fetcher/stack-detector.d.ts +4 -0
  118. package/dist/engine/web-fetcher/stack-detector.d.ts.map +1 -0
  119. package/dist/engine/web-fetcher/stack-detector.js +155 -0
  120. package/dist/engine/web-fetcher/stack-detector.js.map +1 -0
  121. package/dist/index.js +19 -0
  122. package/dist/index.js.map +1 -1
  123. package/dist/storage/audit-trail-store.d.ts +20 -0
  124. package/dist/storage/audit-trail-store.d.ts.map +1 -0
  125. package/dist/storage/audit-trail-store.js +98 -0
  126. package/dist/storage/audit-trail-store.js.map +1 -0
  127. package/dist/storage/auto-promoter-config-store.d.ts +11 -0
  128. package/dist/storage/auto-promoter-config-store.d.ts.map +1 -0
  129. package/dist/storage/auto-promoter-config-store.js +23 -0
  130. package/dist/storage/auto-promoter-config-store.js.map +1 -0
  131. package/dist/storage/budget-store.d.ts +19 -0
  132. package/dist/storage/budget-store.d.ts.map +1 -0
  133. package/dist/storage/budget-store.js +64 -0
  134. package/dist/storage/budget-store.js.map +1 -0
  135. package/dist/storage/gateway-store.d.ts +23 -0
  136. package/dist/storage/gateway-store.d.ts.map +1 -0
  137. package/dist/storage/gateway-store.js +52 -0
  138. package/dist/storage/gateway-store.js.map +1 -0
  139. package/dist/storage/refactor-registry-store.d.ts +21 -0
  140. package/dist/storage/refactor-registry-store.d.ts.map +1 -0
  141. package/dist/storage/refactor-registry-store.js +77 -0
  142. package/dist/storage/refactor-registry-store.js.map +1 -0
  143. package/dist/tools/auto-promoter-handler.d.ts +13 -0
  144. package/dist/tools/auto-promoter-handler.d.ts.map +1 -0
  145. package/dist/tools/auto-promoter-handler.js +50 -0
  146. package/dist/tools/auto-promoter-handler.js.map +1 -0
  147. package/dist/tools/compliance-test-handler.d.ts +5 -0
  148. package/dist/tools/compliance-test-handler.d.ts.map +1 -0
  149. package/dist/tools/compliance-test-handler.js +66 -0
  150. package/dist/tools/compliance-test-handler.js.map +1 -0
  151. package/dist/tools/cost-guardrails-handler.d.ts +15 -0
  152. package/dist/tools/cost-guardrails-handler.d.ts.map +1 -0
  153. package/dist/tools/cost-guardrails-handler.js +72 -0
  154. package/dist/tools/cost-guardrails-handler.js.map +1 -0
  155. package/dist/tools/create-spec/spec-builder.d.ts.map +1 -1
  156. package/dist/tools/create-spec/spec-builder.js +20 -0
  157. package/dist/tools/create-spec/spec-builder.js.map +1 -1
  158. package/dist/tools/create-spec-hu/docs-criteria-adapter.d.ts +14 -0
  159. package/dist/tools/create-spec-hu/docs-criteria-adapter.d.ts.map +1 -0
  160. package/dist/tools/create-spec-hu/docs-criteria-adapter.js +50 -0
  161. package/dist/tools/create-spec-hu/docs-criteria-adapter.js.map +1 -0
  162. package/dist/tools/create-spec-hu.d.ts +1 -1
  163. package/dist/tools/create-spec-hu.d.ts.map +1 -1
  164. package/dist/tools/create-spec-hu.js +5 -1
  165. package/dist/tools/create-spec-hu.js.map +1 -1
  166. package/dist/tools/create-spec.d.ts.map +1 -1
  167. package/dist/tools/create-spec.js +2 -2
  168. package/dist/tools/create-spec.js.map +1 -1
  169. package/dist/tools/doc-compliance-handler.d.ts +3 -0
  170. package/dist/tools/doc-compliance-handler.d.ts.map +1 -0
  171. package/dist/tools/doc-compliance-handler.js +48 -0
  172. package/dist/tools/doc-compliance-handler.js.map +1 -0
  173. package/dist/tools/docs-registry-handler.d.ts +6 -0
  174. package/dist/tools/docs-registry-handler.d.ts.map +1 -0
  175. package/dist/tools/docs-registry-handler.js +73 -0
  176. package/dist/tools/docs-registry-handler.js.map +1 -0
  177. package/dist/tools/dogfood-status-handler.d.ts +3 -0
  178. package/dist/tools/dogfood-status-handler.d.ts.map +1 -0
  179. package/dist/tools/dogfood-status-handler.js +28 -0
  180. package/dist/tools/dogfood-status-handler.js.map +1 -0
  181. package/dist/tools/drift-watcher-handler.d.ts +7 -0
  182. package/dist/tools/drift-watcher-handler.d.ts.map +1 -0
  183. package/dist/tools/drift-watcher-handler.js +65 -0
  184. package/dist/tools/drift-watcher-handler.js.map +1 -0
  185. package/dist/tools/export-audit-trail-handler.d.ts +9 -0
  186. package/dist/tools/export-audit-trail-handler.d.ts.map +1 -0
  187. package/dist/tools/export-audit-trail-handler.js +103 -0
  188. package/dist/tools/export-audit-trail-handler.js.map +1 -0
  189. package/dist/tools/mcp-gateway-handler.d.ts +13 -0
  190. package/dist/tools/mcp-gateway-handler.d.ts.map +1 -0
  191. package/dist/tools/mcp-gateway-handler.js +60 -0
  192. package/dist/tools/mcp-gateway-handler.js.map +1 -0
  193. package/dist/tools/multi-repo-handler.d.ts +15 -0
  194. package/dist/tools/multi-repo-handler.d.ts.map +1 -0
  195. package/dist/tools/multi-repo-handler.js +86 -0
  196. package/dist/tools/multi-repo-handler.js.map +1 -0
  197. package/dist/tools/register-audit-trail-tools.d.ts.map +1 -1
  198. package/dist/tools/register-audit-trail-tools.js +38 -0
  199. package/dist/tools/register-audit-trail-tools.js.map +1 -1
  200. package/dist/tools/register-auto-promoter-tools.d.ts +3 -0
  201. package/dist/tools/register-auto-promoter-tools.d.ts.map +1 -0
  202. package/dist/tools/register-auto-promoter-tools.js +43 -0
  203. package/dist/tools/register-auto-promoter-tools.js.map +1 -0
  204. package/dist/tools/register-compliance-test-tools.d.ts +3 -0
  205. package/dist/tools/register-compliance-test-tools.d.ts.map +1 -0
  206. package/dist/tools/register-compliance-test-tools.js +55 -0
  207. package/dist/tools/register-compliance-test-tools.js.map +1 -0
  208. package/dist/tools/register-cost-guardrails-tools.d.ts +3 -0
  209. package/dist/tools/register-cost-guardrails-tools.d.ts.map +1 -0
  210. package/dist/tools/register-cost-guardrails-tools.js +61 -0
  211. package/dist/tools/register-cost-guardrails-tools.js.map +1 -0
  212. package/dist/tools/register-doc-compliance-tools.d.ts +3 -0
  213. package/dist/tools/register-doc-compliance-tools.d.ts.map +1 -0
  214. package/dist/tools/register-doc-compliance-tools.js +18 -0
  215. package/dist/tools/register-doc-compliance-tools.js.map +1 -0
  216. package/dist/tools/register-docs-registry-tools.d.ts +3 -0
  217. package/dist/tools/register-docs-registry-tools.d.ts.map +1 -0
  218. package/dist/tools/register-docs-registry-tools.js +35 -0
  219. package/dist/tools/register-docs-registry-tools.js.map +1 -0
  220. package/dist/tools/register-dogfood-tools.d.ts +3 -0
  221. package/dist/tools/register-dogfood-tools.d.ts.map +1 -0
  222. package/dist/tools/register-dogfood-tools.js +21 -0
  223. package/dist/tools/register-dogfood-tools.js.map +1 -0
  224. package/dist/tools/register-drift-watcher-tools.d.ts +3 -0
  225. package/dist/tools/register-drift-watcher-tools.d.ts.map +1 -0
  226. package/dist/tools/register-drift-watcher-tools.js +28 -0
  227. package/dist/tools/register-drift-watcher-tools.js.map +1 -0
  228. package/dist/tools/register-mcp-gateway-tools.d.ts +3 -0
  229. package/dist/tools/register-mcp-gateway-tools.d.ts.map +1 -0
  230. package/dist/tools/register-mcp-gateway-tools.js +35 -0
  231. package/dist/tools/register-mcp-gateway-tools.js.map +1 -0
  232. package/dist/tools/register-multi-repo-tools.d.ts +8 -0
  233. package/dist/tools/register-multi-repo-tools.d.ts.map +1 -0
  234. package/dist/tools/register-multi-repo-tools.js +52 -0
  235. package/dist/tools/register-multi-repo-tools.js.map +1 -0
  236. package/dist/tools/safe-handler.d.ts.map +1 -1
  237. package/dist/tools/safe-handler.js +50 -1
  238. package/dist/tools/safe-handler.js.map +1 -1
  239. package/dist/types/audit.d.ts +64 -0
  240. package/dist/types/audit.d.ts.map +1 -0
  241. package/dist/types/audit.js +3 -0
  242. package/dist/types/audit.js.map +1 -0
  243. package/dist/types/auto-promoter.d.ts +26 -0
  244. package/dist/types/auto-promoter.d.ts.map +1 -0
  245. package/dist/types/auto-promoter.js +3 -0
  246. package/dist/types/auto-promoter.js.map +1 -0
  247. package/dist/types/compliance-tests.d.ts +41 -0
  248. package/dist/types/compliance-tests.d.ts.map +1 -0
  249. package/dist/types/compliance-tests.js +3 -0
  250. package/dist/types/compliance-tests.js.map +1 -0
  251. package/dist/types/cost-guardrails.d.ts +41 -0
  252. package/dist/types/cost-guardrails.d.ts.map +1 -0
  253. package/dist/types/cost-guardrails.js +3 -0
  254. package/dist/types/cost-guardrails.js.map +1 -0
  255. package/dist/types/docs.d.ts +70 -0
  256. package/dist/types/docs.d.ts.map +1 -1
  257. package/dist/types/dogfood.d.ts +22 -0
  258. package/dist/types/dogfood.d.ts.map +1 -0
  259. package/dist/types/dogfood.js +3 -0
  260. package/dist/types/dogfood.js.map +1 -0
  261. package/dist/types/drift-watcher.d.ts +35 -0
  262. package/dist/types/drift-watcher.d.ts.map +1 -0
  263. package/dist/types/drift-watcher.js +3 -0
  264. package/dist/types/drift-watcher.js.map +1 -0
  265. package/dist/types/index.d.ts +8 -0
  266. package/dist/types/index.d.ts.map +1 -1
  267. package/dist/types/index.js +8 -0
  268. package/dist/types/index.js.map +1 -1
  269. package/dist/types/mcp-gateway.d.ts +34 -0
  270. package/dist/types/mcp-gateway.d.ts.map +1 -0
  271. package/dist/types/mcp-gateway.js +3 -0
  272. package/dist/types/mcp-gateway.js.map +1 -0
  273. package/dist/types/mcp.d.ts +17 -0
  274. package/dist/types/mcp.d.ts.map +1 -1
  275. package/dist/types/multi-repo.d.ts +39 -0
  276. package/dist/types/multi-repo.d.ts.map +1 -0
  277. package/dist/types/multi-repo.js +5 -0
  278. package/dist/types/multi-repo.js.map +1 -0
  279. package/dist/types/spec/core.d.ts +2 -0
  280. package/dist/types/spec/core.d.ts.map +1 -1
  281. package/package.json +1 -1
  282. package/src/config/license-plans.json +18 -1
@@ -0,0 +1,154 @@
1
+ // Planu — Web Fetcher: Universal Docs Intelligence Engine (SPEC-382)
2
+ import { consultDocsImpl } from './docs-fetcher.js';
3
+ const BEST_PRACTICE_PATTERNS = [
4
+ /\bbest practice[s]?\b/i,
5
+ /\brecommended?\b/i,
6
+ /\byou should\b/i,
7
+ /\balways\b.{0,40}\b(use|prefer|ensure|check)/i,
8
+ /\bprefer\b.{0,40}\bover\b/i,
9
+ /\buse\b.{0,20}\bfor\b.{0,40}/i,
10
+ ];
11
+ const ANTI_PATTERN_PATTERNS = [
12
+ /\bavoid\b/i,
13
+ /\bdeprecated\b/i,
14
+ /\bdo not\b/i,
15
+ /\bnever\b/i,
16
+ /\bnot recommended\b/i,
17
+ /\bobsolete\b/i,
18
+ ];
19
+ const CONVENTION_PATTERNS = [
20
+ /\bconvention\b/i,
21
+ /\bstyle\b.{0,20}\bguid/i,
22
+ /\bnaming\b/i,
23
+ /\bformat\b.{0,20}\bshould\b/i,
24
+ /\bfollow.{0,20}\bpattern\b/i,
25
+ /\bfile structure\b/i,
26
+ ];
27
+ const VERSION_PATTERNS = [
28
+ /\bv?\d+(\.\d+){0,2}\b.{0,60}\b(migration|upgrade|breaking|changed)\b/i,
29
+ /\b(migration|upgrade|breaking change)\b.{0,60}\bv?\d+(\.\d+){0,2}\b/i,
30
+ /\bdeprecated in\b.{0,30}\bv?\d+/i,
31
+ ];
32
+ const TOOL_NAME_PATTERNS = /\b(npm|pnpm|yarn|npx|pip|cargo|brew|apt|go get)\b.{0,80}/i;
33
+ function splitIntoLines(text) {
34
+ return text
35
+ .split(/[\n.!?]/)
36
+ .map((l) => l.trim())
37
+ .filter((l) => l.length > 15 && l.length < 300);
38
+ }
39
+ function stripHtml(html) {
40
+ return html
41
+ .replace(/<script[\s\S]*?<\/script>/gi, '')
42
+ .replace(/<style[\s\S]*?<\/style>/gi, '')
43
+ .replace(/<[^>]+>/g, ' ')
44
+ .replace(/&[a-z]+;/gi, ' ')
45
+ .replace(/\s+/g, ' ')
46
+ .trim();
47
+ }
48
+ function matchesAny(line, patterns) {
49
+ return patterns.some((p) => p.test(line));
50
+ }
51
+ function dedup(items) {
52
+ return [...new Set(items)];
53
+ }
54
+ export function extractStructuredDocs(html, tech) {
55
+ const text = stripHtml(html);
56
+ const lines = splitIntoLines(text);
57
+ const bestPractices = [];
58
+ const antiPatterns = [];
59
+ const conventions = [];
60
+ const versionNotes = [];
61
+ const toolingRecommendations = [];
62
+ for (const line of lines) {
63
+ if (matchesAny(line, ANTI_PATTERN_PATTERNS)) {
64
+ antiPatterns.push(line);
65
+ }
66
+ else if (matchesAny(line, BEST_PRACTICE_PATTERNS)) {
67
+ bestPractices.push(line);
68
+ }
69
+ else if (matchesAny(line, CONVENTION_PATTERNS)) {
70
+ conventions.push(line);
71
+ }
72
+ if (matchesAny(line, VERSION_PATTERNS)) {
73
+ versionNotes.push(line);
74
+ }
75
+ if (TOOL_NAME_PATTERNS.test(line)) {
76
+ toolingRecommendations.push(line);
77
+ }
78
+ }
79
+ return {
80
+ tech,
81
+ docsUrl: '',
82
+ bestPractices: dedup(bestPractices).slice(0, 10),
83
+ antiPatterns: dedup(antiPatterns).slice(0, 10),
84
+ conventions: dedup(conventions).slice(0, 10),
85
+ versionNotes: dedup(versionNotes).slice(0, 5),
86
+ toolingRecommendations: dedup(toolingRecommendations).slice(0, 5),
87
+ source: 'discovered',
88
+ fetchedAt: new Date().toISOString(),
89
+ stale: false,
90
+ };
91
+ }
92
+ export function buildFallbackResult(tech) {
93
+ return {
94
+ tech,
95
+ docsUrl: '',
96
+ bestPractices: [],
97
+ antiPatterns: [],
98
+ conventions: [],
99
+ versionNotes: [],
100
+ toolingRecommendations: [],
101
+ source: 'fallback',
102
+ fetchedAt: new Date().toISOString(),
103
+ stale: true,
104
+ };
105
+ }
106
+ async function fetchOneTech(tech, timeoutMs) {
107
+ try {
108
+ const controller = new AbortController();
109
+ const timer = setTimeout(() => {
110
+ controller.abort();
111
+ }, timeoutMs);
112
+ let result;
113
+ try {
114
+ const docsResult = await consultDocsImpl(tech, tech);
115
+ const html = [docsResult.summary, ...docsResult.bestPractices].join('\n');
116
+ result = extractStructuredDocs(html, tech);
117
+ result.docsUrl = docsResult.docsUrl;
118
+ result.source = docsResult.source === 'local-fallback' ? 'fallback' : 'registry';
119
+ result.stale = docsResult.stale ?? false;
120
+ result.fetchedAt = docsResult.fetchedAt ?? new Date().toISOString();
121
+ }
122
+ finally {
123
+ clearTimeout(timer);
124
+ }
125
+ return result;
126
+ }
127
+ catch {
128
+ return buildFallbackResult(tech);
129
+ }
130
+ }
131
+ export async function fetchDocsBatch(techs, options) {
132
+ const timeoutMs = options?.timeout ?? 10_000;
133
+ const concurrency = options?.concurrency ?? 3;
134
+ const results = new Map();
135
+ for (let i = 0; i < techs.length; i += concurrency) {
136
+ const batch = techs.slice(i, i + concurrency);
137
+ const settled = await Promise.allSettled(batch.map((tech) => fetchOneTech(tech, timeoutMs)));
138
+ for (let j = 0; j < batch.length; j++) {
139
+ const tech = batch[j];
140
+ if (tech === undefined) {
141
+ continue;
142
+ }
143
+ const outcome = settled[j];
144
+ if (outcome === undefined || outcome.status === 'rejected') {
145
+ results.set(tech, buildFallbackResult(tech));
146
+ }
147
+ else {
148
+ results.set(tech, outcome.value);
149
+ }
150
+ }
151
+ }
152
+ return results;
153
+ }
154
+ //# sourceMappingURL=docs-intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-intelligence.js","sourceRoot":"","sources":["../../../src/engine/web-fetcher/docs-intelligence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { DiscoveredDocsEntry, DocsRegistryHealth } from '../../types/index.js';
2
+ /**
3
+ * Verify that a URL is alive with a HEAD request (timeout 3s).
4
+ * Returns true if status is 200, 301, or 302.
5
+ */
6
+ export declare function validateRegistryUrl(url: string): Promise<boolean>;
7
+ /**
8
+ * Discover docs URL for a tech package by querying npm, PyPI, and crates.io.
9
+ * Respects a 1 req/s rate limit per registry via simple delay.
10
+ * Returns null if not found anywhere.
11
+ */
12
+ export declare function discoverDocsUrl(tech: string): Promise<DiscoveredDocsEntry | null>;
13
+ /**
14
+ * Batch validate all entries in the docs registry.
15
+ * Categorizes each entry as healthy (<=2s), slow (2-5s), or broken (timeout/error).
16
+ */
17
+ export declare function checkRegistryHealth(entries: Record<string, {
18
+ base: string;
19
+ }>): Promise<DocsRegistryHealth>;
20
+ //# sourceMappingURL=registry-auto-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-auto-discovery.d.ts","sourceRoot":"","sources":["../../../src/engine/web-fetcher/registry-auto-discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAInB,MAAM,sBAAsB,CAAC;AAkH9B;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGvE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA6BvF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACxC,OAAO,CAAC,kBAAkB,CAAC,CAoC7B"}
@@ -0,0 +1,184 @@
1
+ // Planu — SPEC-386: Docs Registry Auto-Discovery
2
+ // Discovers docs URLs from npm/pypi/crates.io package metadata
3
+ const RATE_LIMIT_DELAY_MS = 1000;
4
+ const VERIFY_TIMEOUT_MS = 3000;
5
+ const HEALTH_TIMEOUT_MS = 5000;
6
+ const SLOW_THRESHOLD_MS = 2000;
7
+ /** Sleep for a given number of milliseconds. */
8
+ function sleep(ms) {
9
+ return new Promise((resolve) => {
10
+ setTimeout(resolve, ms);
11
+ });
12
+ }
13
+ /** Perform a HEAD request with a timeout, returning the HTTP status or null on failure. */
14
+ async function headWithTimeout(url, timeoutMs) {
15
+ const controller = new AbortController();
16
+ const timer = setTimeout(() => {
17
+ controller.abort();
18
+ }, timeoutMs);
19
+ try {
20
+ const res = await fetch(url, { method: 'HEAD', signal: controller.signal, redirect: 'follow' });
21
+ return res.status;
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ finally {
27
+ clearTimeout(timer);
28
+ }
29
+ }
30
+ /** Try to fetch JSON from a URL with a timeout. Returns null on any failure. */
31
+ async function fetchJson(url, timeoutMs = HEALTH_TIMEOUT_MS) {
32
+ const controller = new AbortController();
33
+ const timer = setTimeout(() => {
34
+ controller.abort();
35
+ }, timeoutMs);
36
+ try {
37
+ const res = await fetch(url, { signal: controller.signal });
38
+ if (!res.ok) {
39
+ return null;
40
+ }
41
+ return (await res.json());
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ finally {
47
+ clearTimeout(timer);
48
+ }
49
+ }
50
+ /** Extract a clean HTTPS docs URL from npm package metadata. */
51
+ function extractNpmDocsUrl(pkg) {
52
+ if (pkg.homepage?.startsWith('http')) {
53
+ return pkg.homepage;
54
+ }
55
+ if (pkg.docs?.startsWith('http')) {
56
+ return pkg.docs;
57
+ }
58
+ const repo = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url;
59
+ if (repo) {
60
+ const clean = repo
61
+ .replace(/^git\+/, '')
62
+ .replace(/\.git$/, '')
63
+ .replace(/^git:\/\//, 'https://');
64
+ if (clean.startsWith('https://')) {
65
+ return clean;
66
+ }
67
+ }
68
+ return null;
69
+ }
70
+ /** Try npm registry to find docs URL for a package. */
71
+ async function tryNpm(tech) {
72
+ const pkg = await fetchJson(`https://registry.npmjs.org/${encodeURIComponent(tech)}`);
73
+ if (!pkg) {
74
+ return null;
75
+ }
76
+ return extractNpmDocsUrl(pkg);
77
+ }
78
+ /** Try PyPI registry to find docs URL for a package. */
79
+ async function tryPypi(tech) {
80
+ const data = await fetchJson(`https://pypi.org/pypi/${encodeURIComponent(tech)}/json`);
81
+ if (!data?.info) {
82
+ return null;
83
+ }
84
+ const urls = data.info.project_urls ?? {};
85
+ const docsUrl = urls.Documentation ?? urls.documentation ?? urls.Docs ?? urls.Homepage ?? data.info.home_page;
86
+ if (docsUrl?.startsWith('http')) {
87
+ return docsUrl;
88
+ }
89
+ return null;
90
+ }
91
+ /** Try crates.io registry to find docs URL for a crate. */
92
+ async function tryCrates(tech) {
93
+ const data = await fetchJson(`https://crates.io/api/v1/crates/${encodeURIComponent(tech)}`);
94
+ if (!data?.crate) {
95
+ return null;
96
+ }
97
+ const url = data.crate.documentation ?? data.crate.homepage;
98
+ if (url?.startsWith('http')) {
99
+ return url;
100
+ }
101
+ return null;
102
+ }
103
+ /**
104
+ * Verify that a URL is alive with a HEAD request (timeout 3s).
105
+ * Returns true if status is 200, 301, or 302.
106
+ */
107
+ export async function validateRegistryUrl(url) {
108
+ const status = await headWithTimeout(url, VERIFY_TIMEOUT_MS);
109
+ return status !== null && (status === 200 || status === 301 || status === 302);
110
+ }
111
+ /**
112
+ * Discover docs URL for a tech package by querying npm, PyPI, and crates.io.
113
+ * Respects a 1 req/s rate limit per registry via simple delay.
114
+ * Returns null if not found anywhere.
115
+ */
116
+ export async function discoverDocsUrl(tech) {
117
+ const tryWithDelay = async (fn) => {
118
+ const result = await fn();
119
+ await sleep(RATE_LIMIT_DELAY_MS);
120
+ return result;
121
+ };
122
+ const registries = [
123
+ { source: 'npm', fn: () => tryNpm(tech) },
124
+ { source: 'pypi', fn: () => tryPypi(tech) },
125
+ { source: 'crates', fn: () => tryCrates(tech) },
126
+ ];
127
+ for (const { source, fn } of registries) {
128
+ const url = await tryWithDelay(fn);
129
+ if (url) {
130
+ const verified = await validateRegistryUrl(url);
131
+ return {
132
+ tech,
133
+ docsUrl: url,
134
+ source,
135
+ discoveredAt: new Date().toISOString(),
136
+ verified,
137
+ };
138
+ }
139
+ }
140
+ return null;
141
+ }
142
+ /**
143
+ * Batch validate all entries in the docs registry.
144
+ * Categorizes each entry as healthy (<=2s), slow (2-5s), or broken (timeout/error).
145
+ */
146
+ export async function checkRegistryHealth(entries) {
147
+ const healthy = [];
148
+ const broken = [];
149
+ const slow = [];
150
+ const checks = Object.entries(entries).map(async ([key, entry]) => {
151
+ const start = Date.now();
152
+ const controller = new AbortController();
153
+ const timer = setTimeout(() => {
154
+ controller.abort();
155
+ }, HEALTH_TIMEOUT_MS);
156
+ try {
157
+ const res = await fetch(entry.base, {
158
+ method: 'HEAD',
159
+ signal: controller.signal,
160
+ redirect: 'follow',
161
+ });
162
+ const elapsed = Date.now() - start;
163
+ const ok = res.status === 200 || res.status === 301 || res.status === 302;
164
+ if (!ok) {
165
+ broken.push(key);
166
+ }
167
+ else if (elapsed > SLOW_THRESHOLD_MS) {
168
+ slow.push(key);
169
+ }
170
+ else {
171
+ healthy.push(key);
172
+ }
173
+ }
174
+ catch {
175
+ broken.push(key);
176
+ }
177
+ finally {
178
+ clearTimeout(timer);
179
+ }
180
+ });
181
+ await Promise.all(checks);
182
+ return { healthy, broken, slow };
183
+ }
184
+ //# sourceMappingURL=registry-auto-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-auto-discovery.js","sourceRoot":"","sources":["../../../src/engine/web-fetcher/registry-auto-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { DetectedTech } from '../../types/index.js';
2
+ export declare function detectTechsFromText(text: string): DetectedTech[];
3
+ export declare function detectTechsFromFiles(fileList: string[]): DetectedTech[];
4
+ //# sourceMappingURL=stack-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-detector.d.ts","sourceRoot":"","sources":["../../../src/engine/web-fetcher/stack-detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AA2EzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAyChE;AAiCD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAgBvE"}
@@ -0,0 +1,155 @@
1
+ // Planu — Web Fetcher: Stack Detection from text and file paths (SPEC-382)
2
+ // ~50 well-known technologies with their normalized names
3
+ const KNOWN_TECHS = [
4
+ { pattern: /\bnext\.?js\b/i, normalized: 'next.js' },
5
+ { pattern: /\breact\b/i, normalized: 'react' },
6
+ { pattern: /\bvue\.?js\b|\bvuejs\b/i, normalized: 'vue' },
7
+ { pattern: /\bangular\b/i, normalized: 'angular' },
8
+ { pattern: /\bsvelte\b/i, normalized: 'svelte' },
9
+ { pattern: /\bastro\b/i, normalized: 'astro' },
10
+ { pattern: /\bremix\b/i, normalized: 'remix' },
11
+ { pattern: /\bsolid\.?js\b|\bsolidjs\b/i, normalized: 'solid.js' },
12
+ { pattern: /\bqwik\b/i, normalized: 'qwik' },
13
+ { pattern: /\bnuxt\b/i, normalized: 'nuxt' },
14
+ { pattern: /\bgatsbyjs\b|\bgatsby\b/i, normalized: 'gatsby' },
15
+ { pattern: /\bexpress\.?js\b|\bexpressjs\b/i, normalized: 'express' },
16
+ { pattern: /\bhono\b/i, normalized: 'hono' },
17
+ { pattern: /\bfastify\b/i, normalized: 'fastify' },
18
+ { pattern: /\bkoa\b/i, normalized: 'koa' },
19
+ { pattern: /\bnestjs\b|\bnest\.js\b/i, normalized: 'nestjs' },
20
+ { pattern: /\bdjango\b/i, normalized: 'django' },
21
+ { pattern: /\bflask\b/i, normalized: 'flask' },
22
+ { pattern: /\bfastapi\b/i, normalized: 'fastapi' },
23
+ { pattern: /\brails\b|\bruby on rails\b/i, normalized: 'rails' },
24
+ { pattern: /\blaravel\b/i, normalized: 'laravel' },
25
+ { pattern: /\bspring boot\b|\bspringboot\b/i, normalized: 'spring' },
26
+ { pattern: /\bgin\b.{0,10}\bgo\b|\bgo\b.{0,10}\bgin\b/i, normalized: 'gin' },
27
+ { pattern: /\bfiber\b.{0,10}\bgo\b|\bgo\b.{0,10}\bfiber\b/i, normalized: 'fiber' },
28
+ { pattern: /\btypescript\b/i, normalized: 'typescript' },
29
+ { pattern: /\bjavascript\b/i, normalized: 'javascript' },
30
+ { pattern: /\bpython\b/i, normalized: 'python' },
31
+ { pattern: /\bgolang\b|\bgo lang\b|\b(?:^|\s)go(?:\s|$)\b/i, normalized: 'go' },
32
+ { pattern: /\brust\b/i, normalized: 'rust' },
33
+ { pattern: /\bjava\b/i, normalized: 'java' },
34
+ { pattern: /\bkotlin\b/i, normalized: 'kotlin' },
35
+ { pattern: /\bswift\b/i, normalized: 'swift' },
36
+ { pattern: /\bflutter\b/i, normalized: 'flutter' },
37
+ { pattern: /\bexpo\b/i, normalized: 'expo' },
38
+ { pattern: /\breact native\b|\breact-native\b/i, normalized: 'react-native' },
39
+ { pattern: /\bpostgresql\b|\bpostgres\b/i, normalized: 'postgresql' },
40
+ { pattern: /\bmysql\b/i, normalized: 'mysql' },
41
+ { pattern: /\bmongodb\b|\bmongo\b/i, normalized: 'mongodb' },
42
+ { pattern: /\bsqlite\b/i, normalized: 'sqlite' },
43
+ { pattern: /\bsupabase\b/i, normalized: 'supabase' },
44
+ { pattern: /\bfirebase\b/i, normalized: 'firebase' },
45
+ { pattern: /\bprisma\b/i, normalized: 'prisma' },
46
+ { pattern: /\bdrizzle\b/i, normalized: 'drizzle' },
47
+ { pattern: /\btailwind\b/i, normalized: 'tailwind' },
48
+ { pattern: /\bvite\b/i, normalized: 'vite' },
49
+ { pattern: /\bvitest\b/i, normalized: 'vitest' },
50
+ { pattern: /\bjest\b/i, normalized: 'jest' },
51
+ { pattern: /\bdocker\b/i, normalized: 'docker' },
52
+ { pattern: /\bkubernetes\b|\bk8s\b/i, normalized: 'kubernetes' },
53
+ { pattern: /\bstripe\b/i, normalized: 'stripe' },
54
+ { pattern: /\bgraphql\b/i, normalized: 'graphql' },
55
+ { pattern: /\btrpc\b/i, normalized: 'trpc' },
56
+ { pattern: /\bzod\b/i, normalized: 'zod' },
57
+ { pattern: /\bprisma\b/i, normalized: 'prisma' },
58
+ ];
59
+ // npm package pattern: word with hyphen or scoped (@scope/pkg)
60
+ const NPM_PACKAGE_RE = /(?:^|\s)((?:@[\w-]+\/[\w-]+|[\w][\w-]{1,}))(?=\s|$)/g;
61
+ function extractContext(text, match) {
62
+ const idx = match.index ?? 0;
63
+ const matchLen = match[0].length;
64
+ const start = Math.max(0, idx - 20);
65
+ const end = Math.min(text.length, idx + matchLen + 20);
66
+ return text.slice(start, end).trim();
67
+ }
68
+ function normalizeText(text) {
69
+ return text.replace(/\s+/g, ' ').trim();
70
+ }
71
+ export function detectTechsFromText(text) {
72
+ const normalized = normalizeText(text);
73
+ const found = new Map();
74
+ for (const { pattern, normalized: techName } of KNOWN_TECHS) {
75
+ if (found.has(techName)) {
76
+ continue;
77
+ }
78
+ const match = normalized.match(pattern);
79
+ if (match) {
80
+ found.set(techName, {
81
+ name: techName,
82
+ confidence: 'high',
83
+ context: extractContext(normalized, match),
84
+ });
85
+ }
86
+ }
87
+ // Also detect npm package patterns with medium confidence (not already detected)
88
+ const npmMatches = [...normalized.matchAll(NPM_PACKAGE_RE)];
89
+ for (const match of npmMatches) {
90
+ const pkg = match[1];
91
+ if (!pkg) {
92
+ continue;
93
+ }
94
+ const pkgNorm = pkg.toLowerCase();
95
+ // Skip if already captured by known techs or too short
96
+ if (found.has(pkgNorm) || pkgNorm.length < 3) {
97
+ continue;
98
+ }
99
+ // Only include if it looks like a package (has hyphen or slash → scoped)
100
+ if (pkg.includes('-') || pkg.includes('/')) {
101
+ found.set(pkgNorm, {
102
+ name: pkgNorm,
103
+ confidence: 'low',
104
+ context: extractContext(normalized, match),
105
+ });
106
+ }
107
+ }
108
+ return [...found.values()];
109
+ }
110
+ const FILE_TECH_MAP = [
111
+ { pattern: /package\.json$/, name: 'node', confidence: 'high' },
112
+ { pattern: /next\.config\.[cm]?[jt]s$/, name: 'next.js', confidence: 'high' },
113
+ { pattern: /vite\.config\.[cm]?[jt]s$/, name: 'vite', confidence: 'high' },
114
+ { pattern: /vitest\.config\.[cm]?[jt]s$/, name: 'vitest', confidence: 'high' },
115
+ { pattern: /astro\.config\.[cm]?[jt]s$/, name: 'astro', confidence: 'high' },
116
+ { pattern: /remix\.config\.[cm]?[jt]s$/, name: 'remix', confidence: 'high' },
117
+ { pattern: /svelte\.config\.[cm]?[jt]s$/, name: 'svelte', confidence: 'high' },
118
+ { pattern: /nuxt\.config\.[cm]?[jt]s$/, name: 'nuxt', confidence: 'high' },
119
+ { pattern: /tailwind\.config\.[cm]?[jt]s$/, name: 'tailwind', confidence: 'high' },
120
+ { pattern: /prisma\/schema\.prisma$|\.prisma$/, name: 'prisma', confidence: 'high' },
121
+ { pattern: /drizzle\.config\.[cm]?[jt]s$/, name: 'drizzle', confidence: 'high' },
122
+ { pattern: /Dockerfile$|docker-compose\.ya?ml$/, name: 'docker', confidence: 'high' },
123
+ { pattern: /requirements\.txt$|setup\.py$|pyproject\.toml$/, name: 'python', confidence: 'high' },
124
+ { pattern: /go\.mod$|go\.sum$/, name: 'go', confidence: 'high' },
125
+ { pattern: /Cargo\.toml$|Cargo\.lock$/, name: 'rust', confidence: 'high' },
126
+ { pattern: /pom\.xml$|build\.gradle$/, name: 'java', confidence: 'high' },
127
+ { pattern: /tsconfig\.json$/, name: 'typescript', confidence: 'high' },
128
+ { pattern: /\.tsx?$/, name: 'typescript', confidence: 'medium' },
129
+ { pattern: /\.vue$/, name: 'vue', confidence: 'high' },
130
+ { pattern: /\.svelte$/, name: 'svelte', confidence: 'high' },
131
+ { pattern: /\.tsx$/, name: 'react', confidence: 'medium' },
132
+ { pattern: /\.jsx$/, name: 'react', confidence: 'medium' },
133
+ { pattern: /\.py$/, name: 'python', confidence: 'medium' },
134
+ { pattern: /\.go$/, name: 'go', confidence: 'medium' },
135
+ { pattern: /\.rs$/, name: 'rust', confidence: 'medium' },
136
+ { pattern: /\.kt$/, name: 'kotlin', confidence: 'medium' },
137
+ { pattern: /\.swift$/, name: 'swift', confidence: 'medium' },
138
+ { pattern: /\.dart$/, name: 'flutter', confidence: 'medium' },
139
+ ];
140
+ export function detectTechsFromFiles(fileList) {
141
+ const found = new Map();
142
+ for (const filePath of fileList) {
143
+ for (const { pattern, name, confidence } of FILE_TECH_MAP) {
144
+ if (!found.has(name) && pattern.test(filePath)) {
145
+ found.set(name, {
146
+ name,
147
+ confidence,
148
+ context: filePath,
149
+ });
150
+ }
151
+ }
152
+ }
153
+ return [...found.values()];
154
+ }
155
+ //# sourceMappingURL=stack-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-detector.js","sourceRoot":"","sources":["../../../src/engine/web-fetcher/stack-detector.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // index.ts — Planu SDD MCP Server entry point.
3
3
  // Creates the MCP server, registers tools & resources, and starts stdio transport.
4
+ /* eslint-disable max-lines */
4
5
  // CLI detection — intercept known commands before MCP server setup (SPEC-124)
5
6
  const KNOWN_COMMANDS = [
6
7
  'init',
@@ -193,6 +194,15 @@ import { registerAiderTools } from './tools/register-aider-tools.js';
193
194
  import { registerSweepTools } from './tools/register-sweep-tools.js';
194
195
  import { registerPrAgentTools } from './tools/register-pr-agent-tools.js';
195
196
  import { registerE2eTestGeneratorTools } from './tools/register-e2e-test-generator-tools.js';
197
+ import { registerDocsRegistryTools } from './tools/register-docs-registry-tools.js';
198
+ import { registerDocComplianceTools } from './tools/register-doc-compliance-tools.js';
199
+ import { registerDriftWatcherTools } from './tools/register-drift-watcher-tools.js';
200
+ import { registerMultiRepoTools } from './tools/register-multi-repo-tools.js';
201
+ import { registerComplianceTestTools } from './tools/register-compliance-test-tools.js';
202
+ import { registerAutoPromoterTools } from './tools/register-auto-promoter-tools.js';
203
+ import { registerCostGuardrailsTools } from './tools/register-cost-guardrails-tools.js';
204
+ import { registerMcpGatewayTools } from './tools/register-mcp-gateway-tools.js';
205
+ import { registerDogfoodTools } from './tools/register-dogfood-tools.js';
196
206
  // Server setup
197
207
  const SERVER_INSTRUCTIONS = [
198
208
  'CONTEXT — Why structured specs matter:',
@@ -459,6 +469,15 @@ function registerLatestSpecTools(s) {
459
469
  registerSweepTools(s);
460
470
  registerPrAgentTools(s);
461
471
  registerE2eTestGeneratorTools(s);
472
+ registerDocsRegistryTools(s);
473
+ registerDocComplianceTools(s);
474
+ registerDriftWatcherTools(s);
475
+ registerMultiRepoTools(s);
476
+ registerComplianceTestTools(s);
477
+ registerAutoPromoterTools(s);
478
+ registerCostGuardrailsTools(s);
479
+ registerMcpGatewayTools(s);
480
+ registerDogfoodTools(s);
462
481
  }
463
482
  function createMcpServer() {
464
483
  const s = withToolTracking(new McpServer({ name: 'planu', version: PLANU_VERSION }, { instructions: SERVER_INSTRUCTIONS }));