specweave 0.28.32 → 0.28.33

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 (36) hide show
  1. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
  2. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  3. package/dist/plugins/specweave-github/lib/github-client-v2.js +57 -0
  4. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  5. package/dist/src/cli/helpers/init/external-import.js +4 -0
  6. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  7. package/dist/src/importers/import-coordinator.d.ts +1 -0
  8. package/dist/src/importers/import-coordinator.d.ts.map +1 -1
  9. package/dist/src/importers/import-coordinator.js +3 -0
  10. package/dist/src/importers/import-coordinator.js.map +1 -1
  11. package/dist/src/living-docs/fs-id-allocator.d.ts +11 -0
  12. package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
  13. package/dist/src/living-docs/fs-id-allocator.js +24 -0
  14. package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
  15. package/dist/src/sync/github-reconciler.d.ts +94 -0
  16. package/dist/src/sync/github-reconciler.d.ts.map +1 -0
  17. package/dist/src/sync/github-reconciler.js +435 -0
  18. package/dist/src/sync/github-reconciler.js.map +1 -0
  19. package/package.json +1 -1
  20. package/plugins/specweave/hooks/hooks.json +10 -0
  21. package/plugins/specweave/hooks/post-increment-status-change.sh +123 -32
  22. package/plugins/specweave/hooks/session-start-reconcile.sh +139 -0
  23. package/plugins/specweave/lib/hooks/close-github-issues-abandoned.js +37 -0
  24. package/plugins/specweave/lib/hooks/close-github-issues-abandoned.ts +59 -0
  25. package/plugins/specweave/lib/hooks/reopen-github-issues.js +37 -0
  26. package/plugins/specweave/lib/hooks/reopen-github-issues.ts +59 -0
  27. package/plugins/specweave/lib/hooks/session-start-reconcile-worker.js +36 -0
  28. package/plugins/specweave/lib/hooks/session-start-reconcile-worker.ts +58 -0
  29. package/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +94 -0
  30. package/plugins/specweave/lib/vendor/sync/github-reconciler.js +435 -0
  31. package/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -0
  32. package/plugins/specweave-github/commands/specweave-github-reconcile.md +110 -0
  33. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +24 -0
  34. package/plugins/specweave-github/lib/github-client-v2.js +55 -0
  35. package/plugins/specweave-github/lib/github-client-v2.ts +68 -0
  36. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +36 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * GitHub Reconciler (NEW in v0.28.33)
3
+ *
4
+ * Reconciles GitHub issue states with increment metadata.json statuses.
5
+ * Fixes drift between local SpecWeave state and GitHub:
6
+ * - Closes issues for completed increments that are still open
7
+ * - Reopens issues for in-progress increments that are closed
8
+ *
9
+ * Triggered by:
10
+ * - /specweave-github:reconcile command (manual)
11
+ * - SessionStart hook (automatic, if configured)
12
+ * - post-increment-status-change.sh (on resume/abandon)
13
+ */
14
+ import { Logger } from '../utils/logger.js';
15
+ export interface ReconcileOptions {
16
+ projectRoot: string;
17
+ dryRun?: boolean;
18
+ logger?: Logger;
19
+ }
20
+ export interface IncrementGitHubState {
21
+ incrementId: string;
22
+ incrementPath: string;
23
+ metadataStatus: string;
24
+ featureId?: string;
25
+ mainIssue?: {
26
+ number: number;
27
+ url?: string;
28
+ };
29
+ userStoryIssues: Array<{
30
+ userStoryId: string;
31
+ issueNumber: number;
32
+ }>;
33
+ }
34
+ export interface ReconcileResult {
35
+ scanned: number;
36
+ mismatches: number;
37
+ closed: number;
38
+ reopened: number;
39
+ errors: string[];
40
+ details: Array<{
41
+ incrementId: string;
42
+ action: 'close' | 'reopen' | 'skip' | 'error';
43
+ issueNumber: number;
44
+ reason: string;
45
+ }>;
46
+ }
47
+ export declare class GitHubReconciler {
48
+ private projectRoot;
49
+ private dryRun;
50
+ private logger;
51
+ private client;
52
+ constructor(options: ReconcileOptions);
53
+ /**
54
+ * Main reconciliation entry point
55
+ */
56
+ reconcile(): Promise<ReconcileResult>;
57
+ /**
58
+ * Reconcile a single increment
59
+ */
60
+ private reconcileIncrement;
61
+ /**
62
+ * Reconcile a single issue
63
+ */
64
+ private reconcileIssue;
65
+ /**
66
+ * Scan all non-archived increments and extract GitHub state
67
+ */
68
+ private scanIncrements;
69
+ /**
70
+ * Initialize GitHub client
71
+ */
72
+ private initClient;
73
+ /**
74
+ * Load config
75
+ */
76
+ private loadConfig;
77
+ /**
78
+ * Reopen all GitHub issues for an increment
79
+ * Called by post-increment-status-change.sh when resuming
80
+ */
81
+ static reopenIncrementIssues(projectRoot: string, incrementId: string, reason: string, logger?: Logger): Promise<{
82
+ reopened: number;
83
+ errors: string[];
84
+ }>;
85
+ /**
86
+ * Close all GitHub issues for an abandoned increment
87
+ * Called by post-increment-status-change.sh when abandoning
88
+ */
89
+ static closeAbandonedIncrementIssues(projectRoot: string, incrementId: string, reason: string, logger?: Logger): Promise<{
90
+ closed: number;
91
+ errors: string[];
92
+ }>;
93
+ }
94
+ //# sourceMappingURL=github-reconciler.d.ts.map
@@ -0,0 +1,435 @@
1
+ /**
2
+ * GitHub Reconciler (NEW in v0.28.33)
3
+ *
4
+ * Reconciles GitHub issue states with increment metadata.json statuses.
5
+ * Fixes drift between local SpecWeave state and GitHub:
6
+ * - Closes issues for completed increments that are still open
7
+ * - Reopens issues for in-progress increments that are closed
8
+ *
9
+ * Triggered by:
10
+ * - /specweave-github:reconcile command (manual)
11
+ * - SessionStart hook (automatic, if configured)
12
+ * - post-increment-status-change.sh (on resume/abandon)
13
+ */
14
+ import { promises as fs, existsSync } from 'fs';
15
+ import path from 'path';
16
+ import { GitHubClientV2 } from '../../plugins/specweave-github/lib/github-client-v2.js';
17
+ import { consoleLogger } from '../utils/logger.js';
18
+ export class GitHubReconciler {
19
+ constructor(options) {
20
+ this.client = null;
21
+ this.projectRoot = options.projectRoot;
22
+ this.dryRun = options.dryRun ?? false;
23
+ this.logger = options.logger ?? consoleLogger;
24
+ }
25
+ /**
26
+ * Main reconciliation entry point
27
+ */
28
+ async reconcile() {
29
+ const result = {
30
+ scanned: 0,
31
+ mismatches: 0,
32
+ closed: 0,
33
+ reopened: 0,
34
+ errors: [],
35
+ details: [],
36
+ };
37
+ try {
38
+ // 1. Check if GitHub sync is enabled
39
+ const config = await this.loadConfig();
40
+ const canUpdate = config.sync?.settings?.canUpdateExternalItems ?? false;
41
+ const githubEnabled = config.sync?.github?.enabled ?? false;
42
+ if (!canUpdate || !githubEnabled) {
43
+ this.logger.log('ℹ️ GitHub sync is disabled - skipping reconciliation');
44
+ this.logger.log(' Enable with: canUpdateExternalItems=true AND sync.github.enabled=true');
45
+ return result;
46
+ }
47
+ // 2. Initialize GitHub client
48
+ await this.initClient();
49
+ if (!this.client) {
50
+ result.errors.push('Failed to initialize GitHub client');
51
+ return result;
52
+ }
53
+ // 3. Scan all non-archived increments
54
+ const increments = await this.scanIncrements();
55
+ result.scanned = increments.length;
56
+ this.logger.log(`\n📊 Scanning ${increments.length} increment(s) for GitHub state drift...\n`);
57
+ // 4. Check and fix each increment
58
+ for (const inc of increments) {
59
+ await this.reconcileIncrement(inc, result);
60
+ }
61
+ // 5. Report summary
62
+ this.logger.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
63
+ this.logger.log('📊 RECONCILIATION SUMMARY');
64
+ this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
65
+ this.logger.log(` Increments scanned: ${result.scanned}`);
66
+ this.logger.log(` Mismatches found: ${result.mismatches}`);
67
+ this.logger.log(` Issues closed: ${result.closed}`);
68
+ this.logger.log(` Issues reopened: ${result.reopened}`);
69
+ this.logger.log(` Errors: ${result.errors.length}`);
70
+ if (this.dryRun) {
71
+ this.logger.log('\n ⚠️ DRY RUN - No changes were made');
72
+ }
73
+ this.logger.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
74
+ return result;
75
+ }
76
+ catch (error) {
77
+ result.errors.push(`Reconciliation error: ${error.message}`);
78
+ this.logger.error('❌ Reconciliation failed:', error.message);
79
+ return result;
80
+ }
81
+ }
82
+ /**
83
+ * Reconcile a single increment
84
+ */
85
+ async reconcileIncrement(inc, result) {
86
+ const status = inc.metadataStatus;
87
+ // Determine expected GitHub state
88
+ const shouldBeClosed = status === 'completed' || status === 'abandoned';
89
+ const shouldBeOpen = status === 'in-progress' || status === 'active' || status === 'planning';
90
+ // Check main issue
91
+ if (inc.mainIssue) {
92
+ await this.reconcileIssue(inc.incrementId, inc.mainIssue.number, shouldBeClosed, shouldBeOpen, status, result);
93
+ }
94
+ // Check User Story issues
95
+ for (const us of inc.userStoryIssues) {
96
+ await this.reconcileIssue(`${inc.incrementId}/${us.userStoryId}`, us.issueNumber, shouldBeClosed, shouldBeOpen, status, result);
97
+ }
98
+ }
99
+ /**
100
+ * Reconcile a single issue
101
+ */
102
+ async reconcileIssue(context, issueNumber, shouldBeClosed, shouldBeOpen, metadataStatus, result) {
103
+ try {
104
+ // Get current GitHub state
105
+ const issue = await this.client.getIssue(issueNumber);
106
+ const isCurrentlyClosed = issue.state === 'closed';
107
+ // Check for mismatch
108
+ if (shouldBeClosed && !isCurrentlyClosed) {
109
+ // Should be closed but is open
110
+ result.mismatches++;
111
+ this.logger.log(` ❌ Issue #${issueNumber} (${context}): OPEN but should be CLOSED (status=${metadataStatus})`);
112
+ if (!this.dryRun) {
113
+ const comment = `## 🔄 Auto-Reconciled
114
+
115
+ This issue was closed by SpecWeave reconciliation.
116
+
117
+ **Reason**: Increment status is \`${metadataStatus}\` but GitHub issue was still open.
118
+
119
+ ---
120
+ 🤖 Auto-reconciled by SpecWeave`;
121
+ await this.client.closeIssue(issueNumber, comment);
122
+ result.closed++;
123
+ this.logger.log(` ✅ Closed issue #${issueNumber}`);
124
+ }
125
+ else {
126
+ this.logger.log(` [DRY RUN] Would close issue #${issueNumber}`);
127
+ }
128
+ result.details.push({
129
+ incrementId: context,
130
+ action: this.dryRun ? 'skip' : 'close',
131
+ issueNumber,
132
+ reason: `Status=${metadataStatus}, GH=open`,
133
+ });
134
+ }
135
+ else if (shouldBeOpen && isCurrentlyClosed) {
136
+ // Should be open but is closed
137
+ result.mismatches++;
138
+ this.logger.log(` ❌ Issue #${issueNumber} (${context}): CLOSED but should be OPEN (status=${metadataStatus})`);
139
+ if (!this.dryRun) {
140
+ const comment = `## 🔄 Auto-Reopened
141
+
142
+ This issue was reopened by SpecWeave reconciliation.
143
+
144
+ **Reason**: Increment status is \`${metadataStatus}\` but GitHub issue was closed.
145
+
146
+ This typically happens when:
147
+ - Increment was resumed after being paused/completed
148
+ - Manual status change in metadata.json
149
+
150
+ ---
151
+ 🤖 Auto-reconciled by SpecWeave`;
152
+ await this.client.reopenIssue(issueNumber, comment);
153
+ result.reopened++;
154
+ this.logger.log(` ✅ Reopened issue #${issueNumber}`);
155
+ }
156
+ else {
157
+ this.logger.log(` [DRY RUN] Would reopen issue #${issueNumber}`);
158
+ }
159
+ result.details.push({
160
+ incrementId: context,
161
+ action: this.dryRun ? 'skip' : 'reopen',
162
+ issueNumber,
163
+ reason: `Status=${metadataStatus}, GH=closed`,
164
+ });
165
+ }
166
+ else {
167
+ // State matches - no action needed
168
+ this.logger.log(` ✅ Issue #${issueNumber} (${context}): State matches (${isCurrentlyClosed ? 'closed' : 'open'})`);
169
+ }
170
+ }
171
+ catch (error) {
172
+ result.errors.push(`Issue #${issueNumber}: ${error.message}`);
173
+ result.details.push({
174
+ incrementId: context,
175
+ action: 'error',
176
+ issueNumber,
177
+ reason: error.message,
178
+ });
179
+ this.logger.error(` ⚠️ Error checking issue #${issueNumber}: ${error.message}`);
180
+ }
181
+ }
182
+ /**
183
+ * Scan all non-archived increments and extract GitHub state
184
+ */
185
+ async scanIncrements() {
186
+ const incrementsDir = path.join(this.projectRoot, '.specweave/increments');
187
+ const results = [];
188
+ if (!existsSync(incrementsDir)) {
189
+ return results;
190
+ }
191
+ const entries = await fs.readdir(incrementsDir, { withFileTypes: true });
192
+ for (const entry of entries) {
193
+ // Skip non-directories and archive
194
+ if (!entry.isDirectory() || entry.name === '_archive' || entry.name.startsWith('.')) {
195
+ continue;
196
+ }
197
+ const incrementPath = path.join(incrementsDir, entry.name);
198
+ const metadataPath = path.join(incrementPath, 'metadata.json');
199
+ if (!existsSync(metadataPath)) {
200
+ continue;
201
+ }
202
+ try {
203
+ const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf-8'));
204
+ const state = {
205
+ incrementId: entry.name,
206
+ incrementPath,
207
+ metadataStatus: metadata.status || 'unknown',
208
+ featureId: metadata.feature_id,
209
+ userStoryIssues: [],
210
+ };
211
+ // Extract main issue
212
+ if (metadata.github?.issue) {
213
+ state.mainIssue = {
214
+ number: metadata.github.issue,
215
+ url: metadata.github.url,
216
+ };
217
+ }
218
+ // Extract User Story issues from metadata
219
+ if (metadata.github?.issues && Array.isArray(metadata.github.issues)) {
220
+ for (const issue of metadata.github.issues) {
221
+ if (issue.userStory && issue.number) {
222
+ state.userStoryIssues.push({
223
+ userStoryId: issue.userStory,
224
+ issueNumber: issue.number,
225
+ });
226
+ }
227
+ }
228
+ }
229
+ // FALLBACK: Search GitHub if metadata doesn't have issues stored
230
+ // This handles cases where issues were created but not recorded in metadata.json
231
+ if (state.userStoryIssues.length === 0 && state.featureId) {
232
+ // Check if we have user_stories array (indicates issues might exist)
233
+ const userStories = metadata.user_stories || [];
234
+ if (userStories.length > 0 && this.client) {
235
+ this.logger.log(` 🔍 Searching GitHub for ${state.featureId} issues (not in metadata)...`);
236
+ try {
237
+ // Search for all issues matching the feature pattern
238
+ const foundIssues = await this.client.searchIssuesByFeature(state.featureId);
239
+ for (const issue of foundIssues) {
240
+ // Extract user story ID from title: [FS-063][US-001] Title
241
+ const match = issue.title.match(/\[([A-Z]+-\d+)\]\[([A-Z]+-\d+)\]/);
242
+ if (match && match[1] === state.featureId) {
243
+ const usId = match[2];
244
+ state.userStoryIssues.push({
245
+ userStoryId: usId,
246
+ issueNumber: issue.number,
247
+ });
248
+ }
249
+ }
250
+ if (state.userStoryIssues.length > 0) {
251
+ this.logger.log(` Found ${state.userStoryIssues.length} issue(s) via GitHub search`);
252
+ }
253
+ }
254
+ catch (error) {
255
+ this.logger.log(` ⚠️ GitHub search failed: ${error.message}`);
256
+ }
257
+ }
258
+ }
259
+ // Only include if has GitHub links
260
+ if (state.mainIssue || state.userStoryIssues.length > 0) {
261
+ results.push(state);
262
+ }
263
+ }
264
+ catch (error) {
265
+ // Skip invalid metadata
266
+ this.logger.log(` ⚠️ Skipping ${entry.name}: Invalid metadata.json`);
267
+ }
268
+ }
269
+ return results;
270
+ }
271
+ /**
272
+ * Initialize GitHub client
273
+ */
274
+ async initClient() {
275
+ const repoInfo = await GitHubClientV2.detectRepo(this.projectRoot);
276
+ if (!repoInfo) {
277
+ throw new Error('Could not detect GitHub repository. Ensure you have a git remote configured.');
278
+ }
279
+ this.client = GitHubClientV2.fromRepo(repoInfo.owner, repoInfo.repo);
280
+ this.logger.log(`🔗 GitHub repository: ${repoInfo.owner}/${repoInfo.repo}`);
281
+ }
282
+ /**
283
+ * Load config
284
+ */
285
+ async loadConfig() {
286
+ const configPath = path.join(this.projectRoot, '.specweave/config.json');
287
+ if (!existsSync(configPath)) {
288
+ return {};
289
+ }
290
+ const content = await fs.readFile(configPath, 'utf-8');
291
+ return JSON.parse(content);
292
+ }
293
+ // ==========================================================================
294
+ // Static helpers for single-increment operations (used by hooks)
295
+ // ==========================================================================
296
+ /**
297
+ * Reopen all GitHub issues for an increment
298
+ * Called by post-increment-status-change.sh when resuming
299
+ */
300
+ static async reopenIncrementIssues(projectRoot, incrementId, reason, logger) {
301
+ const log = logger ?? consoleLogger;
302
+ const result = { reopened: 0, errors: [] };
303
+ try {
304
+ // Load metadata
305
+ const metadataPath = path.join(projectRoot, '.specweave/increments', incrementId, 'metadata.json');
306
+ if (!existsSync(metadataPath)) {
307
+ result.errors.push('metadata.json not found');
308
+ return result;
309
+ }
310
+ const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf-8'));
311
+ // Initialize client
312
+ const repoInfo = await GitHubClientV2.detectRepo(projectRoot);
313
+ if (!repoInfo) {
314
+ result.errors.push('Could not detect GitHub repository');
315
+ return result;
316
+ }
317
+ const client = GitHubClientV2.fromRepo(repoInfo.owner, repoInfo.repo);
318
+ const comment = `## ▶️ Increment Resumed
319
+
320
+ This issue was reopened because increment \`${incrementId}\` was resumed.
321
+
322
+ **Reason**: ${reason}
323
+
324
+ ---
325
+ 🤖 Auto-reopened by SpecWeave`;
326
+ // Reopen main issue
327
+ if (metadata.github?.issue) {
328
+ try {
329
+ const issue = await client.getIssue(metadata.github.issue);
330
+ if (issue.state === 'closed') {
331
+ await client.reopenIssue(metadata.github.issue, comment);
332
+ result.reopened++;
333
+ log.log(` ✅ Reopened main issue #${metadata.github.issue}`);
334
+ }
335
+ }
336
+ catch (error) {
337
+ result.errors.push(`Main issue: ${error.message}`);
338
+ }
339
+ }
340
+ // Reopen User Story issues
341
+ if (metadata.github?.issues && Array.isArray(metadata.github.issues)) {
342
+ for (const usIssue of metadata.github.issues) {
343
+ if (usIssue.number) {
344
+ try {
345
+ const issue = await client.getIssue(usIssue.number);
346
+ if (issue.state === 'closed') {
347
+ await client.reopenIssue(usIssue.number, comment);
348
+ result.reopened++;
349
+ log.log(` ✅ Reopened User Story issue #${usIssue.number}`);
350
+ }
351
+ }
352
+ catch (error) {
353
+ result.errors.push(`Issue #${usIssue.number}: ${error.message}`);
354
+ }
355
+ }
356
+ }
357
+ }
358
+ return result;
359
+ }
360
+ catch (error) {
361
+ result.errors.push(error.message);
362
+ return result;
363
+ }
364
+ }
365
+ /**
366
+ * Close all GitHub issues for an abandoned increment
367
+ * Called by post-increment-status-change.sh when abandoning
368
+ */
369
+ static async closeAbandonedIncrementIssues(projectRoot, incrementId, reason, logger) {
370
+ const log = logger ?? consoleLogger;
371
+ const result = { closed: 0, errors: [] };
372
+ try {
373
+ // Load metadata
374
+ const metadataPath = path.join(projectRoot, '.specweave/increments', incrementId, 'metadata.json');
375
+ if (!existsSync(metadataPath)) {
376
+ result.errors.push('metadata.json not found');
377
+ return result;
378
+ }
379
+ const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf-8'));
380
+ // Initialize client
381
+ const repoInfo = await GitHubClientV2.detectRepo(projectRoot);
382
+ if (!repoInfo) {
383
+ result.errors.push('Could not detect GitHub repository');
384
+ return result;
385
+ }
386
+ const client = GitHubClientV2.fromRepo(repoInfo.owner, repoInfo.repo);
387
+ const comment = `## 🗑️ Increment Abandoned
388
+
389
+ This issue was closed because increment \`${incrementId}\` was abandoned.
390
+
391
+ **Reason**: ${reason}
392
+
393
+ ---
394
+ 🤖 Auto-closed by SpecWeave`;
395
+ // Close main issue
396
+ if (metadata.github?.issue) {
397
+ try {
398
+ const issue = await client.getIssue(metadata.github.issue);
399
+ if (issue.state === 'open') {
400
+ await client.closeIssue(metadata.github.issue, comment);
401
+ result.closed++;
402
+ log.log(` ✅ Closed main issue #${metadata.github.issue}`);
403
+ }
404
+ }
405
+ catch (error) {
406
+ result.errors.push(`Main issue: ${error.message}`);
407
+ }
408
+ }
409
+ // Close User Story issues
410
+ if (metadata.github?.issues && Array.isArray(metadata.github.issues)) {
411
+ for (const usIssue of metadata.github.issues) {
412
+ if (usIssue.number) {
413
+ try {
414
+ const issue = await client.getIssue(usIssue.number);
415
+ if (issue.state === 'open') {
416
+ await client.closeIssue(usIssue.number, comment);
417
+ result.closed++;
418
+ log.log(` ✅ Closed User Story issue #${usIssue.number}`);
419
+ }
420
+ }
421
+ catch (error) {
422
+ result.errors.push(`Issue #${usIssue.number}: ${error.message}`);
423
+ }
424
+ }
425
+ }
426
+ }
427
+ return result;
428
+ }
429
+ catch (error) {
430
+ result.errors.push(error.message);
431
+ return result;
432
+ }
433
+ }
434
+ }
435
+ //# sourceMappingURL=github-reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-reconciler.js","sourceRoot":"","sources":["../../../src/sync/github-reconciler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: specweave-github:reconcile
3
+ description: Reconcile GitHub issue states with increment statuses. Fixes drift by closing issues for completed increments and reopening issues for resumed increments.
4
+ ---
5
+
6
+ # GitHub Status Reconciliation
7
+
8
+ Scan all increments and fix any drift between local metadata.json status and GitHub issue states.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /specweave-github:reconcile [options]
14
+ ```
15
+
16
+ ## Options
17
+
18
+ - `--dry-run`: Preview changes without making them
19
+ - `--verbose`: Show detailed output for each issue checked
20
+
21
+ ## What It Does
22
+
23
+ 1. **Scans** all non-archived increments
24
+ 2. **Compares** metadata.json status with GitHub issue state
25
+ 3. **Fixes** mismatches:
26
+ - `metadata=completed` + `GH=open` → **Close** the issue
27
+ - `metadata=in-progress` + `GH=closed` → **Reopen** the issue
28
+
29
+ ## When to Use
30
+
31
+ - After manual metadata.json edits
32
+ - After git pulls that changed increment statuses
33
+ - When you notice open issues for completed work
34
+ - As a periodic health check
35
+
36
+ ## Implementation
37
+
38
+ Run the reconciliation using the GitHubReconciler:
39
+
40
+ ```typescript
41
+ import { GitHubReconciler } from '../../../src/sync/github-reconciler.js';
42
+
43
+ const reconciler = new GitHubReconciler({
44
+ projectRoot: process.cwd(),
45
+ dryRun: args.includes('--dry-run'),
46
+ });
47
+
48
+ const result = await reconciler.reconcile();
49
+
50
+ // Report results
51
+ console.log(`\nReconciliation complete:`);
52
+ console.log(` Scanned: ${result.scanned} increments`);
53
+ console.log(` Fixed: ${result.closed} closed, ${result.reopened} reopened`);
54
+ if (result.errors.length > 0) {
55
+ console.log(` Errors: ${result.errors.length}`);
56
+ }
57
+ ```
58
+
59
+ ## Example Output
60
+
61
+ ```
62
+ 📊 Scanning 5 increment(s) for GitHub state drift...
63
+
64
+ ✅ Issue #765 (0056-plugin-fix/US-001): State matches (open)
65
+ ❌ Issue #771 (0066-import-wizard/US-003): OPEN but should be CLOSED (status=completed)
66
+ ✅ Closed issue #771
67
+ ❌ Issue #763 (0063-multi-repo/US-001): CLOSED but should be OPEN (status=in-progress)
68
+ ✅ Reopened issue #763
69
+
70
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
71
+ 📊 RECONCILIATION SUMMARY
72
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
73
+ Increments scanned: 5
74
+ Mismatches found: 2
75
+ Issues closed: 1
76
+ Issues reopened: 1
77
+ Errors: 0
78
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
79
+ ```
80
+
81
+ ## Dry Run Mode
82
+
83
+ ```bash
84
+ /specweave-github:reconcile --dry-run
85
+ ```
86
+
87
+ Shows what would be changed without making any modifications:
88
+
89
+ ```
90
+ ❌ Issue #771 (0066-import-wizard/US-003): OPEN but should be CLOSED
91
+ [DRY RUN] Would close issue #771
92
+
93
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
94
+ 📊 RECONCILIATION SUMMARY
95
+ ⚠️ DRY RUN - No changes were made
96
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
97
+ ```
98
+
99
+ ## Requirements
100
+
101
+ - GitHub CLI (`gh`) installed and authenticated
102
+ - `sync.github.enabled = true` in config.json
103
+ - `sync.settings.canUpdateExternalItems = true` in config.json
104
+
105
+ ## Related Commands
106
+
107
+ - `/specweave-github:status`: View sync status for increments
108
+ - `/specweave-github:sync`: Manual sync to GitHub
109
+ - `/specweave:done`: Close increment (triggers auto-close)
110
+ - `/specweave:resume`: Resume increment (now triggers auto-reopen)