specweave 0.32.2 → 0.32.5

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 (244) hide show
  1. package/CLAUDE.md +51 -9
  2. package/bin/specweave.js +34 -0
  3. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts +100 -0
  4. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts.map +1 -0
  5. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js +291 -0
  6. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js.map +1 -0
  7. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts +103 -0
  8. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts.map +1 -0
  9. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js +310 -0
  10. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js.map +1 -0
  11. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts +126 -0
  12. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts.map +1 -0
  13. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js +207 -0
  14. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js.map +1 -0
  15. package/dist/src/adapters/codex/README.md +1 -1
  16. package/dist/src/adapters/codex/adapter.js +1 -1
  17. package/dist/src/cli/commands/archive.d.ts +2 -0
  18. package/dist/src/cli/commands/archive.d.ts.map +1 -1
  19. package/dist/src/cli/commands/archive.js +33 -0
  20. package/dist/src/cli/commands/archive.js.map +1 -1
  21. package/dist/src/cli/commands/context.d.ts +92 -0
  22. package/dist/src/cli/commands/context.d.ts.map +1 -0
  23. package/dist/src/cli/commands/context.js +205 -0
  24. package/dist/src/cli/commands/context.js.map +1 -0
  25. package/dist/src/cli/commands/init-multiproject.js +1 -1
  26. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  27. package/dist/src/cli/commands/init.d.ts.map +1 -1
  28. package/dist/src/cli/commands/init.js +111 -69
  29. package/dist/src/cli/commands/init.js.map +1 -1
  30. package/dist/src/cli/commands/migrate-to-multiproject.js +2 -2
  31. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  32. package/dist/src/cli/helpers/init/external-import.d.ts +3 -0
  33. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
  34. package/dist/src/cli/helpers/init/external-import.js +17 -4
  35. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  36. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  37. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  38. package/dist/src/cli/helpers/init/index.js +2 -0
  39. package/dist/src/cli/helpers/init/index.js.map +1 -1
  40. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +70 -0
  41. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -1
  42. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +214 -4
  43. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -1
  44. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts +4 -0
  45. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts.map +1 -1
  46. package/dist/src/cli/helpers/init/living-docs-preflight.js +34 -3
  47. package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
  48. package/dist/src/cli/helpers/init/testing-config.d.ts +3 -0
  49. package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -1
  50. package/dist/src/cli/helpers/init/testing-config.js +9 -2
  51. package/dist/src/cli/helpers/init/testing-config.js.map +1 -1
  52. package/dist/src/cli/helpers/init/translation-config.d.ts +3 -0
  53. package/dist/src/cli/helpers/init/translation-config.d.ts.map +1 -1
  54. package/dist/src/cli/helpers/init/translation-config.js +21 -4
  55. package/dist/src/cli/helpers/init/translation-config.js.map +1 -1
  56. package/dist/src/cli/helpers/init/wizard-navigation.d.ts +45 -0
  57. package/dist/src/cli/helpers/init/wizard-navigation.d.ts.map +1 -0
  58. package/dist/src/cli/helpers/init/wizard-navigation.js +97 -0
  59. package/dist/src/cli/helpers/init/wizard-navigation.js.map +1 -0
  60. package/dist/src/core/increment/increment-archiver.d.ts +25 -4
  61. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  62. package/dist/src/core/increment/increment-archiver.js +64 -20
  63. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  64. package/dist/src/core/increment/increment-utils.d.ts +65 -0
  65. package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
  66. package/dist/src/core/increment/increment-utils.js +114 -0
  67. package/dist/src/core/increment/increment-utils.js.map +1 -1
  68. package/dist/src/core/living-docs/cross-project-sync.d.ts +97 -0
  69. package/dist/src/core/living-docs/cross-project-sync.d.ts.map +1 -0
  70. package/dist/src/core/living-docs/cross-project-sync.js +135 -0
  71. package/dist/src/core/living-docs/cross-project-sync.js.map +1 -0
  72. package/dist/src/core/living-docs/external-sync-orchestrator.d.ts +106 -0
  73. package/dist/src/core/living-docs/external-sync-orchestrator.d.ts.map +1 -0
  74. package/dist/src/core/living-docs/external-sync-orchestrator.js +146 -0
  75. package/dist/src/core/living-docs/external-sync-orchestrator.js.map +1 -0
  76. package/dist/src/core/living-docs/feature-archiver.d.ts +4 -0
  77. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  78. package/dist/src/core/living-docs/feature-archiver.js +32 -10
  79. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  80. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  81. package/dist/src/core/living-docs/feature-id-manager.js +7 -3
  82. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  83. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts +38 -0
  84. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts.map +1 -0
  85. package/dist/src/core/living-docs/governance/ecosystem-detector.js +325 -0
  86. package/dist/src/core/living-docs/governance/ecosystem-detector.js.map +1 -0
  87. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts +74 -0
  88. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts.map +1 -0
  89. package/dist/src/core/living-docs/governance/frontend-standards-parser.js +366 -0
  90. package/dist/src/core/living-docs/governance/frontend-standards-parser.js.map +1 -0
  91. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts +64 -0
  92. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts.map +1 -0
  93. package/dist/src/core/living-docs/governance/go-standards-parser.js +229 -0
  94. package/dist/src/core/living-docs/governance/go-standards-parser.js.map +1 -0
  95. package/dist/src/core/living-docs/governance/index.d.ts +50 -0
  96. package/dist/src/core/living-docs/governance/index.d.ts.map +1 -0
  97. package/dist/src/core/living-docs/governance/index.js +56 -0
  98. package/dist/src/core/living-docs/governance/index.js.map +1 -0
  99. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts +89 -0
  100. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts.map +1 -0
  101. package/dist/src/core/living-docs/governance/java-standards-parser.js +356 -0
  102. package/dist/src/core/living-docs/governance/java-standards-parser.js.map +1 -0
  103. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts +83 -0
  104. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts.map +1 -0
  105. package/dist/src/core/living-docs/governance/python-standards-parser.js +347 -0
  106. package/dist/src/core/living-docs/governance/python-standards-parser.js.map +1 -0
  107. package/dist/src/core/living-docs/governance/standards-generator.d.ts +38 -0
  108. package/dist/src/core/living-docs/governance/standards-generator.d.ts.map +1 -0
  109. package/dist/src/core/living-docs/governance/standards-generator.js +476 -0
  110. package/dist/src/core/living-docs/governance/standards-generator.js.map +1 -0
  111. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -1
  112. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +54 -2
  113. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -1
  114. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +5 -1
  115. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -1
  116. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +358 -30
  117. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -1
  118. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +44 -0
  119. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -1
  120. package/dist/src/core/living-docs/living-docs-sync.d.ts +7 -3
  121. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  122. package/dist/src/core/living-docs/living-docs-sync.js +94 -10
  123. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  124. package/dist/src/core/living-docs/module-analyzer.d.ts +22 -0
  125. package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
  126. package/dist/src/core/living-docs/module-analyzer.js +123 -19
  127. package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
  128. package/dist/src/core/living-docs/sync-helpers/generators.d.ts +8 -1
  129. package/dist/src/core/living-docs/sync-helpers/generators.d.ts.map +1 -1
  130. package/dist/src/core/living-docs/sync-helpers/generators.js +18 -1
  131. package/dist/src/core/living-docs/sync-helpers/generators.js.map +1 -1
  132. package/dist/src/core/living-docs/sync-helpers/index.d.ts +1 -1
  133. package/dist/src/core/living-docs/sync-helpers/index.d.ts.map +1 -1
  134. package/dist/src/core/living-docs/sync-helpers/index.js.map +1 -1
  135. package/dist/src/core/living-docs/sync-helpers/parsers.d.ts +3 -1
  136. package/dist/src/core/living-docs/sync-helpers/parsers.d.ts.map +1 -1
  137. package/dist/src/core/living-docs/sync-helpers/parsers.js +24 -2
  138. package/dist/src/core/living-docs/sync-helpers/parsers.js.map +1 -1
  139. package/dist/src/core/living-docs/types.d.ts +6 -0
  140. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  141. package/dist/src/core/living-docs/validators/index.d.ts +7 -0
  142. package/dist/src/core/living-docs/validators/index.d.ts.map +1 -0
  143. package/dist/src/core/living-docs/validators/index.js +7 -0
  144. package/dist/src/core/living-docs/validators/index.js.map +1 -0
  145. package/dist/src/core/living-docs/validators/project-validator.d.ts +92 -0
  146. package/dist/src/core/living-docs/validators/project-validator.d.ts.map +1 -0
  147. package/dist/src/core/living-docs/validators/project-validator.js +142 -0
  148. package/dist/src/core/living-docs/validators/project-validator.js.map +1 -0
  149. package/dist/src/core/llm/provider-factory.js +2 -2
  150. package/dist/src/core/llm/provider-factory.js.map +1 -1
  151. package/dist/src/core/llm/providers/anthropic-provider.js +1 -1
  152. package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
  153. package/dist/src/core/llm/providers/bedrock-provider.js +8 -4
  154. package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
  155. package/dist/src/core/project/project-manager.d.ts.map +1 -1
  156. package/dist/src/core/project/project-manager.js +19 -17
  157. package/dist/src/core/project/project-manager.js.map +1 -1
  158. package/dist/src/core/types/config.d.ts +4 -2
  159. package/dist/src/core/types/config.d.ts.map +1 -1
  160. package/dist/src/core/types/config.js.map +1 -1
  161. package/dist/src/core/types/increment-metadata.d.ts +34 -0
  162. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  163. package/dist/src/importers/jira-importer.d.ts +14 -0
  164. package/dist/src/importers/jira-importer.d.ts.map +1 -1
  165. package/dist/src/importers/jira-importer.js +75 -0
  166. package/dist/src/importers/jira-importer.js.map +1 -1
  167. package/dist/src/integrations/jira/jira-token-provider.d.ts +93 -0
  168. package/dist/src/integrations/jira/jira-token-provider.d.ts.map +1 -0
  169. package/dist/src/integrations/jira/jira-token-provider.js +160 -0
  170. package/dist/src/integrations/jira/jira-token-provider.js.map +1 -0
  171. package/dist/src/sync/ado-reconciler.d.ts +92 -0
  172. package/dist/src/sync/ado-reconciler.d.ts.map +1 -0
  173. package/dist/src/sync/ado-reconciler.js +335 -0
  174. package/dist/src/sync/ado-reconciler.js.map +1 -0
  175. package/dist/src/sync/jira-reconciler.d.ts +106 -0
  176. package/dist/src/sync/jira-reconciler.d.ts.map +1 -0
  177. package/dist/src/sync/jira-reconciler.js +405 -0
  178. package/dist/src/sync/jira-reconciler.js.map +1 -0
  179. package/dist/src/types/model-selection.d.ts +6 -4
  180. package/dist/src/types/model-selection.d.ts.map +1 -1
  181. package/dist/src/types/model-selection.js +3 -1
  182. package/dist/src/types/model-selection.js.map +1 -1
  183. package/dist/src/utils/cross-cutting-detector.d.ts +66 -0
  184. package/dist/src/utils/cross-cutting-detector.d.ts.map +1 -0
  185. package/dist/src/utils/cross-cutting-detector.js +179 -0
  186. package/dist/src/utils/cross-cutting-detector.js.map +1 -0
  187. package/dist/src/utils/external-tool-drift-detector.d.ts +1 -1
  188. package/dist/src/utils/external-tool-drift-detector.d.ts.map +1 -1
  189. package/dist/src/utils/external-tool-drift-detector.js +5 -4
  190. package/dist/src/utils/external-tool-drift-detector.js.map +1 -1
  191. package/dist/src/utils/feature-id-derivation.d.ts +8 -3
  192. package/dist/src/utils/feature-id-derivation.d.ts.map +1 -1
  193. package/dist/src/utils/feature-id-derivation.js +14 -6
  194. package/dist/src/utils/feature-id-derivation.js.map +1 -1
  195. package/dist/src/utils/model-selection.d.ts +3 -4
  196. package/dist/src/utils/model-selection.d.ts.map +1 -1
  197. package/dist/src/utils/model-selection.js +3 -4
  198. package/dist/src/utils/model-selection.js.map +1 -1
  199. package/dist/src/utils/project-detection.d.ts +12 -8
  200. package/dist/src/utils/project-detection.d.ts.map +1 -1
  201. package/dist/src/utils/project-detection.js +13 -19
  202. package/dist/src/utils/project-detection.js.map +1 -1
  203. package/package.json +1 -1
  204. package/plugins/specweave/agents/code-standards-detective/AGENT.md +48 -0
  205. package/plugins/specweave/commands/specweave-costs.md +4 -4
  206. package/plugins/specweave/commands/specweave-do.md +9 -9
  207. package/plugins/specweave/commands/specweave-done.md +13 -0
  208. package/plugins/specweave/commands/specweave-status.md +64 -0
  209. package/plugins/specweave/commands/specweave-validate.md +27 -1
  210. package/plugins/specweave/hooks/hooks.json +11 -1
  211. package/plugins/specweave/hooks/spec-project-validator.sh +81 -25
  212. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +135 -0
  213. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +34 -0
  214. package/plugins/specweave/scripts/read-costs.sh +3 -3
  215. package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +58 -6
  216. package/plugins/specweave/skills/increment-planner/SKILL.md +135 -29
  217. package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +4 -2
  218. package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +2 -1
  219. package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +1 -1
  220. package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +1 -1
  221. package/plugins/specweave/skills/spec-generator/SKILL.md +78 -7
  222. package/plugins/specweave-ado/commands/cleanup-duplicates.md +212 -0
  223. package/plugins/specweave-ado/commands/reconcile.md +120 -0
  224. package/plugins/specweave-ado/lib/ado-duplicate-detector.js +279 -0
  225. package/plugins/specweave-ado/lib/ado-duplicate-detector.ts +407 -0
  226. package/plugins/specweave-github/agents/github-manager/AGENT.md +2 -2
  227. package/plugins/specweave-infrastructure/skills/hetzner-provisioner/README.md +1 -1
  228. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +1 -1
  229. package/plugins/specweave-jira/agents/jira-multi-project-mapper/AGENT.md +530 -0
  230. package/plugins/specweave-jira/agents/jira-sync-judge/AGENT.md +438 -0
  231. package/plugins/specweave-jira/commands/cleanup-duplicates.md +219 -0
  232. package/plugins/specweave-jira/commands/close.md +297 -0
  233. package/plugins/specweave-jira/commands/create.md +198 -0
  234. package/plugins/specweave-jira/commands/reconcile.md +123 -0
  235. package/plugins/specweave-jira/commands/status.md +215 -0
  236. package/plugins/specweave-jira/lib/jira-duplicate-detector.js +296 -0
  237. package/plugins/specweave-jira/lib/jira-duplicate-detector.ts +434 -0
  238. package/plugins/specweave-jira/lib/jira-permission-gate.js +160 -0
  239. package/plugins/specweave-jira/lib/jira-permission-gate.ts +276 -0
  240. package/plugins/specweave-jira/lib/jira-profile-resolver.js +222 -0
  241. package/plugins/specweave-jira/lib/jira-profile-resolver.ts +427 -0
  242. package/plugins/specweave-jira/reference/jira-specweave-mapping.md +16 -11
  243. package/plugins/specweave-release/commands/specweave-release-npm.md +140 -14
  244. package/plugins/specweave/commands/specweave-switch-project.md +0 -168
@@ -0,0 +1,106 @@
1
+ /**
2
+ * JIRA Reconciler (NEW in v0.33.0)
3
+ *
4
+ * Reconciles JIRA issue states with increment metadata.json statuses.
5
+ * Fixes drift between local SpecWeave state and JIRA:
6
+ * - Closes issues for completed increments that are still open
7
+ * - Reopens issues for in-progress increments that are closed
8
+ *
9
+ * Mirrors the GitHub reconciler pattern for consistency.
10
+ *
11
+ * Triggered by:
12
+ * - /specweave-jira:reconcile command (manual)
13
+ * - SessionStart hook (automatic, if configured)
14
+ * - post-increment-status-change.sh (on resume/abandon)
15
+ */
16
+ import { Logger } from '../utils/logger.js';
17
+ export interface JiraReconcileOptions {
18
+ projectRoot: string;
19
+ dryRun?: boolean;
20
+ logger?: Logger;
21
+ }
22
+ export interface IncrementJiraState {
23
+ incrementId: string;
24
+ incrementPath: string;
25
+ metadataStatus: string;
26
+ featureId?: string;
27
+ issue?: {
28
+ key: string;
29
+ url?: string;
30
+ };
31
+ userStoryIssues: Array<{
32
+ userStoryId: string;
33
+ issueKey: string;
34
+ }>;
35
+ }
36
+ export interface JiraReconcileResult {
37
+ scanned: number;
38
+ mismatches: number;
39
+ closed: number;
40
+ reopened: number;
41
+ errors: string[];
42
+ details: Array<{
43
+ incrementId: string;
44
+ action: 'close' | 'reopen' | 'skip' | 'error';
45
+ issueKey: string;
46
+ reason: string;
47
+ }>;
48
+ }
49
+ export declare class JiraReconciler {
50
+ private projectRoot;
51
+ private dryRun;
52
+ private logger;
53
+ private domain;
54
+ private auth;
55
+ constructor(options: JiraReconcileOptions);
56
+ /**
57
+ * Main reconciliation entry point
58
+ */
59
+ reconcile(): Promise<JiraReconcileResult>;
60
+ /**
61
+ * Reconcile a single increment
62
+ */
63
+ private reconcileIncrement;
64
+ /**
65
+ * Reconcile a single issue
66
+ */
67
+ private reconcileIssue;
68
+ /**
69
+ * Scan increments directory for non-archived increments
70
+ */
71
+ private scanIncrements;
72
+ /**
73
+ * Load config.json
74
+ */
75
+ private loadConfig;
76
+ /**
77
+ * Initialize JIRA credentials
78
+ */
79
+ private initCredentials;
80
+ /**
81
+ * Get issue from JIRA API
82
+ */
83
+ private getIssue;
84
+ /**
85
+ * Get available transitions for an issue
86
+ */
87
+ private getTransitions;
88
+ /**
89
+ * Transition issue to new status and add comment
90
+ */
91
+ private transitionIssue;
92
+ /**
93
+ * Execute transition
94
+ */
95
+ private doTransition;
96
+ /**
97
+ * Add comment to issue
98
+ */
99
+ private addComment;
100
+ }
101
+ /**
102
+ * Convenience function for quick reconciliation
103
+ */
104
+ export declare function reconcileJira(projectRoot?: string, dryRun?: boolean): Promise<JiraReconcileResult>;
105
+ export default JiraReconciler;
106
+ //# sourceMappingURL=jira-reconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira-reconciler.d.ts","sourceRoot":"","sources":["../../../src/sync/jira-reconciler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,eAAe,EAAE,KAAK,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;QAC9C,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAUD,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,IAAI,CAAc;gBAEd,OAAO,EAAE,oBAAoB;IAMzC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAqE/C;;OAEG;YACW,kBAAkB;IAmChC;;OAEG;YACW,cAAc;IA+F5B;;OAEG;YACW,cAAc;IA4D5B;;OAEG;YACW,UAAU;IAWxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;YACW,QAAQ;IAiBtB;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,eAAe;IAwC7B;;OAEG;YACW,YAAY;IAoB1B;;OAEG;YACW,UAAU;CAiCzB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,GAAE,MAAsB,EACnC,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAG9B;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,405 @@
1
+ /**
2
+ * JIRA Reconciler (NEW in v0.33.0)
3
+ *
4
+ * Reconciles JIRA issue states with increment metadata.json statuses.
5
+ * Fixes drift between local SpecWeave state and JIRA:
6
+ * - Closes issues for completed increments that are still open
7
+ * - Reopens issues for in-progress increments that are closed
8
+ *
9
+ * Mirrors the GitHub reconciler pattern for consistency.
10
+ *
11
+ * Triggered by:
12
+ * - /specweave-jira:reconcile command (manual)
13
+ * - SessionStart hook (automatic, if configured)
14
+ * - post-increment-status-change.sh (on resume/abandon)
15
+ */
16
+ import { promises as fs, existsSync } from 'fs';
17
+ import path from 'path';
18
+ import { consoleLogger } from '../utils/logger.js';
19
+ /**
20
+ * JIRA Status Mapping
21
+ */
22
+ const JIRA_STATUSES = {
23
+ CLOSED: ['Done', 'Closed', 'Resolved', "Won't Do"],
24
+ OPEN: ['To Do', 'In Progress', 'In Review', 'Open', 'Reopened'],
25
+ };
26
+ export class JiraReconciler {
27
+ constructor(options) {
28
+ this.domain = '';
29
+ this.auth = '';
30
+ this.projectRoot = options.projectRoot;
31
+ this.dryRun = options.dryRun ?? false;
32
+ this.logger = options.logger ?? consoleLogger;
33
+ }
34
+ /**
35
+ * Main reconciliation entry point
36
+ */
37
+ async reconcile() {
38
+ const result = {
39
+ scanned: 0,
40
+ mismatches: 0,
41
+ closed: 0,
42
+ reopened: 0,
43
+ errors: [],
44
+ details: [],
45
+ };
46
+ try {
47
+ // 1. Check if JIRA sync is enabled
48
+ const config = await this.loadConfig();
49
+ const canUpdate = config.sync?.settings?.canUpdateExternalItems ?? false;
50
+ const canUpdateStatus = config.sync?.settings?.canUpdateStatus ?? false;
51
+ const jiraEnabled = config.sync?.jira?.enabled ?? false;
52
+ if (!canUpdate || !jiraEnabled) {
53
+ this.logger.log('ℹ️ JIRA sync is disabled - skipping reconciliation');
54
+ this.logger.log(' Enable with: canUpdateExternalItems=true AND sync.jira.enabled=true');
55
+ return result;
56
+ }
57
+ if (!canUpdateStatus) {
58
+ this.logger.log('ℹ️ JIRA status updates are disabled - skipping reconciliation');
59
+ this.logger.log(' Enable with: canUpdateStatus=true');
60
+ return result;
61
+ }
62
+ // 2. Verify JIRA credentials
63
+ if (!this.initCredentials()) {
64
+ result.errors.push('JIRA credentials not configured');
65
+ this.logger.error('❌ JIRA credentials not found. Set JIRA_API_TOKEN and JIRA_EMAIL environment variables.');
66
+ return result;
67
+ }
68
+ // 3. Scan all non-archived increments
69
+ const increments = await this.scanIncrements();
70
+ result.scanned = increments.length;
71
+ this.logger.log(`\n📊 Scanning ${increments.length} increment(s) for JIRA state drift...\n`);
72
+ // 4. Check and fix each increment
73
+ for (const inc of increments) {
74
+ await this.reconcileIncrement(inc, result);
75
+ }
76
+ // 5. Report summary
77
+ this.logger.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
78
+ this.logger.log('📊 JIRA RECONCILIATION SUMMARY');
79
+ this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
80
+ this.logger.log(` Increments scanned: ${result.scanned}`);
81
+ this.logger.log(` Mismatches found: ${result.mismatches}`);
82
+ this.logger.log(` Issues closed: ${result.closed}`);
83
+ this.logger.log(` Issues reopened: ${result.reopened}`);
84
+ this.logger.log(` Errors: ${result.errors.length}`);
85
+ if (this.dryRun) {
86
+ this.logger.log('\n ⚠️ DRY RUN - No changes were made');
87
+ }
88
+ this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
89
+ return result;
90
+ }
91
+ catch (error) {
92
+ result.errors.push(`Reconciliation error: ${error.message}`);
93
+ this.logger.error('❌ Reconciliation failed:', error.message);
94
+ return result;
95
+ }
96
+ }
97
+ /**
98
+ * Reconcile a single increment
99
+ */
100
+ async reconcileIncrement(inc, result) {
101
+ const status = inc.metadataStatus;
102
+ // Determine expected JIRA state
103
+ const shouldBeClosed = status === 'completed' || status === 'abandoned';
104
+ const shouldBeOpen = status === 'in-progress' || status === 'active' || status === 'planning';
105
+ // Check main issue
106
+ if (inc.issue) {
107
+ await this.reconcileIssue(inc.incrementId, inc.issue.key, shouldBeClosed, shouldBeOpen, status, result);
108
+ }
109
+ // Check User Story issues
110
+ for (const us of inc.userStoryIssues) {
111
+ await this.reconcileIssue(`${inc.incrementId}/${us.userStoryId}`, us.issueKey, shouldBeClosed, shouldBeOpen, status, result);
112
+ }
113
+ }
114
+ /**
115
+ * Reconcile a single issue
116
+ */
117
+ async reconcileIssue(context, issueKey, shouldBeClosed, shouldBeOpen, metadataStatus, result) {
118
+ try {
119
+ // Get current JIRA state
120
+ const issue = await this.getIssue(issueKey);
121
+ const currentStatus = issue?.fields?.status?.name ?? 'Unknown';
122
+ const isCurrentlyClosed = JIRA_STATUSES.CLOSED.includes(currentStatus);
123
+ // Check for mismatch
124
+ if (shouldBeClosed && !isCurrentlyClosed) {
125
+ // Should be closed but is open
126
+ result.mismatches++;
127
+ this.logger.log(` ❌ Issue ${issueKey} (${context}): ${currentStatus} but should be CLOSED (status=${metadataStatus})`);
128
+ if (!this.dryRun) {
129
+ const comment = `h2. 🔄 Auto-Reconciled by SpecWeave
130
+
131
+ This issue was closed by SpecWeave reconciliation.
132
+
133
+ *Reason*: Increment status is \`${metadataStatus}\` but JIRA issue was still open.
134
+
135
+ ----
136
+ 🤖 Auto-reconciled by SpecWeave`;
137
+ await this.transitionIssue(issueKey, 'Done', comment);
138
+ result.closed++;
139
+ this.logger.log(` ✅ Closed issue ${issueKey}`);
140
+ }
141
+ else {
142
+ this.logger.log(` [DRY RUN] Would close issue ${issueKey}`);
143
+ }
144
+ result.details.push({
145
+ incrementId: context,
146
+ action: this.dryRun ? 'skip' : 'close',
147
+ issueKey,
148
+ reason: `Status=${metadataStatus}, JIRA=${currentStatus}`,
149
+ });
150
+ }
151
+ else if (shouldBeOpen && isCurrentlyClosed) {
152
+ // Should be open but is closed
153
+ result.mismatches++;
154
+ this.logger.log(` ❌ Issue ${issueKey} (${context}): CLOSED but should be OPEN (status=${metadataStatus})`);
155
+ if (!this.dryRun) {
156
+ const comment = `h2. 🔄 Auto-Reconciled by SpecWeave
157
+
158
+ This issue was reopened by SpecWeave reconciliation.
159
+
160
+ *Reason*: Increment status is \`${metadataStatus}\` but JIRA issue was closed.
161
+ This typically happens when an increment was resumed after being paused/completed.
162
+
163
+ ----
164
+ 🤖 Auto-reconciled by SpecWeave`;
165
+ await this.transitionIssue(issueKey, 'To Do', comment);
166
+ result.reopened++;
167
+ this.logger.log(` ✅ Reopened issue ${issueKey}`);
168
+ }
169
+ else {
170
+ this.logger.log(` [DRY RUN] Would reopen issue ${issueKey}`);
171
+ }
172
+ result.details.push({
173
+ incrementId: context,
174
+ action: this.dryRun ? 'skip' : 'reopen',
175
+ issueKey,
176
+ reason: `Status=${metadataStatus}, JIRA=${currentStatus}`,
177
+ });
178
+ }
179
+ else {
180
+ // State matches
181
+ this.logger.log(` ✅ Issue ${issueKey} (${context}): State matches (${currentStatus})`);
182
+ result.details.push({
183
+ incrementId: context,
184
+ action: 'skip',
185
+ issueKey,
186
+ reason: 'State matches',
187
+ });
188
+ }
189
+ }
190
+ catch (error) {
191
+ result.errors.push(`Issue ${issueKey}: ${error.message}`);
192
+ result.details.push({
193
+ incrementId: context,
194
+ action: 'error',
195
+ issueKey,
196
+ reason: error.message,
197
+ });
198
+ }
199
+ }
200
+ /**
201
+ * Scan increments directory for non-archived increments
202
+ */
203
+ async scanIncrements() {
204
+ const incrementsPath = path.join(this.projectRoot, '.specweave', 'increments');
205
+ const results = [];
206
+ if (!existsSync(incrementsPath)) {
207
+ return results;
208
+ }
209
+ const entries = await fs.readdir(incrementsPath, { withFileTypes: true });
210
+ for (const entry of entries) {
211
+ if (!entry.isDirectory())
212
+ continue;
213
+ if (entry.name === '_archive' || entry.name.startsWith('.'))
214
+ continue;
215
+ const incrementPath = path.join(incrementsPath, entry.name);
216
+ const metadataPath = path.join(incrementPath, 'metadata.json');
217
+ if (!existsSync(metadataPath))
218
+ continue;
219
+ try {
220
+ const metadataContent = await fs.readFile(metadataPath, 'utf-8');
221
+ const metadata = JSON.parse(metadataContent);
222
+ // Check for JIRA issue link (support both new and legacy naming)
223
+ const jiraSync = metadata.external_sync?.jira || metadata.external_ids?.jira;
224
+ if (!jiraSync?.issueKey && !jiraSync?.epic)
225
+ continue;
226
+ const state = {
227
+ incrementId: entry.name,
228
+ incrementPath,
229
+ metadataStatus: metadata.status || 'unknown',
230
+ featureId: metadata.featureId,
231
+ issue: {
232
+ key: jiraSync.issueKey || jiraSync.epic,
233
+ url: jiraSync.issueUrl,
234
+ },
235
+ userStoryIssues: [],
236
+ };
237
+ // Extract user story issues if present
238
+ if (jiraSync.stories && Array.isArray(jiraSync.stories)) {
239
+ for (const story of jiraSync.stories) {
240
+ if (story.issueKey || story.key) {
241
+ state.userStoryIssues.push({
242
+ userStoryId: story.id || story.userStoryId,
243
+ issueKey: story.issueKey || story.key,
244
+ });
245
+ }
246
+ }
247
+ }
248
+ results.push(state);
249
+ }
250
+ catch {
251
+ // Skip invalid metadata
252
+ }
253
+ }
254
+ return results;
255
+ }
256
+ /**
257
+ * Load config.json
258
+ */
259
+ async loadConfig() {
260
+ const configPath = path.join(this.projectRoot, '.specweave', 'config.json');
261
+ try {
262
+ const content = await fs.readFile(configPath, 'utf-8');
263
+ return JSON.parse(content);
264
+ }
265
+ catch {
266
+ return {};
267
+ }
268
+ }
269
+ /**
270
+ * Initialize JIRA credentials
271
+ */
272
+ initCredentials() {
273
+ const token = process.env.JIRA_API_TOKEN;
274
+ const email = process.env.JIRA_EMAIL;
275
+ this.domain = process.env.JIRA_DOMAIN || '';
276
+ if (!token || !email || !this.domain) {
277
+ return false;
278
+ }
279
+ this.auth = Buffer.from(`${email}:${token}`).toString('base64');
280
+ return true;
281
+ }
282
+ /**
283
+ * Get issue from JIRA API
284
+ */
285
+ async getIssue(issueKey) {
286
+ const url = `https://${this.domain}/rest/api/3/issue/${issueKey}`;
287
+ const response = await fetch(url, {
288
+ headers: {
289
+ Authorization: `Basic ${this.auth}`,
290
+ Accept: 'application/json',
291
+ },
292
+ });
293
+ if (!response.ok) {
294
+ throw new Error(`Failed to get issue: ${response.status}`);
295
+ }
296
+ return response.json();
297
+ }
298
+ /**
299
+ * Get available transitions for an issue
300
+ */
301
+ async getTransitions(issueKey) {
302
+ const url = `https://${this.domain}/rest/api/3/issue/${issueKey}/transitions`;
303
+ const response = await fetch(url, {
304
+ headers: {
305
+ Authorization: `Basic ${this.auth}`,
306
+ Accept: 'application/json',
307
+ },
308
+ });
309
+ if (!response.ok) {
310
+ throw new Error(`Failed to get transitions: ${response.status}`);
311
+ }
312
+ const data = await response.json();
313
+ return data.transitions || [];
314
+ }
315
+ /**
316
+ * Transition issue to new status and add comment
317
+ */
318
+ async transitionIssue(issueKey, targetStatus, comment) {
319
+ // First, add comment
320
+ await this.addComment(issueKey, comment);
321
+ // Get available transitions
322
+ const transitions = await this.getTransitions(issueKey);
323
+ // Find transition matching target status
324
+ const transition = transitions.find((t) => t.name.toLowerCase() === targetStatus.toLowerCase() ||
325
+ t.to?.name?.toLowerCase() === targetStatus.toLowerCase());
326
+ if (!transition) {
327
+ // Try common alternatives
328
+ const alternatives = targetStatus === 'Done'
329
+ ? ['Closed', 'Resolved', 'Complete']
330
+ : ['Open', 'Reopened', 'In Progress'];
331
+ const altTransition = transitions.find((t) => alternatives.some(alt => t.name.toLowerCase() === alt.toLowerCase() ||
332
+ t.to?.name?.toLowerCase() === alt.toLowerCase()));
333
+ if (!altTransition) {
334
+ throw new Error(`No transition found to "${targetStatus}". Available: ${transitions.map((t) => t.name).join(', ')}`);
335
+ }
336
+ await this.doTransition(issueKey, altTransition.id);
337
+ }
338
+ else {
339
+ await this.doTransition(issueKey, transition.id);
340
+ }
341
+ }
342
+ /**
343
+ * Execute transition
344
+ */
345
+ async doTransition(issueKey, transitionId) {
346
+ const url = `https://${this.domain}/rest/api/3/issue/${issueKey}/transitions`;
347
+ const response = await fetch(url, {
348
+ method: 'POST',
349
+ headers: {
350
+ Authorization: `Basic ${this.auth}`,
351
+ 'Content-Type': 'application/json',
352
+ },
353
+ body: JSON.stringify({
354
+ transition: { id: transitionId },
355
+ }),
356
+ });
357
+ if (!response.ok) {
358
+ const error = await response.text();
359
+ throw new Error(`Failed to transition issue: ${response.status} - ${error}`);
360
+ }
361
+ }
362
+ /**
363
+ * Add comment to issue
364
+ */
365
+ async addComment(issueKey, comment) {
366
+ const url = `https://${this.domain}/rest/api/3/issue/${issueKey}/comment`;
367
+ const response = await fetch(url, {
368
+ method: 'POST',
369
+ headers: {
370
+ Authorization: `Basic ${this.auth}`,
371
+ 'Content-Type': 'application/json',
372
+ },
373
+ body: JSON.stringify({
374
+ body: {
375
+ type: 'doc',
376
+ version: 1,
377
+ content: [
378
+ {
379
+ type: 'paragraph',
380
+ content: [
381
+ {
382
+ type: 'text',
383
+ text: comment,
384
+ },
385
+ ],
386
+ },
387
+ ],
388
+ },
389
+ }),
390
+ });
391
+ if (!response.ok) {
392
+ // Non-fatal, just log warning
393
+ this.logger.log(` ⚠️ Failed to add comment to ${issueKey}`);
394
+ }
395
+ }
396
+ }
397
+ /**
398
+ * Convenience function for quick reconciliation
399
+ */
400
+ export async function reconcileJira(projectRoot = process.cwd(), dryRun = false) {
401
+ const reconciler = new JiraReconciler({ projectRoot, dryRun });
402
+ return reconciler.reconcile();
403
+ }
404
+ export default JiraReconciler;
405
+ //# sourceMappingURL=jira-reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira-reconciler.js","sourceRoot":"","sources":["../../../src/sync/jira-reconciler.ts"],"names":[],"mappings":"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"}
@@ -6,13 +6,15 @@
6
6
  * - Phase detection (planning vs execution vs review)
7
7
  * - User overrides (manual model selection)
8
8
  *
9
- * Achieves 60-70% cost savings by using Haiku for execution, Sonnet for planning.
9
+ * Strategy (Opus 4.5 Default):
10
+ * - Haiku: Simple/cheap operations, translations, mechanical tasks
11
+ * - Opus: Default for complex work, analysis, architecture, planning
10
12
  */
11
13
  /**
12
14
  * Available AI models
13
- * - sonnet: Latest Sonnet 4.5 (planning, complex analysis)
14
- * - haiku: Latest Haiku 4.5 (execution, simple tasks)
15
- * - opus: Latest Opus (rare, critical decisions)
15
+ * - opus: Latest Opus 4.5 (default - planning, analysis, complex work)
16
+ * - haiku: Latest Haiku 4.5 (simple tasks, translations, cheap ops)
17
+ * - sonnet: Sonnet 4 (legacy, rarely used)
16
18
  * - auto: System decides based on context
17
19
  */
18
20
  export type Model = 'sonnet' | 'haiku' | 'opus' | 'auto';
@@ -1 +1 @@
1
- {"version":3,"file":"model-selection.d.ts","sourceRoot":"","sources":["../../../src/types/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,KAAK,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,GAAG,UAAU,CAAC;IACzH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD"}
1
+ {"version":3,"file":"model-selection.d.ts","sourceRoot":"","sources":["../../../src/types/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,KAAK,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,GAAG,UAAU,CAAC;IACzH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD"}
@@ -6,7 +6,9 @@
6
6
  * - Phase detection (planning vs execution vs review)
7
7
  * - User overrides (manual model selection)
8
8
  *
9
- * Achieves 60-70% cost savings by using Haiku for execution, Sonnet for planning.
9
+ * Strategy (Opus 4.5 Default):
10
+ * - Haiku: Simple/cheap operations, translations, mechanical tasks
11
+ * - Opus: Default for complex work, analysis, architecture, planning
10
12
  */
11
13
  export {};
12
14
  //# sourceMappingURL=model-selection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../../src/types/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
1
+ {"version":3,"file":"model-selection.js","sourceRoot":"","sources":["../../../src/types/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Cross-Cutting Feature Detector
3
+ *
4
+ * Detects when a feature spans multiple projects based on keywords,
5
+ * tech stack mentions, and component references.
6
+ *
7
+ * @module utils/cross-cutting-detector
8
+ * @since v0.33.0
9
+ */
10
+ import { Logger } from './logger.js';
11
+ /**
12
+ * Result of cross-cutting detection
13
+ */
14
+ export interface CrossCuttingResult {
15
+ isCrossCutting: boolean;
16
+ confidence: 'high' | 'medium' | 'low';
17
+ suggestedProjects: string[];
18
+ detectedPatterns: DetectedPattern[];
19
+ reason?: string;
20
+ }
21
+ /**
22
+ * Pattern that triggered detection
23
+ */
24
+ export interface DetectedPattern {
25
+ type: 'keyword' | 'tech-stack' | 'component' | 'explicit';
26
+ matched: string;
27
+ suggestedProject?: string;
28
+ }
29
+ /**
30
+ * Cross-Cutting Detector
31
+ */
32
+ export declare class CrossCuttingDetector {
33
+ private logger;
34
+ private customMappings;
35
+ constructor(options?: {
36
+ logger?: Logger;
37
+ customMappings?: Record<string, string[]>;
38
+ });
39
+ /**
40
+ * Detect if a description indicates cross-cutting concerns
41
+ */
42
+ detect(description: string): CrossCuttingResult;
43
+ /**
44
+ * Add custom project mappings
45
+ */
46
+ addCustomMapping(project: string, keywords: string[]): void;
47
+ /**
48
+ * Load custom mappings from config
49
+ */
50
+ loadMappingsFromConfig(projectMappings: Record<string, unknown>): void;
51
+ /**
52
+ * Escape regex special characters
53
+ */
54
+ private escapeRegex;
55
+ }
56
+ /**
57
+ * Convenience function for one-off detection
58
+ */
59
+ export declare function detectCrossCutting(description: string, options?: {
60
+ customMappings?: Record<string, string[]>;
61
+ }): CrossCuttingResult;
62
+ /**
63
+ * Get suggested project for a single-project feature
64
+ */
65
+ export declare function suggestSingleProject(description: string): string | null;
66
+ //# sourceMappingURL=cross-cutting-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-cutting-detector.d.ts","sourceRoot":"","sources":["../../../src/utils/cross-cutting-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAgDD;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAgC;gBAE1C,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAO;IAKxF;;OAEG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB;IA+E/C;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAO3D;;OAEG;IACH,sBAAsB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAUtE;;OAEG;IACH,OAAO,CAAC,WAAW;CAGpB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;CAAE,GACtD,kBAAkB,CAGpB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYvE"}