@planu/cli 0.43.1 → 0.44.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 (369) hide show
  1. package/dist/cli/colors.d.ts +14 -0
  2. package/dist/cli/colors.d.ts.map +1 -0
  3. package/dist/cli/colors.js +26 -0
  4. package/dist/cli/colors.js.map +1 -0
  5. package/dist/cli/commands/audit.d.ts +3 -0
  6. package/dist/cli/commands/audit.d.ts.map +1 -0
  7. package/dist/cli/commands/audit.js +38 -0
  8. package/dist/cli/commands/audit.js.map +1 -0
  9. package/dist/cli/commands/create.d.ts +3 -0
  10. package/dist/cli/commands/create.d.ts.map +1 -0
  11. package/dist/cli/commands/create.js +50 -0
  12. package/dist/cli/commands/create.js.map +1 -0
  13. package/dist/cli/commands/dashboard.d.ts +3 -0
  14. package/dist/cli/commands/dashboard.d.ts.map +1 -0
  15. package/dist/cli/commands/dashboard.js +29 -0
  16. package/dist/cli/commands/dashboard.js.map +1 -0
  17. package/dist/cli/commands/estimate.d.ts +3 -0
  18. package/dist/cli/commands/estimate.d.ts.map +1 -0
  19. package/dist/cli/commands/estimate.js +36 -0
  20. package/dist/cli/commands/estimate.js.map +1 -0
  21. package/dist/cli/commands/handoff.d.ts +3 -0
  22. package/dist/cli/commands/handoff.d.ts.map +1 -0
  23. package/dist/cli/commands/handoff.js +49 -0
  24. package/dist/cli/commands/handoff.js.map +1 -0
  25. package/dist/cli/commands/init.d.ts +3 -0
  26. package/dist/cli/commands/init.d.ts.map +1 -0
  27. package/dist/cli/commands/init.js +43 -0
  28. package/dist/cli/commands/init.js.map +1 -0
  29. package/dist/cli/commands/list.d.ts +3 -0
  30. package/dist/cli/commands/list.d.ts.map +1 -0
  31. package/dist/cli/commands/list.js +36 -0
  32. package/dist/cli/commands/list.js.map +1 -0
  33. package/dist/cli/commands/serve.d.ts +3 -0
  34. package/dist/cli/commands/serve.d.ts.map +1 -0
  35. package/dist/cli/commands/serve.js +34 -0
  36. package/dist/cli/commands/serve.js.map +1 -0
  37. package/dist/cli/commands/status.d.ts +3 -0
  38. package/dist/cli/commands/status.d.ts.map +1 -0
  39. package/dist/cli/commands/status.js +49 -0
  40. package/dist/cli/commands/status.js.map +1 -0
  41. package/dist/cli/commands/validate.d.ts +3 -0
  42. package/dist/cli/commands/validate.d.ts.map +1 -0
  43. package/dist/cli/commands/validate.js +36 -0
  44. package/dist/cli/commands/validate.js.map +1 -0
  45. package/dist/cli/commands/watch.d.ts +3 -0
  46. package/dist/cli/commands/watch.d.ts.map +1 -0
  47. package/dist/cli/commands/watch.js +156 -0
  48. package/dist/cli/commands/watch.js.map +1 -0
  49. package/dist/cli/formatter.d.ts +18 -0
  50. package/dist/cli/formatter.d.ts.map +1 -0
  51. package/dist/cli/formatter.js +78 -0
  52. package/dist/cli/formatter.js.map +1 -0
  53. package/dist/cli/index.d.ts +6 -0
  54. package/dist/cli/index.d.ts.map +1 -0
  55. package/dist/cli/index.js +7 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/cli/interactive.d.ts +13 -0
  58. package/dist/cli/interactive.d.ts.map +1 -0
  59. package/dist/cli/interactive.js +42 -0
  60. package/dist/cli/interactive.js.map +1 -0
  61. package/dist/cli/project-detector.d.ts +6 -0
  62. package/dist/cli/project-detector.d.ts.map +1 -0
  63. package/dist/cli/project-detector.js +12 -0
  64. package/dist/cli/project-detector.js.map +1 -0
  65. package/dist/cli/router.d.ts +5 -0
  66. package/dist/cli/router.d.ts.map +1 -0
  67. package/dist/cli/router.js +104 -0
  68. package/dist/cli/router.js.map +1 -0
  69. package/dist/config/hook-defaults.json +19 -0
  70. package/dist/config/license-plans.json +16 -1
  71. package/dist/config/tool-groups.json +12 -1
  72. package/dist/engine/analyzer/analyze-project.d.ts +15 -0
  73. package/dist/engine/analyzer/analyze-project.d.ts.map +1 -0
  74. package/dist/engine/analyzer/analyze-project.js +101 -0
  75. package/dist/engine/analyzer/analyze-project.js.map +1 -0
  76. package/dist/engine/analyzer/completeness-checker.d.ts +6 -0
  77. package/dist/engine/analyzer/completeness-checker.d.ts.map +1 -0
  78. package/dist/engine/analyzer/completeness-checker.js +79 -0
  79. package/dist/engine/analyzer/completeness-checker.js.map +1 -0
  80. package/dist/engine/analyzer/db-engine.d.ts +9 -0
  81. package/dist/engine/analyzer/db-engine.d.ts.map +1 -0
  82. package/dist/engine/analyzer/db-engine.js +137 -0
  83. package/dist/engine/analyzer/db-engine.js.map +1 -0
  84. package/dist/engine/analyzer/detectors.d.ts +7 -0
  85. package/dist/engine/analyzer/detectors.d.ts.map +1 -0
  86. package/dist/engine/analyzer/detectors.js +234 -0
  87. package/dist/engine/analyzer/detectors.js.map +1 -0
  88. package/dist/engine/analyzer/env-setup.d.ts +6 -0
  89. package/dist/engine/analyzer/env-setup.d.ts.map +1 -0
  90. package/dist/engine/analyzer/env-setup.js +174 -0
  91. package/dist/engine/analyzer/env-setup.js.map +1 -0
  92. package/dist/engine/analyzer/index.d.ts +6 -0
  93. package/dist/engine/analyzer/index.d.ts.map +1 -0
  94. package/dist/engine/analyzer/index.js +8 -0
  95. package/dist/engine/analyzer/index.js.map +1 -0
  96. package/dist/engine/analyzer-db.d.ts +1 -8
  97. package/dist/engine/analyzer-db.d.ts.map +1 -1
  98. package/dist/engine/analyzer-db.js +3 -136
  99. package/dist/engine/analyzer-db.js.map +1 -1
  100. package/dist/engine/analyzer-detectors.d.ts +1 -6
  101. package/dist/engine/analyzer-detectors.d.ts.map +1 -1
  102. package/dist/engine/analyzer-detectors.js +3 -231
  103. package/dist/engine/analyzer-detectors.js.map +1 -1
  104. package/dist/engine/analyzer-env.d.ts +1 -5
  105. package/dist/engine/analyzer-env.d.ts.map +1 -1
  106. package/dist/engine/analyzer-env.js +3 -173
  107. package/dist/engine/analyzer-env.js.map +1 -1
  108. package/dist/engine/analyzer.d.ts +2 -18
  109. package/dist/engine/analyzer.d.ts.map +1 -1
  110. package/dist/engine/analyzer.js +4 -172
  111. package/dist/engine/analyzer.js.map +1 -1
  112. package/dist/engine/dashboard/data-loader.d.ts +16 -1
  113. package/dist/engine/dashboard/data-loader.d.ts.map +1 -1
  114. package/dist/engine/dashboard/data-loader.js +140 -2
  115. package/dist/engine/dashboard/data-loader.js.map +1 -1
  116. package/dist/engine/dashboard/index.d.ts +2 -0
  117. package/dist/engine/dashboard/index.d.ts.map +1 -1
  118. package/dist/engine/dashboard/index.js +2 -0
  119. package/dist/engine/dashboard/index.js.map +1 -1
  120. package/dist/engine/dashboard/kanban-logic.d.ts +31 -0
  121. package/dist/engine/dashboard/kanban-logic.d.ts.map +1 -0
  122. package/dist/engine/dashboard/kanban-logic.js +122 -0
  123. package/dist/engine/dashboard/kanban-logic.js.map +1 -0
  124. package/dist/engine/dashboard/routes.d.ts +2 -0
  125. package/dist/engine/dashboard/routes.d.ts.map +1 -1
  126. package/dist/engine/dashboard/routes.js +112 -23
  127. package/dist/engine/dashboard/routes.js.map +1 -1
  128. package/dist/engine/dashboard/server.d.ts +5 -0
  129. package/dist/engine/dashboard/server.d.ts.map +1 -1
  130. package/dist/engine/dashboard/server.js +48 -0
  131. package/dist/engine/dashboard/server.js.map +1 -1
  132. package/dist/engine/dashboard/spec-updater.d.ts +8 -0
  133. package/dist/engine/dashboard/spec-updater.d.ts.map +1 -0
  134. package/dist/engine/dashboard/spec-updater.js +37 -0
  135. package/dist/engine/dashboard/spec-updater.js.map +1 -0
  136. package/dist/engine/dashboard/templates-kanban.d.ts +6 -0
  137. package/dist/engine/dashboard/templates-kanban.d.ts.map +1 -0
  138. package/dist/engine/dashboard/templates-kanban.js +100 -0
  139. package/dist/engine/dashboard/templates-kanban.js.map +1 -0
  140. package/dist/engine/dashboard/templates-layout.d.ts +3 -3
  141. package/dist/engine/dashboard/templates-layout.d.ts.map +1 -1
  142. package/dist/engine/dashboard/templates-layout.js +167 -44
  143. package/dist/engine/dashboard/templates-layout.js.map +1 -1
  144. package/dist/engine/dashboard/templates-project.d.ts +1 -1
  145. package/dist/engine/dashboard/templates-project.d.ts.map +1 -1
  146. package/dist/engine/dashboard/templates-project.js +109 -3
  147. package/dist/engine/dashboard/templates-project.js.map +1 -1
  148. package/dist/engine/dashboard/templates.d.ts +1 -0
  149. package/dist/engine/dashboard/templates.d.ts.map +1 -1
  150. package/dist/engine/dashboard/templates.js +1 -0
  151. package/dist/engine/dashboard/templates.js.map +1 -1
  152. package/dist/engine/hooks/config-loader.d.ts +36 -0
  153. package/dist/engine/hooks/config-loader.d.ts.map +1 -0
  154. package/dist/engine/hooks/config-loader.js +142 -0
  155. package/dist/engine/hooks/config-loader.js.map +1 -0
  156. package/dist/engine/hooks/debouncer.d.ts +30 -0
  157. package/dist/engine/hooks/debouncer.d.ts.map +1 -0
  158. package/dist/engine/hooks/debouncer.js +124 -0
  159. package/dist/engine/hooks/debouncer.js.map +1 -0
  160. package/dist/engine/hooks/event-bus.d.ts +40 -0
  161. package/dist/engine/hooks/event-bus.d.ts.map +1 -0
  162. package/dist/engine/hooks/event-bus.js +83 -0
  163. package/dist/engine/hooks/event-bus.js.map +1 -0
  164. package/dist/engine/hooks/file-watcher.d.ts +48 -0
  165. package/dist/engine/hooks/file-watcher.d.ts.map +1 -0
  166. package/dist/engine/hooks/file-watcher.js +193 -0
  167. package/dist/engine/hooks/file-watcher.js.map +1 -0
  168. package/dist/engine/hooks/handlers/on-commit.d.ts +26 -0
  169. package/dist/engine/hooks/handlers/on-commit.d.ts.map +1 -0
  170. package/dist/engine/hooks/handlers/on-commit.js +198 -0
  171. package/dist/engine/hooks/handlers/on-commit.js.map +1 -0
  172. package/dist/engine/hooks/handlers/on-create.d.ts +8 -0
  173. package/dist/engine/hooks/handlers/on-create.d.ts.map +1 -0
  174. package/dist/engine/hooks/handlers/on-create.js +30 -0
  175. package/dist/engine/hooks/handlers/on-create.js.map +1 -0
  176. package/dist/engine/hooks/handlers/on-delete.d.ts +9 -0
  177. package/dist/engine/hooks/handlers/on-delete.d.ts.map +1 -0
  178. package/dist/engine/hooks/handlers/on-delete.js +33 -0
  179. package/dist/engine/hooks/handlers/on-delete.js.map +1 -0
  180. package/dist/engine/hooks/handlers/on-save.d.ts +29 -0
  181. package/dist/engine/hooks/handlers/on-save.d.ts.map +1 -0
  182. package/dist/engine/hooks/handlers/on-save.js +118 -0
  183. package/dist/engine/hooks/handlers/on-save.js.map +1 -0
  184. package/dist/engine/hooks/handlers/on-test-pass.d.ts +33 -0
  185. package/dist/engine/hooks/handlers/on-test-pass.d.ts.map +1 -0
  186. package/dist/engine/hooks/handlers/on-test-pass.js +103 -0
  187. package/dist/engine/hooks/handlers/on-test-pass.js.map +1 -0
  188. package/dist/engine/hooks/hook-engine.d.ts +50 -0
  189. package/dist/engine/hooks/hook-engine.d.ts.map +1 -0
  190. package/dist/engine/hooks/hook-engine.js +159 -0
  191. package/dist/engine/hooks/hook-engine.js.map +1 -0
  192. package/dist/engine/hooks/index.d.ts +10 -0
  193. package/dist/engine/hooks/index.d.ts.map +1 -1
  194. package/dist/engine/hooks/index.js +12 -0
  195. package/dist/engine/hooks/index.js.map +1 -1
  196. package/dist/engine/living-spec/annotation-parser.d.ts +18 -0
  197. package/dist/engine/living-spec/annotation-parser.d.ts.map +1 -0
  198. package/dist/engine/living-spec/annotation-parser.js +105 -0
  199. package/dist/engine/living-spec/annotation-parser.js.map +1 -0
  200. package/dist/engine/living-spec/auto-reconciler.d.ts +28 -0
  201. package/dist/engine/living-spec/auto-reconciler.d.ts.map +1 -0
  202. package/dist/engine/living-spec/auto-reconciler.js +103 -0
  203. package/dist/engine/living-spec/auto-reconciler.js.map +1 -0
  204. package/dist/engine/living-spec/bidirectional-sync.d.ts +26 -0
  205. package/dist/engine/living-spec/bidirectional-sync.d.ts.map +1 -0
  206. package/dist/engine/living-spec/bidirectional-sync.js +160 -0
  207. package/dist/engine/living-spec/bidirectional-sync.js.map +1 -0
  208. package/dist/engine/living-spec/dashboard-collector.d.ts +22 -0
  209. package/dist/engine/living-spec/dashboard-collector.d.ts.map +1 -0
  210. package/dist/engine/living-spec/dashboard-collector.js +97 -0
  211. package/dist/engine/living-spec/dashboard-collector.js.map +1 -0
  212. package/dist/engine/living-spec/drift-watcher.d.ts +15 -0
  213. package/dist/engine/living-spec/drift-watcher.d.ts.map +1 -0
  214. package/dist/engine/living-spec/drift-watcher.js +126 -0
  215. package/dist/engine/living-spec/drift-watcher.js.map +1 -0
  216. package/dist/engine/living-spec/hash-tracker.d.ts +24 -0
  217. package/dist/engine/living-spec/hash-tracker.d.ts.map +1 -0
  218. package/dist/engine/living-spec/hash-tracker.js +123 -0
  219. package/dist/engine/living-spec/hash-tracker.js.map +1 -0
  220. package/dist/engine/living-spec/index.d.ts +9 -0
  221. package/dist/engine/living-spec/index.d.ts.map +1 -0
  222. package/dist/engine/living-spec/index.js +10 -0
  223. package/dist/engine/living-spec/index.js.map +1 -0
  224. package/dist/engine/living-spec/signature-tracker.d.ts +18 -0
  225. package/dist/engine/living-spec/signature-tracker.d.ts.map +1 -0
  226. package/dist/engine/living-spec/signature-tracker.js +136 -0
  227. package/dist/engine/living-spec/signature-tracker.js.map +1 -0
  228. package/dist/engine/living-spec/test-coverage-correlator.d.ts +22 -0
  229. package/dist/engine/living-spec/test-coverage-correlator.d.ts.map +1 -0
  230. package/dist/engine/living-spec/test-coverage-correlator.js +130 -0
  231. package/dist/engine/living-spec/test-coverage-correlator.js.map +1 -0
  232. package/dist/engine/plugins/extensions/worker-extension.d.ts.map +1 -1
  233. package/dist/engine/plugins/extensions/worker-extension.js +3 -1
  234. package/dist/engine/plugins/extensions/worker-extension.js.map +1 -1
  235. package/dist/engine/safety/file-mutex.d.ts.map +1 -1
  236. package/dist/engine/safety/file-mutex.js +3 -0
  237. package/dist/engine/safety/file-mutex.js.map +1 -1
  238. package/dist/index.js +29 -0
  239. package/dist/index.js.map +1 -1
  240. package/dist/storage/hash-snapshot-store.d.ts +18 -0
  241. package/dist/storage/hash-snapshot-store.d.ts.map +1 -0
  242. package/dist/storage/hash-snapshot-store.js +43 -0
  243. package/dist/storage/hash-snapshot-store.js.map +1 -0
  244. package/dist/storage/index.d.ts +3 -0
  245. package/dist/storage/index.d.ts.map +1 -1
  246. package/dist/storage/index.js +3 -0
  247. package/dist/storage/index.js.map +1 -1
  248. package/dist/storage/living-dashboard-store.d.ts +10 -0
  249. package/dist/storage/living-dashboard-store.d.ts.map +1 -0
  250. package/dist/storage/living-dashboard-store.js +31 -0
  251. package/dist/storage/living-dashboard-store.js.map +1 -0
  252. package/dist/storage/sync-log-store.d.ts +26 -0
  253. package/dist/storage/sync-log-store.d.ts.map +1 -0
  254. package/dist/storage/sync-log-store.js +60 -0
  255. package/dist/storage/sync-log-store.js.map +1 -0
  256. package/dist/tools/auto-reconcile.d.ts +3 -0
  257. package/dist/tools/auto-reconcile.d.ts.map +1 -0
  258. package/dist/tools/auto-reconcile.js +81 -0
  259. package/dist/tools/auto-reconcile.js.map +1 -0
  260. package/dist/tools/challenge-spec/platform-challenge-scenarios-b2.d.ts.map +1 -1
  261. package/dist/tools/challenge-spec/platform-challenge-scenarios-b2.js +6 -0
  262. package/dist/tools/challenge-spec/platform-challenge-scenarios-b2.js.map +1 -1
  263. package/dist/tools/create-spec/spec-builder.js +2 -0
  264. package/dist/tools/create-spec/spec-builder.js.map +1 -1
  265. package/dist/tools/dashboard.d.ts.map +1 -1
  266. package/dist/tools/dashboard.js +20 -13
  267. package/dist/tools/dashboard.js.map +1 -1
  268. package/dist/tools/generate-annotations.d.ts +3 -0
  269. package/dist/tools/generate-annotations.d.ts.map +1 -0
  270. package/dist/tools/generate-annotations.js +70 -0
  271. package/dist/tools/generate-annotations.js.map +1 -0
  272. package/dist/tools/generate-execution-plan.d.ts.map +1 -1
  273. package/dist/tools/generate-execution-plan.js +1 -0
  274. package/dist/tools/generate-execution-plan.js.map +1 -1
  275. package/dist/tools/github-pr-handler.d.ts.map +1 -1
  276. package/dist/tools/github-pr-handler.js +1 -0
  277. package/dist/tools/github-pr-handler.js.map +1 -1
  278. package/dist/tools/github-review-handler.d.ts.map +1 -1
  279. package/dist/tools/github-review-handler.js +1 -0
  280. package/dist/tools/github-review-handler.js.map +1 -1
  281. package/dist/tools/ide-config-handler.d.ts.map +1 -1
  282. package/dist/tools/ide-config-handler.js +3 -0
  283. package/dist/tools/ide-config-handler.js.map +1 -1
  284. package/dist/tools/init-project/handler.d.ts.map +1 -1
  285. package/dist/tools/init-project/handler.js +0 -3
  286. package/dist/tools/init-project/handler.js.map +1 -1
  287. package/dist/tools/living-spec-coverage.d.ts +3 -0
  288. package/dist/tools/living-spec-coverage.d.ts.map +1 -0
  289. package/dist/tools/living-spec-coverage.js +100 -0
  290. package/dist/tools/living-spec-coverage.js.map +1 -0
  291. package/dist/tools/living-spec-watch.d.ts +4 -0
  292. package/dist/tools/living-spec-watch.d.ts.map +1 -0
  293. package/dist/tools/living-spec-watch.js +94 -0
  294. package/dist/tools/living-spec-watch.js.map +1 -0
  295. package/dist/tools/manage-plugins-handler.d.ts.map +1 -1
  296. package/dist/tools/manage-plugins-handler.js +2 -1
  297. package/dist/tools/manage-plugins-handler.js.map +1 -1
  298. package/dist/tools/orchestrate-distribution.d.ts.map +1 -1
  299. package/dist/tools/orchestrate-distribution.js +1 -0
  300. package/dist/tools/orchestrate-distribution.js.map +1 -1
  301. package/dist/tools/orchestrate-runtime.js +2 -0
  302. package/dist/tools/orchestrate-runtime.js.map +1 -1
  303. package/dist/tools/plan-team-distribution.d.ts.map +1 -1
  304. package/dist/tools/plan-team-distribution.js +2 -0
  305. package/dist/tools/plan-team-distribution.js.map +1 -1
  306. package/dist/tools/register-dashboard-tools.d.ts.map +1 -1
  307. package/dist/tools/register-dashboard-tools.js +5 -1
  308. package/dist/tools/register-dashboard-tools.js.map +1 -1
  309. package/dist/tools/register-hooks-tools.d.ts.map +1 -1
  310. package/dist/tools/register-hooks-tools.js +82 -1
  311. package/dist/tools/register-hooks-tools.js.map +1 -1
  312. package/dist/tools/register-living-spec-advanced-tools.d.ts +6 -0
  313. package/dist/tools/register-living-spec-advanced-tools.d.ts.map +1 -0
  314. package/dist/tools/register-living-spec-advanced-tools.js +113 -0
  315. package/dist/tools/register-living-spec-advanced-tools.js.map +1 -0
  316. package/dist/tools/register-living-spec-tools.d.ts +6 -0
  317. package/dist/tools/register-living-spec-tools.d.ts.map +1 -0
  318. package/dist/tools/register-living-spec-tools.js +67 -0
  319. package/dist/tools/register-living-spec-tools.js.map +1 -0
  320. package/dist/tools/resolve-sync-conflict.d.ts +3 -0
  321. package/dist/tools/resolve-sync-conflict.d.ts.map +1 -0
  322. package/dist/tools/resolve-sync-conflict.js +38 -0
  323. package/dist/tools/resolve-sync-conflict.js.map +1 -0
  324. package/dist/tools/snapshot-spec-hashes.d.ts +3 -0
  325. package/dist/tools/snapshot-spec-hashes.d.ts.map +1 -0
  326. package/dist/tools/snapshot-spec-hashes.js +100 -0
  327. package/dist/tools/snapshot-spec-hashes.js.map +1 -0
  328. package/dist/tools/spec-diff.d.ts +3 -0
  329. package/dist/tools/spec-diff.d.ts.map +1 -0
  330. package/dist/tools/spec-diff.js +58 -0
  331. package/dist/tools/spec-diff.js.map +1 -0
  332. package/dist/tools/start-hooks.d.ts +17 -0
  333. package/dist/tools/start-hooks.d.ts.map +1 -0
  334. package/dist/tools/start-hooks.js +209 -0
  335. package/dist/tools/start-hooks.js.map +1 -0
  336. package/dist/tools/sync-code-to-spec.d.ts +3 -0
  337. package/dist/tools/sync-code-to-spec.d.ts.map +1 -0
  338. package/dist/tools/sync-code-to-spec.js +51 -0
  339. package/dist/tools/sync-code-to-spec.js.map +1 -0
  340. package/dist/tools/sync-spec-to-code.d.ts +3 -0
  341. package/dist/tools/sync-spec-to-code.d.ts.map +1 -0
  342. package/dist/tools/sync-spec-to-code.js +58 -0
  343. package/dist/tools/sync-spec-to-code.js.map +1 -0
  344. package/dist/tools/validate-annotations.d.ts +3 -0
  345. package/dist/tools/validate-annotations.d.ts.map +1 -0
  346. package/dist/tools/validate-annotations.js +90 -0
  347. package/dist/tools/validate-annotations.js.map +1 -0
  348. package/dist/types/cli.d.ts +14 -0
  349. package/dist/types/cli.d.ts.map +1 -0
  350. package/dist/types/cli.js +3 -0
  351. package/dist/types/cli.js.map +1 -0
  352. package/dist/types/dashboard.d.ts +86 -1
  353. package/dist/types/dashboard.d.ts.map +1 -1
  354. package/dist/types/file-hooks.d.ts +230 -0
  355. package/dist/types/file-hooks.d.ts.map +1 -0
  356. package/dist/types/file-hooks.js +3 -0
  357. package/dist/types/file-hooks.js.map +1 -0
  358. package/dist/types/index.d.ts +3 -0
  359. package/dist/types/index.d.ts.map +1 -1
  360. package/dist/types/index.js +3 -0
  361. package/dist/types/index.js.map +1 -1
  362. package/dist/types/living-spec.d.ts +382 -0
  363. package/dist/types/living-spec.d.ts.map +1 -0
  364. package/dist/types/living-spec.js +3 -0
  365. package/dist/types/living-spec.js.map +1 -0
  366. package/package.json +1 -1
  367. package/src/config/hook-defaults.json +19 -0
  368. package/src/config/license-plans.json +16 -1
  369. package/src/config/tool-groups.json +12 -1
@@ -0,0 +1,36 @@
1
+ import type { FileHookConfig, FileHookTypeConfig, ConfigChangeCallback } from '../../types/file-hooks.js';
2
+ export declare class ConfigLoader {
3
+ private config;
4
+ private readonly projectRoot;
5
+ private watcher;
6
+ private changeCallbacks;
7
+ constructor(projectRoot: string);
8
+ /**
9
+ * Load config from `.planu/hooks.json` or `planu.json`.
10
+ * Falls back to defaults if file missing or invalid.
11
+ */
12
+ load(): Promise<FileHookConfig>;
13
+ /**
14
+ * Get current config (synchronous, must call load() first).
15
+ */
16
+ getConfig(): FileHookConfig;
17
+ /**
18
+ * Get config for a specific hook type.
19
+ */
20
+ getHookConfig(hookType: string): FileHookTypeConfig | undefined;
21
+ /**
22
+ * Start watching config files for live reload.
23
+ */
24
+ startWatching(): void;
25
+ /**
26
+ * Register a callback for config changes.
27
+ */
28
+ onChange(callback: ConfigChangeCallback): void;
29
+ /**
30
+ * Stop watching and clean up.
31
+ */
32
+ close(): void;
33
+ private reloadConfig;
34
+ private readJsonFile;
35
+ }
36
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../../src/engine/hooks/config-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAoCnC,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,eAAe,CAA8B;gBAEzC,WAAW,EAAE,MAAM;IAK/B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IAgCrC;;OAEG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI/D;;OAEG;IACH,aAAa,IAAI,IAAI;IAcrB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAI9C;;OAEG;IACH,KAAK,IAAI,IAAI;YAYC,YAAY;YAWZ,YAAY;CAQ3B"}
@@ -0,0 +1,142 @@
1
+ // engine/hooks/config-loader.ts — Load & validate hook config with live reload (SPEC-129)
2
+ import { watch as fsWatch } from 'node:fs';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ import { z } from 'zod';
6
+ // ---------------------------------------------------------------------------
7
+ // Default config (matches hook-defaults.json)
8
+ // ---------------------------------------------------------------------------
9
+ import hookDefaults from '../../config/hook-defaults.json' with { type: 'json' };
10
+ // ---------------------------------------------------------------------------
11
+ // Zod schemas
12
+ // ---------------------------------------------------------------------------
13
+ const hookTypeConfigSchema = z.object({
14
+ enabled: z.boolean().default(true),
15
+ include: z.array(z.string()).optional(),
16
+ exclude: z.array(z.string()).optional(),
17
+ });
18
+ const fileHookConfigSchema = z.object({
19
+ enabled: z.boolean().default(true),
20
+ debounceMs: z.number().min(50).max(10_000).default(300),
21
+ rateLimitPerFileMs: z.number().min(1000).max(60_000).default(5000),
22
+ hooks: z.record(z.string(), hookTypeConfigSchema).default({}),
23
+ });
24
+ // ---------------------------------------------------------------------------
25
+ // Config file paths
26
+ // ---------------------------------------------------------------------------
27
+ const HOOKS_JSON = '.planu/hooks.json';
28
+ const PLANU_JSON = 'planu.json';
29
+ // ---------------------------------------------------------------------------
30
+ // ConfigLoader
31
+ // ---------------------------------------------------------------------------
32
+ export class ConfigLoader {
33
+ config;
34
+ projectRoot;
35
+ watcher = null;
36
+ changeCallbacks = [];
37
+ constructor(projectRoot) {
38
+ this.projectRoot = projectRoot;
39
+ this.config = hookDefaults;
40
+ }
41
+ /**
42
+ * Load config from `.planu/hooks.json` or `planu.json`.
43
+ * Falls back to defaults if file missing or invalid.
44
+ */
45
+ async load() {
46
+ // Try .planu/hooks.json first
47
+ let raw = await this.readJsonFile(join(this.projectRoot, HOOKS_JSON));
48
+ // Try planu.json -> hooks key
49
+ if (!raw) {
50
+ const planuJson = await this.readJsonFile(join(this.projectRoot, PLANU_JSON));
51
+ if (planuJson &&
52
+ typeof planuJson === 'object' &&
53
+ 'hooks' in planuJson) {
54
+ raw = planuJson.hooks;
55
+ }
56
+ }
57
+ if (raw) {
58
+ const parsed = fileHookConfigSchema.safeParse(raw);
59
+ if (parsed.success) {
60
+ this.config = parsed.data;
61
+ }
62
+ else {
63
+ const messages = parsed.error.issues.map((i) => i.message).join(', ');
64
+ console.warn(`[hooks] Invalid hook config, using defaults: ${messages}`);
65
+ this.config = hookDefaults;
66
+ }
67
+ }
68
+ else {
69
+ this.config = hookDefaults;
70
+ }
71
+ return this.config;
72
+ }
73
+ /**
74
+ * Get current config (synchronous, must call load() first).
75
+ */
76
+ getConfig() {
77
+ return this.config;
78
+ }
79
+ /**
80
+ * Get config for a specific hook type.
81
+ */
82
+ getHookConfig(hookType) {
83
+ return this.config.hooks[hookType];
84
+ }
85
+ /**
86
+ * Start watching config files for live reload.
87
+ */
88
+ startWatching() {
89
+ const hooksJsonPath = join(this.projectRoot, HOOKS_JSON);
90
+ try {
91
+ this.watcher = fsWatch(hooksJsonPath, () => {
92
+ void this.reloadConfig();
93
+ });
94
+ this.watcher.on('error', () => {
95
+ // Ignore watch errors — config just won't live-reload
96
+ });
97
+ }
98
+ catch {
99
+ // File doesn't exist yet — that's fine
100
+ }
101
+ }
102
+ /**
103
+ * Register a callback for config changes.
104
+ */
105
+ onChange(callback) {
106
+ this.changeCallbacks.push(callback);
107
+ }
108
+ /**
109
+ * Stop watching and clean up.
110
+ */
111
+ close() {
112
+ if (this.watcher) {
113
+ this.watcher.close();
114
+ this.watcher = null;
115
+ }
116
+ this.changeCallbacks = [];
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Private
120
+ // ---------------------------------------------------------------------------
121
+ async reloadConfig() {
122
+ try {
123
+ await this.load();
124
+ for (const cb of this.changeCallbacks) {
125
+ cb(this.config);
126
+ }
127
+ }
128
+ catch {
129
+ // Ignore reload errors — keep previous config
130
+ }
131
+ }
132
+ async readJsonFile(filePath) {
133
+ try {
134
+ const data = await readFile(filePath, 'utf-8');
135
+ return JSON.parse(data);
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ }
141
+ }
142
+ //# sourceMappingURL=config-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../../src/engine/hooks/config-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { WatcherEvent, DebouncerConfig, DebouncedCallback } from '../../types/file-hooks.js';
2
+ export declare class Debouncer {
3
+ private readonly config;
4
+ /** Pending debounce timers per file path */
5
+ private readonly pendingTimers;
6
+ /** Pending event per file (latest wins) */
7
+ private readonly pendingEvents;
8
+ /** Rate limit buckets per file path */
9
+ private readonly fileBuckets;
10
+ /** Rate limit buckets per spec ID */
11
+ private readonly specBuckets;
12
+ private readonly callback;
13
+ constructor(callback: DebouncedCallback, config?: Partial<DebouncerConfig>);
14
+ /**
15
+ * Feed a raw watcher event. The debouncer will coalesce rapid events
16
+ * and apply rate limiting before invoking the callback.
17
+ */
18
+ push(event: WatcherEvent): void;
19
+ /**
20
+ * Check spec-level rate limit for auto-reconcile.
21
+ * Returns true if allowed, false if rate-limited.
22
+ */
23
+ checkSpecRateLimit(specId: string): boolean;
24
+ /**
25
+ * Cancel all pending timers and clear state.
26
+ */
27
+ dispose(): void;
28
+ private tryEmit;
29
+ }
30
+ //# sourceMappingURL=debouncer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debouncer.d.ts","sourceRoot":"","sources":["../../../src/engine/hooks/debouncer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EAEZ,eAAe,EACf,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AA4CnC,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoD;IAClF,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,uCAAuC;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;gBAEjC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAK1E;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAyB/B;;;OAGG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAU3C;;OAEG;IACH,OAAO,IAAI,IAAI;IAcf,OAAO,CAAC,OAAO;CAkBhB"}
@@ -0,0 +1,124 @@
1
+ // engine/hooks/debouncer.ts — Debounce + rate limit for file events (SPEC-129)
2
+ // 300ms debounce per file, global rate limit per file per 5s,
3
+ // per-spec rate limit per 5 min. Token bucket algorithm.
4
+ // ---------------------------------------------------------------------------
5
+ // Token Bucket helpers
6
+ // ---------------------------------------------------------------------------
7
+ function createBucket(capacity, refillIntervalMs) {
8
+ return {
9
+ tokens: capacity,
10
+ lastRefill: Date.now(),
11
+ capacity,
12
+ refillIntervalMs,
13
+ };
14
+ }
15
+ function tryConsume(bucket, now) {
16
+ // Refill tokens based on elapsed time
17
+ const elapsed = now - bucket.lastRefill;
18
+ const tokensToAdd = Math.floor(elapsed / bucket.refillIntervalMs);
19
+ if (tokensToAdd > 0) {
20
+ const updated = {
21
+ ...bucket,
22
+ tokens: Math.min(bucket.capacity, bucket.tokens + tokensToAdd),
23
+ lastRefill: now,
24
+ };
25
+ Object.assign(bucket, updated);
26
+ }
27
+ if (bucket.tokens > 0) {
28
+ Object.assign(bucket, { tokens: bucket.tokens - 1 });
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ // ---------------------------------------------------------------------------
34
+ // Debouncer
35
+ // ---------------------------------------------------------------------------
36
+ const DEFAULT_CONFIG = {
37
+ debounceMs: 300,
38
+ rateLimitPerFileMs: 5000,
39
+ rateLimitPerSpecMs: 300_000,
40
+ };
41
+ export class Debouncer {
42
+ config;
43
+ /** Pending debounce timers per file path */
44
+ pendingTimers = new Map();
45
+ /** Pending event per file (latest wins) */
46
+ pendingEvents = new Map();
47
+ /** Rate limit buckets per file path */
48
+ fileBuckets = new Map();
49
+ /** Rate limit buckets per spec ID */
50
+ specBuckets = new Map();
51
+ callback;
52
+ constructor(callback, config) {
53
+ this.callback = callback;
54
+ this.config = { ...DEFAULT_CONFIG, ...config };
55
+ }
56
+ /**
57
+ * Feed a raw watcher event. The debouncer will coalesce rapid events
58
+ * and apply rate limiting before invoking the callback.
59
+ */
60
+ push(event) {
61
+ const key = event.path;
62
+ // Store the latest event (coalescing — last wins)
63
+ this.pendingEvents.set(key, event);
64
+ // Clear existing timer for this path
65
+ const existing = this.pendingTimers.get(key);
66
+ if (existing !== undefined) {
67
+ clearTimeout(existing);
68
+ }
69
+ // Set new debounce timer
70
+ const timer = setTimeout(() => {
71
+ this.pendingTimers.delete(key);
72
+ const latest = this.pendingEvents.get(key);
73
+ this.pendingEvents.delete(key);
74
+ if (latest) {
75
+ this.tryEmit(latest);
76
+ }
77
+ }, this.config.debounceMs);
78
+ this.pendingTimers.set(key, timer);
79
+ }
80
+ /**
81
+ * Check spec-level rate limit for auto-reconcile.
82
+ * Returns true if allowed, false if rate-limited.
83
+ */
84
+ checkSpecRateLimit(specId) {
85
+ const now = Date.now();
86
+ let bucket = this.specBuckets.get(specId);
87
+ if (!bucket) {
88
+ bucket = createBucket(1, this.config.rateLimitPerSpecMs);
89
+ this.specBuckets.set(specId, bucket);
90
+ }
91
+ return tryConsume(bucket, now);
92
+ }
93
+ /**
94
+ * Cancel all pending timers and clear state.
95
+ */
96
+ dispose() {
97
+ for (const timer of this.pendingTimers.values()) {
98
+ clearTimeout(timer);
99
+ }
100
+ this.pendingTimers.clear();
101
+ this.pendingEvents.clear();
102
+ this.fileBuckets.clear();
103
+ this.specBuckets.clear();
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // Private
107
+ // ---------------------------------------------------------------------------
108
+ tryEmit(event) {
109
+ const now = Date.now();
110
+ const key = event.path;
111
+ // File-level rate limit
112
+ let bucket = this.fileBuckets.get(key);
113
+ if (!bucket) {
114
+ bucket = createBucket(1, this.config.rateLimitPerFileMs);
115
+ this.fileBuckets.set(key, bucket);
116
+ }
117
+ if (!tryConsume(bucket, now)) {
118
+ // Rate limited — drop the event
119
+ return;
120
+ }
121
+ this.callback(event);
122
+ }
123
+ }
124
+ //# sourceMappingURL=debouncer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debouncer.js","sourceRoot":"","sources":["../../../src/engine/hooks/debouncer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { EventBusEvent } from '../../types/file-hooks.js';
3
+ /**
4
+ * Typed event bus extending EventEmitter.
5
+ * Provides typed events with discriminated unions, filtering,
6
+ * event history (FIFO, last 100), and meta-events.
7
+ */
8
+ export declare class EventBus extends EventEmitter {
9
+ private readonly history;
10
+ private idCounter;
11
+ constructor();
12
+ /**
13
+ * Emit a typed event. Automatically adds to history and fires meta-events.
14
+ */
15
+ emitEvent(type: EventBusEvent['type'], data: Record<string, unknown>): EventBusEvent;
16
+ /**
17
+ * Subscribe to events of a specific type.
18
+ */
19
+ onEvent(type: EventBusEvent['type'] | '*', listener: (event: EventBusEvent) => void): this;
20
+ /**
21
+ * Subscribe to events once.
22
+ */
23
+ onceEvent(type: EventBusEvent['type'] | '*', listener: (event: EventBusEvent) => void): this;
24
+ /**
25
+ * Get filtered event history.
26
+ */
27
+ getHistory(filter?: {
28
+ type?: EventBusEvent['type'];
29
+ filePattern?: string;
30
+ }): EventBusEvent[];
31
+ /**
32
+ * Get all events in history (readonly).
33
+ */
34
+ getFullHistory(): readonly EventBusEvent[];
35
+ /**
36
+ * Clear history.
37
+ */
38
+ clearHistory(): void;
39
+ }
40
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/engine/hooks/event-bus.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAY/D;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,YAAY;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,SAAS,CAAK;;IAOtB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa;IAoBpF;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAI1F;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAI5F;;OAEG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,EAAE;IAkB5F;;OAEG;IACH,cAAc,IAAI,SAAS,aAAa,EAAE;IAI1C;;OAEG;IACH,YAAY,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,83 @@
1
+ // engine/hooks/event-bus.ts — Typed event bus with history (SPEC-130)
2
+ import { EventEmitter } from 'node:events';
3
+ // ---------------------------------------------------------------------------
4
+ // Constants
5
+ // ---------------------------------------------------------------------------
6
+ const MAX_HISTORY = 100;
7
+ // ---------------------------------------------------------------------------
8
+ // EventBus
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Typed event bus extending EventEmitter.
12
+ * Provides typed events with discriminated unions, filtering,
13
+ * event history (FIFO, last 100), and meta-events.
14
+ */
15
+ export class EventBus extends EventEmitter {
16
+ history = [];
17
+ idCounter = 0;
18
+ constructor() {
19
+ super();
20
+ this.setMaxListeners(50);
21
+ }
22
+ /**
23
+ * Emit a typed event. Automatically adds to history and fires meta-events.
24
+ */
25
+ emitEvent(type, data) {
26
+ const event = {
27
+ id: `evt-${String(++this.idCounter)}-${Date.now()}`,
28
+ type,
29
+ timestamp: Date.now(),
30
+ data,
31
+ };
32
+ // FIFO eviction
33
+ if (this.history.length >= MAX_HISTORY) {
34
+ this.history.shift();
35
+ }
36
+ this.history.push(event);
37
+ this.emit(type, event);
38
+ this.emit('*', event);
39
+ return event;
40
+ }
41
+ /**
42
+ * Subscribe to events of a specific type.
43
+ */
44
+ onEvent(type, listener) {
45
+ return this.on(type, listener);
46
+ }
47
+ /**
48
+ * Subscribe to events once.
49
+ */
50
+ onceEvent(type, listener) {
51
+ return this.once(type, listener);
52
+ }
53
+ /**
54
+ * Get filtered event history.
55
+ */
56
+ getHistory(filter) {
57
+ let result = [...this.history];
58
+ if (filter?.type) {
59
+ result = result.filter((e) => e.type === filter.type);
60
+ }
61
+ if (filter?.filePattern) {
62
+ const regex = new RegExp(filter.filePattern);
63
+ result = result.filter((e) => {
64
+ const path = e.data.path;
65
+ return typeof path === 'string' && regex.test(path);
66
+ });
67
+ }
68
+ return result;
69
+ }
70
+ /**
71
+ * Get all events in history (readonly).
72
+ */
73
+ getFullHistory() {
74
+ return this.history;
75
+ }
76
+ /**
77
+ * Clear history.
78
+ */
79
+ clearHistory() {
80
+ this.history.length = 0;
81
+ }
82
+ }
83
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/engine/hooks/event-bus.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,OAAO,QAAS,SAAQ,YAAY;IACvB,OAAO,GAAoB,EAAE,CAAC;IACvC,SAAS,GAAG,CAAC,CAAC;IAEtB;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAA2B,EAAE,IAA6B;QAClE,MAAM,KAAK,GAAkB;YAC3B,EAAE,EAAE,OAAO,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;YACnD,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI;SACL,CAAC;QAEF,gBAAgB;QAChB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEzB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAiC,EAAE,QAAwC;QACjF,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAAiC,EAAE,QAAwC;QACnF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAA+D;QACxE,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAE/B,IAAI,MAAM,EAAE,IAAI,EAAE,CAAC;YACjB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACzB,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtD,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { FileWatcherOptions } from '../../types/file-hooks.js';
3
+ /**
4
+ * Convert a glob pattern to a RegExp. Supports:
5
+ * - `**` matches any path segment (including nested)
6
+ * - `*` matches any characters except path separator
7
+ * - `?` matches a single character
8
+ */
9
+ export declare function globToRegex(pattern: string): RegExp;
10
+ /**
11
+ * Test whether `filePath` matches a glob pattern.
12
+ */
13
+ export declare function matchesGlobPattern(filePath: string, pattern: string): boolean;
14
+ /**
15
+ * Returns true if filePath matches any include pattern
16
+ * and does not match any exclude pattern.
17
+ */
18
+ export declare function matchesPatterns(filePath: string, include?: string[], exclude?: string[]): boolean;
19
+ export declare class FileWatcher extends EventEmitter {
20
+ private watcher;
21
+ private readonly rootDir;
22
+ private readonly include;
23
+ private readonly exclude;
24
+ /** Track known files to distinguish create vs modify */
25
+ private readonly knownFiles;
26
+ private closed;
27
+ constructor(options: FileWatcherOptions);
28
+ /**
29
+ * Start watching. Emits 'change' events with WatcherEvent payloads.
30
+ * Emits 'error' on watch failure — never throws.
31
+ */
32
+ start(): void;
33
+ /**
34
+ * Mark a file as known (pre-existing). Call this for initial file scan.
35
+ */
36
+ addKnownFile(relPath: string): void;
37
+ /**
38
+ * Mark multiple files as known.
39
+ */
40
+ addKnownFiles(paths: string[]): void;
41
+ /**
42
+ * Graceful shutdown: release all handles.
43
+ */
44
+ close(): void;
45
+ private handleFsEvent;
46
+ private determineEventType;
47
+ }
48
+ //# sourceMappingURL=file-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../../src/engine/hooks/file-watcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAkC,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpG;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6BnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAYjG;AAYD,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,kBAAkB;IAOvC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAqBb;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAMpC;;OAEG;IACH,KAAK,IAAI,IAAI;YAaC,aAAa;YA4Bb,kBAAkB;CAoBjC"}