@planu/cli 1.11.0 → 1.13.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 (298) hide show
  1. package/dist/config/ai-tool-registry.json +71 -0
  2. package/dist/config/autopilot-config.json +21 -0
  3. package/dist/config/competitive-catalog.json +83 -0
  4. package/dist/config/license-plans.json +43 -2
  5. package/dist/engine/agent-registry/lifecycle-manager.d.ts +8 -0
  6. package/dist/engine/agent-registry/lifecycle-manager.d.ts.map +1 -0
  7. package/dist/engine/agent-registry/lifecycle-manager.js +81 -0
  8. package/dist/engine/agent-registry/lifecycle-manager.js.map +1 -0
  9. package/dist/engine/agent-registry/role-catalog.d.ts +17 -0
  10. package/dist/engine/agent-registry/role-catalog.d.ts.map +1 -0
  11. package/dist/engine/agent-registry/role-catalog.js +55 -0
  12. package/dist/engine/agent-registry/role-catalog.js.map +1 -0
  13. package/dist/engine/api-compat/compatibility-checker.d.ts +4 -0
  14. package/dist/engine/api-compat/compatibility-checker.d.ts.map +1 -0
  15. package/dist/engine/api-compat/compatibility-checker.js +118 -0
  16. package/dist/engine/api-compat/compatibility-checker.js.map +1 -0
  17. package/dist/engine/autopilot/action-executor.d.ts +18 -0
  18. package/dist/engine/autopilot/action-executor.d.ts.map +1 -0
  19. package/dist/engine/autopilot/action-executor.js +91 -0
  20. package/dist/engine/autopilot/action-executor.js.map +1 -0
  21. package/dist/engine/autopilot/event-bus.d.ts +8 -0
  22. package/dist/engine/autopilot/event-bus.d.ts.map +1 -0
  23. package/dist/engine/autopilot/event-bus.js +28 -0
  24. package/dist/engine/autopilot/event-bus.js.map +1 -0
  25. package/dist/engine/autopilot/trigger-rules.d.ts +3 -0
  26. package/dist/engine/autopilot/trigger-rules.d.ts.map +1 -0
  27. package/dist/engine/autopilot/trigger-rules.js +125 -0
  28. package/dist/engine/autopilot/trigger-rules.js.map +1 -0
  29. package/dist/engine/checkpoint/checkpoint-manager.d.ts +22 -0
  30. package/dist/engine/checkpoint/checkpoint-manager.d.ts.map +1 -0
  31. package/dist/engine/checkpoint/checkpoint-manager.js +76 -0
  32. package/dist/engine/checkpoint/checkpoint-manager.js.map +1 -0
  33. package/dist/engine/checkpoint/policy-engine.d.ts +10 -0
  34. package/dist/engine/checkpoint/policy-engine.d.ts.map +1 -0
  35. package/dist/engine/checkpoint/policy-engine.js +87 -0
  36. package/dist/engine/checkpoint/policy-engine.js.map +1 -0
  37. package/dist/engine/competitive/gap-analyzer.d.ts +12 -0
  38. package/dist/engine/competitive/gap-analyzer.d.ts.map +1 -0
  39. package/dist/engine/competitive/gap-analyzer.js +214 -0
  40. package/dist/engine/competitive/gap-analyzer.js.map +1 -0
  41. package/dist/engine/compliance/auto-remediator.d.ts +9 -0
  42. package/dist/engine/compliance/auto-remediator.d.ts.map +1 -0
  43. package/dist/engine/compliance/auto-remediator.js +118 -0
  44. package/dist/engine/compliance/auto-remediator.js.map +1 -0
  45. package/dist/engine/context-profile/profile-catalog.d.ts +5 -0
  46. package/dist/engine/context-profile/profile-catalog.d.ts.map +1 -0
  47. package/dist/engine/context-profile/profile-catalog.js +145 -0
  48. package/dist/engine/context-profile/profile-catalog.js.map +1 -0
  49. package/dist/engine/critical-path/path-analyzer.d.ts +3 -0
  50. package/dist/engine/critical-path/path-analyzer.d.ts.map +1 -0
  51. package/dist/engine/critical-path/path-analyzer.js +145 -0
  52. package/dist/engine/critical-path/path-analyzer.js.map +1 -0
  53. package/dist/engine/drift/violation-resolver.d.ts +9 -0
  54. package/dist/engine/drift/violation-resolver.d.ts.map +1 -0
  55. package/dist/engine/drift/violation-resolver.js +128 -0
  56. package/dist/engine/drift/violation-resolver.js.map +1 -0
  57. package/dist/engine/ears/criterion-scorer.d.ts +7 -0
  58. package/dist/engine/ears/criterion-scorer.d.ts.map +1 -0
  59. package/dist/engine/ears/criterion-scorer.js +87 -0
  60. package/dist/engine/ears/criterion-scorer.js.map +1 -0
  61. package/dist/engine/ears/pattern-matcher.d.ts +5 -0
  62. package/dist/engine/ears/pattern-matcher.d.ts.map +1 -0
  63. package/dist/engine/ears/pattern-matcher.js +48 -0
  64. package/dist/engine/ears/pattern-matcher.js.map +1 -0
  65. package/dist/engine/ears/rewriter.d.ts +7 -0
  66. package/dist/engine/ears/rewriter.d.ts.map +1 -0
  67. package/dist/engine/ears/rewriter.js +45 -0
  68. package/dist/engine/ears/rewriter.js.map +1 -0
  69. package/dist/engine/ears/spec-linter.d.ts +7 -0
  70. package/dist/engine/ears/spec-linter.d.ts.map +1 -0
  71. package/dist/engine/ears/spec-linter.js +127 -0
  72. package/dist/engine/ears/spec-linter.js.map +1 -0
  73. package/dist/engine/health/auto-fixer.d.ts +7 -0
  74. package/dist/engine/health/auto-fixer.d.ts.map +1 -0
  75. package/dist/engine/health/auto-fixer.js +130 -0
  76. package/dist/engine/health/auto-fixer.js.map +1 -0
  77. package/dist/engine/hook-generator/ai-hook-templates.d.ts +8 -0
  78. package/dist/engine/hook-generator/ai-hook-templates.d.ts.map +1 -0
  79. package/dist/engine/hook-generator/ai-hook-templates.js +43 -0
  80. package/dist/engine/hook-generator/ai-hook-templates.js.map +1 -0
  81. package/dist/engine/hook-generator/hook-merger.d.ts +13 -0
  82. package/dist/engine/hook-generator/hook-merger.d.ts.map +1 -0
  83. package/dist/engine/hook-generator/hook-merger.js +148 -0
  84. package/dist/engine/hook-generator/hook-merger.js.map +1 -0
  85. package/dist/engine/hook-generator/stack-hook-templates.d.ts +10 -0
  86. package/dist/engine/hook-generator/stack-hook-templates.d.ts.map +1 -0
  87. package/dist/engine/hook-generator/stack-hook-templates.js +105 -0
  88. package/dist/engine/hook-generator/stack-hook-templates.js.map +1 -0
  89. package/dist/engine/mcp-catalog/catalog-advisor.d.ts +3 -0
  90. package/dist/engine/mcp-catalog/catalog-advisor.d.ts.map +1 -0
  91. package/dist/engine/mcp-catalog/catalog-advisor.js +180 -0
  92. package/dist/engine/mcp-catalog/catalog-advisor.js.map +1 -0
  93. package/dist/engine/project-dna/ai-tool-detector.d.ts +12 -0
  94. package/dist/engine/project-dna/ai-tool-detector.d.ts.map +1 -0
  95. package/dist/engine/project-dna/ai-tool-detector.js +103 -0
  96. package/dist/engine/project-dna/ai-tool-detector.js.map +1 -0
  97. package/dist/engine/project-dna/rules-generator.d.ts +18 -0
  98. package/dist/engine/project-dna/rules-generator.d.ts.map +1 -0
  99. package/dist/engine/project-dna/rules-generator.js +193 -0
  100. package/dist/engine/project-dna/rules-generator.js.map +1 -0
  101. package/dist/engine/project-dna/stack-detector.d.ts +24 -0
  102. package/dist/engine/project-dna/stack-detector.d.ts.map +1 -0
  103. package/dist/engine/project-dna/stack-detector.js +309 -0
  104. package/dist/engine/project-dna/stack-detector.js.map +1 -0
  105. package/dist/engine/similar-problems/similarity-finder.d.ts +3 -0
  106. package/dist/engine/similar-problems/similarity-finder.d.ts.map +1 -0
  107. package/dist/engine/similar-problems/similarity-finder.js +144 -0
  108. package/dist/engine/similar-problems/similarity-finder.js.map +1 -0
  109. package/dist/engine/sync/asana-puller.d.ts +9 -0
  110. package/dist/engine/sync/asana-puller.d.ts.map +1 -0
  111. package/dist/engine/sync/asana-puller.js +91 -0
  112. package/dist/engine/sync/asana-puller.js.map +1 -0
  113. package/dist/engine/sync/conflict-resolver.d.ts +17 -0
  114. package/dist/engine/sync/conflict-resolver.d.ts.map +1 -0
  115. package/dist/engine/sync/conflict-resolver.js +58 -0
  116. package/dist/engine/sync/conflict-resolver.js.map +1 -0
  117. package/dist/engine/sync/monday-puller.d.ts +9 -0
  118. package/dist/engine/sync/monday-puller.d.ts.map +1 -0
  119. package/dist/engine/sync/monday-puller.js +110 -0
  120. package/dist/engine/sync/monday-puller.js.map +1 -0
  121. package/dist/engine/sync/notion-puller.d.ts +15 -0
  122. package/dist/engine/sync/notion-puller.d.ts.map +1 -0
  123. package/dist/engine/sync/notion-puller.js +101 -0
  124. package/dist/engine/sync/notion-puller.js.map +1 -0
  125. package/dist/engine/verifier/code-scanner.d.ts +8 -0
  126. package/dist/engine/verifier/code-scanner.d.ts.map +1 -0
  127. package/dist/engine/verifier/code-scanner.js +73 -0
  128. package/dist/engine/verifier/code-scanner.js.map +1 -0
  129. package/dist/engine/verifier/compliance-scorer.d.ts +17 -0
  130. package/dist/engine/verifier/compliance-scorer.d.ts.map +1 -0
  131. package/dist/engine/verifier/compliance-scorer.js +131 -0
  132. package/dist/engine/verifier/compliance-scorer.js.map +1 -0
  133. package/dist/engine/verifier/criterion-matcher.d.ts +15 -0
  134. package/dist/engine/verifier/criterion-matcher.d.ts.map +1 -0
  135. package/dist/engine/verifier/criterion-matcher.js +210 -0
  136. package/dist/engine/verifier/criterion-matcher.js.map +1 -0
  137. package/dist/index.js +24 -0
  138. package/dist/index.js.map +1 -1
  139. package/dist/storage/agent-registry-store.d.ts +11 -0
  140. package/dist/storage/agent-registry-store.d.ts.map +1 -0
  141. package/dist/storage/agent-registry-store.js +45 -0
  142. package/dist/storage/agent-registry-store.js.map +1 -0
  143. package/dist/storage/compliance-score-store.d.ts +16 -0
  144. package/dist/storage/compliance-score-store.d.ts.map +1 -0
  145. package/dist/storage/compliance-score-store.js +30 -0
  146. package/dist/storage/compliance-score-store.js.map +1 -0
  147. package/dist/storage/context-profile-store.d.ts +14 -0
  148. package/dist/storage/context-profile-store.d.ts.map +1 -0
  149. package/dist/storage/context-profile-store.js +34 -0
  150. package/dist/storage/context-profile-store.js.map +1 -0
  151. package/dist/storage/workflow-checkpoint-store.d.ts +16 -0
  152. package/dist/storage/workflow-checkpoint-store.d.ts.map +1 -0
  153. package/dist/storage/workflow-checkpoint-store.js +71 -0
  154. package/dist/storage/workflow-checkpoint-store.js.map +1 -0
  155. package/dist/tools/checkpoint/approve-checkpoint-handler.d.ts +3 -0
  156. package/dist/tools/checkpoint/approve-checkpoint-handler.d.ts.map +1 -0
  157. package/dist/tools/checkpoint/approve-checkpoint-handler.js +32 -0
  158. package/dist/tools/checkpoint/approve-checkpoint-handler.js.map +1 -0
  159. package/dist/tools/checkpoint/configure-policy-handler.d.ts +3 -0
  160. package/dist/tools/checkpoint/configure-policy-handler.d.ts.map +1 -0
  161. package/dist/tools/checkpoint/configure-policy-handler.js +60 -0
  162. package/dist/tools/checkpoint/configure-policy-handler.js.map +1 -0
  163. package/dist/tools/checkpoint/list-checkpoints-handler.d.ts +3 -0
  164. package/dist/tools/checkpoint/list-checkpoints-handler.d.ts.map +1 -0
  165. package/dist/tools/checkpoint/list-checkpoints-handler.js +25 -0
  166. package/dist/tools/checkpoint/list-checkpoints-handler.js.map +1 -0
  167. package/dist/tools/checkpoint/reject-checkpoint-handler.d.ts +3 -0
  168. package/dist/tools/checkpoint/reject-checkpoint-handler.d.ts.map +1 -0
  169. package/dist/tools/checkpoint/reject-checkpoint-handler.js +32 -0
  170. package/dist/tools/checkpoint/reject-checkpoint-handler.js.map +1 -0
  171. package/dist/tools/checkpoint/require-checkpoint-handler.d.ts +3 -0
  172. package/dist/tools/checkpoint/require-checkpoint-handler.d.ts.map +1 -0
  173. package/dist/tools/checkpoint/require-checkpoint-handler.js +44 -0
  174. package/dist/tools/checkpoint/require-checkpoint-handler.js.map +1 -0
  175. package/dist/tools/competitive-handlers.d.ts +30 -0
  176. package/dist/tools/competitive-handlers.d.ts.map +1 -0
  177. package/dist/tools/competitive-handlers.js +155 -0
  178. package/dist/tools/competitive-handlers.js.map +1 -0
  179. package/dist/tools/create-spec/post-creation.d.ts +1 -1
  180. package/dist/tools/create-spec/post-creation.d.ts.map +1 -1
  181. package/dist/tools/create-spec/post-creation.js +13 -1
  182. package/dist/tools/create-spec/post-creation.js.map +1 -1
  183. package/dist/tools/create-spec.js +1 -1
  184. package/dist/tools/create-spec.js.map +1 -1
  185. package/dist/tools/hook-generator-handler.d.ts +8 -0
  186. package/dist/tools/hook-generator-handler.d.ts.map +1 -0
  187. package/dist/tools/hook-generator-handler.js +154 -0
  188. package/dist/tools/hook-generator-handler.js.map +1 -0
  189. package/dist/tools/project-dna-handler.d.ts +34 -0
  190. package/dist/tools/project-dna-handler.d.ts.map +1 -0
  191. package/dist/tools/project-dna-handler.js +261 -0
  192. package/dist/tools/project-dna-handler.js.map +1 -0
  193. package/dist/tools/pull-sync-handler.d.ts +25 -0
  194. package/dist/tools/pull-sync-handler.d.ts.map +1 -0
  195. package/dist/tools/pull-sync-handler.js +161 -0
  196. package/dist/tools/pull-sync-handler.js.map +1 -0
  197. package/dist/tools/register-agent-registry.d.ts +5 -0
  198. package/dist/tools/register-agent-registry.d.ts.map +1 -0
  199. package/dist/tools/register-agent-registry.js +254 -0
  200. package/dist/tools/register-agent-registry.js.map +1 -0
  201. package/dist/tools/register-auto-remediation.d.ts +3 -0
  202. package/dist/tools/register-auto-remediation.d.ts.map +1 -0
  203. package/dist/tools/register-auto-remediation.js +174 -0
  204. package/dist/tools/register-auto-remediation.js.map +1 -0
  205. package/dist/tools/register-autopilot.d.ts +3 -0
  206. package/dist/tools/register-autopilot.d.ts.map +1 -0
  207. package/dist/tools/register-autopilot.js +78 -0
  208. package/dist/tools/register-autopilot.js.map +1 -0
  209. package/dist/tools/register-checkpoints.d.ts +3 -0
  210. package/dist/tools/register-checkpoints.d.ts.map +1 -0
  211. package/dist/tools/register-checkpoints.js +134 -0
  212. package/dist/tools/register-checkpoints.js.map +1 -0
  213. package/dist/tools/register-competitive.d.ts +3 -0
  214. package/dist/tools/register-competitive.d.ts.map +1 -0
  215. package/dist/tools/register-competitive.js +88 -0
  216. package/dist/tools/register-competitive.js.map +1 -0
  217. package/dist/tools/register-context-profile.d.ts +3 -0
  218. package/dist/tools/register-context-profile.d.ts.map +1 -0
  219. package/dist/tools/register-context-profile.js +106 -0
  220. package/dist/tools/register-context-profile.js.map +1 -0
  221. package/dist/tools/register-ears.d.ts +3 -0
  222. package/dist/tools/register-ears.d.ts.map +1 -0
  223. package/dist/tools/register-ears.js +148 -0
  224. package/dist/tools/register-ears.js.map +1 -0
  225. package/dist/tools/register-enterprise-compliance.js +1 -1
  226. package/dist/tools/register-enterprise-compliance.js.map +1 -1
  227. package/dist/tools/register-hook-generator.d.ts +3 -0
  228. package/dist/tools/register-hook-generator.d.ts.map +1 -0
  229. package/dist/tools/register-hook-generator.js +96 -0
  230. package/dist/tools/register-hook-generator.js.map +1 -0
  231. package/dist/tools/register-project-dna.d.ts +3 -0
  232. package/dist/tools/register-project-dna.d.ts.map +1 -0
  233. package/dist/tools/register-project-dna.js +43 -0
  234. package/dist/tools/register-project-dna.js.map +1 -0
  235. package/dist/tools/register-pull-sync.d.ts +3 -0
  236. package/dist/tools/register-pull-sync.d.ts.map +1 -0
  237. package/dist/tools/register-pull-sync.js +71 -0
  238. package/dist/tools/register-pull-sync.js.map +1 -0
  239. package/dist/tools/register-spec405-tools.d.ts +7 -0
  240. package/dist/tools/register-spec405-tools.d.ts.map +1 -0
  241. package/dist/tools/register-spec405-tools.js +194 -0
  242. package/dist/tools/register-spec405-tools.js.map +1 -0
  243. package/dist/tools/register-verifier.d.ts +3 -0
  244. package/dist/tools/register-verifier.d.ts.map +1 -0
  245. package/dist/tools/register-verifier.js +141 -0
  246. package/dist/tools/register-verifier.js.map +1 -0
  247. package/dist/tools/update-status/side-effects.d.ts.map +1 -1
  248. package/dist/tools/update-status/side-effects.js +32 -0
  249. package/dist/tools/update-status/side-effects.js.map +1 -1
  250. package/dist/types/agent-registry.d.ts +53 -0
  251. package/dist/types/agent-registry.d.ts.map +1 -0
  252. package/dist/types/agent-registry.js +2 -0
  253. package/dist/types/agent-registry.js.map +1 -0
  254. package/dist/types/analysis.d.ts +98 -0
  255. package/dist/types/analysis.d.ts.map +1 -1
  256. package/dist/types/autopilot.d.ts +36 -0
  257. package/dist/types/autopilot.d.ts.map +1 -0
  258. package/dist/types/autopilot.js +3 -0
  259. package/dist/types/autopilot.js.map +1 -0
  260. package/dist/types/competitive.d.ts +41 -0
  261. package/dist/types/competitive.d.ts.map +1 -0
  262. package/dist/types/competitive.js +3 -0
  263. package/dist/types/competitive.js.map +1 -0
  264. package/dist/types/context-profile.d.ts +22 -0
  265. package/dist/types/context-profile.d.ts.map +1 -0
  266. package/dist/types/context-profile.js +2 -0
  267. package/dist/types/context-profile.js.map +1 -0
  268. package/dist/types/ears.d.ts +34 -0
  269. package/dist/types/ears.d.ts.map +1 -0
  270. package/dist/types/ears.js +3 -0
  271. package/dist/types/ears.js.map +1 -0
  272. package/dist/types/health.d.ts +40 -0
  273. package/dist/types/health.d.ts.map +1 -0
  274. package/dist/types/health.js +3 -0
  275. package/dist/types/health.js.map +1 -0
  276. package/dist/types/hook-generator.d.ts +49 -0
  277. package/dist/types/hook-generator.d.ts.map +1 -0
  278. package/dist/types/hook-generator.js +3 -0
  279. package/dist/types/hook-generator.js.map +1 -0
  280. package/dist/types/index.d.ts +9 -0
  281. package/dist/types/index.d.ts.map +1 -1
  282. package/dist/types/index.js +9 -0
  283. package/dist/types/index.js.map +1 -1
  284. package/dist/types/notion-asana-monday.d.ts +38 -0
  285. package/dist/types/notion-asana-monday.d.ts.map +1 -1
  286. package/dist/types/project-dna.d.ts +46 -0
  287. package/dist/types/project-dna.d.ts.map +1 -0
  288. package/dist/types/project-dna.js +4 -0
  289. package/dist/types/project-dna.js.map +1 -0
  290. package/dist/types/workflow-checkpoint.d.ts +66 -0
  291. package/dist/types/workflow-checkpoint.d.ts.map +1 -0
  292. package/dist/types/workflow-checkpoint.js +4 -0
  293. package/dist/types/workflow-checkpoint.js.map +1 -0
  294. package/package.json +1 -1
  295. package/src/config/ai-tool-registry.json +71 -0
  296. package/src/config/autopilot-config.json +21 -0
  297. package/src/config/competitive-catalog.json +83 -0
  298. package/src/config/license-plans.json +43 -2
@@ -0,0 +1,91 @@
1
+ // engine/autopilot/action-executor.ts — SPEC-413: Executes trigger actions
2
+ import { readFile, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { DEFAULT_TRIGGER_RULES } from './trigger-rules.js';
5
+ const CONFIG_PATH_IN_PLANU = 'planu/autopilot-config.json';
6
+ export async function loadAutopilotConfig(projectPath) {
7
+ const localPath = join(projectPath, CONFIG_PATH_IN_PLANU);
8
+ try {
9
+ const raw = await readFile(localPath, 'utf-8');
10
+ return JSON.parse(raw);
11
+ }
12
+ catch {
13
+ // Fall back to bundled defaults
14
+ const { createRequire } = await import('node:module');
15
+ const req = createRequire(import.meta.url);
16
+ return req('../../config/autopilot-config.json');
17
+ }
18
+ }
19
+ export async function saveAutopilotConfig(projectPath, config) {
20
+ const localPath = join(projectPath, CONFIG_PATH_IN_PLANU);
21
+ await writeFile(localPath, JSON.stringify(config, null, 2), 'utf-8');
22
+ }
23
+ function conditionMet(condition, event) {
24
+ if (!condition) {
25
+ return true;
26
+ }
27
+ const payload = event.payload ?? {};
28
+ if (condition.minEstimatedHours !== undefined) {
29
+ const hours = typeof payload.estimatedHours === 'number' ? payload.estimatedHours : 0;
30
+ if (hours < condition.minEstimatedHours) {
31
+ return false;
32
+ }
33
+ }
34
+ if (condition.riskLevel !== undefined) {
35
+ const risk = typeof payload.risk === 'string' ? payload.risk : '';
36
+ if (!condition.riskLevel.includes(risk)) {
37
+ return false;
38
+ }
39
+ }
40
+ if (condition.minDriftScore !== undefined) {
41
+ const score = typeof payload.driftScore === 'number' ? payload.driftScore : 0;
42
+ if (score < condition.minDriftScore) {
43
+ return false;
44
+ }
45
+ }
46
+ return true;
47
+ }
48
+ /**
49
+ * Executes all enabled trigger rules that match the given event.
50
+ * Each action is logged but never awaited — fire-and-forget.
51
+ */
52
+ export async function executeTriggersForEvent(event) {
53
+ const config = await loadAutopilotConfig(event.projectPath);
54
+ const triggered = [];
55
+ for (const rule of DEFAULT_TRIGGER_RULES) {
56
+ if (rule.event !== event.name) {
57
+ continue;
58
+ }
59
+ // Check config override
60
+ const ruleConfig = config.rules[rule.id];
61
+ const isEnabled = ruleConfig !== undefined ? ruleConfig.enabled : rule.enabled;
62
+ if (!isEnabled) {
63
+ continue;
64
+ }
65
+ // Check conditions
66
+ if (!conditionMet(rule.condition, event)) {
67
+ continue;
68
+ }
69
+ triggered.push(rule.action);
70
+ console.error(`[autopilot] triggered: ${rule.id} for ${event.name}${event.specId ? ` (${event.specId})` : ''}`);
71
+ }
72
+ return triggered;
73
+ }
74
+ /**
75
+ * Returns the current autopilot status for a project.
76
+ */
77
+ export async function getAutopilotStatus(projectPath) {
78
+ const config = await loadAutopilotConfig(projectPath);
79
+ const rules = DEFAULT_TRIGGER_RULES.map((rule) => {
80
+ const override = config.rules[rule.id];
81
+ return { ...rule, enabled: override !== undefined ? override.enabled : rule.enabled };
82
+ });
83
+ const disabledRules = rules.filter((r) => !r.enabled).map((r) => r.id);
84
+ return {
85
+ totalRules: rules.length,
86
+ enabledRules: rules.filter((r) => r.enabled).length,
87
+ disabledRules,
88
+ rules,
89
+ };
90
+ }
91
+ //# sourceMappingURL=action-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-executor.js","sourceRoot":"","sources":["../../../src/engine/autopilot/action-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AutopilotEvent, AutopilotEventName } from '../../types/index.js';
2
+ type EventHandler = (event: AutopilotEvent) => void;
3
+ export declare function onAutopilotEvent(name: AutopilotEventName, handler: EventHandler): void;
4
+ export declare function emitAutopilotEvent(event: AutopilotEvent): void;
5
+ /** Clears all handlers — used in tests */
6
+ export declare function clearAutopilotHandlers(): void;
7
+ export {};
8
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/engine/autopilot/event-bus.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/E,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAIpD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAItF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAe9D;AAED,0CAA0C;AAC1C,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,28 @@
1
+ // engine/autopilot/event-bus.ts — SPEC-413: Simple in-memory event bus for autopilot triggers
2
+ const handlers = new Map();
3
+ export function onAutopilotEvent(name, handler) {
4
+ const existing = handlers.get(name) ?? [];
5
+ existing.push(handler);
6
+ handlers.set(name, existing);
7
+ }
8
+ export function emitAutopilotEvent(event) {
9
+ // Fire-and-forget: never throw, never await
10
+ const eventHandlers = handlers.get(event.name) ?? [];
11
+ for (const handler of eventHandlers) {
12
+ // Execute each handler in its own micro-task to avoid blocking
13
+ Promise.resolve()
14
+ .then(() => {
15
+ handler(event);
16
+ })
17
+ .catch((err) => {
18
+ // Silent: autopilot errors never surface to user
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ console.error(`[autopilot] handler error for ${event.name}: ${message}`);
21
+ });
22
+ }
23
+ }
24
+ /** Clears all handlers — used in tests */
25
+ export function clearAutopilotHandlers() {
26
+ handlers.clear();
27
+ }
28
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/engine/autopilot/event-bus.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAO9F,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsC,CAAC;AAE/D,MAAM,UAAU,gBAAgB,CAAC,IAAwB,EAAE,OAAqB;IAC9E,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAqB;IACtD,4CAA4C;IAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrD,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,+DAA+D;QAC/D,OAAO,CAAC,OAAO,EAAE;aACd,IAAI,CAAC,GAAG,EAAE;YACT,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,iDAAiD;YACjD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,iCAAiC,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACP,CAAC;AACH,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,sBAAsB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TriggerRule } from '../../types/index.js';
2
+ export declare const DEFAULT_TRIGGER_RULES: TriggerRule[];
3
+ //# sourceMappingURL=trigger-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-rules.d.ts","sourceRoot":"","sources":["../../../src/engine/autopilot/trigger-rules.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,eAAO,MAAM,qBAAqB,EAAE,WAAW,EA0H9C,CAAC"}
@@ -0,0 +1,125 @@
1
+ // engine/autopilot/trigger-rules.ts — SPEC-413: Catalog of default trigger rules
2
+ export const DEFAULT_TRIGGER_RULES = [
3
+ // ── post spec:created ──────────────────────────────────────────────────────
4
+ {
5
+ id: 'post-create:validate_criteria_quality',
6
+ event: 'spec:created',
7
+ action: 'validate_criteria_quality',
8
+ enabled: true,
9
+ description: 'Scores EARS quality of acceptance criteria after spec creation',
10
+ },
11
+ {
12
+ id: 'post-create:suggest_criteria',
13
+ event: 'spec:created',
14
+ action: 'suggest_criteria',
15
+ enabled: true,
16
+ description: 'Suggests missing domain criteria (security, compliance, edge cases)',
17
+ },
18
+ {
19
+ id: 'post-create:detect_contradictions',
20
+ event: 'spec:created',
21
+ action: 'detect_contradictions',
22
+ enabled: true,
23
+ description: 'Runs full contradiction detection on new spec criteria',
24
+ },
25
+ // ── post spec:status:approved ──────────────────────────────────────────────
26
+ {
27
+ id: 'post-approved:challenge_spec',
28
+ event: 'spec:status:approved',
29
+ action: 'challenge_spec',
30
+ enabled: true,
31
+ condition: { minEstimatedHours: 20, riskLevel: ['high', 'critical'] },
32
+ description: 'Stress-tests approved specs with >20h estimate or high risk',
33
+ },
34
+ {
35
+ id: 'post-approved:spec_quality_score',
36
+ event: 'spec:status:approved',
37
+ action: 'spec_quality_score',
38
+ enabled: true,
39
+ description: 'Generates A-F quality score at approval time',
40
+ },
41
+ {
42
+ id: 'post-approved:generate_orchestration_plan',
43
+ event: 'spec:status:approved',
44
+ action: 'generate_orchestration_plan',
45
+ enabled: true,
46
+ condition: { minEstimatedHours: 20 },
47
+ description: 'Suggests multi-agent plan for large specs (>20h)',
48
+ },
49
+ // ── post spec:status:implementing ─────────────────────────────────────────
50
+ {
51
+ id: 'post-implementing:tdd_scaffold',
52
+ event: 'spec:status:implementing',
53
+ action: 'tdd_scaffold',
54
+ enabled: true,
55
+ description: 'Generates test scaffold from acceptance criteria when implementation starts',
56
+ },
57
+ {
58
+ id: 'post-implementing:watch_spec_drift_start',
59
+ event: 'spec:status:implementing',
60
+ action: 'watch_spec_drift',
61
+ enabled: true,
62
+ description: 'Starts file watcher for real-time drift detection',
63
+ },
64
+ // ── post spec:status:done ──────────────────────────────────────────────────
65
+ {
66
+ id: 'post-done:watch_spec_drift_stop',
67
+ event: 'spec:status:done',
68
+ action: 'watch_spec_drift',
69
+ enabled: true,
70
+ description: 'Stops drift watcher when spec is marked done',
71
+ },
72
+ {
73
+ id: 'post-done:auto_fix_health',
74
+ event: 'spec:status:done',
75
+ action: 'auto_fix_health',
76
+ enabled: true,
77
+ description: 'Auto-repairs deterministic health issues post-done',
78
+ },
79
+ {
80
+ id: 'post-done:generate_changelog',
81
+ event: 'spec:status:done',
82
+ action: 'generate_changelog',
83
+ enabled: true,
84
+ description: 'Generates changelog entry when spec completes',
85
+ },
86
+ // ── drift:detected ────────────────────────────────────────────────────────
87
+ {
88
+ id: 'drift-detected:resolve_drift_violations',
89
+ event: 'drift:detected',
90
+ action: 'resolve_drift_violations',
91
+ enabled: true,
92
+ condition: { minDriftScore: 0.3 },
93
+ description: 'Auto-resolves drift violations when score exceeds threshold',
94
+ },
95
+ {
96
+ id: 'drift-detected:log_lesson',
97
+ event: 'drift:detected',
98
+ action: 'log_lesson',
99
+ enabled: true,
100
+ description: 'Logs lesson learned when drift is detected',
101
+ },
102
+ // ── cron:daily ────────────────────────────────────────────────────────────
103
+ {
104
+ id: 'cron:health_check_all',
105
+ event: 'cron:daily',
106
+ action: 'health_check_all',
107
+ enabled: false,
108
+ description: 'Daily health check across all specs (opt-in)',
109
+ },
110
+ {
111
+ id: 'cron:velocity_report',
112
+ event: 'cron:daily',
113
+ action: 'velocity_report',
114
+ enabled: false,
115
+ description: 'Daily velocity metrics (opt-in)',
116
+ },
117
+ {
118
+ id: 'cron:estimation_accuracy_report',
119
+ event: 'cron:daily',
120
+ action: 'estimation_accuracy_report',
121
+ enabled: false,
122
+ description: 'Daily estimation calibration (opt-in)',
123
+ },
124
+ ];
125
+ //# sourceMappingURL=trigger-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-rules.js","sourceRoot":"","sources":["../../../src/engine/autopilot/trigger-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { WorkflowCheckpoint, CheckpointPolicy } from '../../types/index.js';
2
+ /**
3
+ * Creates a new pending checkpoint for the given spec transition.
4
+ * If the policy has autoApproveAfterHours set, schedules the auto-approve time.
5
+ */
6
+ export declare function requestCheckpoint(projectPath: string, specId: string, policy: CheckpointPolicy, requestedBy: string): Promise<WorkflowCheckpoint>;
7
+ /**
8
+ * Approves a pending checkpoint.
9
+ * Returns the updated checkpoint and a flag indicating the blocked transition can now proceed.
10
+ */
11
+ export declare function approveCheckpoint(projectPath: string, checkpointId: string, approvedBy: string): Promise<{
12
+ checkpoint: WorkflowCheckpoint;
13
+ transitionApplied: boolean;
14
+ }>;
15
+ /** Rejects a pending checkpoint with a mandatory reason. */
16
+ export declare function rejectCheckpoint(projectPath: string, checkpointId: string, rejectedBy: string, reason: string): Promise<WorkflowCheckpoint>;
17
+ /**
18
+ * Scans all pending checkpoints for a project and auto-approves any that have
19
+ * passed their autoApproveAt deadline. Returns the list of auto-approved checkpoints.
20
+ */
21
+ export declare function checkAutoApprovals(projectPath: string): Promise<WorkflowCheckpoint[]>;
22
+ //# sourceMappingURL=checkpoint-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-manager.d.ts","sourceRoot":"","sources":["../../../src/engine/checkpoint/checkpoint-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAYjF;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAmB7B;AAMD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAAC,CAMzE;AAMD,4DAA4D;AAC5D,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAM7B;AAMD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAmB3F"}
@@ -0,0 +1,76 @@
1
+ // engine/checkpoint/checkpoint-manager.ts — Checkpoint lifecycle management (SPEC-411)
2
+ import { hashProjectPath } from '../../storage/base-store.js';
3
+ import { createWorkflowCheckpoint, resolveWorkflowCheckpoint, getPendingWorkflowCheckpoints, } from '../../storage/workflow-checkpoint-store.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Request
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * Creates a new pending checkpoint for the given spec transition.
9
+ * If the policy has autoApproveAfterHours set, schedules the auto-approve time.
10
+ */
11
+ export async function requestCheckpoint(projectPath, specId, policy, requestedBy) {
12
+ const projectId = hashProjectPath(projectPath);
13
+ const autoApproveAt = policy.autoApproveAfterHours !== undefined
14
+ ? new Date(Date.now() + policy.autoApproveAfterHours * 3_600_000).toISOString()
15
+ : undefined;
16
+ return createWorkflowCheckpoint(projectPath, {
17
+ specId,
18
+ projectId,
19
+ policyId: policy.id,
20
+ blockingTransition: policy.transition,
21
+ requiredRole: policy.requiredRole,
22
+ requestedBy,
23
+ requestedAt: new Date().toISOString(),
24
+ status: 'pending',
25
+ autoApproveAt,
26
+ });
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Approve
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Approves a pending checkpoint.
33
+ * Returns the updated checkpoint and a flag indicating the blocked transition can now proceed.
34
+ */
35
+ export async function approveCheckpoint(projectPath, checkpointId, approvedBy) {
36
+ const checkpoint = await resolveWorkflowCheckpoint(projectPath, checkpointId, {
37
+ status: 'approved',
38
+ resolvedBy: approvedBy,
39
+ });
40
+ return { checkpoint, transitionApplied: true };
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Reject
44
+ // ---------------------------------------------------------------------------
45
+ /** Rejects a pending checkpoint with a mandatory reason. */
46
+ export async function rejectCheckpoint(projectPath, checkpointId, rejectedBy, reason) {
47
+ return resolveWorkflowCheckpoint(projectPath, checkpointId, {
48
+ status: 'rejected',
49
+ resolvedBy: rejectedBy,
50
+ rejectionReason: reason,
51
+ });
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // Auto-approve
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * Scans all pending checkpoints for a project and auto-approves any that have
58
+ * passed their autoApproveAt deadline. Returns the list of auto-approved checkpoints.
59
+ */
60
+ export async function checkAutoApprovals(projectPath) {
61
+ const pending = await getPendingWorkflowCheckpoints(projectPath);
62
+ const now = Date.now();
63
+ const autoApproved = [];
64
+ for (const checkpoint of pending) {
65
+ if (checkpoint.autoApproveAt !== undefined &&
66
+ new Date(checkpoint.autoApproveAt).getTime() <= now) {
67
+ const updated = await resolveWorkflowCheckpoint(projectPath, checkpoint.id, {
68
+ status: 'approved',
69
+ resolvedBy: 'system:auto-approve',
70
+ });
71
+ autoApproved.push(updated);
72
+ }
73
+ }
74
+ return autoApproved;
75
+ }
76
+ //# sourceMappingURL=checkpoint-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-manager.js","sourceRoot":"","sources":["../../../src/engine/checkpoint/checkpoint-manager.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAGvF,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,4CAA4C,CAAC;AAEpD,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,MAAc,EACd,MAAwB,EACxB,WAAmB;IAEnB,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAE/C,MAAM,aAAa,GACjB,MAAM,CAAC,qBAAqB,KAAK,SAAS;QACxC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAAC,WAAW,EAAE;QAC/E,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO,wBAAwB,CAAC,WAAW,EAAE;QAC3C,MAAM;QACN,SAAS;QACT,QAAQ,EAAE,MAAM,CAAC,EAAE;QACnB,kBAAkB,EAAE,MAAM,CAAC,UAAU;QACrC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,WAAW;QACX,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,MAAM,EAAE,SAAS;QACjB,aAAa;KACd,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,YAAoB,EACpB,UAAkB;IAElB,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC,WAAW,EAAE,YAAY,EAAE;QAC5E,MAAM,EAAE,UAAU;QAClB,UAAU,EAAE,UAAU;KACvB,CAAC,CAAC;IACH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,YAAoB,EACpB,UAAkB,EAClB,MAAc;IAEd,OAAO,yBAAyB,CAAC,WAAW,EAAE,YAAY,EAAE;QAC1D,MAAM,EAAE,UAAU;QAClB,UAAU,EAAE,UAAU;QACtB,eAAe,EAAE,MAAM;KACxB,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,WAAmB;IAC1D,MAAM,OAAO,GAAG,MAAM,6BAA6B,CAAC,WAAW,CAAC,CAAC;IACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,YAAY,GAAyB,EAAE,CAAC;IAE9C,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,IACE,UAAU,CAAC,aAAa,KAAK,SAAS;YACtC,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,IAAI,GAAG,EACnD,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,EAAE;gBAC1E,MAAM,EAAE,UAAU;gBAClB,UAAU,EAAE,qBAAqB;aAClC,CAAC,CAAC;YACH,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CheckpointPolicy, WorkflowCheckpointConfig, WorkflowSpecStatus, CheckpointPolicyPreset } from '../../types/index.js';
2
+ export declare const POLICY_PRESETS: Record<string, CheckpointPolicyPreset>;
3
+ /**
4
+ * Returns the matching policy if the given transition requires a checkpoint,
5
+ * or null if the transition is free to proceed.
6
+ */
7
+ export declare function requiresCheckpoint(config: WorkflowCheckpointConfig, fromStatus: WorkflowSpecStatus, toStatus: WorkflowSpecStatus): CheckpointPolicy | null;
8
+ export declare function loadCheckpointConfig(projectPath: string): Promise<WorkflowCheckpointConfig>;
9
+ export declare function saveCheckpointConfig(projectPath: string, config: WorkflowCheckpointConfig): Promise<void>;
10
+ //# sourceMappingURL=policy-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-engine.d.ts","sourceRoot":"","sources":["../../../src/engine/checkpoint/policy-engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAO9B,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAsDjE,CAAC;AAMF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,wBAAwB,EAChC,UAAU,EAAE,kBAAkB,EAC9B,QAAQ,EAAE,kBAAkB,GAC3B,gBAAgB,GAAG,IAAI,CAGzB;AAYD,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAGjG;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,87 @@
1
+ // engine/checkpoint/policy-engine.ts — Checkpoint policy evaluation (SPEC-411)
2
+ import { readJson, writeJson, projectDataDir, hashProjectPath } from '../../storage/base-store.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Built-in presets
5
+ // ---------------------------------------------------------------------------
6
+ export const POLICY_PRESETS = {
7
+ strict: {
8
+ name: 'strict',
9
+ description: 'All major transitions require explicit approval',
10
+ policies: [
11
+ {
12
+ transition: 'draft->review',
13
+ requiredRole: 'developer',
14
+ description: 'Self-review before submitting',
15
+ },
16
+ {
17
+ transition: 'review->approved',
18
+ requiredRole: 'tech_lead',
19
+ description: 'Tech lead must approve before work starts',
20
+ },
21
+ {
22
+ transition: 'approved->implementing',
23
+ requiredRole: 'product_owner',
24
+ description: 'PO confirms priority before devs start',
25
+ },
26
+ {
27
+ transition: 'implementing->done',
28
+ requiredRole: 'qa',
29
+ description: 'QA must verify before marking done',
30
+ },
31
+ ],
32
+ },
33
+ balanced: {
34
+ name: 'balanced',
35
+ description: 'Only critical transitions need approval',
36
+ policies: [
37
+ {
38
+ transition: 'review->approved',
39
+ requiredRole: 'tech_lead',
40
+ description: 'Tech lead approves specs',
41
+ },
42
+ {
43
+ transition: 'implementing->done',
44
+ requiredRole: 'qa',
45
+ description: 'QA verifies completion',
46
+ },
47
+ ],
48
+ },
49
+ relaxed: {
50
+ name: 'relaxed',
51
+ description: 'Only final completion needs approval',
52
+ policies: [
53
+ {
54
+ transition: 'implementing->done',
55
+ requiredRole: 'tech_lead',
56
+ description: 'Lead confirms done',
57
+ },
58
+ ],
59
+ },
60
+ };
61
+ // ---------------------------------------------------------------------------
62
+ // Policy evaluation
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Returns the matching policy if the given transition requires a checkpoint,
66
+ * or null if the transition is free to proceed.
67
+ */
68
+ export function requiresCheckpoint(config, fromStatus, toStatus) {
69
+ const transition = `${fromStatus}->${toStatus}`;
70
+ return config.policies.find((p) => p.transition === transition) ?? null;
71
+ }
72
+ // ---------------------------------------------------------------------------
73
+ // Config persistence
74
+ // ---------------------------------------------------------------------------
75
+ function configFilePath(projectId) {
76
+ return `${projectDataDir(projectId)}/checkpoint-config.json`;
77
+ }
78
+ const EMPTY_CONFIG = { policies: [] };
79
+ export async function loadCheckpointConfig(projectPath) {
80
+ const projectId = hashProjectPath(projectPath);
81
+ return readJson(configFilePath(projectId), EMPTY_CONFIG);
82
+ }
83
+ export async function saveCheckpointConfig(projectPath, config) {
84
+ const projectId = hashProjectPath(projectPath);
85
+ await writeJson(configFilePath(projectId), config);
86
+ }
87
+ //# sourceMappingURL=policy-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../../../src/engine/checkpoint/policy-engine.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAQ/E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnG,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,cAAc,GAA2C;IACpE,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,iDAAiD;QAC9D,QAAQ,EAAE;YACR;gBACE,UAAU,EAAE,eAAe;gBAC3B,YAAY,EAAE,WAAW;gBACzB,WAAW,EAAE,+BAA+B;aAC7C;YACD;gBACE,UAAU,EAAE,kBAAkB;gBAC9B,YAAY,EAAE,WAAW;gBACzB,WAAW,EAAE,2CAA2C;aACzD;YACD;gBACE,UAAU,EAAE,wBAAwB;gBACpC,YAAY,EAAE,eAAe;gBAC7B,WAAW,EAAE,wCAAwC;aACtD;YACD;gBACE,UAAU,EAAE,oBAAoB;gBAChC,YAAY,EAAE,IAAI;gBAClB,WAAW,EAAE,oCAAoC;aAClD;SACF;KACF;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,yCAAyC;QACtD,QAAQ,EAAE;YACR;gBACE,UAAU,EAAE,kBAAkB;gBAC9B,YAAY,EAAE,WAAW;gBACzB,WAAW,EAAE,0BAA0B;aACxC;YACD;gBACE,UAAU,EAAE,oBAAoB;gBAChC,YAAY,EAAE,IAAI;gBAClB,WAAW,EAAE,wBAAwB;aACtC;SACF;KACF;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,sCAAsC;QACnD,QAAQ,EAAE;YACR;gBACE,UAAU,EAAE,oBAAoB;gBAChC,YAAY,EAAE,WAAW;gBACzB,WAAW,EAAE,oBAAoB;aAClC;SACF;KACF;CACF,CAAC;AAEF,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAgC,EAChC,UAA8B,EAC9B,QAA4B;IAE5B,MAAM,UAAU,GAAG,GAAG,UAAU,KAAK,QAAQ,EAAW,CAAC;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC;AAC1E,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAS,cAAc,CAAC,SAAiB;IACvC,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,yBAAyB,CAAC;AAC/D,CAAC;AAED,MAAM,YAAY,GAA6B,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,MAAgC;IAEhC,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CompetitiveCatalog, GapAnalysisResult } from '../../types/index.js';
2
+ /**
3
+ * Extracts lowercase keywords from free text, removing stop words and
4
+ * short tokens. Returns a deduplicated array.
5
+ */
6
+ export declare function extractKeywords(text: string): string[];
7
+ /**
8
+ * Analyzes a feature (expressed as keywords) against all competitors in the
9
+ * catalog and returns a structured GapAnalysisResult.
10
+ */
11
+ export declare function analyzeGap(featureKeywords: string[], catalog: CompetitiveCatalog): GapAnalysisResult;
12
+ //# sourceMappingURL=gap-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gap-analyzer.d.ts","sourceRoot":"","sources":["../../../src/engine/competitive/gap-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAmHlF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQtD;AA4CD;;;GAGG;AACH,wBAAgB,UAAU,CACxB,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,EAAE,kBAAkB,GAC1B,iBAAiB,CAyEnB"}