specweave 0.17.15 ā 0.18.0
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 +405 -2495
- package/README.md +92 -2
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +188 -36
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts +54 -0
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js +86 -0
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +139 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.js +389 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts +26 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js +249 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client.d.ts +1 -1
- package/dist/plugins/specweave-github/lib/github-client.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client.js +25 -13
- package/dist/plugins/specweave-github/lib/github-client.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +83 -0
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +451 -0
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.d.ts +43 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.js +82 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts +5 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/task-sync.js +38 -2
- package/dist/plugins/specweave-github/lib/task-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts +66 -0
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js +274 -0
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts +56 -0
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js +93 -0
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +48 -3
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts +142 -0
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -0
- package/dist/src/core/living-docs/hierarchy-mapper.js +453 -0
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -0
- package/dist/src/core/living-docs/index.d.ts +10 -84
- package/dist/src/core/living-docs/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/index.js +10 -164
- package/dist/src/core/living-docs/index.js.map +1 -1
- package/dist/src/core/living-docs/spec-distributor.d.ts +106 -0
- package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -0
- package/dist/src/core/living-docs/spec-distributor.js +823 -0
- package/dist/src/core/living-docs/spec-distributor.js.map +1 -0
- package/dist/src/core/living-docs/types.d.ts +201 -0
- package/dist/src/core/living-docs/types.d.ts.map +1 -0
- package/dist/src/core/living-docs/types.js +15 -0
- package/dist/src/core/living-docs/types.js.map +1 -0
- package/dist/src/core/logging/prompt-logger.d.ts +70 -0
- package/dist/src/core/logging/prompt-logger.d.ts.map +1 -0
- package/dist/src/core/logging/prompt-logger.js +247 -0
- package/dist/src/core/logging/prompt-logger.js.map +1 -0
- package/dist/src/core/status-line/status-line-manager.d.ts +15 -24
- package/dist/src/core/status-line/status-line-manager.d.ts.map +1 -1
- package/dist/src/core/status-line/status-line-manager.js +33 -70
- package/dist/src/core/status-line/status-line-manager.js.map +1 -1
- package/dist/src/core/status-line/types.d.ts +19 -31
- package/dist/src/core/status-line/types.d.ts.map +1 -1
- package/dist/src/core/status-line/types.js +5 -9
- package/dist/src/core/status-line/types.js.map +1 -1
- package/dist/src/core/sync/conflict-resolver.d.ts +66 -0
- package/dist/src/core/sync/conflict-resolver.d.ts.map +1 -0
- package/dist/src/core/sync/conflict-resolver.js +108 -0
- package/dist/src/core/sync/conflict-resolver.js.map +1 -0
- package/dist/src/core/sync/enhanced-content-builder.d.ts +77 -0
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -0
- package/dist/src/core/sync/enhanced-content-builder.js +199 -0
- package/dist/src/core/sync/enhanced-content-builder.js.map +1 -0
- package/dist/src/core/sync/label-detector.d.ts +66 -0
- package/dist/src/core/sync/label-detector.d.ts.map +1 -0
- package/dist/src/core/sync/label-detector.js +211 -0
- package/dist/src/core/sync/label-detector.js.map +1 -0
- package/dist/src/core/sync/retry-logic.d.ts +64 -0
- package/dist/src/core/sync/retry-logic.d.ts.map +1 -0
- package/dist/src/core/sync/retry-logic.js +165 -0
- package/dist/src/core/sync/retry-logic.js.map +1 -0
- package/dist/src/core/sync/spec-increment-mapper.d.ts +100 -0
- package/dist/src/core/sync/spec-increment-mapper.d.ts.map +1 -0
- package/dist/src/core/sync/spec-increment-mapper.js +424 -0
- package/dist/src/core/sync/spec-increment-mapper.js.map +1 -0
- package/dist/src/core/sync/status-cache.d.ts +91 -0
- package/dist/src/core/sync/status-cache.d.ts.map +1 -0
- package/dist/src/core/sync/status-cache.js +140 -0
- package/dist/src/core/sync/status-cache.js.map +1 -0
- package/dist/src/core/sync/status-mapper.d.ts +69 -0
- package/dist/src/core/sync/status-mapper.d.ts.map +1 -0
- package/dist/src/core/sync/status-mapper.js +90 -0
- package/dist/src/core/sync/status-mapper.js.map +1 -0
- package/dist/src/core/sync/status-sync-engine.d.ts +162 -0
- package/dist/src/core/sync/status-sync-engine.d.ts.map +1 -0
- package/dist/src/core/sync/status-sync-engine.js +347 -0
- package/dist/src/core/sync/status-sync-engine.js.map +1 -0
- package/dist/src/core/sync/sync-event-logger.d.ts +99 -0
- package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -0
- package/dist/src/core/sync/sync-event-logger.js +103 -0
- package/dist/src/core/sync/sync-event-logger.js.map +1 -0
- package/dist/src/core/sync/workflow-detector.d.ts +95 -0
- package/dist/src/core/sync/workflow-detector.d.ts.map +1 -0
- package/dist/src/core/sync/workflow-detector.js +175 -0
- package/dist/src/core/sync/workflow-detector.js.map +1 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.js +31 -0
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/utils/github-url.d.ts +53 -0
- package/dist/src/utils/github-url.d.ts.map +1 -0
- package/dist/src/utils/github-url.js +90 -0
- package/dist/src/utils/github-url.js.map +1 -0
- package/dist/src/utils/plugin-validator.d.ts +9 -0
- package/dist/src/utils/plugin-validator.d.ts.map +1 -1
- package/dist/src/utils/plugin-validator.js +86 -19
- package/dist/src/utils/plugin-validator.js.map +1 -1
- package/dist/src/utils/spec-parser.d.ts +145 -0
- package/dist/src/utils/spec-parser.d.ts.map +1 -0
- package/dist/src/utils/spec-parser.js +640 -0
- package/dist/src/utils/spec-parser.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/agents/pm/AGENT.md +1 -1
- package/plugins/specweave/agents/pm/templates/increment-spec.md +158 -0
- package/plugins/specweave/agents/pm/templates/living-docs-spec.md +113 -0
- package/plugins/specweave/commands/specweave-done.md +163 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +79 -111
- package/plugins/specweave/hooks/post-increment-planning.sh +107 -35
- package/plugins/specweave/lib/hooks/sync-living-docs.js +139 -34
- package/plugins/specweave/lib/hooks/sync-living-docs.ts +234 -38
- package/plugins/specweave/skills/SKILLS-INDEX.md +4 -24
- package/plugins/specweave/skills/increment-planner/SKILL.md +94 -0
- package/plugins/specweave/skills/increment-work-router/SKILL.md +466 -0
- package/plugins/specweave/skills/plugin-validator/SKILL.md +16 -13
- package/plugins/specweave-ado/lib/ado-status-sync.js +80 -0
- package/plugins/specweave-ado/lib/ado-status-sync.ts +121 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +205 -0
- package/plugins/specweave-github/commands/specweave-github-sync-epic.md +248 -0
- package/plugins/specweave-github/lib/duplicate-detector.js +370 -0
- package/plugins/specweave-github/lib/duplicate-detector.ts +525 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.ts +322 -0
- package/plugins/specweave-github/lib/github-client.js +21 -10
- package/plugins/specweave-github/lib/github-client.ts +27 -16
- package/plugins/specweave-github/lib/github-epic-sync.js +489 -0
- package/plugins/specweave-github/lib/github-epic-sync.ts +690 -0
- package/plugins/specweave-github/lib/github-status-sync.js +71 -0
- package/plugins/specweave-github/lib/github-status-sync.ts +107 -0
- package/plugins/specweave-github/lib/task-sync.js +33 -2
- package/plugins/specweave-github/lib/task-sync.ts +44 -2
- package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +267 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.ts.disabled +222 -0
- package/plugins/specweave-jira/lib/jira-epic-sync.js +304 -0
- package/plugins/specweave-jira/lib/jira-epic-sync.ts +459 -0
- package/plugins/specweave-jira/lib/jira-status-sync.js +79 -0
- package/plugins/specweave-jira/lib/jira-status-sync.ts +139 -0
- package/src/templates/AGENTS.md.template +88 -1
- package/src/templates/CLAUDE.md.template +49 -0
- package/plugins/specweave/skills/increment-quality-judge/SKILL.md +0 -524
- package/plugins/specweave/skills/plugin-installer/SKILL.md +0 -353
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Duplicate Detection System for GitHub Issues
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL ARCHITECTURE:
|
|
5
|
+
* ALL GitHub issue creation in SpecWeave MUST use this module.
|
|
6
|
+
* This is the SINGLE SOURCE OF TRUTH for duplicate prevention.
|
|
7
|
+
*
|
|
8
|
+
* THREE-PHASE PROTECTION:
|
|
9
|
+
* 1. Detection (Before Create): Search GitHub for existing issues
|
|
10
|
+
* 2. Verification (After Create): Count check to detect duplicates
|
|
11
|
+
* 3. Reflection (Auto-Correct): Close duplicate issues automatically
|
|
12
|
+
*
|
|
13
|
+
* USAGE:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Simple: Create with full protection
|
|
16
|
+
* const result = await DuplicateDetector.createWithProtection({
|
|
17
|
+
* title: '[FS-031] Feature Title',
|
|
18
|
+
* body: 'Description...',
|
|
19
|
+
* titlePattern: '[FS-031]',
|
|
20
|
+
* labels: ['specweave', 'feature']
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // Manual: Check before creating
|
|
24
|
+
* const existing = await DuplicateDetector.checkBeforeCreate('[FS-031]');
|
|
25
|
+
* if (!existing) {
|
|
26
|
+
* // Create issue...
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @module duplicate-detector
|
|
31
|
+
*/
|
|
32
|
+
export interface GitHubIssue {
|
|
33
|
+
number: number;
|
|
34
|
+
title: string;
|
|
35
|
+
url: string;
|
|
36
|
+
body?: string;
|
|
37
|
+
state?: 'open' | 'closed';
|
|
38
|
+
createdAt?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface VerificationResult {
|
|
41
|
+
success: boolean;
|
|
42
|
+
expectedCount: number;
|
|
43
|
+
actualCount: number;
|
|
44
|
+
duplicates: GitHubIssue[];
|
|
45
|
+
message: string;
|
|
46
|
+
}
|
|
47
|
+
export interface CorrectionResult {
|
|
48
|
+
success: boolean;
|
|
49
|
+
duplicatesClosed: number;
|
|
50
|
+
keptIssue: number;
|
|
51
|
+
errors: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface CreateOptions {
|
|
54
|
+
title: string;
|
|
55
|
+
body: string;
|
|
56
|
+
titlePattern: string;
|
|
57
|
+
incrementId?: string;
|
|
58
|
+
labels?: string[];
|
|
59
|
+
milestone?: string;
|
|
60
|
+
assignees?: string[];
|
|
61
|
+
repo?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface CreateResult {
|
|
64
|
+
issue: GitHubIssue;
|
|
65
|
+
duplicatesFound: number;
|
|
66
|
+
duplicatesClosed: number;
|
|
67
|
+
wasReused: boolean;
|
|
68
|
+
}
|
|
69
|
+
export declare class DuplicateDetector {
|
|
70
|
+
/**
|
|
71
|
+
* PHASE 1: Detection (Before Creating Issue)
|
|
72
|
+
*
|
|
73
|
+
* Searches GitHub for existing issues matching the title pattern.
|
|
74
|
+
* This is the PRIMARY defense against duplicates.
|
|
75
|
+
*
|
|
76
|
+
* @param titlePattern - Pattern to search (e.g., "[FS-031]" or "[INC-0031]")
|
|
77
|
+
* @param incrementId - Optional increment ID for more precise matching
|
|
78
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
79
|
+
* @returns Existing issue if found, null otherwise
|
|
80
|
+
*/
|
|
81
|
+
static checkBeforeCreate(titlePattern: string, incrementId?: string, repo?: string): Promise<GitHubIssue | null>;
|
|
82
|
+
/**
|
|
83
|
+
* PHASE 2: Verification (After Creating Issue)
|
|
84
|
+
*
|
|
85
|
+
* Counts issues matching the pattern and identifies duplicates.
|
|
86
|
+
* This is the SECONDARY defense - catches duplicates that slipped through.
|
|
87
|
+
*
|
|
88
|
+
* @param titlePattern - Pattern to search (e.g., "[FS-031]")
|
|
89
|
+
* @param expectedCount - Expected number of issues (usually 1)
|
|
90
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
91
|
+
* @returns Verification result with duplicate list
|
|
92
|
+
*/
|
|
93
|
+
static verifyAfterCreate(titlePattern: string, expectedCount?: number, repo?: string): Promise<VerificationResult>;
|
|
94
|
+
/**
|
|
95
|
+
* PHASE 3: Reflection (Auto-Correct Duplicates)
|
|
96
|
+
*
|
|
97
|
+
* Automatically closes duplicate issues and keeps the oldest one.
|
|
98
|
+
* This is the CLEANUP phase - fixes problems that occurred.
|
|
99
|
+
*
|
|
100
|
+
* @param duplicates - List of duplicate issues to close
|
|
101
|
+
* @param keepIssueNumber - Issue number to keep (usually the oldest)
|
|
102
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
103
|
+
* @returns Correction result with count of closed issues
|
|
104
|
+
*/
|
|
105
|
+
static correctDuplicates(duplicates: GitHubIssue[], keepIssueNumber: number, repo?: string): Promise<CorrectionResult>;
|
|
106
|
+
/**
|
|
107
|
+
* ALL-IN-ONE: Create Issue with Full Protection
|
|
108
|
+
*
|
|
109
|
+
* This is the RECOMMENDED way to create GitHub issues in SpecWeave.
|
|
110
|
+
* Combines all 3 phases: Detection ā Creation ā Verification ā Reflection
|
|
111
|
+
*
|
|
112
|
+
* GUARANTEES:
|
|
113
|
+
* - No duplicates will be created
|
|
114
|
+
* - Existing duplicates will be detected and closed
|
|
115
|
+
* - Idempotent: can run multiple times safely
|
|
116
|
+
*
|
|
117
|
+
* @param options - Create options (title, body, labels, etc.)
|
|
118
|
+
* @returns Create result with issue details and duplicate stats
|
|
119
|
+
*/
|
|
120
|
+
static createWithProtection(options: CreateOptions): Promise<CreateResult>;
|
|
121
|
+
/**
|
|
122
|
+
* Utility: Extract title pattern from full title
|
|
123
|
+
*
|
|
124
|
+
* Examples:
|
|
125
|
+
* - "[FS-031] Feature Title" ā "[FS-031]"
|
|
126
|
+
* - "[INC-0031] Increment Title" ā "[INC-0031]"
|
|
127
|
+
*
|
|
128
|
+
* @param title - Full issue title
|
|
129
|
+
* @returns Extracted pattern or null
|
|
130
|
+
*/
|
|
131
|
+
static extractTitlePattern(title: string): string | null;
|
|
132
|
+
/**
|
|
133
|
+
* Utility: Check if GitHub CLI is available and authenticated
|
|
134
|
+
*
|
|
135
|
+
* @returns true if gh CLI is ready, false otherwise
|
|
136
|
+
*/
|
|
137
|
+
static checkGitHubCLI(): boolean;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=duplicate-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-detector.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/duplicate-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAQH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAMD,qBAAa,iBAAiB;IAC5B;;;;;;;;;;OAUG;WACU,iBAAiB,CAC5B,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA+D9B;;;;;;;;;;OAUG;WACU,iBAAiB,CAC5B,YAAY,EAAE,MAAM,EACpB,aAAa,GAAE,MAAU,EACzB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC;IAwF9B;;;;;;;;;;OAUG;WACU,iBAAiB,CAC5B,UAAU,EAAE,WAAW,EAAE,EACzB,eAAe,EAAE,MAAM,EACvB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,gBAAgB,CAAC;IA0E5B;;;;;;;;;;;;;OAaG;WACU,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA+HhF;;;;;;;;;OASG;IACH,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKxD;;;;OAIG;IACH,MAAM,CAAC,cAAc,IAAI,OAAO;CAQjC"}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Duplicate Detection System for GitHub Issues
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL ARCHITECTURE:
|
|
5
|
+
* ALL GitHub issue creation in SpecWeave MUST use this module.
|
|
6
|
+
* This is the SINGLE SOURCE OF TRUTH for duplicate prevention.
|
|
7
|
+
*
|
|
8
|
+
* THREE-PHASE PROTECTION:
|
|
9
|
+
* 1. Detection (Before Create): Search GitHub for existing issues
|
|
10
|
+
* 2. Verification (After Create): Count check to detect duplicates
|
|
11
|
+
* 3. Reflection (Auto-Correct): Close duplicate issues automatically
|
|
12
|
+
*
|
|
13
|
+
* USAGE:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Simple: Create with full protection
|
|
16
|
+
* const result = await DuplicateDetector.createWithProtection({
|
|
17
|
+
* title: '[FS-031] Feature Title',
|
|
18
|
+
* body: 'Description...',
|
|
19
|
+
* titlePattern: '[FS-031]',
|
|
20
|
+
* labels: ['specweave', 'feature']
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // Manual: Check before creating
|
|
24
|
+
* const existing = await DuplicateDetector.checkBeforeCreate('[FS-031]');
|
|
25
|
+
* if (!existing) {
|
|
26
|
+
* // Create issue...
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @module duplicate-detector
|
|
31
|
+
*/
|
|
32
|
+
import { execFileSync } from 'child_process';
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// MAIN CLASS
|
|
35
|
+
// ============================================================================
|
|
36
|
+
export class DuplicateDetector {
|
|
37
|
+
/**
|
|
38
|
+
* PHASE 1: Detection (Before Creating Issue)
|
|
39
|
+
*
|
|
40
|
+
* Searches GitHub for existing issues matching the title pattern.
|
|
41
|
+
* This is the PRIMARY defense against duplicates.
|
|
42
|
+
*
|
|
43
|
+
* @param titlePattern - Pattern to search (e.g., "[FS-031]" or "[INC-0031]")
|
|
44
|
+
* @param incrementId - Optional increment ID for more precise matching
|
|
45
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
46
|
+
* @returns Existing issue if found, null otherwise
|
|
47
|
+
*/
|
|
48
|
+
static async checkBeforeCreate(titlePattern, incrementId, repo) {
|
|
49
|
+
console.log(`š DETECTION: Checking for existing issue with pattern: ${titlePattern}`);
|
|
50
|
+
try {
|
|
51
|
+
const args = [
|
|
52
|
+
'issue',
|
|
53
|
+
'list',
|
|
54
|
+
'--search', `"${titlePattern}" in:title`,
|
|
55
|
+
'--json', 'number,title,url,body,createdAt',
|
|
56
|
+
'--limit', '20',
|
|
57
|
+
'--state', 'all' // Check both open and closed
|
|
58
|
+
];
|
|
59
|
+
if (repo) {
|
|
60
|
+
args.push('--repo', repo);
|
|
61
|
+
}
|
|
62
|
+
const output = execFileSync('gh', args, { encoding: 'utf-8' });
|
|
63
|
+
const issues = JSON.parse(output);
|
|
64
|
+
if (issues.length === 0) {
|
|
65
|
+
console.log(' ā
No existing issues found (safe to create)');
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
console.log(` š Found ${issues.length} issue(s) matching pattern`);
|
|
69
|
+
// Strategy 1: Exact title match
|
|
70
|
+
const exactMatch = issues.find(issue => issue.title.includes(titlePattern));
|
|
71
|
+
if (exactMatch) {
|
|
72
|
+
console.log(` ā ļø DUPLICATE DETECTED: Issue #${exactMatch.number}`);
|
|
73
|
+
console.log(` š URL: ${exactMatch.url}`);
|
|
74
|
+
return exactMatch;
|
|
75
|
+
}
|
|
76
|
+
// Strategy 2: Body match (if incrementId provided)
|
|
77
|
+
if (incrementId) {
|
|
78
|
+
const bodyMatch = issues.find(issue => issue.body && (issue.body.includes(`**Increment**: ${incrementId}`) ||
|
|
79
|
+
issue.body.includes(incrementId)));
|
|
80
|
+
if (bodyMatch) {
|
|
81
|
+
console.log(` ā ļø DUPLICATE DETECTED (body match): Issue #${bodyMatch.number}`);
|
|
82
|
+
console.log(` š URL: ${bodyMatch.url}`);
|
|
83
|
+
return bodyMatch;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log(' ā
No exact match found (safe to create)');
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.warn(` ā ļø Detection failed (continuing anyway): ${error.message}`);
|
|
91
|
+
return null; // Fail gracefully - allow creation to proceed
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* PHASE 2: Verification (After Creating Issue)
|
|
96
|
+
*
|
|
97
|
+
* Counts issues matching the pattern and identifies duplicates.
|
|
98
|
+
* This is the SECONDARY defense - catches duplicates that slipped through.
|
|
99
|
+
*
|
|
100
|
+
* @param titlePattern - Pattern to search (e.g., "[FS-031]")
|
|
101
|
+
* @param expectedCount - Expected number of issues (usually 1)
|
|
102
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
103
|
+
* @returns Verification result with duplicate list
|
|
104
|
+
*/
|
|
105
|
+
static async verifyAfterCreate(titlePattern, expectedCount = 1, repo) {
|
|
106
|
+
console.log(`\nš VERIFICATION: Checking issue count for pattern: ${titlePattern}`);
|
|
107
|
+
try {
|
|
108
|
+
const args = [
|
|
109
|
+
'issue',
|
|
110
|
+
'list',
|
|
111
|
+
'--search', `"${titlePattern}" in:title`,
|
|
112
|
+
'--json', 'number,title,url,createdAt',
|
|
113
|
+
'--limit', '50',
|
|
114
|
+
'--state', 'all'
|
|
115
|
+
];
|
|
116
|
+
if (repo) {
|
|
117
|
+
args.push('--repo', repo);
|
|
118
|
+
}
|
|
119
|
+
const output = execFileSync('gh', args, { encoding: 'utf-8' });
|
|
120
|
+
const issues = JSON.parse(output);
|
|
121
|
+
// Filter exact matches only
|
|
122
|
+
const exactMatches = issues.filter(issue => issue.title.includes(titlePattern));
|
|
123
|
+
const actualCount = exactMatches.length;
|
|
124
|
+
console.log(` Expected: ${expectedCount} issue(s)`);
|
|
125
|
+
console.log(` Actual: ${actualCount} issue(s)`);
|
|
126
|
+
if (actualCount === expectedCount) {
|
|
127
|
+
console.log(` ā
VERIFICATION PASSED: Count matches!`);
|
|
128
|
+
return {
|
|
129
|
+
success: true,
|
|
130
|
+
expectedCount,
|
|
131
|
+
actualCount,
|
|
132
|
+
duplicates: [],
|
|
133
|
+
message: 'Verification passed'
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
else if (actualCount > expectedCount) {
|
|
137
|
+
// DUPLICATES DETECTED!
|
|
138
|
+
console.warn(` ā ļø VERIFICATION FAILED: ${actualCount - expectedCount} duplicate(s) detected!`);
|
|
139
|
+
// Sort by creation date (oldest first)
|
|
140
|
+
const sorted = exactMatches.sort((a, b) => {
|
|
141
|
+
const dateA = new Date(a.createdAt || 0).getTime();
|
|
142
|
+
const dateB = new Date(b.createdAt || 0).getTime();
|
|
143
|
+
return dateA - dateB;
|
|
144
|
+
});
|
|
145
|
+
// Keep first (oldest), mark rest as duplicates
|
|
146
|
+
const duplicates = sorted.slice(1);
|
|
147
|
+
console.warn(` š Duplicate issues:`);
|
|
148
|
+
duplicates.forEach(dup => {
|
|
149
|
+
console.warn(` - #${dup.number}: ${dup.title}`);
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
expectedCount,
|
|
154
|
+
actualCount,
|
|
155
|
+
duplicates,
|
|
156
|
+
message: `${duplicates.length} duplicate(s) found`
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.warn(` ā ļø VERIFICATION WARNING: Expected ${expectedCount} but found ${actualCount}`);
|
|
161
|
+
return {
|
|
162
|
+
success: false,
|
|
163
|
+
expectedCount,
|
|
164
|
+
actualCount,
|
|
165
|
+
duplicates: [],
|
|
166
|
+
message: 'Count mismatch (fewer than expected)'
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.error(` ā Verification failed: ${error.message}`);
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
expectedCount,
|
|
175
|
+
actualCount: -1,
|
|
176
|
+
duplicates: [],
|
|
177
|
+
message: `Verification error: ${error.message}`
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* PHASE 3: Reflection (Auto-Correct Duplicates)
|
|
183
|
+
*
|
|
184
|
+
* Automatically closes duplicate issues and keeps the oldest one.
|
|
185
|
+
* This is the CLEANUP phase - fixes problems that occurred.
|
|
186
|
+
*
|
|
187
|
+
* @param duplicates - List of duplicate issues to close
|
|
188
|
+
* @param keepIssueNumber - Issue number to keep (usually the oldest)
|
|
189
|
+
* @param repo - Optional repo (format: "owner/repo")
|
|
190
|
+
* @returns Correction result with count of closed issues
|
|
191
|
+
*/
|
|
192
|
+
static async correctDuplicates(duplicates, keepIssueNumber, repo) {
|
|
193
|
+
if (duplicates.length === 0) {
|
|
194
|
+
return {
|
|
195
|
+
success: true,
|
|
196
|
+
duplicatesClosed: 0,
|
|
197
|
+
keptIssue: keepIssueNumber,
|
|
198
|
+
errors: []
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
console.log(`\nš§ REFLECTION: Auto-correcting ${duplicates.length} duplicate(s)...`);
|
|
202
|
+
const errors = [];
|
|
203
|
+
let closed = 0;
|
|
204
|
+
for (const duplicate of duplicates) {
|
|
205
|
+
try {
|
|
206
|
+
console.log(` šļø Closing duplicate #${duplicate.number}...`);
|
|
207
|
+
const comment = `Duplicate of #${keepIssueNumber}
|
|
208
|
+
|
|
209
|
+
This issue was automatically closed by SpecWeave's Global Duplicate Detection System.
|
|
210
|
+
|
|
211
|
+
The original issue (#${keepIssueNumber}) should be used for tracking instead.
|
|
212
|
+
|
|
213
|
+
š¤ Auto-closed by SpecWeave`;
|
|
214
|
+
const commentArgs = [
|
|
215
|
+
'issue',
|
|
216
|
+
'comment',
|
|
217
|
+
duplicate.number.toString(),
|
|
218
|
+
'--body', comment
|
|
219
|
+
];
|
|
220
|
+
if (repo) {
|
|
221
|
+
commentArgs.push('--repo', repo);
|
|
222
|
+
}
|
|
223
|
+
// Add comment explaining closure
|
|
224
|
+
execFileSync('gh', commentArgs, { encoding: 'utf-8' });
|
|
225
|
+
const closeArgs = [
|
|
226
|
+
'issue',
|
|
227
|
+
'close',
|
|
228
|
+
duplicate.number.toString()
|
|
229
|
+
];
|
|
230
|
+
if (repo) {
|
|
231
|
+
closeArgs.push('--repo', repo);
|
|
232
|
+
}
|
|
233
|
+
// Close the issue
|
|
234
|
+
execFileSync('gh', closeArgs, { encoding: 'utf-8' });
|
|
235
|
+
console.log(` ā
Closed #${duplicate.number}`);
|
|
236
|
+
closed++;
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
const errorMsg = `Failed to close #${duplicate.number}: ${error.message}`;
|
|
240
|
+
console.error(` ā ${errorMsg}`);
|
|
241
|
+
errors.push(errorMsg);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
console.log(`\n ā
REFLECTION COMPLETE: Kept #${keepIssueNumber}, closed ${closed}/${duplicates.length} duplicate(s)`);
|
|
245
|
+
return {
|
|
246
|
+
success: errors.length === 0,
|
|
247
|
+
duplicatesClosed: closed,
|
|
248
|
+
keptIssue: keepIssueNumber,
|
|
249
|
+
errors
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* ALL-IN-ONE: Create Issue with Full Protection
|
|
254
|
+
*
|
|
255
|
+
* This is the RECOMMENDED way to create GitHub issues in SpecWeave.
|
|
256
|
+
* Combines all 3 phases: Detection ā Creation ā Verification ā Reflection
|
|
257
|
+
*
|
|
258
|
+
* GUARANTEES:
|
|
259
|
+
* - No duplicates will be created
|
|
260
|
+
* - Existing duplicates will be detected and closed
|
|
261
|
+
* - Idempotent: can run multiple times safely
|
|
262
|
+
*
|
|
263
|
+
* @param options - Create options (title, body, labels, etc.)
|
|
264
|
+
* @returns Create result with issue details and duplicate stats
|
|
265
|
+
*/
|
|
266
|
+
static async createWithProtection(options) {
|
|
267
|
+
const { title, body, titlePattern, incrementId, labels = ['specweave'], milestone, assignees = [], repo } = options;
|
|
268
|
+
console.log(`\nš”ļø Creating GitHub issue with FULL PROTECTION...`);
|
|
269
|
+
console.log(` Title: ${title}`);
|
|
270
|
+
console.log(` Pattern: ${titlePattern}`);
|
|
271
|
+
// PHASE 1: Detection (Check if issue already exists)
|
|
272
|
+
console.log(`\nāāā PHASE 1: DETECTION āāā`);
|
|
273
|
+
const existing = await this.checkBeforeCreate(titlePattern, incrementId, repo);
|
|
274
|
+
let issueNumber;
|
|
275
|
+
let issueUrl;
|
|
276
|
+
let wasReused = false;
|
|
277
|
+
if (existing) {
|
|
278
|
+
// Reuse existing issue instead of creating duplicate
|
|
279
|
+
console.log(`\nā»ļø Using existing issue #${existing.number} (skipping creation)`);
|
|
280
|
+
issueNumber = existing.number;
|
|
281
|
+
issueUrl = existing.url;
|
|
282
|
+
wasReused = true;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// PHASE 2: Creation (No duplicate found, safe to create)
|
|
286
|
+
console.log(`\nāāā PHASE 2: CREATION āāā`);
|
|
287
|
+
console.log(` Creating new GitHub issue...`);
|
|
288
|
+
try {
|
|
289
|
+
const args = [
|
|
290
|
+
'issue',
|
|
291
|
+
'create',
|
|
292
|
+
'--title', title,
|
|
293
|
+
'--body', body
|
|
294
|
+
];
|
|
295
|
+
if (repo) {
|
|
296
|
+
args.push('--repo', repo);
|
|
297
|
+
}
|
|
298
|
+
// Add labels
|
|
299
|
+
labels.forEach(label => {
|
|
300
|
+
args.push('--label', label);
|
|
301
|
+
});
|
|
302
|
+
// Add milestone if provided
|
|
303
|
+
if (milestone) {
|
|
304
|
+
args.push('--milestone', milestone);
|
|
305
|
+
}
|
|
306
|
+
// Add assignees if provided
|
|
307
|
+
assignees.forEach(assignee => {
|
|
308
|
+
args.push('--assignee', assignee);
|
|
309
|
+
});
|
|
310
|
+
const output = execFileSync('gh', args, { encoding: 'utf-8' });
|
|
311
|
+
// Extract issue number from output (format: "https://github.com/owner/repo/issues/123")
|
|
312
|
+
const match = output.match(/\/issues\/(\d+)/);
|
|
313
|
+
if (!match) {
|
|
314
|
+
throw new Error('Could not extract issue number from gh CLI output');
|
|
315
|
+
}
|
|
316
|
+
issueNumber = parseInt(match[1], 10);
|
|
317
|
+
issueUrl = output.trim();
|
|
318
|
+
console.log(` ā
Created issue #${issueNumber}`);
|
|
319
|
+
console.log(` š ${issueUrl}`);
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
throw new Error(`Failed to create GitHub issue: ${error.message}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// PHASE 3: Verification (Count check for duplicates)
|
|
326
|
+
console.log(`\nāāā PHASE 3: VERIFICATION āāā`);
|
|
327
|
+
const verification = await this.verifyAfterCreate(titlePattern, 1, repo);
|
|
328
|
+
let duplicatesClosed = 0;
|
|
329
|
+
if (!verification.success && verification.duplicates.length > 0) {
|
|
330
|
+
// PHASE 4: Reflection (Auto-correct duplicates)
|
|
331
|
+
console.log(`\nāāā PHASE 4: REFLECTION āāā`);
|
|
332
|
+
console.warn(` ā ļø ${verification.duplicates.length} duplicate(s) detected!`);
|
|
333
|
+
const correction = await this.correctDuplicates(verification.duplicates, issueNumber, repo);
|
|
334
|
+
duplicatesClosed = correction.duplicatesClosed;
|
|
335
|
+
if (correction.errors.length > 0) {
|
|
336
|
+
console.warn(` ā ļø Some duplicates could not be closed:`);
|
|
337
|
+
correction.errors.forEach(err => console.warn(` - ${err}`));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
else if (verification.success) {
|
|
341
|
+
console.log(` ā
No duplicates detected!`);
|
|
342
|
+
}
|
|
343
|
+
// Final Summary
|
|
344
|
+
console.log(`\nā
Issue creation complete!`);
|
|
345
|
+
console.log(` Issue: #${issueNumber}`);
|
|
346
|
+
console.log(` Duplicates found: ${verification.duplicates.length}`);
|
|
347
|
+
console.log(` Duplicates closed: ${duplicatesClosed}`);
|
|
348
|
+
console.log(` Reused existing: ${wasReused ? 'Yes' : 'No'}`);
|
|
349
|
+
return {
|
|
350
|
+
issue: {
|
|
351
|
+
number: issueNumber,
|
|
352
|
+
title,
|
|
353
|
+
url: issueUrl
|
|
354
|
+
},
|
|
355
|
+
duplicatesFound: verification.duplicates.length,
|
|
356
|
+
duplicatesClosed,
|
|
357
|
+
wasReused
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Utility: Extract title pattern from full title
|
|
362
|
+
*
|
|
363
|
+
* Examples:
|
|
364
|
+
* - "[FS-031] Feature Title" ā "[FS-031]"
|
|
365
|
+
* - "[INC-0031] Increment Title" ā "[INC-0031]"
|
|
366
|
+
*
|
|
367
|
+
* @param title - Full issue title
|
|
368
|
+
* @returns Extracted pattern or null
|
|
369
|
+
*/
|
|
370
|
+
static extractTitlePattern(title) {
|
|
371
|
+
const match = title.match(/^(\[[^\]]+\])/);
|
|
372
|
+
return match ? match[1] : null;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Utility: Check if GitHub CLI is available and authenticated
|
|
376
|
+
*
|
|
377
|
+
* @returns true if gh CLI is ready, false otherwise
|
|
378
|
+
*/
|
|
379
|
+
static checkGitHubCLI() {
|
|
380
|
+
try {
|
|
381
|
+
execFileSync('gh', ['auth', 'status'], { encoding: 'utf-8' });
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=duplicate-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-detector.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/duplicate-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced GitHub Spec Content Sync
|
|
3
|
+
*
|
|
4
|
+
* Uses EnhancedContentBuilder and SpecIncrementMapper for rich external descriptions.
|
|
5
|
+
* NEW (v0.21.0): Supports task checkboxes and automatic labeling.
|
|
6
|
+
*/
|
|
7
|
+
export interface EnhancedGitHubSyncOptions {
|
|
8
|
+
specPath: string;
|
|
9
|
+
owner?: string;
|
|
10
|
+
repo?: string;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface EnhancedSyncResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
action: 'created' | 'updated' | 'no-change' | 'error';
|
|
17
|
+
issueNumber?: number;
|
|
18
|
+
issueUrl?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
tasksLinked?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Enhanced sync with rich content including task mappings
|
|
24
|
+
*/
|
|
25
|
+
export declare function syncSpecWithEnhancedContent(options: EnhancedGitHubSyncOptions): Promise<EnhancedSyncResult>;
|
|
26
|
+
//# sourceMappingURL=enhanced-github-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enhanced-github-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/enhanced-github-sync.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAsL7B"}
|