specweave 0.28.15 ā 0.28.19
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/bin/specweave.js +1 -1
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts +94 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js +219 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts +19 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js +380 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js.map +1 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts +92 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js +349 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts +50 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js +84 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js.map +1 -0
- package/dist/src/cli/commands/import-external.d.ts.map +1 -1
- package/dist/src/cli/commands/import-external.js +12 -7
- package/dist/src/cli/commands/import-external.js.map +1 -1
- package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/external-import.js +138 -23
- package/dist/src/cli/helpers/init/external-import.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts +65 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js +278 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts +64 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js +251 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js.map +1 -0
- package/dist/src/core/ac-test-validator-cli.js +4 -1
- package/dist/src/core/ac-test-validator-cli.js.map +1 -1
- package/dist/src/core/ac-test-validator.d.ts.map +1 -1
- package/dist/src/core/ac-test-validator.js +4 -1
- package/dist/src/core/ac-test-validator.js.map +1 -1
- package/dist/src/core/qa/qa-runner.js +7 -10
- package/dist/src/core/qa/qa-runner.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +75 -0
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.d.ts +137 -5
- package/dist/src/core/types/sync-profile.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.js +63 -0
- package/dist/src/core/types/sync-profile.js.map +1 -1
- package/dist/src/importers/external-importer.d.ts +25 -0
- package/dist/src/importers/external-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.js +5 -3
- package/dist/src/importers/github-importer.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +51 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +39 -12
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/repo/types.d.ts +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +72 -3
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +142 -16
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/locales/de/cli.json +14 -0
- package/dist/src/locales/es/cli.json +14 -0
- package/dist/src/locales/fr/cli.json +14 -0
- package/dist/src/locales/ja/cli.json +14 -0
- package/dist/src/locales/ko/cli.json +14 -0
- package/dist/src/locales/pt/cli.json +14 -0
- package/dist/src/locales/ru/cli.json +14 -0
- package/dist/src/locales/zh/cli.json +14 -0
- package/dist/src/utils/chalk-fallback.d.ts +38 -0
- package/dist/src/utils/chalk-fallback.d.ts.map +1 -0
- package/dist/src/utils/chalk-fallback.js +118 -0
- package/dist/src/utils/chalk-fallback.js.map +1 -0
- package/dist/src/utils/project-id-generator.d.ts +127 -0
- package/dist/src/utils/project-id-generator.d.ts.map +1 -0
- package/dist/src/utils/project-id-generator.js +228 -0
- package/dist/src/utils/project-id-generator.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/agents/AGENTS-INDEX.md +9 -7
- package/plugins/specweave/agents/pm/AGENT.md +202 -0
- package/plugins/specweave/commands/specweave-import-external.md +5 -3
- package/plugins/specweave/commands/specweave-qa.md +9 -9
- package/plugins/specweave/commands/specweave-save.md +531 -193
- package/plugins/specweave/commands/specweave-sync-docs.md +6 -2
- package/plugins/specweave/commands/specweave-validate.md +8 -7
- package/plugins/specweave/hooks/pre-task-completion.sh +35 -17
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +121 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js +295 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +75 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +179 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js +319 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
- package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
- package/plugins/specweave/skills/docs-updater/SKILL.md +61 -0
- package/plugins/specweave/skills/increment-planner/SKILL.md +10 -335
- package/plugins/specweave/skills/increment-planner/templates/metadata.json +13 -0
- package/plugins/specweave/skills/increment-planner/templates/plan.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +48 -0
- package/plugins/specweave/skills/increment-quality-judge-v2/SKILL.md +18 -0
- package/plugins/specweave-ado/commands/specweave-ado-import-areas.md +358 -0
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +1 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +1 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +1 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +1 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +1 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +14 -10
- package/plugins/specweave-github/commands/specweave-github-sync.md +57 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +86 -0
- package/plugins/specweave-github/lib/github-feature-sync.ts +6 -11
- package/plugins/specweave-github/lib/github-increment-sync-cli.js +343 -0
- package/plugins/specweave-github/lib/github-increment-sync-cli.ts +484 -0
- package/plugins/specweave-github/lib/increment-issue-builder.js +368 -0
- package/plugins/specweave-github/lib/increment-issue-builder.ts +471 -0
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +19 -24
- package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +15 -23
- package/plugins/specweave-jira/commands/specweave-jira-import-boards.md +331 -0
- package/plugins/specweave-ml/agents/data-scientist/AGENT.md +16 -20
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +18 -19
- package/plugins/specweave-ml/skills/{ml-pipeline-workflow ā mlops-dag-builder}/SKILL.md +18 -14
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +129 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +1 -1
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +10 -122
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +0 -70
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +0 -258
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +0 -83
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +0 -466
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +0 -1
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +0 -705
- package/plugins/specweave-github/lib/epic-content-builder.js +0 -265
- package/plugins/specweave-github/lib/epic-content-builder.ts +0 -376
- package/plugins/specweave-github/lib/github-epic-sync.js +0 -488
- package/plugins/specweave-github/lib/github-epic-sync.ts +0 -715
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GitHub Increment Sync CLI
|
|
4
|
+
*
|
|
5
|
+
* For brownfield projects without living docs structure.
|
|
6
|
+
* Creates GitHub issues directly from increment spec.md with proper format.
|
|
7
|
+
*
|
|
8
|
+
* CORRECT FORMAT:
|
|
9
|
+
* - Single issue per increment: [FS-XXX] Increment Title
|
|
10
|
+
* - With User Stories and ACs as sections
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* node github-increment-sync-cli.js <increment-id>
|
|
14
|
+
* node github-increment-sync-cli.js 0063-fix-external-import
|
|
15
|
+
*
|
|
16
|
+
* @see ADR-0143 (GitHub Issue Format)
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, readFileSync } from 'fs';
|
|
19
|
+
import * as fs from 'fs/promises';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { IncrementIssueBuilder } from './increment-issue-builder.js';
|
|
22
|
+
import { execFileNoThrow } from '../../../src/utils/execFileNoThrow.js';
|
|
23
|
+
async function loadGitHubConfig() {
|
|
24
|
+
const projectRoot = process.cwd();
|
|
25
|
+
const configPath = path.join(projectRoot, '.specweave/config.json');
|
|
26
|
+
let owner = process.env.GITHUB_OWNER || '';
|
|
27
|
+
let repo = process.env.GITHUB_REPO || '';
|
|
28
|
+
const token = process.env.GITHUB_TOKEN || '';
|
|
29
|
+
// Try to load from config.json
|
|
30
|
+
if (existsSync(configPath)) {
|
|
31
|
+
try {
|
|
32
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
33
|
+
// Method 1: sync.github
|
|
34
|
+
if (config.sync?.github?.owner && config.sync?.github?.repo) {
|
|
35
|
+
owner = config.sync.github.owner;
|
|
36
|
+
repo = config.sync.github.repo;
|
|
37
|
+
}
|
|
38
|
+
// Method 2: multiProject.projects[activeProject].externalTools.github
|
|
39
|
+
else if (config.multiProject?.enabled && config.multiProject?.activeProject) {
|
|
40
|
+
const activeProject = config.multiProject.activeProject;
|
|
41
|
+
const projectConfig = config.multiProject.projects?.[activeProject];
|
|
42
|
+
if (projectConfig?.externalTools?.github?.repository) {
|
|
43
|
+
const parts = projectConfig.externalTools.github.repository.split('/');
|
|
44
|
+
if (parts.length === 2) {
|
|
45
|
+
owner = parts[0];
|
|
46
|
+
repo = parts[1];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Method 3: sync.profiles[activeProfile]
|
|
51
|
+
else if (config.sync?.activeProfile && config.sync?.profiles) {
|
|
52
|
+
const profile = config.sync.profiles[config.sync.activeProfile];
|
|
53
|
+
if (profile?.config?.owner && profile?.config?.repo) {
|
|
54
|
+
owner = profile.config.owner;
|
|
55
|
+
repo = profile.config.repo;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error('ā ļø Failed to parse config.json:', error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Fallback: detect from git remote
|
|
64
|
+
if (!owner || !repo) {
|
|
65
|
+
const result = await execFileNoThrow('git', ['remote', 'get-url', 'origin']);
|
|
66
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
67
|
+
const remoteUrl = result.stdout.trim();
|
|
68
|
+
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
|
|
69
|
+
if (match) {
|
|
70
|
+
owner = owner || match[1];
|
|
71
|
+
repo = repo || match[2];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!token) {
|
|
76
|
+
console.error('ā GITHUB_TOKEN not set');
|
|
77
|
+
console.error(' Set it in .env file or export GITHUB_TOKEN=ghp_xxx');
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (!owner || !repo) {
|
|
81
|
+
console.error('ā Could not detect GitHub owner/repo');
|
|
82
|
+
console.error(' Set sync.github.owner and sync.github.repo in .specweave/config.json');
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return { owner, repo, token };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Find increment folder by ID (supports partial matching)
|
|
89
|
+
*/
|
|
90
|
+
async function findIncrementFolder(incrementId) {
|
|
91
|
+
const projectRoot = process.cwd();
|
|
92
|
+
const incrementsDir = path.join(projectRoot, '.specweave/increments');
|
|
93
|
+
if (!existsSync(incrementsDir)) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const entries = await fs.readdir(incrementsDir, { withFileTypes: true });
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
if (!entry.isDirectory())
|
|
99
|
+
continue;
|
|
100
|
+
if (entry.name.startsWith('_'))
|
|
101
|
+
continue; // Skip _archive, _backlog
|
|
102
|
+
// Exact match
|
|
103
|
+
if (entry.name === incrementId) {
|
|
104
|
+
return path.join(incrementsDir, entry.name);
|
|
105
|
+
}
|
|
106
|
+
// Partial match (e.g., "0063" matches "0063-fix-external-import")
|
|
107
|
+
if (entry.name.startsWith(incrementId + '-')) {
|
|
108
|
+
return path.join(incrementsDir, entry.name);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if GitHub issue already exists for this increment
|
|
115
|
+
*/
|
|
116
|
+
async function findExistingIssue(owner, repo, featureId) {
|
|
117
|
+
// Search for issues with this feature ID in title
|
|
118
|
+
const result = await execFileNoThrow('gh', [
|
|
119
|
+
'search', 'issues',
|
|
120
|
+
`repo:${owner}/${repo}`,
|
|
121
|
+
`"[${featureId}]" in:title`,
|
|
122
|
+
'is:open',
|
|
123
|
+
'--json', 'number,title',
|
|
124
|
+
'--limit', '5'
|
|
125
|
+
]);
|
|
126
|
+
if (result.exitCode !== 0 || !result.stdout.trim()) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const issues = JSON.parse(result.stdout);
|
|
131
|
+
if (issues.length > 0) {
|
|
132
|
+
return issues[0].number;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Parse error, no existing issue
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Create GitHub issue via gh CLI
|
|
142
|
+
*/
|
|
143
|
+
async function createGitHubIssue(owner, repo, title, body, labels) {
|
|
144
|
+
const args = [
|
|
145
|
+
'issue', 'create',
|
|
146
|
+
'--repo', `${owner}/${repo}`,
|
|
147
|
+
'--title', title,
|
|
148
|
+
'--body', body
|
|
149
|
+
];
|
|
150
|
+
// Add labels
|
|
151
|
+
if (labels.length > 0) {
|
|
152
|
+
args.push('--label', labels.join(','));
|
|
153
|
+
}
|
|
154
|
+
const result = await execFileNoThrow('gh', args);
|
|
155
|
+
if (result.exitCode !== 0) {
|
|
156
|
+
throw new Error(`Failed to create issue: ${result.stderr || result.stdout}`);
|
|
157
|
+
}
|
|
158
|
+
// Parse issue URL from output
|
|
159
|
+
const urlMatch = result.stdout.match(/https:\/\/github\.com\/[^\s]+\/issues\/(\d+)/);
|
|
160
|
+
if (!urlMatch) {
|
|
161
|
+
throw new Error('Could not parse issue URL from gh output');
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
number: parseInt(urlMatch[1], 10),
|
|
165
|
+
url: urlMatch[0]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Update existing GitHub issue
|
|
170
|
+
*/
|
|
171
|
+
async function updateGitHubIssue(owner, repo, issueNumber, body) {
|
|
172
|
+
const result = await execFileNoThrow('gh', [
|
|
173
|
+
'issue', 'edit',
|
|
174
|
+
String(issueNumber),
|
|
175
|
+
'--repo', `${owner}/${repo}`,
|
|
176
|
+
'--body', body
|
|
177
|
+
]);
|
|
178
|
+
if (result.exitCode !== 0) {
|
|
179
|
+
throw new Error(`Failed to update issue: ${result.stderr || result.stdout}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Load existing GitHub issue link from metadata.json
|
|
184
|
+
* This is the PRIMARY source for existing issue detection
|
|
185
|
+
*/
|
|
186
|
+
function loadExistingGitHubLink(incrementPath) {
|
|
187
|
+
const metadataPath = path.join(incrementPath, 'metadata.json');
|
|
188
|
+
if (!existsSync(metadataPath)) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
193
|
+
// Check for github.issue (new format)
|
|
194
|
+
if (metadata.github?.issue) {
|
|
195
|
+
return {
|
|
196
|
+
issue: metadata.github.issue,
|
|
197
|
+
url: metadata.github.url
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// Check for sync.issueNumber (alternative format)
|
|
201
|
+
if (metadata.sync?.issueNumber) {
|
|
202
|
+
return {
|
|
203
|
+
issue: metadata.sync.issueNumber,
|
|
204
|
+
url: metadata.sync.issueUrl
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Update increment metadata with GitHub issue link
|
|
215
|
+
*/
|
|
216
|
+
async function updateIncrementMetadata(incrementPath, issueNumber, issueUrl) {
|
|
217
|
+
const metadataPath = path.join(incrementPath, 'metadata.json');
|
|
218
|
+
let metadata = {};
|
|
219
|
+
if (existsSync(metadataPath)) {
|
|
220
|
+
try {
|
|
221
|
+
metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Start fresh
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Update github section
|
|
228
|
+
metadata.github = {
|
|
229
|
+
issue: issueNumber,
|
|
230
|
+
url: issueUrl,
|
|
231
|
+
lastSync: new Date().toISOString()
|
|
232
|
+
};
|
|
233
|
+
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2) + '\n');
|
|
234
|
+
}
|
|
235
|
+
async function main() {
|
|
236
|
+
const args = process.argv.slice(2);
|
|
237
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
238
|
+
console.log('Usage: node github-increment-sync-cli.js <increment-id> [options]');
|
|
239
|
+
console.log('');
|
|
240
|
+
console.log('Arguments:');
|
|
241
|
+
console.log(' increment-id Increment ID (e.g., 0063 or 0063-fix-external-import)');
|
|
242
|
+
console.log('');
|
|
243
|
+
console.log('Options:');
|
|
244
|
+
console.log(' --force Force create even if issue exists');
|
|
245
|
+
console.log(' --dry-run Preview issue without creating');
|
|
246
|
+
console.log('');
|
|
247
|
+
console.log('Environment:');
|
|
248
|
+
console.log(' GITHUB_TOKEN Required - GitHub personal access token');
|
|
249
|
+
console.log('');
|
|
250
|
+
console.log('Example:');
|
|
251
|
+
console.log(' GITHUB_TOKEN=ghp_xxx node github-increment-sync-cli.js 0063');
|
|
252
|
+
process.exit(args.length === 0 ? 1 : 0);
|
|
253
|
+
}
|
|
254
|
+
const incrementId = args[0];
|
|
255
|
+
const force = args.includes('--force');
|
|
256
|
+
const dryRun = args.includes('--dry-run');
|
|
257
|
+
console.log(`\nš GitHub Increment Sync CLI`);
|
|
258
|
+
console.log(` Increment: ${incrementId}`);
|
|
259
|
+
// Find increment folder
|
|
260
|
+
const incrementPath = await findIncrementFolder(incrementId);
|
|
261
|
+
if (!incrementPath) {
|
|
262
|
+
console.error(`ā Increment not found: ${incrementId}`);
|
|
263
|
+
console.error(' Check: ls .specweave/increments/');
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
const fullIncrementId = path.basename(incrementPath);
|
|
267
|
+
console.log(` Found: ${fullIncrementId}`);
|
|
268
|
+
// For dry-run, we can skip config validation
|
|
269
|
+
let config = null;
|
|
270
|
+
if (!dryRun) {
|
|
271
|
+
config = await loadGitHubConfig();
|
|
272
|
+
if (!config) {
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
console.log(` Repository: ${config.owner}/${config.repo}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Try to detect repo for dry-run preview (non-fatal)
|
|
279
|
+
config = await loadGitHubConfig().catch(() => null);
|
|
280
|
+
if (config) {
|
|
281
|
+
console.log(` Repository: ${config.owner}/${config.repo}`);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
console.log(` Repository: (not detected - dry run mode)`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// Parse increment and build issue
|
|
288
|
+
const projectRoot = process.cwd();
|
|
289
|
+
const builder = new IncrementIssueBuilder(incrementPath, projectRoot);
|
|
290
|
+
try {
|
|
291
|
+
console.log(`\nš Parsing increment spec.md...`);
|
|
292
|
+
const incrementData = await builder.parse();
|
|
293
|
+
console.log(` š¦ Title: ${incrementData.title}`);
|
|
294
|
+
console.log(` š User Stories: ${incrementData.userStories.length}`);
|
|
295
|
+
const totalACs = incrementData.userStories.reduce((sum, us) => sum + us.acceptanceCriteria.length, 0);
|
|
296
|
+
console.log(` ā Acceptance Criteria: ${totalACs}`);
|
|
297
|
+
// Build issue content
|
|
298
|
+
const githubRepo = config ? `${config.owner}/${config.repo}` : undefined;
|
|
299
|
+
const issue = builder.buildIncrementIssue(incrementData, githubRepo);
|
|
300
|
+
console.log(`\nš Issue Preview:`);
|
|
301
|
+
console.log(` Title: ${issue.title}`);
|
|
302
|
+
console.log(` Labels: ${issue.labels.join(', ')}`);
|
|
303
|
+
if (dryRun) {
|
|
304
|
+
console.log(`\nš Issue Body Preview:\n`);
|
|
305
|
+
console.log(issue.body);
|
|
306
|
+
console.log(`\nā
Dry run complete (no issue created)`);
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
309
|
+
// After dry-run check, config is guaranteed to be non-null
|
|
310
|
+
if (!config) {
|
|
311
|
+
console.error('ā GitHub config not available');
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
// STEP 1: Check metadata.json for existing issue link (PRIMARY detection)
|
|
315
|
+
const metadataLink = loadExistingGitHubLink(incrementPath);
|
|
316
|
+
if (metadataLink) {
|
|
317
|
+
console.log(`\nš Found existing issue link in metadata: #${metadataLink.issue}`);
|
|
318
|
+
// Update existing issue with new format
|
|
319
|
+
console.log(`š Updating issue #${metadataLink.issue} with new format...`);
|
|
320
|
+
// Update body
|
|
321
|
+
await updateGitHubIssue(config.owner, config.repo, metadataLink.issue, issue.body);
|
|
322
|
+
console.log(` ā
Body updated with User Stories and ACs`);
|
|
323
|
+
// Update title to new format (fix the [0002] ā [FS-XXX] issue)
|
|
324
|
+
const updateTitleResult = await execFileNoThrow('gh', [
|
|
325
|
+
'issue', 'edit',
|
|
326
|
+
String(metadataLink.issue),
|
|
327
|
+
'--repo', `${config.owner}/${config.repo}`,
|
|
328
|
+
'--title', issue.title
|
|
329
|
+
]);
|
|
330
|
+
if (updateTitleResult.exitCode === 0) {
|
|
331
|
+
console.log(` ā
Title updated to: ${issue.title}`);
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
console.log(` ā ļø Could not update title (may need permissions)`);
|
|
335
|
+
}
|
|
336
|
+
// Update metadata with lastSync
|
|
337
|
+
await updateIncrementMetadata(incrementPath, metadataLink.issue, `https://github.com/${config.owner}/${config.repo}/issues/${metadataLink.issue}`);
|
|
338
|
+
console.log(`\nā
Sync complete!`);
|
|
339
|
+
console.log(` š https://github.com/${config.owner}/${config.repo}/issues/${metadataLink.issue}`);
|
|
340
|
+
process.exit(0);
|
|
341
|
+
}
|
|
342
|
+
// STEP 2: Search GitHub by feature ID (fallback)
|
|
343
|
+
const featureId = incrementData.frontmatter.feature_id ||
|
|
344
|
+
`FS-${fullIncrementId.match(/^(\d+)/)?.[1]?.padStart(3, '0') || 'UNKNOWN'}`;
|
|
345
|
+
console.log(`\nš Searching GitHub for existing issue [${featureId}]...`);
|
|
346
|
+
const existingIssue = await findExistingIssue(config.owner, config.repo, featureId);
|
|
347
|
+
if (existingIssue) {
|
|
348
|
+
console.log(` Found existing issue: #${existingIssue}`);
|
|
349
|
+
// Update existing issue
|
|
350
|
+
console.log(`š Updating issue #${existingIssue}...`);
|
|
351
|
+
await updateGitHubIssue(config.owner, config.repo, existingIssue, issue.body);
|
|
352
|
+
console.log(` ā
Issue #${existingIssue} updated`);
|
|
353
|
+
await updateIncrementMetadata(incrementPath, existingIssue, `https://github.com/${config.owner}/${config.repo}/issues/${existingIssue}`);
|
|
354
|
+
console.log(`\nā
Sync complete!`);
|
|
355
|
+
console.log(` š https://github.com/${config.owner}/${config.repo}/issues/${existingIssue}`);
|
|
356
|
+
process.exit(0);
|
|
357
|
+
}
|
|
358
|
+
// STEP 3: Create new issue (no existing found)
|
|
359
|
+
console.log(` No existing issue found`);
|
|
360
|
+
console.log(`\nš Creating GitHub issue...`);
|
|
361
|
+
const created = await createGitHubIssue(config.owner, config.repo, issue.title, issue.body, issue.labels);
|
|
362
|
+
console.log(` ā
Issue #${created.number} created`);
|
|
363
|
+
// Update metadata
|
|
364
|
+
await updateIncrementMetadata(incrementPath, created.number, created.url);
|
|
365
|
+
console.log(` š Metadata updated`);
|
|
366
|
+
console.log(`\nā
Sync complete!`);
|
|
367
|
+
console.log(` š ${created.url}`);
|
|
368
|
+
process.exit(0);
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
console.error(`\nā Sync failed:`, error);
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Run CLI
|
|
376
|
+
main().catch(error => {
|
|
377
|
+
console.error('Fatal error:', error);
|
|
378
|
+
process.exit(1);
|
|
379
|
+
});
|
|
380
|
+
//# sourceMappingURL=github-increment-sync-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-increment-sync-cli.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-increment-sync-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Increment Issue Builder - Generate GitHub issues from increment spec.md
|
|
3
|
+
*
|
|
4
|
+
* For brownfield projects without full living docs structure,
|
|
5
|
+
* this builder extracts User Stories and ACs directly from spec.md
|
|
6
|
+
* and generates properly formatted GitHub issues.
|
|
7
|
+
*
|
|
8
|
+
* Correct format: [FS-XXX][US-YYY] User Story Title
|
|
9
|
+
* With ACs as checkable items in issue body.
|
|
10
|
+
*
|
|
11
|
+
* @see ADR-0143 (GitHub Issue Format)
|
|
12
|
+
*/
|
|
13
|
+
export interface IncrementFrontmatter {
|
|
14
|
+
increment: string;
|
|
15
|
+
feature_id?: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
status?: string;
|
|
18
|
+
created?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface AcceptanceCriterion {
|
|
21
|
+
id: string;
|
|
22
|
+
description: string;
|
|
23
|
+
completed: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface UserStory {
|
|
26
|
+
id: string;
|
|
27
|
+
title: string;
|
|
28
|
+
asA: string;
|
|
29
|
+
iWant: string;
|
|
30
|
+
soThat: string;
|
|
31
|
+
acceptanceCriteria: AcceptanceCriterion[];
|
|
32
|
+
}
|
|
33
|
+
export interface Task {
|
|
34
|
+
id: string;
|
|
35
|
+
title: string;
|
|
36
|
+
completed: boolean;
|
|
37
|
+
userStories: string[];
|
|
38
|
+
priority?: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface IncrementData {
|
|
42
|
+
frontmatter: IncrementFrontmatter;
|
|
43
|
+
title: string;
|
|
44
|
+
problemStatement: string;
|
|
45
|
+
userStories: UserStory[];
|
|
46
|
+
tasks: Task[];
|
|
47
|
+
outOfScope: string[];
|
|
48
|
+
}
|
|
49
|
+
export interface GitHubIssueContent {
|
|
50
|
+
title: string;
|
|
51
|
+
body: string;
|
|
52
|
+
labels: string[];
|
|
53
|
+
}
|
|
54
|
+
export declare class IncrementIssueBuilder {
|
|
55
|
+
private incrementPath;
|
|
56
|
+
private projectRoot;
|
|
57
|
+
constructor(incrementPath: string, projectRoot: string);
|
|
58
|
+
/**
|
|
59
|
+
* Parse increment spec.md and extract all data
|
|
60
|
+
*/
|
|
61
|
+
parse(): Promise<IncrementData>;
|
|
62
|
+
/**
|
|
63
|
+
* Extract tasks from tasks.md
|
|
64
|
+
*/
|
|
65
|
+
private extractTasks;
|
|
66
|
+
/**
|
|
67
|
+
* Extract a section by heading
|
|
68
|
+
*/
|
|
69
|
+
private extractSection;
|
|
70
|
+
/**
|
|
71
|
+
* Extract user stories from spec.md
|
|
72
|
+
*/
|
|
73
|
+
private extractUserStories;
|
|
74
|
+
/**
|
|
75
|
+
* Extract acceptance criteria from a user story block
|
|
76
|
+
*/
|
|
77
|
+
private extractAcceptanceCriteria;
|
|
78
|
+
/**
|
|
79
|
+
* Build GitHub issue for a single user story
|
|
80
|
+
*/
|
|
81
|
+
buildUserStoryIssue(story: UserStory, incrementData: IncrementData, githubRepo?: string): GitHubIssueContent;
|
|
82
|
+
/**
|
|
83
|
+
* Build GitHub issue for the entire increment (epic-style)
|
|
84
|
+
*/
|
|
85
|
+
buildIncrementIssue(incrementData: IncrementData, githubRepo?: string): GitHubIssueContent;
|
|
86
|
+
/**
|
|
87
|
+
* Generate a feature ID if not present in frontmatter
|
|
88
|
+
* Uses date-based format: FS-YY-MM-DD
|
|
89
|
+
*/
|
|
90
|
+
private generateFeatureId;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=increment-issue-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"increment-issue-builder.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/increment-issue-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,oBAAoB,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAKtD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;IAgDrC;;OAEG;YACW,YAAY;IAgE1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwC1B;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAuBjC;;OAEG;IACH,mBAAmB,CACjB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,aAAa,EAC5B,UAAU,CAAC,EAAE,MAAM,GAClB,kBAAkB;IAmErB;;OAEG;IACH,mBAAmB,CACjB,aAAa,EAAE,aAAa,EAC5B,UAAU,CAAC,EAAE,MAAM,GAClB,kBAAkB;IAkGrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CAkB1B"}
|