specweave 0.26.4 → 0.26.9
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.
- package/CLAUDE.md +154 -4
- package/bin/specweave.js +15 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.js +2 -2
- package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +28 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +191 -19
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +3 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +25 -2
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -1
- package/dist/src/cli/commands/archive.d.ts +10 -0
- package/dist/src/cli/commands/archive.d.ts.map +1 -0
- package/dist/src/cli/commands/archive.js +78 -0
- package/dist/src/cli/commands/archive.js.map +1 -0
- package/dist/src/cli/commands/init.js +2 -2
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js +48 -8
- package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
- package/dist/src/core/increment/increment-reopener.d.ts.map +1 -1
- package/dist/src/core/increment/increment-reopener.js +13 -14
- package/dist/src/core/increment/increment-reopener.js.map +1 -1
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +19 -0
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts +85 -0
- package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -0
- package/dist/src/core/increment/status-change-sync-trigger.js +137 -0
- package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -0
- package/dist/src/core/increment/sync-circuit-breaker.d.ts +64 -0
- package/dist/src/core/increment/sync-circuit-breaker.d.ts.map +1 -0
- package/dist/src/core/increment/sync-circuit-breaker.js +95 -0
- package/dist/src/core/increment/sync-circuit-breaker.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +12 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +157 -24
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/init/repo/types.d.ts +1 -1
- package/package.json +2 -2
- package/plugins/specweave/agents/pm/AGENT.md +13 -7
- package/plugins/specweave/commands/sync-diagnostics.md +227 -0
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +20 -8
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +19 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/skills/brownfield-analyzer/SKILL.md +267 -868
- package/plugins/specweave/skills/increment-planner/SKILL.md +379 -1245
- package/plugins/specweave/skills/role-orchestrator/SKILL.md +293 -969
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-docs/skills/technical-writing/SKILL.md +333 -839
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1080 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/completion-calculator.js +1 -1
- package/plugins/specweave-github/lib/completion-calculator.ts +2 -2
- package/plugins/specweave-github/lib/github-feature-sync.js +152 -18
- package/plugins/specweave-github/lib/github-feature-sync.ts +225 -22
- package/plugins/specweave-github/lib/user-story-issue-builder.js +21 -1
- package/plugins/specweave-github/lib/user-story-issue-builder.ts +31 -3
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +981 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/plugins/specweave-testing/skills/tdd-expert/SKILL.md +269 -749
- package/plugins/specweave-testing/skills/unit-testing-expert/SKILL.md +318 -810
package/CLAUDE.md
CHANGED
|
@@ -14,6 +14,8 @@ For **contributors to SpecWeave itself** (not users).
|
|
|
14
14
|
|
|
15
15
|
**NEVER run commands you know will fail.** Act on reasoning BEFORE execution.
|
|
16
16
|
|
|
17
|
+
**Context Management**: Active increment with 10+ tasks + editing unrelated 2000+ line file = crash risk (context overflow). Pause first: `/specweave:pause XXXX` → edit → `/specweave:resume XXXX`. See ADR-0133, Section 15.
|
|
18
|
+
|
|
17
19
|
```bash
|
|
18
20
|
# ❌ WRONG: node -e "require('./dist/file.js')" (before build)
|
|
19
21
|
# ✅ CORRECT: npm run rebuild && node -e "require('./dist/file.js')"
|
|
@@ -69,11 +71,36 @@ bash scripts/refresh-marketplace.sh --local # Local dev only (filesystem coupli
|
|
|
69
71
|
3. `README.md` (optional)
|
|
70
72
|
|
|
71
73
|
**Inside increment folders - ONLY at root**: `spec.md`, `plan.md`, `tasks.md`, `metadata.json`
|
|
72
|
-
|
|
74
|
+
|
|
75
|
+
**Everything else → subfolders**:
|
|
76
|
+
- `reports/` - Completion reports, investigation findings, final summaries
|
|
77
|
+
- `scripts/` - Helper scripts, automation, migration tools
|
|
78
|
+
- `logs/` - Debug logs, performance logs, execution traces
|
|
79
|
+
- `backups/` - Backup files, .backup versions
|
|
80
|
+
- `docs/` - Additional documentation, diagrams, references
|
|
81
|
+
|
|
82
|
+
**Examples**:
|
|
83
|
+
```
|
|
84
|
+
0055-feature/
|
|
85
|
+
├── spec.md ✅ Required
|
|
86
|
+
├── plan.md ✅ Required
|
|
87
|
+
├── tasks.md ✅ Required
|
|
88
|
+
├── metadata.json ✅ Required
|
|
89
|
+
├── reports/ ✅ Good organization
|
|
90
|
+
│ ├── completion-summary.md
|
|
91
|
+
│ └── FINAL-REPORT.md
|
|
92
|
+
├── scripts/ ✅ Good organization
|
|
93
|
+
│ └── migration.sh
|
|
94
|
+
└── backups/ ✅ Good organization
|
|
95
|
+
└── SKILL.md.backup
|
|
96
|
+
```
|
|
73
97
|
|
|
74
98
|
```bash
|
|
75
99
|
# Validation (should output NOTHING):
|
|
76
100
|
ls -1 .specweave/increments/ | grep -v "^[0-9]" | grep -v "^_archive" | grep -v "^README.md"
|
|
101
|
+
|
|
102
|
+
# Check for misplaced files in increment roots:
|
|
103
|
+
find .specweave/increments -maxdepth 2 -type f ! -name "spec.md" ! -name "plan.md" ! -name "tasks.md" ! -name "metadata.json" | grep -E "/[0-9]{4}-"
|
|
77
104
|
```
|
|
78
105
|
|
|
79
106
|
---
|
|
@@ -264,6 +291,39 @@ ls .specweave/docs/internal/architecture/adr/*.md | grep -E '/[0-9]{4}-' | \
|
|
|
264
291
|
|
|
265
292
|
**Agent naming**: `{plugin}:{directory}:{yaml-name}`
|
|
266
293
|
|
|
294
|
+
### Skills Must NOT Spawn Large Content-Generating Agents (ADR-0133)
|
|
295
|
+
|
|
296
|
+
**CRITICAL**: Skills spawning agents via `Task()` causes Claude Code crashes due to context explosion.
|
|
297
|
+
|
|
298
|
+
**Problem**: Skill (1500 lines) + Agent (600 lines) + Agent output (2000+ lines) = 4000+ lines in memory = CRASH 💥
|
|
299
|
+
|
|
300
|
+
**❌ FORBIDDEN**:
|
|
301
|
+
```typescript
|
|
302
|
+
// In a skill SKILL.md:
|
|
303
|
+
Task({
|
|
304
|
+
subagent_type: "specweave:architect:architect", // ❌ Generates 1000-3000 lines
|
|
305
|
+
subagent_type: "specweave:pm:pm", // ❌ Generates 500-2000 lines
|
|
306
|
+
subagent_type: "specweave:test-aware-planner", // ❌ Generates 500-1500 lines
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**✅ CORRECT**:
|
|
311
|
+
```typescript
|
|
312
|
+
// Skills create templates and guide users:
|
|
313
|
+
1. Create basic templates (< 50 lines each)
|
|
314
|
+
2. Output: "Tell Claude: 'Complete the spec for increment 0005-feature'"
|
|
315
|
+
3. Agents activate in MAIN context (not nested) = SAFE
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**When to use Task() from skills**:
|
|
319
|
+
- ✅ Small utility agents (output < 200 lines)
|
|
320
|
+
- ✅ Data processing agents (no large generation)
|
|
321
|
+
- ❌ Content generators (specs, ADRs, plans, tasks)
|
|
322
|
+
|
|
323
|
+
**Main Context Pattern**: Same explosion occurs when editing files outside active increments. Large increment spec (800+ lines) + unrelated file edit (2000+ lines) + tool invocation (AskUserQuestion) = crash. Solution: Pause increment before editing unrelated files (see Section 0).
|
|
324
|
+
|
|
325
|
+
**Reference**: ADR-0133, Architect crash incident (2025-11-24, Increment 0052); Context explosion incident (2025-11-24, Increment 0058, init.ts edit)
|
|
326
|
+
|
|
267
327
|
---
|
|
268
328
|
|
|
269
329
|
## 16. YAML Frontmatter
|
|
@@ -307,6 +367,94 @@ const result = await provider.validateRepository('owner', 'repo', token);
|
|
|
307
367
|
|
|
308
368
|
---
|
|
309
369
|
|
|
370
|
+
## Sync Orchestration Architecture (v0.26.3+)
|
|
371
|
+
|
|
372
|
+
### **How GitHub Issue Sync Works**
|
|
373
|
+
|
|
374
|
+
**3-Phase Sync Flow**:
|
|
375
|
+
```
|
|
376
|
+
TodoWrite → Hook → US Completion Orchestrator → Living Docs Sync → External Tool Sync → GitHub Issues Updated
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Phase 1: Task Completion Detection**
|
|
380
|
+
- User marks task complete via `TodoWrite`
|
|
381
|
+
- `post-task-completion.sh` fires (sets `SKIP_GITHUB_SYNC=true` to prevent duplicate syncs)
|
|
382
|
+
- `consolidated-sync.js` runs 6 operations sequentially
|
|
383
|
+
|
|
384
|
+
**Phase 2: US Completion Orchestration**
|
|
385
|
+
- `syncCompletedUserStories()` (operation 5 of 6) detects newly completed user stories
|
|
386
|
+
- Checks if all ACs for a US are complete (100% → status: "completed")
|
|
387
|
+
- **Throttle**: 60s window prevents spam (manual override: `/specweave:sync-progress`)
|
|
388
|
+
- If newly completed USs found → triggers Phase 3
|
|
389
|
+
|
|
390
|
+
**Phase 3: External Tool Sync**
|
|
391
|
+
- `LivingDocsSync.syncIncrement()` called
|
|
392
|
+
- `detectExternalTools()` checks **3 levels** for GitHub config:
|
|
393
|
+
- **Level 1**: `metadata.json` (increment-cached links)
|
|
394
|
+
- **Level 2**: `config.json` - **4 detection methods** (ADR-0137):
|
|
395
|
+
- Method 1: `config.sync.github.enabled` ← **Most common (60% of users)**
|
|
396
|
+
- Method 2: `config.sync.profiles[activeProfile]` ← Multi-profile setups
|
|
397
|
+
- Method 3: `config.multiProject.projects[project].externalTools.github` ← Multi-project
|
|
398
|
+
- Method 4: `config.plugins.settings['specweave-github']` ← Legacy
|
|
399
|
+
- **Level 3**: Environment variables (`GITHUB_TOKEN` + `GITHUB_OWNER`/`GITHUB_REPOSITORY`)
|
|
400
|
+
- If GitHub detected → `syncToGitHub()` → `GitHubFeatureSync.syncFeatureToGitHub()`
|
|
401
|
+
- Updates GitHub issues with completed AC checkboxes
|
|
402
|
+
|
|
403
|
+
### **GitHub Configuration (Required)**
|
|
404
|
+
|
|
405
|
+
**Recommended Setup (Pattern 1 - Simplest)**:
|
|
406
|
+
```json
|
|
407
|
+
// .specweave/config.json
|
|
408
|
+
{
|
|
409
|
+
"sync": {
|
|
410
|
+
"github": {
|
|
411
|
+
"enabled": true,
|
|
412
|
+
"owner": "your-org",
|
|
413
|
+
"repo": "your-repo"
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Plus `.env`**:
|
|
420
|
+
```bash
|
|
421
|
+
GITHUB_TOKEN=ghp_your_token_here
|
|
422
|
+
GITHUB_OWNER=your-org # Optional if in config.json
|
|
423
|
+
GITHUB_REPO=your-repo # Optional if in config.json
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Diagnostic**: Run `node dist/test-github-detection.js` to verify detection (create this file if needed)
|
|
427
|
+
|
|
428
|
+
### **Troubleshooting Sync Issues**
|
|
429
|
+
|
|
430
|
+
**Issue**: GitHub issues not updating after US completion
|
|
431
|
+
**Diagnosis**:
|
|
432
|
+
```bash
|
|
433
|
+
# 1. Check detection
|
|
434
|
+
grep "External tools detected" .specweave/logs/hooks-debug.log | tail -5
|
|
435
|
+
# Should see: "📡 External tools detected: github"
|
|
436
|
+
|
|
437
|
+
# 2. Check config
|
|
438
|
+
cat .specweave/config.json | jq '.sync.github'
|
|
439
|
+
# Should have: enabled: true, owner: "...", repo: "..."
|
|
440
|
+
|
|
441
|
+
# 3. Check throttle
|
|
442
|
+
grep "throttled" .specweave/logs/hooks-debug.log | tail -3
|
|
443
|
+
# If throttled → wait 60s OR run: /specweave:sync-progress
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Issue**: Throttle blocking sync
|
|
447
|
+
**Solution**: Manual sync (bypasses throttle):
|
|
448
|
+
```bash
|
|
449
|
+
/specweave:sync-progress 0054 # Sync specific increment
|
|
450
|
+
/specweave-github:sync FS-054 # Sync entire feature
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Issue**: Detection not finding GitHub config
|
|
454
|
+
**Fix**: ADR-0137 enhanced detection (v0.26.3+)
|
|
455
|
+
- Checks 4 config locations + env vars
|
|
456
|
+
- Update to latest version: `npm update specweave`
|
|
457
|
+
|
|
310
458
|
## Hook Performance & Safety
|
|
311
459
|
|
|
312
460
|
**Emergency**: `export SPECWEAVE_DISABLE_HOOKS=1` → `rm -f .specweave/state/.hook-*` → `npm run rebuild`
|
|
@@ -316,6 +464,7 @@ const result = await provider.validateRepository('owner', 'repo', token);
|
|
|
316
464
|
**Targets**: <100ms, 0-2 processes, 0 breaker trips
|
|
317
465
|
|
|
318
466
|
**Critical Fixes**:
|
|
467
|
+
- v0.26.3: **Multi-location GitHub config detection!** (ADR-0137) → Checks 4 config patterns + env vars
|
|
319
468
|
- v0.26.1: **Automatic US sync restored!** `SKIP_US_SYNC` removed → Smart throttle (60s window) → fs.writeFile() validated safe
|
|
320
469
|
- v0.25.2: `SKIP_EXTERNAL_SYNC` guard at LivingDocsSync layer → prevents recursion cascade
|
|
321
470
|
- v0.25.1: TodoWrite crash → emergency `SKIP_US_SYNC=true` → manual `/specweave:sync-progress` (temporary fix)
|
|
@@ -455,12 +604,13 @@ plugins/ # Skills, agents, commands, hooks
|
|
|
455
604
|
|
|
456
605
|
**Remember**:
|
|
457
606
|
1. Push → GitHub → auto-updates (5-10s)
|
|
458
|
-
2. Keep
|
|
607
|
+
2. **Keep increment roots clean**: Only spec.md, plan.md, tasks.md, metadata.json. Everything else in subfolders (reports/, scripts/, logs/, backups/, docs/)
|
|
459
608
|
3. Test before commit
|
|
460
609
|
4. NEVER delete `.specweave/`
|
|
461
610
|
5. Use `/specweave:done` (not manual edits)
|
|
462
611
|
6. ALWAYS use GitHub mode for marketplace refresh (unless actively developing uncommitted changes)
|
|
463
612
|
7. tasks.md + spec.md are SOURCE OF TRUTH (not internal TODO)
|
|
613
|
+
8. Pause large increments (10+ tasks) before editing unrelated files to prevent crashes
|
|
464
614
|
|
|
465
615
|
**See**: `.github/CONTRIBUTING.md`, https://spec-weave.com
|
|
466
616
|
|
|
@@ -470,8 +620,8 @@ plugins/ # Skills, agents, commands, hooks
|
|
|
470
620
|
|
|
471
621
|
**ADRs**: 0032 (GitHub Hierarchy), 0050 (Config Management), 0051 (Caching), 0060 (Hook Optimization), 0061 (No Increment References), 0064 (AC Presence), 0069 (Git Provider Abstraction), 0070 (Hook Consolidation), 0129 (US Sync Guard Rails), 0132 (No Early Returns)
|
|
472
622
|
|
|
473
|
-
**Emergency Procedures**: `.specweave/docs/internal/emergency-procedures/HOOK-CRASH-RECOVERY.md`, `TODOWRITE-CRASH-RECOVERY.md`, `AC-SYNC-CONFLICT-FIX-2025-11-24.md`
|
|
623
|
+
**Emergency Procedures**: `.specweave/docs/internal/emergency-procedures/HOOK-CRASH-RECOVERY.md`, `TODOWRITE-CRASH-RECOVERY.md`, `AC-SYNC-CONFLICT-FIX-2025-11-24.md`, `CONTEXT-EXPLOSION-PREVENTION.md`
|
|
474
624
|
|
|
475
|
-
**Incident Reports**: See increment 0044 (TODO desync), 0047 (GitHub sync removal), 0050 (Hook crashes, AC presence, GitHub issues), 0051 (PROJECT_ROOT order), 0053 (Safe deletion, TodoWrite crash, AC parser, GitHub multi-repo)
|
|
625
|
+
**Incident Reports**: See increment 0044 (TODO desync), 0047 (GitHub sync removal), 0050 (Hook crashes, AC presence, GitHub issues), 0051 (PROJECT_ROOT order), 0053 (Safe deletion, TodoWrite crash, AC parser, GitHub multi-repo), 0058 (Context explosion, init.ts edit crash)
|
|
476
626
|
|
|
477
627
|
**Validation Scripts**: `validate-marketplace-plugins.sh`, `validate-plugin-directories.sh`, `validate-hook-variable-order.sh`, `cleanup-duplicate-github-issues.sh`
|
package/bin/specweave.js
CHANGED
|
@@ -104,6 +104,21 @@ program
|
|
|
104
104
|
await abandonCommand(incrementId, options);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
// Archive command - Archive completed increments and sync living docs
|
|
108
|
+
program
|
|
109
|
+
.command('archive [increments...]')
|
|
110
|
+
.description('Archive completed increments and sync living docs (_features/ + project-specific)')
|
|
111
|
+
.option('--keep-last <n>', 'Keep last N increments, archive the rest', '10')
|
|
112
|
+
.option('--older-than <days>', 'Archive increments older than N days')
|
|
113
|
+
.option('--pattern <pattern>', 'Archive increments matching pattern (regex)')
|
|
114
|
+
.option('--archive-completed', 'Archive all completed increments')
|
|
115
|
+
.option('--no-preserve-active', 'Allow archiving active/paused increments (dangerous!)')
|
|
116
|
+
.option('--dry-run', 'Preview what would be archived without moving files')
|
|
117
|
+
.action(async (incrementIds, options) => {
|
|
118
|
+
const { archiveCommand } = await import('../dist/src/cli/commands/archive.js');
|
|
119
|
+
await archiveCommand(incrementIds, options);
|
|
120
|
+
});
|
|
121
|
+
|
|
107
122
|
// Delete feature command - Registered dynamically in startup
|
|
108
123
|
// (See registerDeleteFeatureCommand call below)
|
|
109
124
|
|
|
@@ -169,8 +169,8 @@ export class CompletionCalculator {
|
|
|
169
169
|
const taskId = match[1];
|
|
170
170
|
const taskTitle = match[2].trim();
|
|
171
171
|
const taskBody = match[3];
|
|
172
|
-
// Extract AC list
|
|
173
|
-
const acMatch = taskBody.match(/\*\*AC\*\*:\s*([^\n]+)/);
|
|
172
|
+
// Extract AC list (support both old and new field names)
|
|
173
|
+
const acMatch = taskBody.match(/\*\*(?:Satisfies ACs?|AC)\*\*:\s*([^\n]+)/);
|
|
174
174
|
if (!acMatch) {
|
|
175
175
|
continue; // Skip tasks without AC field
|
|
176
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion-calculator.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/completion-calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAsD7B,MAAM,OAAO,oBAAoB;IAG/B,YAAY,WAAmB;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,mBAAmB,CAAC,aAAqB;QAC7C,oCAAoC;QACpC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAE5D,sCAAsC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAEpD,mDAAmD;QACnD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;QAE/D,4BAA4B;QAC5B,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;QAC7D,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;QAE/D,uCAAuC;QACvC,aAAa;QACb,0CAA0C;QAC1C,sBAAsB;QACtB,6DAA6D;QAC7D,MAAM,eAAe,GACnB,GAAG,CAAC,MAAM,GAAG,CAAC;YACd,YAAY,KAAK,GAAG,CAAC,MAAM;YAC3B,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC;QAE1D,OAAO;YACL,QAAQ,EAAE,GAAG,CAAC,MAAM;YACpB,YAAY;YACZ,aAAa,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACrE,UAAU,EAAE,KAAK,CAAC,MAAM;YACxB,cAAc;YACd,eAAe,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7E,eAAe;YACf,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClE,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,yBAAyB,CAAC,OAAe;QAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAErD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAyB,CAAC;IACtD,CAAC;IAED;;;;;;;;;;;OAWG;IACK,yBAAyB,CAAC,OAAe;QAC/C,MAAM,QAAQ,GAAyB,EAAE,CAAC;QAE1C,yCAAyC;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAErF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAE7B,sCAAsC;QACtC,4CAA4C;QAC5C,yCAAyC;QACzC,MAAM,qBAAqB,GACzB,mFAAmF,CAAC;QAEtF,wCAAwC;QACxC,wCAAwC;QACxC,MAAM,mBAAmB,GACvB,uEAAuE,CAAC;QAE1E,oCAAoC;QACpC,IAAI,KAAK,CAAC;QACV,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAChE,QAAQ,GAAG,IAAI,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,gCAAgC;gBAC9C,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC5B,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,qCAAqC;aACnE,CAAC,CAAC;QACL,CAAC;QAED,yDAAyD;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC9D,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,gCAAgC;oBAC9C,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;oBAC5B,SAAS,EAAE,KAAK,EAAE,2BAA2B;iBAC9C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,YAAY,CAAC,gBAAwB,EAAE,WAAmB;QACtE,MAAM,KAAK,GAAW,EAAE,CAAC;QAEzB,wDAAwD;QACxD,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAE3F,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,CAAC,wBAAwB;QACxC,CAAC;QAED,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAEjC,mDAAmD;QACnD,gEAAgE;QAChE,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAE9E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC,CAAC,sBAAsB;QACtC,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAEtC,mCAAmC;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,IAAI,CAAC,WAAW,EAChB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,CACX,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC,CAAC,gCAAgC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAExD,0DAA0D;QAC1D,WAAW;QACX,wBAAwB;QACxB,sBAAsB;QACtB,+DAA+D;QAC/D,+BAA+B;QAC/B,MAAM,WAAW,GAAG,8DAA8D,CAAC;QACnF,IAAI,KAAK,CAAC;QAEV,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAE1B,
|
|
1
|
+
{"version":3,"file":"completion-calculator.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/completion-calculator.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export declare class GitHubFeatureSync {
|
|
|
20
20
|
private specsDir;
|
|
21
21
|
private projectRoot;
|
|
22
22
|
private calculator;
|
|
23
|
+
private static syncLocks;
|
|
24
|
+
private static readonly LOCK_DURATION_MS;
|
|
23
25
|
constructor(client: GitHubClientV2, specsDir: string, projectRoot: string);
|
|
24
26
|
/**
|
|
25
27
|
* Sync Feature folder to GitHub (Milestone + User Story Issues)
|
|
@@ -54,7 +56,7 @@ export declare class GitHubFeatureSync {
|
|
|
54
56
|
*/
|
|
55
57
|
private findProjectFolders;
|
|
56
58
|
/**
|
|
57
|
-
* Create GitHub Milestone for Feature
|
|
59
|
+
* Create GitHub Milestone for Feature (with duplicate detection)
|
|
58
60
|
*/
|
|
59
61
|
private createMilestone;
|
|
60
62
|
/**
|
|
@@ -75,6 +77,31 @@ export declare class GitHubFeatureSync {
|
|
|
75
77
|
* This prevents Issue #574 type bugs (premature closure)
|
|
76
78
|
*/
|
|
77
79
|
private updateUserStoryIssue;
|
|
80
|
+
/**
|
|
81
|
+
* Update status labels on GitHub issue based on completion state
|
|
82
|
+
*
|
|
83
|
+
* SMART LABEL MANAGEMENT:
|
|
84
|
+
* - Only manages status:* labels (status:not_started, status:in-progress, status:completed)
|
|
85
|
+
* - Preserves all other labels (priority, type, custom labels)
|
|
86
|
+
* - Ensures exactly one status label is present
|
|
87
|
+
*/
|
|
88
|
+
private updateStatusLabels;
|
|
89
|
+
/**
|
|
90
|
+
* Post progress comment only if it differs from the last comment
|
|
91
|
+
*
|
|
92
|
+
* DEDUPLICATION FIX (2025-11-24):
|
|
93
|
+
* - Prevents posting identical consecutive comments
|
|
94
|
+
* - Fetches last comment from issue
|
|
95
|
+
* - Compares content (ignoring timestamps)
|
|
96
|
+
* - Only posts if progress has changed
|
|
97
|
+
*
|
|
98
|
+
* Root Cause: updateUserStoryIssue() was posting progress comments on EVERY sync,
|
|
99
|
+
* even when progress hadn't changed, causing 4+ duplicate comments.
|
|
100
|
+
*
|
|
101
|
+
* @param issueNumber - GitHub issue number
|
|
102
|
+
* @param completion - Completion status with AC/task metrics
|
|
103
|
+
*/
|
|
104
|
+
private postProgressCommentIfChanged;
|
|
78
105
|
/**
|
|
79
106
|
* Update FEATURE.md with GitHub Milestone link
|
|
80
107
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-feature-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-feature-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgCvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAuB;
|
|
1
|
+
{"version":3,"file":"github-feature-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-feature-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgCvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAuB;IAIzC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAkC;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAErC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAOzE;;;;;;;;OAQG;IACG,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QACpD,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IAkMF;;OAEG;YACW,iBAAiB;IAU/B;;OAEG;YACW,cAAc;IAW5B;;OAEG;YACW,eAAe;IA4C7B;;OAEG;YACW,kBAAkB;IAgBhC;;OAEG;YACW,eAAe;IA0D7B;;;;;;OAMG;YACW,oBAAoB;IA6DlC;;;;;;;;OAQG;YACW,oBAAoB;IAmElC;;;;;;;OAOG;YACW,kBAAkB;IAqEhC;;;;;;;;;;;;;;OAcG;YACW,4BAA4B;IA+D1C;;OAEG;YACW,eAAe;IA+B7B;;OAEG;YACW,0BAA0B;CA8BzC"}
|
|
@@ -39,6 +39,27 @@ export class GitHubFeatureSync {
|
|
|
39
39
|
* 4. Update frontmatter with GitHub issue links
|
|
40
40
|
*/
|
|
41
41
|
async syncFeatureToGitHub(featureId) {
|
|
42
|
+
// SYNC LOCK CHECK: Prevent concurrent/rapid syncs of the same feature
|
|
43
|
+
// Root cause: Two sync paths (task completion + status change) can fire simultaneously
|
|
44
|
+
// Result: Duplicate GitHub comments due to race condition
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const lastSync = GitHubFeatureSync.syncLocks.get(featureId);
|
|
47
|
+
if (lastSync && (now - lastSync) < GitHubFeatureSync.LOCK_DURATION_MS) {
|
|
48
|
+
const secondsRemaining = Math.ceil((GitHubFeatureSync.LOCK_DURATION_MS - (now - lastSync)) / 1000);
|
|
49
|
+
console.log(`\n⏭️ Sync already in progress for ${featureId} (or completed ${Math.floor((now - lastSync) / 1000)}s ago)`);
|
|
50
|
+
console.log(` ℹ️ Sync will be available in ${secondsRemaining}s to prevent duplicates`);
|
|
51
|
+
console.log(` 💡 This prevents race conditions between task completion and status change syncs`);
|
|
52
|
+
// Return placeholder result (sync was skipped, not failed)
|
|
53
|
+
return {
|
|
54
|
+
milestoneNumber: 0,
|
|
55
|
+
milestoneUrl: '',
|
|
56
|
+
issuesCreated: 0,
|
|
57
|
+
issuesUpdated: 0,
|
|
58
|
+
userStoriesProcessed: 0
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Acquire lock
|
|
62
|
+
GitHubFeatureSync.syncLocks.set(featureId, now);
|
|
42
63
|
console.log(`\n🔄 Syncing Feature ${featureId} to GitHub...`);
|
|
43
64
|
// 1. Load Feature FEATURE.md
|
|
44
65
|
const featureFolder = await this.findFeatureFolder(featureId);
|
|
@@ -147,14 +168,20 @@ export class GitHubFeatureSync {
|
|
|
147
168
|
}
|
|
148
169
|
// Update User Story frontmatter with issue link
|
|
149
170
|
await this.updateUserStoryFrontmatter(userStory.filePath, issueNumber);
|
|
171
|
+
// ✅ CRITICAL FIX (2025-11-24): Check completion for ALL issues (new AND reused)
|
|
172
|
+
// BUG: Previously only checked completion for reused issues, not new ones
|
|
173
|
+
// RESULT: New issues stayed OPEN even if status:complete
|
|
174
|
+
//
|
|
175
|
+
// Now we always call updateUserStoryIssue() which:
|
|
176
|
+
// 1. Calculates ACTUAL completion from [x] checkboxes
|
|
177
|
+
// 2. Closes issue if all ACs and tasks verified complete
|
|
178
|
+
// 3. Updates status labels automatically
|
|
179
|
+
await this.updateUserStoryIssue(issueNumber, issueContent, userStory.filePath);
|
|
150
180
|
// Update completion tracking
|
|
151
181
|
if (result.wasReused) {
|
|
152
|
-
// Update existing issue with latest content
|
|
153
|
-
await this.updateUserStoryIssue(issueNumber, issueContent, userStory.filePath);
|
|
154
182
|
issuesUpdated++;
|
|
155
183
|
}
|
|
156
184
|
else {
|
|
157
|
-
// New issue created
|
|
158
185
|
issuesCreated++;
|
|
159
186
|
}
|
|
160
187
|
}
|
|
@@ -246,10 +273,32 @@ export class GitHubFeatureSync {
|
|
|
246
273
|
return folders;
|
|
247
274
|
}
|
|
248
275
|
/**
|
|
249
|
-
* Create GitHub Milestone for Feature
|
|
276
|
+
* Create GitHub Milestone for Feature (with duplicate detection)
|
|
250
277
|
*/
|
|
251
278
|
async createMilestone(featureData) {
|
|
252
279
|
const title = `${featureData.id}: ${featureData.title}`;
|
|
280
|
+
// CRITICAL: Check if milestone already exists before creating
|
|
281
|
+
const existingResult = await execFileNoThrow('gh', [
|
|
282
|
+
'api',
|
|
283
|
+
'repos/:owner/:repo/milestones',
|
|
284
|
+
'--jq',
|
|
285
|
+
`.[] | select(.title == "${title}") | {number, html_url}`,
|
|
286
|
+
]);
|
|
287
|
+
// DEBUG: Log detection result
|
|
288
|
+
console.log(` 🔍 Milestone detection: exitCode=${existingResult.exitCode}, stdout length=${existingResult.stdout.length}`);
|
|
289
|
+
if (existingResult.exitCode !== 0) {
|
|
290
|
+
console.log(` ⚠️ Detection failed: ${existingResult.stderr}`);
|
|
291
|
+
}
|
|
292
|
+
if (existingResult.exitCode === 0 && existingResult.stdout.trim()) {
|
|
293
|
+
const existing = JSON.parse(existingResult.stdout);
|
|
294
|
+
console.log(` ♻️ Reusing existing Milestone #${existing.number}`);
|
|
295
|
+
return {
|
|
296
|
+
number: existing.number,
|
|
297
|
+
url: existing.html_url,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
console.log(` ℹ️ No existing milestone found, creating new one...`);
|
|
301
|
+
// Milestone doesn't exist, create new one
|
|
253
302
|
const description = `Feature ${featureData.id}\n\nStatus: ${featureData.status}\nCreated: ${featureData.created}`;
|
|
254
303
|
const result = await execFileNoThrow('gh', [
|
|
255
304
|
'api',
|
|
@@ -316,15 +365,10 @@ export class GitHubFeatureSync {
|
|
|
316
365
|
console.log(` ✅ Created and verified complete: ${completion.acsCompleted}/${completion.acsTotal} ACs, ${completion.tasksCompleted}/${completion.tasksTotal} tasks`);
|
|
317
366
|
}
|
|
318
367
|
else {
|
|
319
|
-
// ⚠️ INCOMPLETE - Leave open with progress comment
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
issueNumber.toString(),
|
|
324
|
-
'--body',
|
|
325
|
-
this.calculator.buildProgressComment(completion),
|
|
326
|
-
]);
|
|
327
|
-
console.log(` 📊 Created: ${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks`);
|
|
368
|
+
// ⚠️ INCOMPLETE - Leave open with progress comment (with deduplication)
|
|
369
|
+
// Note: For newly created issues, this is the first comment so deduplication
|
|
370
|
+
// will likely pass through, but the logic is here for consistency
|
|
371
|
+
await this.postProgressCommentIfChanged(issueNumber, completion);
|
|
328
372
|
}
|
|
329
373
|
return issueNumber;
|
|
330
374
|
}
|
|
@@ -381,18 +425,142 @@ export class GitHubFeatureSync {
|
|
|
381
425
|
console.log(` ⚠️ Reopened: ${completion.blockingAcs.length + completion.blockingTasks.length} items incomplete`);
|
|
382
426
|
}
|
|
383
427
|
else {
|
|
384
|
-
// Update progress comment
|
|
428
|
+
// Update progress comment (with deduplication)
|
|
429
|
+
await this.postProgressCommentIfChanged(issueNumber, completion);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// **NEW (2025-11-24)**: Update status labels based on completion
|
|
433
|
+
await this.updateStatusLabels(issueNumber, completion);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Update status labels on GitHub issue based on completion state
|
|
437
|
+
*
|
|
438
|
+
* SMART LABEL MANAGEMENT:
|
|
439
|
+
* - Only manages status:* labels (status:not_started, status:in-progress, status:completed)
|
|
440
|
+
* - Preserves all other labels (priority, type, custom labels)
|
|
441
|
+
* - Ensures exactly one status label is present
|
|
442
|
+
*/
|
|
443
|
+
async updateStatusLabels(issueNumber, completion) {
|
|
444
|
+
try {
|
|
445
|
+
// Get current issue labels
|
|
446
|
+
const issueData = await this.client.getIssue(issueNumber);
|
|
447
|
+
const currentLabels = issueData.labels || [];
|
|
448
|
+
// Separate status labels from other labels
|
|
449
|
+
const statusLabels = currentLabels.filter((label) => label.startsWith('status:'));
|
|
450
|
+
const otherLabels = currentLabels.filter((label) => !label.startsWith('status:'));
|
|
451
|
+
// Determine correct status label based on completion
|
|
452
|
+
// NOTE: Label names must match repository labels exactly
|
|
453
|
+
let newStatusLabel;
|
|
454
|
+
if (completion.overallComplete) {
|
|
455
|
+
newStatusLabel = 'status:complete'; // Repository uses "complete" not "completed"
|
|
456
|
+
}
|
|
457
|
+
else if (completion.acsPercentage > 0 || completion.tasksPercentage > 0) {
|
|
458
|
+
newStatusLabel = 'status:active'; // Repository uses "active" not "in-progress"
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
newStatusLabel = 'status:not_started';
|
|
462
|
+
}
|
|
463
|
+
// Check if update needed
|
|
464
|
+
const needsUpdate = statusLabels.length !== 1 || !statusLabels.includes(newStatusLabel);
|
|
465
|
+
if (!needsUpdate) {
|
|
466
|
+
return; // Status label already correct
|
|
467
|
+
}
|
|
468
|
+
// Update labels using gh CLI
|
|
469
|
+
// Strategy: Remove old status labels first (if any), then add new one
|
|
470
|
+
// Step 1: Remove old status labels (only if they exist)
|
|
471
|
+
if (statusLabels.length > 0) {
|
|
385
472
|
await execFileNoThrow('gh', [
|
|
386
473
|
'issue',
|
|
387
|
-
'
|
|
474
|
+
'edit',
|
|
388
475
|
issueNumber.toString(),
|
|
389
|
-
'--
|
|
390
|
-
|
|
476
|
+
'--remove-label',
|
|
477
|
+
...statusLabels,
|
|
391
478
|
]);
|
|
392
|
-
console.log(` 📊 Progress: ${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks`);
|
|
393
479
|
}
|
|
480
|
+
// Step 2: Add new status label
|
|
481
|
+
const result = await execFileNoThrow('gh', [
|
|
482
|
+
'issue',
|
|
483
|
+
'edit',
|
|
484
|
+
issueNumber.toString(),
|
|
485
|
+
'--add-label',
|
|
486
|
+
newStatusLabel,
|
|
487
|
+
]);
|
|
488
|
+
if (result.exitCode === 0) {
|
|
489
|
+
console.log(` 🏷️ Updated label: ${newStatusLabel}`);
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
console.warn(` ⚠️ Failed to add label ${newStatusLabel}: ${result.stderr}`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
// Non-blocking: Label update failure shouldn't break sync
|
|
497
|
+
console.warn(` ⚠️ Failed to update status labels: ${error.message}`);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Post progress comment only if it differs from the last comment
|
|
502
|
+
*
|
|
503
|
+
* DEDUPLICATION FIX (2025-11-24):
|
|
504
|
+
* - Prevents posting identical consecutive comments
|
|
505
|
+
* - Fetches last comment from issue
|
|
506
|
+
* - Compares content (ignoring timestamps)
|
|
507
|
+
* - Only posts if progress has changed
|
|
508
|
+
*
|
|
509
|
+
* Root Cause: updateUserStoryIssue() was posting progress comments on EVERY sync,
|
|
510
|
+
* even when progress hadn't changed, causing 4+ duplicate comments.
|
|
511
|
+
*
|
|
512
|
+
* @param issueNumber - GitHub issue number
|
|
513
|
+
* @param completion - Completion status with AC/task metrics
|
|
514
|
+
*/
|
|
515
|
+
async postProgressCommentIfChanged(issueNumber, completion) {
|
|
516
|
+
try {
|
|
517
|
+
// 1. Fetch last comment from the issue
|
|
518
|
+
const commentsResult = await execFileNoThrow('gh', [
|
|
519
|
+
'api',
|
|
520
|
+
'repos/:owner/:repo/issues/' + issueNumber + '/comments',
|
|
521
|
+
'--jq',
|
|
522
|
+
'.[-1] | {body: .body, created_at: .created_at}', // Get last comment only
|
|
523
|
+
]);
|
|
524
|
+
let lastCommentBody = '';
|
|
525
|
+
if (commentsResult.exitCode === 0 && commentsResult.stdout.trim()) {
|
|
526
|
+
try {
|
|
527
|
+
const lastComment = JSON.parse(commentsResult.stdout);
|
|
528
|
+
lastCommentBody = lastComment.body || '';
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
// No valid last comment, proceed with posting
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// 2. Build new progress comment
|
|
535
|
+
const newCommentBody = this.calculator.buildProgressComment(completion);
|
|
536
|
+
// 3. Normalize both comments for comparison (remove timestamps, whitespace differences)
|
|
537
|
+
const normalizeComment = (text) => {
|
|
538
|
+
return text
|
|
539
|
+
.replace(/🤖 Auto-updated by SpecWeave AC Completion Gate/g, '')
|
|
540
|
+
.replace(/\s+/g, ' ')
|
|
541
|
+
.trim();
|
|
542
|
+
};
|
|
543
|
+
const normalizedLast = normalizeComment(lastCommentBody);
|
|
544
|
+
const normalizedNew = normalizeComment(newCommentBody);
|
|
545
|
+
// 4. Check if comments are identical (ignoring formatting differences)
|
|
546
|
+
if (normalizedLast === normalizedNew) {
|
|
547
|
+
console.log(` ⏭️ Progress unchanged (${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks) - skipping duplicate comment`);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
// 5. Post new comment only if progress has changed
|
|
551
|
+
await execFileNoThrow('gh', [
|
|
552
|
+
'issue',
|
|
553
|
+
'comment',
|
|
554
|
+
issueNumber.toString(),
|
|
555
|
+
'--body',
|
|
556
|
+
newCommentBody,
|
|
557
|
+
]);
|
|
558
|
+
console.log(` 📊 Progress: ${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks (updated)`);
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
// Non-blocking: Log error but don't break sync
|
|
562
|
+
console.error(` ⚠️ Failed to check/post progress comment: ${error.message}`);
|
|
394
563
|
}
|
|
395
|
-
// Note: Labels are not updated to avoid overwriting manually added labels
|
|
396
564
|
}
|
|
397
565
|
/**
|
|
398
566
|
* Update FEATURE.md with GitHub Milestone link
|
|
@@ -441,4 +609,8 @@ export class GitHubFeatureSync {
|
|
|
441
609
|
await writeFile(userStoryPath, newContent, 'utf-8');
|
|
442
610
|
}
|
|
443
611
|
}
|
|
612
|
+
// SYNC LOCK: Prevent concurrent syncs of the same feature
|
|
613
|
+
// Maps featureId → last sync timestamp
|
|
614
|
+
GitHubFeatureSync.syncLocks = new Map();
|
|
615
|
+
GitHubFeatureSync.LOCK_DURATION_MS = 30000; // 30 seconds
|
|
444
616
|
//# sourceMappingURL=github-feature-sync.js.map
|