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,281 @@
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 * as fs from '../../utils/fs-native.js';
10
+ import * as path from 'path';
11
+ import { glob } from 'glob';
12
+ /**
13
+ * Scan all increment folders and detect duplicates
14
+ */
15
+ export async function detectAllDuplicates(rootDir) {
16
+ const incrementsDir = path.join(rootDir, '.specweave', 'increments');
17
+ // Check if increments directory exists
18
+ if (!await fs.pathExists(incrementsDir)) {
19
+ return {
20
+ duplicates: [],
21
+ totalChecked: 0,
22
+ duplicateCount: 0
23
+ };
24
+ }
25
+ // Scan all locations in parallel
26
+ const [active, archived, abandoned] = await Promise.all([
27
+ scanDirectory(incrementsDir, false),
28
+ scanDirectory(path.join(incrementsDir, '_archive'), false),
29
+ scanDirectory(path.join(incrementsDir, '_abandoned'), false)
30
+ ]);
31
+ // Group by increment number
32
+ const byNumber = new Map();
33
+ const allIncrements = [...active, ...archived, ...abandoned];
34
+ for (const inc of allIncrements) {
35
+ const number = extractIncrementNumber(inc.name);
36
+ if (!number)
37
+ continue; // Skip non-increment folders
38
+ if (!byNumber.has(number)) {
39
+ byNumber.set(number, []);
40
+ }
41
+ byNumber.get(number).push(inc);
42
+ }
43
+ // Find duplicates (increment number exists in >1 location or >1 name)
44
+ const duplicates = [];
45
+ byNumber.forEach((locations, number) => {
46
+ if (locations.length > 1) {
47
+ // Duplicate found!
48
+ const winner = selectWinner(locations);
49
+ duplicates.push({
50
+ incrementNumber: number,
51
+ locations,
52
+ recommendedWinner: winner,
53
+ losingVersions: locations.filter(l => l !== winner),
54
+ resolutionReason: explainWinner(winner, locations)
55
+ });
56
+ }
57
+ });
58
+ return {
59
+ duplicates,
60
+ totalChecked: allIncrements.length,
61
+ duplicateCount: duplicates.length
62
+ };
63
+ }
64
+ /**
65
+ * Detect duplicates for a specific increment number
66
+ *
67
+ * Returns ALL increments that have the given number, even if there's only one.
68
+ * This is used for validation before creating a new increment.
69
+ */
70
+ export async function detectDuplicatesByNumber(incrementNumber, rootDir) {
71
+ const incrementsDir = path.join(rootDir, '.specweave', 'increments');
72
+ // Check if increments directory exists
73
+ if (!await fs.pathExists(incrementsDir)) {
74
+ return [];
75
+ }
76
+ // Normalize increment number (pad to 4 digits)
77
+ const normalizedNumber = incrementNumber.padStart(4, '0');
78
+ // Scan all locations in parallel
79
+ const [active, archived, abandoned] = await Promise.all([
80
+ scanDirectory(incrementsDir, false),
81
+ scanDirectory(path.join(incrementsDir, '_archive'), false),
82
+ scanDirectory(path.join(incrementsDir, '_abandoned'), false)
83
+ ]);
84
+ // Combine all increments and filter by number
85
+ const allIncrements = [...active, ...archived, ...abandoned];
86
+ const matchingIncrements = allIncrements.filter(inc => {
87
+ const number = extractIncrementNumber(inc.name);
88
+ return number === normalizedNumber;
89
+ });
90
+ return matchingIncrements;
91
+ }
92
+ /**
93
+ * Scan a directory for increment folders
94
+ */
95
+ async function scanDirectory(dir, throwOnError = false) {
96
+ try {
97
+ // Check if directory exists
98
+ if (!await fs.pathExists(dir)) {
99
+ return [];
100
+ }
101
+ // Find all directories matching increment pattern (####-*)
102
+ const pattern = path.join(dir, '[0-9][0-9][0-9][0-9]-*');
103
+ const allPaths = await glob(pattern);
104
+ const locations = [];
105
+ for (const incPath of allPaths) {
106
+ try {
107
+ const stats = await fs.stat(incPath);
108
+ if (!stats.isDirectory())
109
+ continue;
110
+ const name = path.basename(incPath);
111
+ // Skip nested .specweave folders
112
+ if (incPath.includes('.specweave/increments/.specweave')) {
113
+ continue;
114
+ }
115
+ // Read metadata
116
+ const metadataPath = path.join(incPath, 'metadata.json');
117
+ let metadata = {
118
+ status: 'unknown',
119
+ lastActivity: new Date(stats.mtime).toISOString()
120
+ };
121
+ if (await fs.pathExists(metadataPath)) {
122
+ try {
123
+ metadata = await fs.readJson(metadataPath);
124
+ }
125
+ catch (error) {
126
+ // Skip corrupted metadata (will be caught by validation)
127
+ }
128
+ }
129
+ // Count files recursively
130
+ const allFiles = await glob(path.join(incPath, '**/*'));
131
+ const fileCount = allFiles.filter(async (f) => {
132
+ try {
133
+ const fstats = await fs.stat(f);
134
+ return fstats.isFile();
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }).length;
140
+ // Calculate total size
141
+ let totalSize = 0;
142
+ for (const file of allFiles) {
143
+ try {
144
+ const fstats = await fs.stat(file);
145
+ if (fstats.isFile()) {
146
+ totalSize += fstats.size;
147
+ }
148
+ }
149
+ catch {
150
+ // Skip files we can't read
151
+ }
152
+ }
153
+ // Check for reports folder
154
+ const reportsDir = path.join(incPath, 'reports');
155
+ const hasReports = await fs.pathExists(reportsDir);
156
+ // Check for GitHub link in metadata
157
+ const hasGitHubLink = metadata.github && metadata.github.issue;
158
+ locations.push({
159
+ path: incPath,
160
+ name,
161
+ status: metadata.status || 'unknown',
162
+ lastActivity: metadata.lastActivity || new Date(stats.mtime).toISOString(),
163
+ fileCount,
164
+ totalSize,
165
+ hasReports,
166
+ hasGitHubLink
167
+ });
168
+ }
169
+ catch (error) {
170
+ // Skip increments we can't read
171
+ if (throwOnError)
172
+ throw error;
173
+ }
174
+ }
175
+ return locations;
176
+ }
177
+ catch (error) {
178
+ if (throwOnError)
179
+ throw error;
180
+ return [];
181
+ }
182
+ }
183
+ /**
184
+ * Extract increment number from increment name (e.g., "0001-feature" → "0001")
185
+ */
186
+ function extractIncrementNumber(name) {
187
+ const match = name.match(/^(\d{3,4})E?-/);
188
+ return match ? match[1].padStart(4, '0') : null;
189
+ }
190
+ /**
191
+ * Status priority for winner selection (higher = better)
192
+ */
193
+ const STATUS_PRIORITY = {
194
+ active: 5,
195
+ completed: 4,
196
+ paused: 3,
197
+ backlog: 2,
198
+ abandoned: 1,
199
+ unknown: 0
200
+ };
201
+ /**
202
+ * Location priority for winner selection (higher = better)
203
+ */
204
+ const LOCATION_PRIORITY = {
205
+ active: 3,
206
+ archive: 2,
207
+ abandoned: 1
208
+ };
209
+ /**
210
+ * Get location type from path
211
+ */
212
+ function getLocationType(loc) {
213
+ if (loc.path.includes('_abandoned'))
214
+ return 'abandoned';
215
+ if (loc.path.includes('_archive'))
216
+ return 'archive';
217
+ return 'active';
218
+ }
219
+ /**
220
+ * Get status priority for a location
221
+ */
222
+ function getStatusPriority(loc) {
223
+ return STATUS_PRIORITY[loc.status] ?? 0;
224
+ }
225
+ /**
226
+ * Get location priority for a location
227
+ */
228
+ function getLocationPriority(loc) {
229
+ return LOCATION_PRIORITY[getLocationType(loc)];
230
+ }
231
+ /**
232
+ * Select winning version based on priority rules
233
+ */
234
+ function selectWinner(locations) {
235
+ const sorted = [...locations].sort((a, b) => {
236
+ // 1. Status priority
237
+ const statusDiff = getStatusPriority(b) - getStatusPriority(a);
238
+ if (statusDiff !== 0)
239
+ return statusDiff;
240
+ // 2. Most recent activity
241
+ const timeDiff = new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime();
242
+ if (timeDiff !== 0)
243
+ return timeDiff;
244
+ // 3. Most complete (more files)
245
+ const fileDiff = b.fileCount - a.fileCount;
246
+ if (fileDiff !== 0)
247
+ return fileDiff;
248
+ // 4. Location preference (active > _archive > _abandoned)
249
+ return getLocationPriority(b) - getLocationPriority(a);
250
+ });
251
+ return sorted[0];
252
+ }
253
+ /**
254
+ * Explain why this version won
255
+ */
256
+ function explainWinner(winner, all) {
257
+ const reasons = [];
258
+ const winnerStatusPriority = getStatusPriority(winner);
259
+ const winnerTime = new Date(winner.lastActivity).getTime();
260
+ const winnerLocation = getLocationType(winner);
261
+ const winnerLocationPriority = getLocationPriority(winner);
262
+ // Check status
263
+ if (all.some(loc => loc !== winner && getStatusPriority(loc) < winnerStatusPriority)) {
264
+ reasons.push(`Higher status (${winner.status})`);
265
+ }
266
+ // Check recency
267
+ if (all.some(loc => loc !== winner && new Date(loc.lastActivity).getTime() < winnerTime)) {
268
+ const date = new Date(winner.lastActivity).toISOString().split('T')[0];
269
+ reasons.push(`Most recent activity (${date})`);
270
+ }
271
+ // Check completeness
272
+ if (all.some(loc => loc !== winner && loc.fileCount < winner.fileCount)) {
273
+ reasons.push(`Most complete (${winner.fileCount} files)`);
274
+ }
275
+ // Check location
276
+ if (all.some(loc => loc !== winner && getLocationPriority(loc) < winnerLocationPriority)) {
277
+ reasons.push(`In ${winnerLocation} location`);
278
+ }
279
+ return reasons.length > 0 ? reasons.join(', ') : 'Default selection';
280
+ }
281
+ //# sourceMappingURL=duplicate-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-detector.js","sourceRoot":"","sources":["../../../../src/core/increment/duplicate-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Metadata Manager
3
+ *
4
+ * Handles CRUD operations for increment metadata (status, type, timestamps).
5
+ * Part of increment 0007: Smart Status Management
6
+ */
7
+ import { IncrementMetadata, IncrementMetadataExtended, IncrementMetadataV2, IncrementStatus, IncrementType, SyncTarget, PrRef } from '../types/increment-metadata.js';
8
+ import { Logger } from '../../utils/logger.js';
9
+ /**
10
+ * Error thrown when metadata operations fail
11
+ */
12
+ export declare class MetadataError extends Error {
13
+ incrementId: string;
14
+ cause?: Error | undefined;
15
+ constructor(message: string, incrementId: string, cause?: Error | undefined);
16
+ }
17
+ /**
18
+ * Metadata Manager
19
+ *
20
+ * Provides CRUD operations and queries for increment metadata
21
+ */
22
+ export declare class MetadataManager {
23
+ /**
24
+ * Logger instance (injectable for testing)
25
+ */
26
+ private static logger;
27
+ /**
28
+ * Set logger instance (primarily for testing with silentLogger)
29
+ *
30
+ * @param logger - Logger instance to use
31
+ */
32
+ static setLogger(logger: Logger): void;
33
+ /**
34
+ * Get metadata file path for increment
35
+ *
36
+ * Uses resolveEffectiveRoot() to find the umbrella root in multi-repo setups,
37
+ * or the nearest project root in single-repo setups.
38
+ *
39
+ * SECURITY: Validates increment ID to prevent path traversal attacks.
40
+ */
41
+ private static getMetadataPath;
42
+ /**
43
+ * Get increment directory path
44
+ *
45
+ * Uses resolveEffectiveRoot() to find the umbrella root in multi-repo setups,
46
+ * or the nearest project root in single-repo setups.
47
+ *
48
+ * SECURITY: Validates increment ID to prevent path traversal attacks.
49
+ */
50
+ private static getIncrementPath;
51
+ /**
52
+ * Check if metadata file exists
53
+ */
54
+ static exists(incrementId: string, rootDir?: string): boolean;
55
+ /**
56
+ * Read metadata from file
57
+ * Creates default metadata if file doesn't exist (lazy initialization)
58
+ */
59
+ static read(incrementId: string, rootDir?: string): IncrementMetadata;
60
+ /**
61
+ * Reserved increment IDs that cannot be used
62
+ * These are status values, special folders, and state files
63
+ */
64
+ private static readonly RESERVED_INCREMENT_IDS;
65
+ /**
66
+ * Validate increment ID is not a reserved name
67
+ * Throws if ID is reserved
68
+ */
69
+ private static validateNotReserved;
70
+ /**
71
+ * Validate increment before creation (check for duplicates and reserved names)
72
+ * Throws if duplicates exist in other locations or ID is reserved
73
+ */
74
+ static validateBeforeCreate(incrementId: string, rootDir?: string): Promise<void>;
75
+ /**
76
+ * Write metadata to file
77
+ * Uses atomic write (temp file → rename)
78
+ *
79
+ * @param incrementId - Increment ID
80
+ * @param metadata - Metadata to write
81
+ * @param rootDir - Optional root directory (defaults to process.cwd())
82
+ */
83
+ static write(incrementId: string, metadata: IncrementMetadata, rootDir?: string): void;
84
+ /**
85
+ * Delete metadata file
86
+ */
87
+ static delete(incrementId: string, rootDir?: string): void;
88
+ /**
89
+ * Update increment status
90
+ * Validates transition and updates timestamps
91
+ *
92
+ * **CRITICAL**: Also updates active increment state automatically!
93
+ *
94
+ * NOTE: This method is now SYNCHRONOUS to ensure spec.md is updated
95
+ * before returning. This prevents race conditions in tests and ensures
96
+ * data consistency.
97
+ */
98
+ static updateStatus(incrementId: string, newStatus: IncrementStatus, reason?: string, rootDir?: string): IncrementMetadata;
99
+ /**
100
+ * Update spec.md status synchronously (used by updateStatus)
101
+ *
102
+ * This is a private helper to avoid async/await in updateStatus() which would
103
+ * break backward compatibility with callers expecting sync behavior.
104
+ */
105
+ private static updateSpecMdStatusSync;
106
+ /**
107
+ * Update increment type
108
+ */
109
+ static updateType(incrementId: string, type: IncrementType): IncrementMetadata;
110
+ /**
111
+ * Touch increment (update lastActivity)
112
+ */
113
+ static touch(incrementId: string): IncrementMetadata;
114
+ /**
115
+ * Get all increments
116
+ *
117
+ * Uses resolveEffectiveRoot() to find umbrella root in multi-repo setups.
118
+ */
119
+ static getAll(): IncrementMetadata[];
120
+ /**
121
+ * Get increments by status
122
+ */
123
+ static getByStatus(status: IncrementStatus): IncrementMetadata[];
124
+ /**
125
+ * Get active increments (FAST: cache-first strategy)
126
+ *
127
+ * **PERFORMANCE UPGRADE**: Uses ActiveIncrementManager cache instead of scanning all increments
128
+ * - Old: Scan 31 metadata files (~50ms)
129
+ * - New: Read 1 cache file + 1-2 metadata files (~5ms) = **10x faster**
130
+ *
131
+ * Fallback to full scan if cache is stale or missing
132
+ */
133
+ static getActive(): IncrementMetadata[];
134
+ /**
135
+ * Get backlog increments
136
+ */
137
+ static getBacklog(): IncrementMetadata[];
138
+ /**
139
+ * Get paused increments
140
+ */
141
+ static getPaused(): IncrementMetadata[];
142
+ /**
143
+ * Get completed increments
144
+ */
145
+ static getCompleted(): IncrementMetadata[];
146
+ /**
147
+ * Get abandoned increments
148
+ */
149
+ static getAbandoned(): IncrementMetadata[];
150
+ /**
151
+ * Get increments by type
152
+ */
153
+ static getByType(type: IncrementType): IncrementMetadata[];
154
+ /**
155
+ * Get stale increments (paused >7 days or active >30 days)
156
+ */
157
+ static getStale(): IncrementMetadata[];
158
+ /**
159
+ * Get increments that should be auto-abandoned (experiments inactive >14 days)
160
+ */
161
+ static getShouldAutoAbandon(): IncrementMetadata[];
162
+ /**
163
+ * Get extended metadata with computed fields (progress, age, etc.)
164
+ */
165
+ static getExtended(incrementId: string): IncrementMetadataExtended;
166
+ /**
167
+ * Validate and auto-correct metadata schema issues.
168
+ *
169
+ * Fixes:
170
+ * - id: short numeric IDs (e.g. "0399") expanded to full slug using folderName
171
+ * - type: non-standard aliases mapped to canonical enum values
172
+ * - created/createdAt: legacy field renamed
173
+ * - externalLinks: ensured to exist (defaults to {})
174
+ * - status/priority/testMode/coverageTarget: sensible defaults applied
175
+ *
176
+ * @returns corrected metadata, whether any correction was made, and warnings
177
+ */
178
+ private static validateMetadataSchema;
179
+ /**
180
+ * Validate metadata schema
181
+ */
182
+ static validate(metadata: IncrementMetadata): boolean;
183
+ /**
184
+ * Check if status transition is allowed
185
+ */
186
+ static canTransition(from: IncrementStatus, to: IncrementStatus): boolean;
187
+ /**
188
+ * Get human-readable status transition error message
189
+ */
190
+ static getTransitionError(from: IncrementStatus, to: IncrementStatus): string;
191
+ /**
192
+ * Set the external tool sync target for an increment
193
+ *
194
+ * This explicitly specifies which sync profile the increment uses.
195
+ * The sync target provides audit trail and deterministic sync behavior.
196
+ *
197
+ * @param incrementId - Increment ID
198
+ * @param syncTarget - Sync target configuration
199
+ * @param rootDir - Optional root directory
200
+ * @returns Updated metadata
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * MetadataManager.setSyncTarget('0142-feature', {
205
+ * profileId: 'github-frontend',
206
+ * provider: 'github',
207
+ * derivedFrom: 'project-mapping',
208
+ * setAt: new Date().toISOString(),
209
+ * sourceProjectId: 'frontend-app'
210
+ * });
211
+ * ```
212
+ */
213
+ static setSyncTarget(incrementId: string, syncTarget: SyncTarget, rootDir?: string): IncrementMetadataV2;
214
+ /**
215
+ * Get the sync target for an increment
216
+ *
217
+ * @param incrementId - Increment ID
218
+ * @param rootDir - Optional root directory
219
+ * @returns Sync target or undefined if not set
220
+ */
221
+ static getSyncTarget(incrementId: string, rootDir?: string): SyncTarget | undefined;
222
+ /**
223
+ * Clear the sync target for an increment
224
+ *
225
+ * Use this when the external tool configuration changes and
226
+ * the increment needs to be re-resolved.
227
+ *
228
+ * @param incrementId - Increment ID
229
+ * @param rootDir - Optional root directory
230
+ * @returns Updated metadata
231
+ */
232
+ static clearSyncTarget(incrementId: string, rootDir?: string): IncrementMetadataV2;
233
+ /**
234
+ * Check if increment has a sync target configured
235
+ *
236
+ * @param incrementId - Increment ID
237
+ * @param rootDir - Optional root directory
238
+ * @returns true if sync target is set
239
+ */
240
+ static hasSyncTarget(incrementId: string, rootDir?: string): boolean;
241
+ /**
242
+ * Add a pull request reference to an increment (v1.0.437+)
243
+ *
244
+ * Appends a PrRef to the prRefs array. Deduplicates by repoSlug
245
+ * (or by branch name for single-repo increments without repoSlug).
246
+ *
247
+ * @param incrementId - Increment ID
248
+ * @param ref - Pull request reference to add
249
+ * @param rootDir - Optional root directory
250
+ * @returns Updated metadata
251
+ */
252
+ static addPrRef(incrementId: string, ref: PrRef, rootDir?: string): IncrementMetadataV2;
253
+ /**
254
+ * Get pull request references for an increment
255
+ *
256
+ * @param incrementId - Increment ID
257
+ * @param rootDir - Optional root directory
258
+ * @returns Array of PR refs, or empty array if none
259
+ */
260
+ static getPrRefs(incrementId: string, rootDir?: string): PrRef[];
261
+ /**
262
+ * Get all increments with a specific sync provider
263
+ *
264
+ * Useful for bulk operations on all GitHub/JIRA/ADO synced increments.
265
+ *
266
+ * @param provider - Provider type ('github', 'jira', 'ado')
267
+ * @returns Array of increments with that provider configured
268
+ */
269
+ static getByProvider(provider: 'github' | 'jira' | 'ado'): IncrementMetadataV2[];
270
+ /**
271
+ * Get all increments with a specific sync profile
272
+ *
273
+ * @param profileId - Profile ID from config.sync.profiles
274
+ * @returns Array of increments using that profile
275
+ */
276
+ static getByProfile(profileId: string): IncrementMetadataV2[];
277
+ }
278
+ //# sourceMappingURL=metadata-manager.d.ts.map