sedd 0.1.8 → 0.1.10
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/README.md +140 -2
- package/commands/sedd.board.md +67 -0
- package/commands/sedd.clarify.md +86 -21
- package/commands/sedd.specify.md +27 -1
- package/dist/cli/board.d.ts +9 -0
- package/dist/cli/board.d.ts.map +1 -0
- package/dist/cli/board.js +211 -0
- package/dist/cli/board.js.map +1 -0
- package/dist/cli/clarify.d.ts +5 -1
- package/dist/cli/clarify.d.ts.map +1 -1
- package/dist/cli/clarify.js +52 -8
- package/dist/cli/clarify.js.map +1 -1
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup-github.d.ts +5 -0
- package/dist/cli/setup-github.d.ts.map +1 -0
- package/dist/cli/setup-github.js +437 -0
- package/dist/cli/setup-github.js.map +1 -0
- package/dist/cli/specify.d.ts +1 -0
- package/dist/cli/specify.d.ts.map +1 -1
- package/dist/cli/specify.js +97 -9
- package/dist/cli/specify.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +31 -0
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/tasks.d.ts.map +1 -1
- package/dist/cli/tasks.js +102 -1
- package/dist/cli/tasks.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +21 -0
- package/dist/cli/update.js.map +1 -1
- package/dist/core/board-manager.d.ts +65 -0
- package/dist/core/board-manager.d.ts.map +1 -0
- package/dist/core/board-manager.js +326 -0
- package/dist/core/board-manager.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +117 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/github.d.ts +99 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +488 -0
- package/dist/utils/github.js.map +1 -0
- package/package.json +61 -61
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { loadConfig } from '../types/index.js';
|
|
7
|
+
import { GitHubOperations } from '../utils/github.js';
|
|
8
|
+
function saveConfig(cwd, config) {
|
|
9
|
+
const configPath = join(cwd, 'sedd.config.json');
|
|
10
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
11
|
+
}
|
|
12
|
+
export async function githubSetup() {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const config = loadConfig(cwd);
|
|
15
|
+
const gh = new GitHubOperations(cwd);
|
|
16
|
+
console.log(chalk.cyan.bold('\nSEDD GitHub Integration Setup'));
|
|
17
|
+
console.log(chalk.gray('━'.repeat(36)));
|
|
18
|
+
console.log(chalk.white('\nStep 1/7: Checking GitHub CLI...'));
|
|
19
|
+
if (!gh.hasGh()) {
|
|
20
|
+
console.log(chalk.red(' ✗ gh CLI not found'));
|
|
21
|
+
console.log(chalk.yellow(' Install it:'));
|
|
22
|
+
console.log(chalk.gray(' Windows: winget install GitHub.cli'));
|
|
23
|
+
console.log(chalk.gray(' Mac: brew install gh'));
|
|
24
|
+
console.log(chalk.gray(' Linux: sudo apt install gh'));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const version = gh.getGhVersion();
|
|
28
|
+
console.log(chalk.green(` ✓ gh v${version} found`));
|
|
29
|
+
console.log(chalk.white('\nStep 2/7: Checking authentication...'));
|
|
30
|
+
if (!gh.isAuthenticated()) {
|
|
31
|
+
console.log(chalk.red(' ✗ Not authenticated'));
|
|
32
|
+
const { runLogin } = await inquirer.prompt([{
|
|
33
|
+
type: 'confirm',
|
|
34
|
+
name: 'runLogin',
|
|
35
|
+
message: 'Run "gh auth login" now?',
|
|
36
|
+
default: true,
|
|
37
|
+
}]);
|
|
38
|
+
if (!runLogin) {
|
|
39
|
+
console.log(chalk.yellow(' Run manually: gh auth login'));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.log(chalk.cyan('\n Starting gh auth login...'));
|
|
43
|
+
console.log(chalk.gray(' Select: GitHub.com > HTTPS > Login with a web browser'));
|
|
44
|
+
console.log(chalk.gray(' Copy the code from the terminal and paste it in the browser when prompted.\n'));
|
|
45
|
+
try {
|
|
46
|
+
execSync('gh auth login -h github.com -p https -w', { cwd: process.cwd(), stdio: 'inherit' });
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
console.log(chalk.red('\n ✗ Authentication failed'));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
if (!gh.isAuthenticated()) {
|
|
53
|
+
console.log(chalk.red(' ✗ Still not authenticated'));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const username = gh.getUsername();
|
|
58
|
+
console.log(chalk.green(` ✓ Logged in as ${username || 'unknown'}`));
|
|
59
|
+
console.log(chalk.white('\nStep 3/7: Checking project scope...'));
|
|
60
|
+
const hasScope = gh.hasProjectScope();
|
|
61
|
+
if (!hasScope) {
|
|
62
|
+
console.log(chalk.yellow(' ⚠ Scope "project" not found'));
|
|
63
|
+
const { addScope } = await inquirer.prompt([{
|
|
64
|
+
type: 'confirm',
|
|
65
|
+
name: 'addScope',
|
|
66
|
+
message: 'Run "gh auth refresh -s project" to add it?',
|
|
67
|
+
default: true,
|
|
68
|
+
}]);
|
|
69
|
+
if (addScope) {
|
|
70
|
+
console.log(chalk.gray('\n Copy the code from the terminal and paste it in the browser when prompted.\n'));
|
|
71
|
+
try {
|
|
72
|
+
execSync('gh auth refresh -s project', { cwd: process.cwd(), stdio: 'inherit' });
|
|
73
|
+
console.log(chalk.green(' ✓ Project scope added'));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
console.log(chalk.yellow(' ⚠ Could not add scope. Continuing anyway...'));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log(chalk.yellow(' Continuing without project scope. You may see permission errors.'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(chalk.green(' ✓ Project scope available'));
|
|
85
|
+
}
|
|
86
|
+
console.log(chalk.white('\nStep 4/7: Detecting repository...'));
|
|
87
|
+
const ownerRepo = gh.detectOwnerRepo();
|
|
88
|
+
if (!ownerRepo) {
|
|
89
|
+
console.log(chalk.red(' ✗ Could not detect owner/repo from git remote'));
|
|
90
|
+
console.log(chalk.yellow(' Make sure this is a GitHub repository with a remote set.'));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
console.log(chalk.green(` ✓ ${ownerRepo.owner}/${ownerRepo.repo} (from git remote)`));
|
|
94
|
+
console.log(chalk.white('\nStep 5/7: Select organization...'));
|
|
95
|
+
console.log(chalk.gray(` Detected owner: ${ownerRepo.owner} (from git remote)`));
|
|
96
|
+
const orgs = gh.listUserOrganizations();
|
|
97
|
+
const ownerChoices = buildOwnerChoices(username, orgs);
|
|
98
|
+
console.log(chalk.gray('\n Available:'));
|
|
99
|
+
ownerChoices.forEach((c, i) => {
|
|
100
|
+
console.log(chalk.white(` ${i + 1}. ${c.label}`));
|
|
101
|
+
});
|
|
102
|
+
const detectedIndex = ownerChoices.findIndex(c => c.value === ownerRepo.owner);
|
|
103
|
+
const defaultOwnerIndex = detectedIndex >= 0 ? detectedIndex + 1 : 1;
|
|
104
|
+
const { ownerIndex } = await inquirer.prompt([{
|
|
105
|
+
type: 'number',
|
|
106
|
+
name: 'ownerIndex',
|
|
107
|
+
message: `Select owner for projects [1-${ownerChoices.length}]:`,
|
|
108
|
+
default: defaultOwnerIndex,
|
|
109
|
+
validate: (val) => val >= 1 && val <= ownerChoices.length ? true : `Enter 1-${ownerChoices.length}`,
|
|
110
|
+
}]);
|
|
111
|
+
let selectedOwner = ownerChoices[ownerIndex - 1].value;
|
|
112
|
+
if (selectedOwner === '__manual__') {
|
|
113
|
+
const { manualOwner } = await inquirer.prompt([{
|
|
114
|
+
type: 'input',
|
|
115
|
+
name: 'manualOwner',
|
|
116
|
+
message: 'Enter organization/user login:',
|
|
117
|
+
validate: (val) => val.trim().length > 0 ? true : 'Cannot be empty',
|
|
118
|
+
}]);
|
|
119
|
+
selectedOwner = manualOwner.trim();
|
|
120
|
+
}
|
|
121
|
+
console.log(chalk.green(` ✓ Using: ${selectedOwner}`));
|
|
122
|
+
console.log(chalk.white('\nStep 6/7: Select project...'));
|
|
123
|
+
const projects = gh.listProjects(selectedOwner);
|
|
124
|
+
if (projects.length === 0) {
|
|
125
|
+
console.log(chalk.yellow(' No projects found.'));
|
|
126
|
+
console.log(chalk.gray(' Create one at: github.com → repo → Projects → New Project → Board'));
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
console.log(chalk.gray(' Projects found:'));
|
|
130
|
+
projects.forEach((p, i) => {
|
|
131
|
+
console.log(chalk.white(` ${i + 1}. ${p.title} (#${p.number})`));
|
|
132
|
+
});
|
|
133
|
+
const { projectIndex } = await inquirer.prompt([{
|
|
134
|
+
type: 'number',
|
|
135
|
+
name: 'projectIndex',
|
|
136
|
+
message: `Select [1-${projects.length}]:`,
|
|
137
|
+
default: 1,
|
|
138
|
+
validate: (val) => val >= 1 && val <= projects.length ? true : `Enter 1-${projects.length}`,
|
|
139
|
+
}]);
|
|
140
|
+
const selectedProject = projects[projectIndex - 1];
|
|
141
|
+
console.log(chalk.green(` ✓ Selected: ${selectedProject.title}`));
|
|
142
|
+
console.log(chalk.white('\nStep 7/7: Reading board columns...'));
|
|
143
|
+
const statusField = gh.getStatusField(selectedProject.id);
|
|
144
|
+
if (!statusField || !statusField.options || statusField.options.length === 0) {
|
|
145
|
+
console.log(chalk.red(' ✗ Could not read Status field columns'));
|
|
146
|
+
console.log(chalk.yellow(' Make sure your project has a "Status" field with options.'));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const columnNames = statusField.options.map(o => o.name);
|
|
150
|
+
const columnOptions = {};
|
|
151
|
+
for (const opt of statusField.options) {
|
|
152
|
+
columnOptions[opt.name] = opt.id;
|
|
153
|
+
}
|
|
154
|
+
console.log(chalk.gray(` Columns found: ${columnNames.join(', ')}`));
|
|
155
|
+
const defaultMapping = {
|
|
156
|
+
pending: findBestMatch(columnNames, ['Todo', 'To Do', 'Backlog', 'New']),
|
|
157
|
+
'in-progress': findBestMatch(columnNames, ['In Progress', 'Doing', 'Active', 'Working']),
|
|
158
|
+
completed: findBestMatch(columnNames, ['Done', 'Completed', 'Closed', 'Finished']),
|
|
159
|
+
blocked: findBestMatch(columnNames, ['Blocked', 'On Hold', 'Waiting']),
|
|
160
|
+
};
|
|
161
|
+
console.log(chalk.gray('\n Column mapping:'));
|
|
162
|
+
console.log(chalk.gray(` pending → ${defaultMapping.pending || '(none)'}`));
|
|
163
|
+
console.log(chalk.gray(` in-progress → ${defaultMapping['in-progress'] || '(none)'}`));
|
|
164
|
+
console.log(chalk.gray(` completed → ${defaultMapping.completed || '(none)'}`));
|
|
165
|
+
console.log(chalk.gray(` blocked → ${defaultMapping.blocked || '(none)'}`));
|
|
166
|
+
const { customizeMapping } = await inquirer.prompt([{
|
|
167
|
+
type: 'confirm',
|
|
168
|
+
name: 'customizeMapping',
|
|
169
|
+
message: 'Customize column mapping?',
|
|
170
|
+
default: false,
|
|
171
|
+
}]);
|
|
172
|
+
let columnMapping = defaultMapping;
|
|
173
|
+
if (customizeMapping) {
|
|
174
|
+
const choices = [...columnNames, '(none - skip)'];
|
|
175
|
+
const answers = await inquirer.prompt([
|
|
176
|
+
{ type: 'list', name: 'pending', message: 'Map "pending" to:', choices, default: defaultMapping.pending || choices[0] },
|
|
177
|
+
{ type: 'list', name: 'in-progress', message: 'Map "in-progress" to:', choices, default: defaultMapping['in-progress'] || choices[0] },
|
|
178
|
+
{ type: 'list', name: 'completed', message: 'Map "completed" to:', choices, default: defaultMapping.completed || choices[0] },
|
|
179
|
+
{ type: 'list', name: 'blocked', message: 'Map "blocked" to:', choices, default: defaultMapping.blocked || choices[0] },
|
|
180
|
+
]);
|
|
181
|
+
columnMapping = {
|
|
182
|
+
pending: answers.pending === '(none - skip)' ? '' : answers.pending,
|
|
183
|
+
'in-progress': answers['in-progress'] === '(none - skip)' ? '' : answers['in-progress'],
|
|
184
|
+
completed: answers.completed === '(none - skip)' ? '' : answers.completed,
|
|
185
|
+
blocked: answers.blocked === '(none - skip)' ? '' : answers.blocked,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const { setWip } = await inquirer.prompt([{
|
|
189
|
+
type: 'confirm',
|
|
190
|
+
name: 'setWip',
|
|
191
|
+
message: 'Set WIP limits? (optional)',
|
|
192
|
+
default: false,
|
|
193
|
+
}]);
|
|
194
|
+
let wipLimits;
|
|
195
|
+
let wipEnforcement;
|
|
196
|
+
if (setWip) {
|
|
197
|
+
wipLimits = {};
|
|
198
|
+
for (const col of columnNames) {
|
|
199
|
+
const { limit } = await inquirer.prompt([{
|
|
200
|
+
type: 'number',
|
|
201
|
+
name: 'limit',
|
|
202
|
+
message: ` ${col} max (0 = unlimited):`,
|
|
203
|
+
default: 0,
|
|
204
|
+
}]);
|
|
205
|
+
if (limit > 0) {
|
|
206
|
+
wipLimits[col] = limit;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const { enforcement } = await inquirer.prompt([{
|
|
210
|
+
type: 'list',
|
|
211
|
+
name: 'enforcement',
|
|
212
|
+
message: 'WIP enforcement mode:',
|
|
213
|
+
choices: [
|
|
214
|
+
{ name: 'Warn (show warning but allow)', value: 'warn' },
|
|
215
|
+
{ name: 'Block (prevent exceeding limits)', value: 'block' },
|
|
216
|
+
],
|
|
217
|
+
default: 'warn',
|
|
218
|
+
}]);
|
|
219
|
+
wipEnforcement = enforcement;
|
|
220
|
+
}
|
|
221
|
+
const { engine } = await inquirer.prompt([{
|
|
222
|
+
type: 'list',
|
|
223
|
+
name: 'engine',
|
|
224
|
+
message: 'Task engine mode:',
|
|
225
|
+
choices: [
|
|
226
|
+
{ name: 'both - Local tasks + GitHub sync (Recommended)', value: 'both' },
|
|
227
|
+
{ name: 'github - GitHub issues only', value: 'github' },
|
|
228
|
+
{ name: 'local - Local only (no sync)', value: 'local' },
|
|
229
|
+
],
|
|
230
|
+
default: 'both',
|
|
231
|
+
}]);
|
|
232
|
+
const { autoSync } = await inquirer.prompt([{
|
|
233
|
+
type: 'list',
|
|
234
|
+
name: 'autoSync',
|
|
235
|
+
message: 'Auto-sync behavior when moving tasks:',
|
|
236
|
+
choices: [
|
|
237
|
+
{ name: 'ask - Ask before syncing to GitHub (Recommended)', value: 'ask' },
|
|
238
|
+
{ name: 'auto - Sync automatically without asking', value: 'auto' },
|
|
239
|
+
{ name: 'off - Never sync automatically (manual only)', value: 'off' },
|
|
240
|
+
],
|
|
241
|
+
default: 'ask',
|
|
242
|
+
}]);
|
|
243
|
+
const githubConfig = {
|
|
244
|
+
engine,
|
|
245
|
+
owner: selectedOwner,
|
|
246
|
+
repo: ownerRepo.repo,
|
|
247
|
+
project: {
|
|
248
|
+
projectNumber: selectedProject.number,
|
|
249
|
+
projectId: selectedProject.id,
|
|
250
|
+
title: selectedProject.title,
|
|
251
|
+
},
|
|
252
|
+
columns: {
|
|
253
|
+
fieldId: statusField.id,
|
|
254
|
+
options: columnOptions,
|
|
255
|
+
},
|
|
256
|
+
columnMapping,
|
|
257
|
+
wipLimits: wipLimits && Object.keys(wipLimits).length > 0 ? wipLimits : undefined,
|
|
258
|
+
wipEnforcement,
|
|
259
|
+
autoSync,
|
|
260
|
+
};
|
|
261
|
+
config.github = githubConfig;
|
|
262
|
+
saveConfig(cwd, config);
|
|
263
|
+
console.log(chalk.green('\n✓ Saved to sedd.config.json'));
|
|
264
|
+
console.log(chalk.cyan('\nGitHub integration is ready!'));
|
|
265
|
+
console.log(chalk.gray(' Run "sedd github status" to verify.'));
|
|
266
|
+
console.log(chalk.gray(' Run "sedd board" to see your kanban board.\n'));
|
|
267
|
+
}
|
|
268
|
+
export async function githubStatus() {
|
|
269
|
+
const cwd = process.cwd();
|
|
270
|
+
const config = loadConfig(cwd);
|
|
271
|
+
const gh = new GitHubOperations(cwd);
|
|
272
|
+
console.log(chalk.cyan.bold('\nSEDD GitHub Integration Status\n'));
|
|
273
|
+
if (!config.github || config.github.engine === 'local') {
|
|
274
|
+
console.log(chalk.yellow('Engine: local (GitHub integration not configured)'));
|
|
275
|
+
console.log(chalk.gray('Run "sedd github setup" to configure.\n'));
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const ghConfig = config.github;
|
|
279
|
+
console.log(chalk.gray('Engine:'), chalk.white(ghConfig.engine));
|
|
280
|
+
console.log(chalk.gray('Repository:'), chalk.white(`${ghConfig.owner}/${ghConfig.repo}`));
|
|
281
|
+
if (ghConfig.project) {
|
|
282
|
+
console.log(chalk.gray('Project:'), chalk.white(`${ghConfig.project.title} (#${ghConfig.project.projectNumber})`));
|
|
283
|
+
}
|
|
284
|
+
console.log(chalk.gray('\nConnection test:'));
|
|
285
|
+
if (!gh.hasGh()) {
|
|
286
|
+
console.log(chalk.red(' ✗ gh CLI not found'));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
console.log(chalk.green(' ✓ gh CLI available'));
|
|
290
|
+
if (!gh.isAuthenticated()) {
|
|
291
|
+
console.log(chalk.red(' ✗ Not authenticated'));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
console.log(chalk.green(' ✓ Authenticated'));
|
|
295
|
+
if (ghConfig.project) {
|
|
296
|
+
const statusField = gh.getStatusField(ghConfig.project.projectId);
|
|
297
|
+
if (statusField && statusField.options) {
|
|
298
|
+
const currentCols = statusField.options.map(o => o.name);
|
|
299
|
+
const configCols = Object.keys(ghConfig.columns.options);
|
|
300
|
+
const missing = configCols.filter(c => !currentCols.includes(c));
|
|
301
|
+
if (missing.length > 0) {
|
|
302
|
+
console.log(chalk.yellow(` ⚠ Columns changed on GitHub. Missing: ${missing.join(', ')}`));
|
|
303
|
+
console.log(chalk.gray(' Run "sedd github refresh" to update.'));
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
console.log(chalk.green(' ✓ Columns valid'));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
console.log(chalk.gray('\nColumn mapping:'));
|
|
311
|
+
const mapping = ghConfig.columnMapping;
|
|
312
|
+
console.log(chalk.gray(` pending → ${mapping.pending || '(none)'}`));
|
|
313
|
+
console.log(chalk.gray(` in-progress → ${mapping['in-progress'] || '(none)'}`));
|
|
314
|
+
console.log(chalk.gray(` completed → ${mapping.completed || '(none)'}`));
|
|
315
|
+
console.log(chalk.gray(` blocked → ${mapping.blocked || '(none)'}`));
|
|
316
|
+
if (ghConfig.wipLimits) {
|
|
317
|
+
console.log(chalk.gray('\nWIP limits:'));
|
|
318
|
+
for (const [col, limit] of Object.entries(ghConfig.wipLimits)) {
|
|
319
|
+
if (limit)
|
|
320
|
+
console.log(chalk.gray(` ${col}: ${limit}`));
|
|
321
|
+
}
|
|
322
|
+
console.log(chalk.gray(` Enforcement: ${ghConfig.wipEnforcement || 'warn'}`));
|
|
323
|
+
}
|
|
324
|
+
console.log('');
|
|
325
|
+
}
|
|
326
|
+
export async function githubSync() {
|
|
327
|
+
const cwd = process.cwd();
|
|
328
|
+
const config = loadConfig(cwd);
|
|
329
|
+
if (!config.github || config.github.engine === 'local') {
|
|
330
|
+
console.log(chalk.yellow('GitHub integration not configured. Run "sedd github setup" first.'));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const { BoardManager } = await import('../core/board-manager.js');
|
|
334
|
+
const { GitOperations } = await import('../utils/git.js');
|
|
335
|
+
const git = new GitOperations(cwd);
|
|
336
|
+
const bm = new BoardManager(config, cwd);
|
|
337
|
+
if (!bm.isGitHubEnabled()) {
|
|
338
|
+
console.log(chalk.yellow('GitHub sync not enabled. Check gh CLI and engine config.'));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const specsDir = join(cwd, config.specsDir);
|
|
342
|
+
const { readdirSync } = await import('node:fs');
|
|
343
|
+
const featureDirs = readdirSync(specsDir, { withFileTypes: true })
|
|
344
|
+
.filter(d => d.isDirectory() && /^\d{3}-/.test(d.name))
|
|
345
|
+
.map(d => d.name);
|
|
346
|
+
if (featureDirs.length === 0) {
|
|
347
|
+
console.log(chalk.yellow('No features found.'));
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
console.log(chalk.cyan('Syncing with GitHub...\n'));
|
|
351
|
+
let totalCreated = 0;
|
|
352
|
+
let totalMoved = 0;
|
|
353
|
+
let totalSynced = 0;
|
|
354
|
+
const allErrors = [];
|
|
355
|
+
for (const feature of featureDirs) {
|
|
356
|
+
const featureDir = join(specsDir, feature);
|
|
357
|
+
const metaPath = join(featureDir, '_meta.json');
|
|
358
|
+
if (!existsSync(metaPath))
|
|
359
|
+
continue;
|
|
360
|
+
const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
|
|
361
|
+
const result = bm.syncToGitHub(featureDir, meta);
|
|
362
|
+
totalCreated += result.created;
|
|
363
|
+
totalMoved += result.moved;
|
|
364
|
+
totalSynced += result.synced;
|
|
365
|
+
allErrors.push(...result.errors);
|
|
366
|
+
if (result.created > 0 || result.moved > 0) {
|
|
367
|
+
console.log(chalk.green(` ✓ ${feature}: created ${result.created}, moved ${result.moved}`));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
console.log(chalk.green(`\n✓ Sync complete: ${totalSynced} synced, ${totalCreated} created, ${totalMoved} moved`));
|
|
371
|
+
if (allErrors.length > 0) {
|
|
372
|
+
allErrors.forEach(e => console.log(chalk.yellow(` ⚠ ${e}`)));
|
|
373
|
+
}
|
|
374
|
+
console.log('');
|
|
375
|
+
}
|
|
376
|
+
export async function githubRefresh() {
|
|
377
|
+
const cwd = process.cwd();
|
|
378
|
+
const config = loadConfig(cwd);
|
|
379
|
+
const gh = new GitHubOperations(cwd);
|
|
380
|
+
if (!config.github?.project) {
|
|
381
|
+
console.log(chalk.yellow('No GitHub project configured. Run "sedd github setup" first.'));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
console.log(chalk.cyan('Refreshing columns from GitHub...'));
|
|
385
|
+
const statusField = gh.getStatusField(config.github.project.projectId);
|
|
386
|
+
if (!statusField || !statusField.options) {
|
|
387
|
+
console.log(chalk.red('Could not read Status field from project.'));
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const newOptions = {};
|
|
391
|
+
for (const opt of statusField.options) {
|
|
392
|
+
newOptions[opt.name] = opt.id;
|
|
393
|
+
}
|
|
394
|
+
config.github.columns = {
|
|
395
|
+
fieldId: statusField.id,
|
|
396
|
+
options: newOptions,
|
|
397
|
+
};
|
|
398
|
+
saveConfig(cwd, config);
|
|
399
|
+
const columnNames = statusField.options.map(o => o.name);
|
|
400
|
+
console.log(chalk.green(`✓ Updated columns: ${columnNames.join(', ')}`));
|
|
401
|
+
const mapping = config.github.columnMapping;
|
|
402
|
+
const invalid = [];
|
|
403
|
+
for (const [seddStatus, colName] of Object.entries(mapping)) {
|
|
404
|
+
if (colName && !columnNames.includes(colName)) {
|
|
405
|
+
invalid.push(`${seddStatus} → ${colName}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (invalid.length > 0) {
|
|
409
|
+
console.log(chalk.yellow(`\n⚠ Some mappings reference removed columns:`));
|
|
410
|
+
invalid.forEach(m => console.log(chalk.yellow(` ${m}`)));
|
|
411
|
+
console.log(chalk.gray(' Run "sedd github setup" to reconfigure mapping.'));
|
|
412
|
+
}
|
|
413
|
+
console.log('');
|
|
414
|
+
}
|
|
415
|
+
function buildOwnerChoices(username, orgs) {
|
|
416
|
+
const choices = [];
|
|
417
|
+
if (username) {
|
|
418
|
+
choices.push({ label: `${username} (personal)`, value: username });
|
|
419
|
+
}
|
|
420
|
+
for (const org of orgs) {
|
|
421
|
+
if (org.login === username)
|
|
422
|
+
continue;
|
|
423
|
+
const label = org.name !== org.login ? `${org.login} (${org.name})` : org.login;
|
|
424
|
+
choices.push({ label, value: org.login });
|
|
425
|
+
}
|
|
426
|
+
choices.push({ label: 'Enter manually...', value: '__manual__' });
|
|
427
|
+
return choices;
|
|
428
|
+
}
|
|
429
|
+
function findBestMatch(columns, candidates) {
|
|
430
|
+
for (const candidate of candidates) {
|
|
431
|
+
const found = columns.find(c => c.toLowerCase() === candidate.toLowerCase());
|
|
432
|
+
if (found)
|
|
433
|
+
return found;
|
|
434
|
+
}
|
|
435
|
+
return '';
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=setup-github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-github.js","sourceRoot":"","sources":["../../src/cli/setup-github.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/specify.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specify.d.ts","sourceRoot":"","sources":["../../src/cli/specify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"specify.d.ts","sourceRoot":"","sources":["../../src/cli/specify.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA4Of"}
|
package/dist/cli/specify.js
CHANGED
|
@@ -2,10 +2,54 @@ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { loadConfig } from '../types/index.js';
|
|
5
|
+
import { GitOperations } from '../utils/git.js';
|
|
6
|
+
import { GitHubOperations } from '../utils/github.js';
|
|
7
|
+
import { BoardManager } from '../core/board-manager.js';
|
|
5
8
|
export async function specify(featureId, featureName, options = {}) {
|
|
6
9
|
const cwd = process.cwd();
|
|
7
10
|
const config = loadConfig(cwd);
|
|
11
|
+
const gh = new GitHubOperations(cwd);
|
|
12
|
+
const bm = new BoardManager(config, cwd);
|
|
13
|
+
let issueData = null;
|
|
14
|
+
let sourceIssue;
|
|
15
|
+
if (options.fromIssue) {
|
|
16
|
+
console.log(chalk.blue('i'), `Fetching issue from: ${options.fromIssue}`);
|
|
17
|
+
const issue = gh.getIssueFromUrl(options.fromIssue);
|
|
18
|
+
if (!issue) {
|
|
19
|
+
console.log(chalk.red('Error: Could not fetch issue from URL'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
issueData = issue;
|
|
23
|
+
sourceIssue = {
|
|
24
|
+
number: issue.number,
|
|
25
|
+
url: issue.url || options.fromIssue,
|
|
26
|
+
title: issue.title,
|
|
27
|
+
};
|
|
28
|
+
// Use issue title as feature name if the provided one is a placeholder
|
|
29
|
+
if (featureName === '_' || featureName === 'from-issue') {
|
|
30
|
+
featureName = issue.title
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
33
|
+
.replace(/^-|-$/g, '')
|
|
34
|
+
.substring(0, 50);
|
|
35
|
+
}
|
|
36
|
+
console.log(chalk.green('✓'), `Issue #${issue.number}: ${issue.title}`);
|
|
37
|
+
}
|
|
8
38
|
const branchName = `${featureId}-${featureName}`;
|
|
39
|
+
const git = new GitOperations(cwd);
|
|
40
|
+
const currentBranch = git.getCurrentBranch();
|
|
41
|
+
if (!git.isFeatureBranch(currentBranch)) {
|
|
42
|
+
console.log(chalk.blue('i'), `On ${currentBranch}, creating feature branch...`);
|
|
43
|
+
const success = git.createBranch(branchName);
|
|
44
|
+
if (!success) {
|
|
45
|
+
console.log(chalk.red('Error: Could not create branch'), branchName);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
console.log(chalk.green('✓'), `Created and switched to branch: ${branchName}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(chalk.blue('i'), `Already on feature branch: ${currentBranch}`);
|
|
52
|
+
}
|
|
9
53
|
const featureDir = join(cwd, config.specsDir, branchName);
|
|
10
54
|
if (existsSync(featureDir)) {
|
|
11
55
|
console.log(chalk.yellow(`Feature already exists: ${featureDir}`));
|
|
@@ -13,9 +57,12 @@ export async function specify(featureId, featureName, options = {}) {
|
|
|
13
57
|
}
|
|
14
58
|
mkdirSync(featureDir, { recursive: true });
|
|
15
59
|
console.log(chalk.green('✓'), `Created: ${featureDir}`);
|
|
60
|
+
if (issueData?.body) {
|
|
61
|
+
issueData.body = gh.downloadIssueImages(issueData.body, featureDir);
|
|
62
|
+
}
|
|
16
63
|
const now = new Date().toISOString();
|
|
17
|
-
const description = options.description || '';
|
|
18
|
-
const expectation = options.expectation || '';
|
|
64
|
+
const description = issueData?.body || options.description || '';
|
|
65
|
+
const expectation = options.expectation || (issueData ? issueData.title : '');
|
|
19
66
|
const meta = {
|
|
20
67
|
featureId,
|
|
21
68
|
featureName,
|
|
@@ -27,9 +74,17 @@ export async function specify(featureId, featureName, options = {}) {
|
|
|
27
74
|
splits: [],
|
|
28
75
|
commits: [],
|
|
29
76
|
expectation: expectation || undefined,
|
|
77
|
+
sourceIssue,
|
|
30
78
|
};
|
|
31
79
|
writeFileSync(join(featureDir, '_meta.json'), JSON.stringify(meta, null, 2), 'utf-8');
|
|
32
80
|
console.log(chalk.green('✓'), 'Created: _meta.json');
|
|
81
|
+
let acceptanceCriteria = '';
|
|
82
|
+
if (issueData?.body) {
|
|
83
|
+
const acMatch = issueData.body.match(/##?\s*acceptance\s*criteria[\s\S]*?(?=##|$)/i);
|
|
84
|
+
if (acMatch) {
|
|
85
|
+
acceptanceCriteria = acMatch[0].trim();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
33
88
|
const expectationSection = expectation
|
|
34
89
|
? `## Expectation
|
|
35
90
|
|
|
@@ -43,9 +98,16 @@ export async function specify(featureId, featureName, options = {}) {
|
|
|
43
98
|
[Define your expectation here]
|
|
44
99
|
|
|
45
100
|
`;
|
|
101
|
+
const issueSection = sourceIssue
|
|
102
|
+
? `## Source Issue
|
|
103
|
+
|
|
104
|
+
> [#${sourceIssue.number}](${sourceIssue.url}) — ${sourceIssue.title}
|
|
105
|
+
|
|
106
|
+
`
|
|
107
|
+
: '';
|
|
46
108
|
const specContent = `# ${featureName}
|
|
47
109
|
|
|
48
|
-
## Overview
|
|
110
|
+
${issueSection}## Overview
|
|
49
111
|
|
|
50
112
|
${description}
|
|
51
113
|
|
|
@@ -68,8 +130,7 @@ ${expectationSection}## Goals
|
|
|
68
130
|
|
|
69
131
|
#### Acceptance Criteria
|
|
70
132
|
|
|
71
|
-
- [ ] Criterion 1
|
|
72
|
-
- [ ] Criterion 2
|
|
133
|
+
${acceptanceCriteria || '- [ ] Criterion 1\n- [ ] Criterion 2'}
|
|
73
134
|
|
|
74
135
|
## Technical Requirements
|
|
75
136
|
|
|
@@ -122,10 +183,37 @@ All notable changes to this feature will be documented in this file.
|
|
|
122
183
|
`;
|
|
123
184
|
writeFileSync(join(featureDir, 'CHANGELOG.md'), changelogContent, 'utf-8');
|
|
124
185
|
console.log(chalk.green('✓'), 'Created: CHANGELOG.md');
|
|
186
|
+
if (sourceIssue && bm.isGitHubEnabled()) {
|
|
187
|
+
const ghConfig = config.github;
|
|
188
|
+
const comment = [
|
|
189
|
+
`🚀 SEDD feature ${branchName} created from this issue`,
|
|
190
|
+
`Branch: ${branchName}`,
|
|
191
|
+
`Spec: ${config.specsDir}/${branchName}/spec.md`,
|
|
192
|
+
].join('\n');
|
|
193
|
+
gh.addIssueComment(sourceIssue.number, comment);
|
|
194
|
+
if (ghConfig.project) {
|
|
195
|
+
const itemId = gh.addIssueToProject(ghConfig.project.projectId, sourceIssue.url);
|
|
196
|
+
if (itemId) {
|
|
197
|
+
const inProgressCol = ghConfig.columnMapping['in-progress'];
|
|
198
|
+
const optionId = ghConfig.columns.options[inProgressCol];
|
|
199
|
+
if (optionId) {
|
|
200
|
+
gh.moveItem(ghConfig.project.projectId, itemId, ghConfig.columns.fieldId, optionId);
|
|
201
|
+
}
|
|
202
|
+
const sourceSyncPath = join(featureDir, '.github-source-sync.json');
|
|
203
|
+
writeFileSync(sourceSyncPath, JSON.stringify({ itemId, issueNumber: sourceIssue.number }, null, 2), 'utf-8');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
console.log(chalk.green('✓'), `Issue #${sourceIssue.number} moved to "In Progress"`);
|
|
207
|
+
}
|
|
125
208
|
console.log(chalk.cyan('\n✨ Feature structure created successfully!'));
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
209
|
+
if (sourceIssue) {
|
|
210
|
+
console.log(chalk.cyan(`Created from issue #${sourceIssue.number}. Run /sedd.clarify to start.`));
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
console.log(chalk.cyan('Next steps:'));
|
|
214
|
+
console.log(' 1. Edit spec.md with detailed requirements');
|
|
215
|
+
console.log(' 2. Define interfaces in interfaces.ts');
|
|
216
|
+
console.log(' 3. Run /sedd.clarify to start first migration');
|
|
217
|
+
}
|
|
130
218
|
}
|
|
131
219
|
//# sourceMappingURL=specify.js.map
|