specweave 1.0.464 → 1.0.466

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 (109) hide show
  1. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
  2. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +139 -0
  3. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
  4. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
  5. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js +304 -0
  6. package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
  7. package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
  8. package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +359 -0
  9. package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
  10. package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +121 -0
  11. package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +273 -0
  12. package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
  13. package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +72 -0
  14. package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +237 -0
  15. package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
  16. package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
  17. package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +281 -0
  18. package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
  19. package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +278 -0
  20. package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +925 -0
  21. package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
  22. package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.d.ts +113 -0
  23. package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js +317 -0
  24. package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js.map +1 -0
  25. package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +442 -0
  26. package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js +246 -0
  27. package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
  28. package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.d.ts +64 -0
  29. package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js +228 -0
  30. package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js.map +1 -0
  31. package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
  32. package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js +300 -0
  33. package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
  34. package/dist/plugins/specweave/lib/vendor/sync/config.d.ts +73 -0
  35. package/dist/plugins/specweave/lib/vendor/sync/config.js +132 -0
  36. package/dist/plugins/specweave/lib/vendor/sync/config.js.map +1 -0
  37. package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +163 -0
  38. package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js +898 -0
  39. package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -0
  40. package/dist/plugins/specweave/lib/vendor/sync/provider-router.d.ts +86 -0
  41. package/dist/plugins/specweave/lib/vendor/sync/provider-router.js +147 -0
  42. package/dist/plugins/specweave/lib/vendor/sync/provider-router.js.map +1 -0
  43. package/dist/plugins/specweave/lib/vendor/sync/status-mapper.d.ts +120 -0
  44. package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js +164 -0
  45. package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js.map +1 -0
  46. package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
  47. package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
  48. package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
  49. package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
  50. package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
  51. package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
  52. package/dist/plugins/specweave/lib/vendor/utils/clean-env.d.ts +47 -0
  53. package/dist/plugins/specweave/lib/vendor/utils/clean-env.js +63 -0
  54. package/dist/plugins/specweave/lib/vendor/utils/clean-env.js.map +1 -0
  55. package/dist/plugins/specweave/lib/vendor/utils/credential-masker.d.ts +118 -0
  56. package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js +275 -0
  57. package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js.map +1 -0
  58. package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.d.ts +99 -0
  59. package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js +149 -0
  60. package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js.map +1 -0
  61. package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.d.ts +63 -0
  62. package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js +85 -0
  63. package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js.map +1 -0
  64. package/dist/plugins/specweave/lib/vendor/utils/fs-native.d.ts +219 -0
  65. package/dist/plugins/specweave/lib/vendor/utils/fs-native.js +397 -0
  66. package/dist/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
  67. package/dist/plugins/specweave/lib/vendor/utils/logger.d.ts +56 -0
  68. package/dist/plugins/specweave/lib/vendor/utils/logger.js +123 -0
  69. package/dist/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
  70. package/dist/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
  71. package/dist/plugins/specweave/lib/vendor/utils/translation.js +414 -0
  72. package/dist/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
  73. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
  74. package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
  75. package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
  76. package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
  77. package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +2 -2
  78. package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +1 -1
  79. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
  80. package/dist/plugins/specweave-github/lib/github-feature-sync.js +13 -4
  81. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
  82. package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
  83. package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +1 -1
  84. package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
  85. package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +1 -1
  86. package/dist/src/sync/spec-to-living-docs-sync.js +1 -1
  87. package/dist/src/sync/spec-to-living-docs-sync.js.map +1 -1
  88. package/package.json +1 -1
  89. package/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
  90. package/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
  91. package/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
  92. package/plugins/specweave/skills/team-lead/SKILL.md +150 -56
  93. package/plugins/specweave/skills/team-lead/agents/backend.md +13 -9
  94. package/plugins/specweave/skills/team-lead/agents/database.md +13 -9
  95. package/plugins/specweave/skills/team-lead/agents/frontend.md +12 -8
  96. package/plugins/specweave/skills/team-lead/agents/security.md +13 -9
  97. package/plugins/specweave/skills/team-lead/agents/testing.md +12 -8
  98. package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
  99. package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +1 -1
  100. package/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
  101. package/plugins/specweave-ado/lib/ado-spec-sync.ts +1 -1
  102. package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +1 -1
  103. package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +2 -2
  104. package/plugins/specweave-github/lib/github-feature-sync.js +11 -3
  105. package/plugins/specweave-github/lib/github-feature-sync.ts +13 -4
  106. package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
  107. package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +1 -1
  108. package/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
  109. package/plugins/specweave-jira/lib/jira-spec-sync.ts +1 -1
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Active Increment Manager
3
+ *
4
+ * Manages the `.specweave/state/active-increment.json` file which tracks
5
+ * the currently active increment for status line display.
6
+ *
7
+ * **Critical**: This file MUST be updated whenever increment status changes:
8
+ * - When new increment is created → Set as active
9
+ * - When increment is completed → Clear or set to next active
10
+ * - When increment is paused → Set to next active (or clear if none)
11
+ * - When increment is resumed → Set as active
12
+ *
13
+ * Part of increment 0021: Fix Active Increment Tracking
14
+ */
15
+ import * as fs from '../../utils/fs-native.js';
16
+ import path from 'path';
17
+ import { IncrementStatus } from '../types/increment-metadata.js';
18
+ import { MetadataManager } from './metadata-manager.js';
19
+ /**
20
+ * Active Increment Manager
21
+ *
22
+ * Central authority for managing which increment is currently active.
23
+ */
24
+ export class ActiveIncrementManager {
25
+ constructor(rootDir = process.cwd()) {
26
+ this.rootDir = rootDir;
27
+ this.stateFile = path.join(rootDir, '.specweave/state/active-increment.json');
28
+ }
29
+ /**
30
+ * Get all currently active increment IDs
31
+ * Returns empty array if no increments are active
32
+ *
33
+ * **NEW**: Returns array of ALL active increments (max 2)
34
+ */
35
+ getActive() {
36
+ try {
37
+ if (!fs.existsSync(this.stateFile)) {
38
+ return [];
39
+ }
40
+ const content = fs.readFileSync(this.stateFile, 'utf-8');
41
+ const state = JSON.parse(content);
42
+ // Backwards compatibility: Support old format
43
+ if (state.id && !state.ids) {
44
+ return [state.id];
45
+ }
46
+ return state.ids || [];
47
+ }
48
+ catch (error) {
49
+ // File read/parse error = no active increments
50
+ return [];
51
+ }
52
+ }
53
+ /**
54
+ * Get the primary active increment (first in list)
55
+ * Returns null if no increments are active
56
+ *
57
+ * This maintains backwards compatibility with code expecting a single ID
58
+ */
59
+ getPrimary() {
60
+ const active = this.getActive();
61
+ return active.length > 0 ? active[0] : null;
62
+ }
63
+ /**
64
+ * Add an increment to the active list
65
+ * Validates that the increment exists and is actually active
66
+ *
67
+ * **NEW**: Adds to list instead of replacing (max 2)
68
+ * @param skipValidation - Skip validation (used during lazy initialization to prevent circular dependency)
69
+ */
70
+ addActive(incrementId, skipValidation = false) {
71
+ // Validate increment exists and is active (unless skipValidation is true)
72
+ if (!skipValidation) {
73
+ const metadata = MetadataManager.read(incrementId, this.rootDir);
74
+ // Validate increment is actually active
75
+ if (metadata.status !== IncrementStatus.ACTIVE) {
76
+ throw new Error(`Cannot add ${incrementId} as active: status is ${metadata.status}, not active`);
77
+ }
78
+ }
79
+ // Get current active list
80
+ const currentActive = this.getActive();
81
+ // Don't add if already in list
82
+ if (currentActive.includes(incrementId)) {
83
+ return;
84
+ }
85
+ // Add to list (max 2)
86
+ const newActive = [...currentActive, incrementId].slice(0, 2);
87
+ // Write state
88
+ const state = {
89
+ ids: newActive,
90
+ lastUpdated: new Date().toISOString()
91
+ };
92
+ this.writeState(state);
93
+ }
94
+ /**
95
+ * Remove an increment from the active list
96
+ */
97
+ removeActive(incrementId) {
98
+ const currentActive = this.getActive();
99
+ const newActive = currentActive.filter(id => id !== incrementId);
100
+ const state = {
101
+ ids: newActive,
102
+ lastUpdated: new Date().toISOString()
103
+ };
104
+ this.writeState(state);
105
+ }
106
+ /**
107
+ * Set the active increment (legacy method for backwards compatibility)
108
+ * Now delegates to addActive()
109
+ * @param skipValidation - Skip validation (used during lazy initialization to prevent circular dependency)
110
+ */
111
+ setActive(incrementId, skipValidation = false) {
112
+ this.addActive(incrementId, skipValidation);
113
+ }
114
+ /**
115
+ * Clear all active increments
116
+ */
117
+ clearActive() {
118
+ const state = {
119
+ ids: [],
120
+ lastUpdated: new Date().toISOString()
121
+ };
122
+ this.writeState(state);
123
+ }
124
+ /**
125
+ * Smart update: Rebuild active list from metadata
126
+ *
127
+ * This is called when:
128
+ * - An increment is completed
129
+ * - An increment is paused
130
+ * - An increment is abandoned
131
+ *
132
+ * Logic:
133
+ * 1. Scan all increments for status=active
134
+ * 2. Update cache to match reality
135
+ * 3. Max 2 increments (sorted by lastActivity)
136
+ */
137
+ smartUpdate() {
138
+ // Use getByStatus directly to avoid caching circular dependency
139
+ // MetadataManager.getActive() uses this cache, so we can't call it here
140
+ const activeIncrements = MetadataManager.getByStatus(IncrementStatus.ACTIVE);
141
+ if (activeIncrements.length > 0) {
142
+ // Sort by lastActivity (most recent first)
143
+ const sorted = activeIncrements.sort((a, b) => {
144
+ const aTime = new Date(a.lastActivity).getTime();
145
+ const bTime = new Date(b.lastActivity).getTime();
146
+ return bTime - aTime; // Descending
147
+ });
148
+ // Take max 2
149
+ const activeIds = sorted.slice(0, 2).map(m => m.id);
150
+ const state = {
151
+ ids: activeIds,
152
+ lastUpdated: new Date().toISOString()
153
+ };
154
+ this.writeState(state);
155
+ }
156
+ else {
157
+ // No active increments
158
+ this.clearActive();
159
+ }
160
+ }
161
+ /**
162
+ * Validate that all active increment pointers are correct
163
+ * Does NOT fix stale pointers - caller should call smartUpdate() if needed
164
+ *
165
+ * Returns true if all valid, false if any invalid
166
+ */
167
+ validate() {
168
+ const currentActive = this.getActive();
169
+ // No active increments = valid (nothing to validate)
170
+ if (currentActive.length === 0) {
171
+ return true;
172
+ }
173
+ let hasStale = false;
174
+ for (const incrementId of currentActive) {
175
+ try {
176
+ // Check if increment still exists
177
+ const metadata = MetadataManager.read(incrementId);
178
+ // Check if increment is actually active
179
+ if (metadata.status !== IncrementStatus.ACTIVE) {
180
+ // Stale pointer! Mark for fix
181
+ console.warn(`⚠️ Active increment pointer is stale: ${incrementId} is ${metadata.status}`);
182
+ hasStale = true;
183
+ }
184
+ }
185
+ catch (error) {
186
+ // Increment doesn't exist = stale pointer
187
+ console.warn(`⚠️ Active increment pointer is invalid: ${incrementId} not found`);
188
+ hasStale = true;
189
+ }
190
+ }
191
+ // Return false if stale found, but DON'T auto-fix (prevents circular dependency)
192
+ // Caller should call smartUpdate() if needed
193
+ return !hasStale;
194
+ }
195
+ /**
196
+ * Validate and auto-repair the active increment state
197
+ *
198
+ * This is the recommended method to call on startup to ensure
199
+ * the active-increment.json is in sync with metadata.json files.
200
+ *
201
+ * Part of 0168: Status Single Source of Truth
202
+ *
203
+ * @returns Object with validation result and any repairs made
204
+ */
205
+ validateAndRepair() {
206
+ const details = [];
207
+ const currentActive = this.getActive();
208
+ // Track what needs repair
209
+ const staleIds = [];
210
+ const missingIds = [];
211
+ // Check each currently "active" increment
212
+ for (const incrementId of currentActive) {
213
+ try {
214
+ const metadata = MetadataManager.read(incrementId, this.rootDir);
215
+ if (metadata.status !== IncrementStatus.ACTIVE) {
216
+ staleIds.push(incrementId);
217
+ details.push(`Stale: ${incrementId} is ${metadata.status}, not active`);
218
+ }
219
+ }
220
+ catch {
221
+ missingIds.push(incrementId);
222
+ details.push(`Missing: ${incrementId} not found`);
223
+ }
224
+ }
225
+ // Check for active increments NOT in our list (missed additions)
226
+ // Note: We use getByStatus directly to scan all metadata files
227
+ // This avoids potential caching issues with getActive()
228
+ const actuallyActive = MetadataManager.getByStatus(IncrementStatus.ACTIVE);
229
+ const actuallyActiveIds = actuallyActive.map(m => m.id);
230
+ const missingFromList = actuallyActiveIds.filter(id => !currentActive.includes(id));
231
+ for (const id of missingFromList) {
232
+ details.push(`Missing from list: ${id} is active but not tracked`);
233
+ }
234
+ // If anything is wrong, repair by calling smartUpdate
235
+ const needsRepair = staleIds.length > 0 || missingIds.length > 0 || missingFromList.length > 0;
236
+ if (needsRepair) {
237
+ this.smartUpdate();
238
+ details.push('Auto-repaired: Rebuilt active increment list from metadata');
239
+ }
240
+ return {
241
+ valid: !needsRepair,
242
+ repaired: needsRepair,
243
+ details
244
+ };
245
+ }
246
+ /**
247
+ * Write state file atomically (temp file → rename)
248
+ */
249
+ writeState(state) {
250
+ // Ensure state directory exists
251
+ const stateDir = path.dirname(this.stateFile);
252
+ if (!fs.existsSync(stateDir)) {
253
+ fs.mkdirSync(stateDir, { recursive: true });
254
+ }
255
+ // Atomic write: temp file → rename
256
+ const tempFile = `${this.stateFile}.tmp`;
257
+ fs.writeFileSync(tempFile, JSON.stringify(state, null, 2), 'utf-8');
258
+ fs.renameSync(tempFile, this.stateFile);
259
+ }
260
+ /**
261
+ * Get state file path (for testing)
262
+ */
263
+ getStateFilePath() {
264
+ return this.stateFile;
265
+ }
266
+ /**
267
+ * Check if state file exists (for testing)
268
+ */
269
+ exists() {
270
+ return fs.existsSync(this.stateFile);
271
+ }
272
+ }
273
+ //# sourceMappingURL=active-increment-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-increment-manager.js","sourceRoot":"","sources":["../../../../src/core/increment/active-increment-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Auto-Transition Manager
3
+ *
4
+ * Automatically transitions increment status based on lifecycle events:
5
+ * - spec.md created → BACKLOG → PLANNING
6
+ * - tasks.md created → PLANNING/BACKLOG → ACTIVE
7
+ * - first task started → PLANNING → ACTIVE
8
+ *
9
+ * Part of increment 0039: Ultra-Smart Next Command
10
+ */
11
+ import { IncrementStatus } from '../types/increment-metadata.js';
12
+ export interface TransitionEvent {
13
+ incrementId: string;
14
+ from: IncrementStatus;
15
+ to: IncrementStatus;
16
+ trigger: 'spec-created' | 'tasks-created' | 'task-started' | 'auto-correct';
17
+ timestamp: string;
18
+ }
19
+ export interface AutoTransitionResult {
20
+ transitioned: boolean;
21
+ from?: IncrementStatus;
22
+ to?: IncrementStatus;
23
+ reason: string;
24
+ }
25
+ /**
26
+ * Manages automatic status transitions based on increment artifacts
27
+ */
28
+ export declare class AutoTransitionManager {
29
+ private projectRoot;
30
+ constructor(projectRoot: string);
31
+ /**
32
+ * Handle spec.md creation event
33
+ * BACKLOG → PLANNING
34
+ */
35
+ handleSpecCreated(incrementId: string): Promise<AutoTransitionResult>;
36
+ /**
37
+ * Handle tasks.md creation event
38
+ * PLANNING/BACKLOG → ACTIVE
39
+ *
40
+ * CRITICAL FIX (2025-11-24): Also trigger living docs sync if feature_id is null
41
+ * In single-prompt scenarios, increment may be created with "active" status
42
+ * directly, bypassing the normal transition flow. When tasks.md is created,
43
+ * we know spec.md exists and can safely sync living docs.
44
+ */
45
+ handleTasksCreated(incrementId: string): Promise<AutoTransitionResult>;
46
+ /**
47
+ * Trigger living docs sync if feature_id is missing
48
+ *
49
+ * Called when tasks.md is created but increment is already ACTIVE.
50
+ * At this point spec.md exists, so sync will succeed.
51
+ */
52
+ private triggerLivingDocsSyncIfNeeded;
53
+ /**
54
+ * Handle first task started event
55
+ * PLANNING → ACTIVE
56
+ */
57
+ handleTaskStarted(incrementId: string): Promise<AutoTransitionResult>;
58
+ /**
59
+ * Detect increment phase based on artifacts (spec.md, plan.md, tasks.md)
60
+ */
61
+ detectPhase(incrementId: string): Promise<IncrementStatus>;
62
+ /**
63
+ * Auto-correct status based on artifacts
64
+ * Useful for fixing increments with invalid "planned"/"planning" statuses
65
+ */
66
+ autoCorrect(incrementId: string, force?: boolean): Promise<AutoTransitionResult>;
67
+ /**
68
+ * Get transition event for logging
69
+ */
70
+ createTransitionEvent(incrementId: string, from: IncrementStatus, to: IncrementStatus, trigger: TransitionEvent['trigger']): TransitionEvent;
71
+ }
72
+ //# sourceMappingURL=auto-transition-manager.d.ts.map
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Auto-Transition Manager
3
+ *
4
+ * Automatically transitions increment status based on lifecycle events:
5
+ * - spec.md created → BACKLOG → PLANNING
6
+ * - tasks.md created → PLANNING/BACKLOG → ACTIVE
7
+ * - first task started → PLANNING → ACTIVE
8
+ *
9
+ * Part of increment 0039: Ultra-Smart Next Command
10
+ */
11
+ import { IncrementStatus, validateTransition } from '../types/increment-metadata.js';
12
+ import { MetadataManager } from './metadata-manager.js';
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ /**
16
+ * Manages automatic status transitions based on increment artifacts
17
+ */
18
+ export class AutoTransitionManager {
19
+ constructor(projectRoot) {
20
+ this.projectRoot = projectRoot;
21
+ // Note: MetadataManager uses process.cwd() internally
22
+ // In production, this manager should be instantiated from the project root
23
+ // In tests, we use integration tests with real file system
24
+ }
25
+ /**
26
+ * Handle spec.md creation event
27
+ * BACKLOG → PLANNING
28
+ */
29
+ async handleSpecCreated(incrementId) {
30
+ try {
31
+ const metadata = MetadataManager.read(incrementId);
32
+ // Only transition from BACKLOG to PLANNING
33
+ if (metadata.status === IncrementStatus.BACKLOG) {
34
+ validateTransition(metadata.status, IncrementStatus.PLANNING);
35
+ MetadataManager.updateStatus(incrementId, IncrementStatus.PLANNING);
36
+ return {
37
+ transitioned: true,
38
+ from: IncrementStatus.BACKLOG,
39
+ to: IncrementStatus.PLANNING,
40
+ reason: 'spec.md created - planning phase started'
41
+ };
42
+ }
43
+ return {
44
+ transitioned: false,
45
+ reason: `Already in ${metadata.status} - no transition needed`
46
+ };
47
+ }
48
+ catch (error) {
49
+ return {
50
+ transitioned: false,
51
+ reason: `Error: ${error instanceof Error ? error.message : String(error)}`
52
+ };
53
+ }
54
+ }
55
+ /**
56
+ * Handle tasks.md creation event
57
+ * PLANNING/BACKLOG → ACTIVE
58
+ *
59
+ * CRITICAL FIX (2025-11-24): Also trigger living docs sync if feature_id is null
60
+ * In single-prompt scenarios, increment may be created with "active" status
61
+ * directly, bypassing the normal transition flow. When tasks.md is created,
62
+ * we know spec.md exists and can safely sync living docs.
63
+ */
64
+ async handleTasksCreated(incrementId) {
65
+ try {
66
+ const metadata = MetadataManager.read(incrementId);
67
+ // Transition to ACTIVE from PLANNING or BACKLOG
68
+ if (metadata.status === IncrementStatus.PLANNING || metadata.status === IncrementStatus.BACKLOG) {
69
+ const from = metadata.status;
70
+ validateTransition(from, IncrementStatus.ACTIVE);
71
+ MetadataManager.updateStatus(incrementId, IncrementStatus.ACTIVE);
72
+ // Note: updateStatus() triggers StatusChangeSyncTrigger which handles living docs sync
73
+ return {
74
+ transitioned: true,
75
+ from,
76
+ to: IncrementStatus.ACTIVE,
77
+ reason: 'tasks.md created - execution phase started'
78
+ };
79
+ }
80
+ // CRITICAL FIX: Even if already ACTIVE, check if living docs need sync
81
+ // This handles single-prompt scenarios where increment was created with "active" status
82
+ if (metadata.status === IncrementStatus.ACTIVE) {
83
+ await this.triggerLivingDocsSyncIfNeeded(incrementId);
84
+ }
85
+ return {
86
+ transitioned: false,
87
+ reason: `Already in ${metadata.status} - no transition needed`
88
+ };
89
+ }
90
+ catch (error) {
91
+ return {
92
+ transitioned: false,
93
+ reason: `Error: ${error instanceof Error ? error.message : String(error)}`
94
+ };
95
+ }
96
+ }
97
+ /**
98
+ * Trigger living docs sync if feature_id is missing
99
+ *
100
+ * Called when tasks.md is created but increment is already ACTIVE.
101
+ * At this point spec.md exists, so sync will succeed.
102
+ */
103
+ async triggerLivingDocsSyncIfNeeded(incrementId) {
104
+ try {
105
+ const metadataPath = path.join(this.projectRoot, '.specweave/increments', incrementId, 'metadata.json');
106
+ if (!fs.existsSync(metadataPath)) {
107
+ return;
108
+ }
109
+ const content = fs.readFileSync(metadataPath, 'utf-8');
110
+ const metadata = JSON.parse(content);
111
+ // Only sync if feature_id is missing
112
+ if (!metadata.feature_id) {
113
+ console.log(`📚 Increment ${incrementId} missing feature_id - triggering living docs sync...`);
114
+ // Dynamic import to avoid circular dependency
115
+ const { LivingDocsSync } = await import('../living-docs/living-docs-sync.js');
116
+ const sync = new LivingDocsSync(this.projectRoot);
117
+ const result = await sync.syncIncrement(incrementId);
118
+ if (result.success) {
119
+ console.log(`✅ Living docs synced for ${incrementId} → ${result.featureId}`);
120
+ }
121
+ else {
122
+ console.warn(`⚠️ Living docs sync completed with errors for ${incrementId}`);
123
+ }
124
+ }
125
+ }
126
+ catch (error) {
127
+ // Non-fatal - log warning but don't fail the transition
128
+ console.warn(`⚠️ Failed to check/trigger living docs sync: ${error}`);
129
+ }
130
+ }
131
+ /**
132
+ * Handle first task started event
133
+ * PLANNING → ACTIVE
134
+ */
135
+ async handleTaskStarted(incrementId) {
136
+ try {
137
+ const metadata = MetadataManager.read(incrementId);
138
+ // Force transition to ACTIVE if still in PLANNING
139
+ if (metadata.status === IncrementStatus.PLANNING) {
140
+ validateTransition(metadata.status, IncrementStatus.ACTIVE);
141
+ MetadataManager.updateStatus(incrementId, IncrementStatus.ACTIVE);
142
+ return {
143
+ transitioned: true,
144
+ from: IncrementStatus.PLANNING,
145
+ to: IncrementStatus.ACTIVE,
146
+ reason: 'task execution started - moved to active'
147
+ };
148
+ }
149
+ return {
150
+ transitioned: false,
151
+ reason: `Already in ${metadata.status} - no transition needed`
152
+ };
153
+ }
154
+ catch (error) {
155
+ return {
156
+ transitioned: false,
157
+ reason: `Error: ${error instanceof Error ? error.message : String(error)}`
158
+ };
159
+ }
160
+ }
161
+ /**
162
+ * Detect increment phase based on artifacts (spec.md, plan.md, tasks.md)
163
+ */
164
+ async detectPhase(incrementId) {
165
+ const incrementPath = path.join(this.projectRoot, '.specweave/increments', incrementId);
166
+ const hasSpec = fs.existsSync(path.join(incrementPath, 'spec.md'));
167
+ const hasPlan = fs.existsSync(path.join(incrementPath, 'plan.md'));
168
+ const hasTasks = fs.existsSync(path.join(incrementPath, 'tasks.md'));
169
+ // Artifact-based phase detection
170
+ if (hasTasks) {
171
+ return IncrementStatus.ACTIVE; // Tasks exist → execution phase
172
+ }
173
+ else if (hasSpec || hasPlan) {
174
+ return IncrementStatus.PLANNING; // Spec/plan exist → planning phase
175
+ }
176
+ else {
177
+ return IncrementStatus.BACKLOG; // Nothing exists → backlog
178
+ }
179
+ }
180
+ /**
181
+ * Auto-correct status based on artifacts
182
+ * Useful for fixing increments with invalid "planned"/"planning" statuses
183
+ */
184
+ async autoCorrect(incrementId, force = false) {
185
+ try {
186
+ const metadata = MetadataManager.read(incrementId);
187
+ const detectedPhase = await this.detectPhase(incrementId);
188
+ // Check for status mismatch
189
+ if (metadata.status !== detectedPhase) {
190
+ // Validate transition is allowed
191
+ try {
192
+ validateTransition(metadata.status, detectedPhase);
193
+ }
194
+ catch (error) {
195
+ if (!force) {
196
+ return {
197
+ transitioned: false,
198
+ reason: `Cannot auto-correct: ${error instanceof Error ? error.message : String(error)}`
199
+ };
200
+ }
201
+ // Force mode: skip validation
202
+ }
203
+ const from = metadata.status;
204
+ MetadataManager.updateStatus(incrementId, detectedPhase);
205
+ return {
206
+ transitioned: true,
207
+ from,
208
+ to: detectedPhase,
209
+ reason: `Auto-corrected based on artifacts (${force ? 'forced' : 'validated'})`
210
+ };
211
+ }
212
+ return {
213
+ transitioned: false,
214
+ reason: `Status already correct (${metadata.status})`
215
+ };
216
+ }
217
+ catch (error) {
218
+ return {
219
+ transitioned: false,
220
+ reason: `Error: ${error instanceof Error ? error.message : String(error)}`
221
+ };
222
+ }
223
+ }
224
+ /**
225
+ * Get transition event for logging
226
+ */
227
+ createTransitionEvent(incrementId, from, to, trigger) {
228
+ return {
229
+ incrementId,
230
+ from,
231
+ to,
232
+ trigger,
233
+ timestamp: new Date().toISOString()
234
+ };
235
+ }
236
+ }
237
+ //# sourceMappingURL=auto-transition-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-transition-manager.js","sourceRoot":"","sources":["../../../../src/core/increment/auto-transition-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Duplicate Detector - Scan filesystem and detect duplicate increments
3
+ *
4
+ * Detects increments that exist in multiple locations (active, archive, abandoned)
5
+ * or have the same increment number with different names.
6
+ *
7
+ * Part of increment 0033: Duplicate Increment Prevention System
8
+ */
9
+ import { IncrementStatus } from '../types/increment-metadata.js';
10
+ /**
11
+ * Report of all duplicates found
12
+ */
13
+ export interface DuplicateReport {
14
+ duplicates: Duplicate[];
15
+ totalChecked: number;
16
+ duplicateCount: number;
17
+ }
18
+ /**
19
+ * A duplicate increment (same number in multiple locations or with different names)
20
+ */
21
+ export interface Duplicate {
22
+ incrementNumber: string;
23
+ locations: IncrementLocation[];
24
+ recommendedWinner: IncrementLocation;
25
+ losingVersions: IncrementLocation[];
26
+ resolutionReason: string;
27
+ }
28
+ /**
29
+ * Information about an increment location
30
+ */
31
+ export interface IncrementLocation {
32
+ path: string;
33
+ name: string;
34
+ status: IncrementStatus;
35
+ lastActivity: string;
36
+ fileCount: number;
37
+ totalSize: number;
38
+ hasReports: boolean;
39
+ hasGitHubLink: boolean;
40
+ }
41
+ /**
42
+ * Scan all increment folders and detect duplicates
43
+ */
44
+ export declare function detectAllDuplicates(rootDir: string): Promise<DuplicateReport>;
45
+ /**
46
+ * Detect duplicates for a specific increment number
47
+ *
48
+ * Returns ALL increments that have the given number, even if there's only one.
49
+ * This is used for validation before creating a new increment.
50
+ */
51
+ export declare function detectDuplicatesByNumber(incrementNumber: string, rootDir: string): Promise<IncrementLocation[]>;
52
+ //# sourceMappingURL=duplicate-detector.d.ts.map