claude-cli-advanced-starter-pack 1.8.4 → 1.8.6
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/package.json +1 -1
- package/src/cli/menu.js +172 -2
- package/src/cli/mobile-menu.js +230 -0
- package/src/commands/explore-mcp/claude-md-updater.js +38 -3
- package/src/commands/init.js +89 -0
- package/src/commands/panel.js +84 -0
- package/src/commands/setup-wizard.js +85 -30
- package/src/data/releases.json +30 -0
- package/src/utils/happy-detect.js +66 -0
- package/src/utils/version-check.js +43 -17
- package/templates/commands/create-task-list-for-issue.template.md +72 -0
- package/templates/commands/create-task-list.template.md +73 -0
- package/templates/commands/detect-tech-stack.template.md +137 -0
- package/templates/commands/menu-for-happy-ui.template.md +109 -0
- package/templates/commands/menu-issues-list.template.md +72 -0
- package/templates/hooks/ccasp-update-check.template.js +36 -1
- package/templates/hooks/github-progress-hook.template.cjs +248 -0
- package/templates/hooks/github-progress-hook.template.js +0 -197
package/src/commands/panel.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
ensureQueueDir,
|
|
21
21
|
} from '../panel/queue.js';
|
|
22
22
|
import { getVersion } from '../utils.js';
|
|
23
|
+
import { isHappyMode } from '../utils/happy-detect.js';
|
|
23
24
|
|
|
24
25
|
// Panel ASCII Banner
|
|
25
26
|
const PANEL_BANNER = `
|
|
@@ -249,8 +250,15 @@ export async function runPanel(options = {}) {
|
|
|
249
250
|
|
|
250
251
|
/**
|
|
251
252
|
* Launch panel in a new terminal window
|
|
253
|
+
* Automatically detects Happy CLI and falls back to inline mode
|
|
252
254
|
*/
|
|
253
255
|
export async function launchPanel() {
|
|
256
|
+
// If Happy mode detected, use inline panel instead of new window
|
|
257
|
+
if (isHappyMode()) {
|
|
258
|
+
console.log(chalk.cyan('\n Happy CLI detected - using inline panel\n'));
|
|
259
|
+
return launchPanelInline();
|
|
260
|
+
}
|
|
261
|
+
|
|
254
262
|
console.log(chalk.cyan('\n Launching CCASP Panel in new window...\n'));
|
|
255
263
|
|
|
256
264
|
const ccaspPath = join(process.cwd(), 'node_modules', '.bin', 'ccasp');
|
|
@@ -295,3 +303,79 @@ export async function launchPanel() {
|
|
|
295
303
|
console.log(chalk.dim(` Run manually: ${chalk.white('ccasp panel')}\n`));
|
|
296
304
|
}
|
|
297
305
|
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Launch panel inline (mobile-friendly, no new window)
|
|
309
|
+
* Used when Happy CLI is detected or explicitly requested
|
|
310
|
+
*/
|
|
311
|
+
export async function launchPanelInline() {
|
|
312
|
+
const MOBILE_PANEL_BANNER = `
|
|
313
|
+
${chalk.cyan('╔══════════════════════════════════╗')}
|
|
314
|
+
${chalk.cyan('║')} ${chalk.bold('Panel')} ${chalk.dim('(inline)')}${' '.repeat(17)}${chalk.cyan('║')}
|
|
315
|
+
${chalk.cyan('╚══════════════════════════════════╝')}`;
|
|
316
|
+
|
|
317
|
+
console.clear();
|
|
318
|
+
console.log(MOBILE_PANEL_BANNER);
|
|
319
|
+
console.log('');
|
|
320
|
+
|
|
321
|
+
// Simplified single-column panel for mobile
|
|
322
|
+
const sections = [
|
|
323
|
+
{ header: 'Agents', items: [
|
|
324
|
+
{ key: 'A', label: 'Create Agent', cmd: '/create-agent' },
|
|
325
|
+
{ key: 'H', label: 'Create Hook', cmd: '/create-hook' },
|
|
326
|
+
{ key: 'S', label: 'Create Skill', cmd: '/create-skill' },
|
|
327
|
+
{ key: 'M', label: 'Explore MCP', cmd: '/explore-mcp' },
|
|
328
|
+
]},
|
|
329
|
+
{ header: 'Actions', items: [
|
|
330
|
+
{ key: 'P', label: 'Phase Dev', cmd: '/phase-dev-plan' },
|
|
331
|
+
{ key: 'G', label: 'GitHub Task', cmd: '/github-task' },
|
|
332
|
+
{ key: 'T', label: 'E2E Tests', cmd: '/e2e-test' },
|
|
333
|
+
]},
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
// Build choices
|
|
337
|
+
const choices = [];
|
|
338
|
+
for (const section of sections) {
|
|
339
|
+
choices.push(new inquirer.Separator(chalk.cyan(` ${section.header}`)));
|
|
340
|
+
for (const item of section.items) {
|
|
341
|
+
choices.push({
|
|
342
|
+
name: `${chalk.yellow(item.key + ')')} ${item.label}`,
|
|
343
|
+
value: item.cmd,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
choices.push(new inquirer.Separator(chalk.dim('─'.repeat(34))));
|
|
348
|
+
choices.push({ name: `${chalk.yellow('B)')} Back`, value: 'back' });
|
|
349
|
+
|
|
350
|
+
const { action } = await inquirer.prompt([{
|
|
351
|
+
type: 'list',
|
|
352
|
+
name: 'action',
|
|
353
|
+
message: 'Select:',
|
|
354
|
+
choices,
|
|
355
|
+
pageSize: 12,
|
|
356
|
+
}]);
|
|
357
|
+
|
|
358
|
+
if (action === 'back') {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Show command and copy to clipboard
|
|
363
|
+
console.log('');
|
|
364
|
+
console.log(chalk.cyan(`Command: ${action}`));
|
|
365
|
+
|
|
366
|
+
const copied = copyToClipboard(action);
|
|
367
|
+
if (copied) {
|
|
368
|
+
console.log(chalk.green('✓ Copied to clipboard'));
|
|
369
|
+
}
|
|
370
|
+
console.log(chalk.dim('Paste in Claude Code'));
|
|
371
|
+
console.log('');
|
|
372
|
+
|
|
373
|
+
await inquirer.prompt([{
|
|
374
|
+
type: 'input',
|
|
375
|
+
name: 'continue',
|
|
376
|
+
message: 'Enter to continue...',
|
|
377
|
+
}]);
|
|
378
|
+
|
|
379
|
+
// Loop back to panel
|
|
380
|
+
return launchPanelInline();
|
|
381
|
+
}
|
|
@@ -578,43 +578,60 @@ function showSetupHeader() {
|
|
|
578
578
|
}
|
|
579
579
|
|
|
580
580
|
/**
|
|
581
|
-
*
|
|
581
|
+
* Streamlined setup options - 3 core paths for easy mobile input
|
|
582
|
+
* Issue #8: Simplified from 7 options to reduce scrolling
|
|
582
583
|
*/
|
|
583
584
|
const SETUP_OPTIONS = [
|
|
584
585
|
{
|
|
585
|
-
name: `${chalk.
|
|
586
|
-
value: '
|
|
587
|
-
short: '
|
|
586
|
+
name: `${chalk.green('1.')} Auto Install ${chalk.dim('- Full features + backup (recommended)')}`,
|
|
587
|
+
value: 'auto',
|
|
588
|
+
short: 'Auto Install',
|
|
588
589
|
},
|
|
589
590
|
{
|
|
590
|
-
name: `${chalk.yellow('2.')}
|
|
591
|
-
value: 'full',
|
|
592
|
-
short: 'Full Setup',
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
name: `${chalk.yellow('3.')} GitHub Setup ${chalk.dim('- Connect project board')}`,
|
|
591
|
+
name: `${chalk.yellow('2.')} GitHub Setup ${chalk.dim('- Connect project board')}`,
|
|
596
592
|
value: 'github',
|
|
597
593
|
short: 'GitHub',
|
|
598
594
|
},
|
|
599
595
|
{
|
|
600
|
-
name: `${chalk.
|
|
596
|
+
name: `${chalk.dim('3.')} More Options ${chalk.dim('- Templates, releases, remove')}`,
|
|
597
|
+
value: 'more',
|
|
598
|
+
short: 'More',
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: `${chalk.dim('0.')} Exit`,
|
|
602
|
+
value: 'exit',
|
|
603
|
+
short: 'Exit',
|
|
604
|
+
},
|
|
605
|
+
];
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Advanced options submenu - accessed via "More Options"
|
|
609
|
+
*/
|
|
610
|
+
const ADVANCED_OPTIONS = [
|
|
611
|
+
{
|
|
612
|
+
name: `${chalk.yellow('1.')} Custom Setup ${chalk.dim('- Choose specific features')}`,
|
|
613
|
+
value: 'custom',
|
|
614
|
+
short: 'Custom',
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
name: `${chalk.yellow('2.')} View Templates ${chalk.dim('- Browse available items')}`,
|
|
601
618
|
value: 'templates',
|
|
602
619
|
short: 'Templates',
|
|
603
620
|
},
|
|
604
621
|
{
|
|
605
|
-
name: `${chalk.yellow('
|
|
622
|
+
name: `${chalk.yellow('3.')} Prior Releases ${chalk.dim('- Add features from past versions')}`,
|
|
606
623
|
value: 'releases',
|
|
607
624
|
short: 'Releases',
|
|
608
625
|
},
|
|
609
626
|
{
|
|
610
|
-
name: `${chalk.yellow('
|
|
627
|
+
name: `${chalk.yellow('4.')} Remove CCASP ${chalk.dim('- Uninstall from this project')}`,
|
|
611
628
|
value: 'remove',
|
|
612
629
|
short: 'Remove',
|
|
613
630
|
},
|
|
614
631
|
{
|
|
615
|
-
name: `${chalk.
|
|
616
|
-
value: '
|
|
617
|
-
short: '
|
|
632
|
+
name: `${chalk.dim('0.')} Back`,
|
|
633
|
+
value: 'back',
|
|
634
|
+
short: 'Back',
|
|
618
635
|
},
|
|
619
636
|
];
|
|
620
637
|
|
|
@@ -1292,7 +1309,7 @@ export async function runSetupWizard(options = {}) {
|
|
|
1292
1309
|
console.log(chalk.green('✓ CLAUDE.md exists\n'));
|
|
1293
1310
|
}
|
|
1294
1311
|
|
|
1295
|
-
// Main menu loop
|
|
1312
|
+
// Main menu loop - streamlined 3-path flow (Issue #8)
|
|
1296
1313
|
let running = true;
|
|
1297
1314
|
while (running) {
|
|
1298
1315
|
const { action } = await inquirer.prompt([
|
|
@@ -1301,28 +1318,67 @@ export async function runSetupWizard(options = {}) {
|
|
|
1301
1318
|
name: 'action',
|
|
1302
1319
|
message: 'What would you like to do?',
|
|
1303
1320
|
choices: SETUP_OPTIONS,
|
|
1304
|
-
pageSize:
|
|
1321
|
+
pageSize: 6, // All options visible without scrolling
|
|
1305
1322
|
},
|
|
1306
1323
|
]);
|
|
1307
1324
|
|
|
1308
1325
|
switch (action) {
|
|
1309
|
-
case '
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1326
|
+
case 'auto':
|
|
1327
|
+
// Auto Install: Full features with mandatory backup (Issue #8 requirement)
|
|
1328
|
+
console.log(chalk.cyan('\n📦 Auto Install Mode - Full features with backup\n'));
|
|
1329
|
+
await runInit({
|
|
1330
|
+
interactive: false,
|
|
1331
|
+
backup: true, // Mandatory backup
|
|
1332
|
+
force: true, // Overwrite enabled for testing phase
|
|
1333
|
+
skipPrompts: true,
|
|
1334
|
+
preset: 'full' // All features
|
|
1335
|
+
});
|
|
1316
1336
|
showRestartReminder();
|
|
1317
1337
|
running = false;
|
|
1318
1338
|
break;
|
|
1319
1339
|
|
|
1320
1340
|
case 'github':
|
|
1321
1341
|
await runGitHubSetup({});
|
|
1322
|
-
// GitHub setup modifies .claude/ config
|
|
1323
1342
|
showRestartReminder();
|
|
1324
1343
|
break;
|
|
1325
1344
|
|
|
1345
|
+
case 'more':
|
|
1346
|
+
// Advanced options submenu
|
|
1347
|
+
await showAdvancedOptions();
|
|
1348
|
+
break;
|
|
1349
|
+
|
|
1350
|
+
case 'exit':
|
|
1351
|
+
running = false;
|
|
1352
|
+
console.log(chalk.dim('\nRun `ccasp wizard` anytime to return.\n'));
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* Advanced options submenu - Issue #8: Moved less-used options here
|
|
1360
|
+
*/
|
|
1361
|
+
async function showAdvancedOptions() {
|
|
1362
|
+
let inSubmenu = true;
|
|
1363
|
+
|
|
1364
|
+
while (inSubmenu) {
|
|
1365
|
+
const { action } = await inquirer.prompt([
|
|
1366
|
+
{
|
|
1367
|
+
type: 'list',
|
|
1368
|
+
name: 'action',
|
|
1369
|
+
message: 'Advanced Options:',
|
|
1370
|
+
choices: ADVANCED_OPTIONS,
|
|
1371
|
+
pageSize: 6,
|
|
1372
|
+
},
|
|
1373
|
+
]);
|
|
1374
|
+
|
|
1375
|
+
switch (action) {
|
|
1376
|
+
case 'custom':
|
|
1377
|
+
await runInit({ interactive: true });
|
|
1378
|
+
showRestartReminder();
|
|
1379
|
+
inSubmenu = false;
|
|
1380
|
+
break;
|
|
1381
|
+
|
|
1326
1382
|
case 'templates':
|
|
1327
1383
|
await showTemplates();
|
|
1328
1384
|
break;
|
|
@@ -1334,13 +1390,12 @@ export async function runSetupWizard(options = {}) {
|
|
|
1334
1390
|
case 'remove':
|
|
1335
1391
|
const removed = await runRemove();
|
|
1336
1392
|
if (removed) {
|
|
1337
|
-
|
|
1393
|
+
inSubmenu = false;
|
|
1338
1394
|
}
|
|
1339
1395
|
break;
|
|
1340
1396
|
|
|
1341
|
-
case '
|
|
1342
|
-
|
|
1343
|
-
console.log(chalk.dim('\nRun `ccasp wizard` anytime to return.\n'));
|
|
1397
|
+
case 'back':
|
|
1398
|
+
inSubmenu = false;
|
|
1344
1399
|
break;
|
|
1345
1400
|
}
|
|
1346
1401
|
}
|
package/src/data/releases.json
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"releases": [
|
|
3
|
+
{
|
|
4
|
+
"version": "1.8.6",
|
|
5
|
+
"date": "2026-01-31",
|
|
6
|
+
"summary": "Release notes pending",
|
|
7
|
+
"highlights": [],
|
|
8
|
+
"newFeatures": {
|
|
9
|
+
"commands": [],
|
|
10
|
+
"agents": [],
|
|
11
|
+
"skills": [],
|
|
12
|
+
"hooks": [],
|
|
13
|
+
"other": []
|
|
14
|
+
},
|
|
15
|
+
"breaking": [],
|
|
16
|
+
"deprecated": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"version": "1.8.5",
|
|
20
|
+
"date": "2026-01-31",
|
|
21
|
+
"summary": "Release notes pending",
|
|
22
|
+
"highlights": [],
|
|
23
|
+
"newFeatures": {
|
|
24
|
+
"commands": [],
|
|
25
|
+
"agents": [],
|
|
26
|
+
"skills": [],
|
|
27
|
+
"hooks": [],
|
|
28
|
+
"other": []
|
|
29
|
+
},
|
|
30
|
+
"breaking": [],
|
|
31
|
+
"deprecated": []
|
|
32
|
+
},
|
|
3
33
|
{
|
|
4
34
|
"version": "1.8.4",
|
|
5
35
|
"date": "2026-01-31",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Happy CLI Detection Utility
|
|
3
|
+
*
|
|
4
|
+
* Detects if CCASP is running inside Happy Coder mobile CLI wrapper.
|
|
5
|
+
* Happy CLI sets HAPPY_* environment variables when active.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/slopus/happy-cli
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Check if running inside Happy CLI environment
|
|
12
|
+
* @returns {boolean} True if Happy CLI detected
|
|
13
|
+
*/
|
|
14
|
+
export function isHappyMode() {
|
|
15
|
+
return !!(
|
|
16
|
+
process.env.HAPPY_HOME_DIR ||
|
|
17
|
+
process.env.HAPPY_SERVER_URL ||
|
|
18
|
+
process.env.HAPPY_WEBAPP_URL ||
|
|
19
|
+
process.env.HAPPY_EXPERIMENTAL
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get Happy CLI configuration from environment
|
|
25
|
+
* @returns {object} Happy configuration details
|
|
26
|
+
*/
|
|
27
|
+
export function getHappyConfig() {
|
|
28
|
+
return {
|
|
29
|
+
detected: isHappyMode(),
|
|
30
|
+
homeDir: process.env.HAPPY_HOME_DIR || null,
|
|
31
|
+
serverUrl: process.env.HAPPY_SERVER_URL || 'https://api.cluster-fluster.com',
|
|
32
|
+
webappUrl: process.env.HAPPY_WEBAPP_URL || 'https://app.happy.engineering',
|
|
33
|
+
experimental: process.env.HAPPY_EXPERIMENTAL === 'true',
|
|
34
|
+
disableCaffeinate: process.env.HAPPY_DISABLE_CAFFEINATE === 'true',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get recommended terminal width for mobile display
|
|
40
|
+
* @returns {number} Optimal width for mobile screens
|
|
41
|
+
*/
|
|
42
|
+
export function getMobileWidth() {
|
|
43
|
+
// Happy mobile UI typically works best at 40 chars
|
|
44
|
+
// to avoid horizontal scrolling on phone screens
|
|
45
|
+
return 40;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if we should use mobile-optimized UI
|
|
50
|
+
* Respects both Happy CLI detection and tech-stack.json happyMode.enabled
|
|
51
|
+
* @param {object} techStack - Optional tech-stack.json config
|
|
52
|
+
* @returns {boolean} True if mobile UI should be used
|
|
53
|
+
*/
|
|
54
|
+
export function shouldUseMobileUI(techStack = null) {
|
|
55
|
+
// Auto-detect Happy CLI environment
|
|
56
|
+
if (isHappyMode()) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check tech-stack.json happyMode.enabled setting
|
|
61
|
+
if (techStack?.happyMode?.enabled) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
@@ -19,8 +19,9 @@ const PACKAGE_NAME = 'claude-cli-advanced-starter-pack';
|
|
|
19
19
|
// Cache duration: 1 hour (in milliseconds)
|
|
20
20
|
const CACHE_DURATION = 60 * 60 * 1000;
|
|
21
21
|
|
|
22
|
-
// Update notification
|
|
23
|
-
|
|
22
|
+
// Update notification reminder: Show reminder again after 7 days
|
|
23
|
+
// Issue #8: Changed from 1-day suppression to 7-day reminder
|
|
24
|
+
const UPDATE_NOTIFICATION_REMINDER = 7 * 24 * 60 * 60 * 1000;
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Get the current installed version from package.json
|
|
@@ -313,19 +314,52 @@ export function compareVersions(v1, v2) {
|
|
|
313
314
|
/**
|
|
314
315
|
* Check npm registry for the latest version
|
|
315
316
|
* Returns null if check fails (network error, etc.)
|
|
317
|
+
* Issue #8: Added npm registry API fallback for Windows compatibility
|
|
316
318
|
*/
|
|
317
319
|
export async function checkLatestVersion() {
|
|
320
|
+
// Try npm CLI first
|
|
318
321
|
try {
|
|
319
|
-
// Use npm view command to get latest version
|
|
320
322
|
const result = execSync(`npm view ${PACKAGE_NAME} version`, {
|
|
321
323
|
encoding: 'utf8',
|
|
322
|
-
timeout: 10000,
|
|
324
|
+
timeout: 10000,
|
|
323
325
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
324
326
|
});
|
|
325
327
|
|
|
326
|
-
|
|
328
|
+
const version = result.trim();
|
|
329
|
+
if (version && /^\d+\.\d+\.\d+/.test(version)) {
|
|
330
|
+
return version;
|
|
331
|
+
}
|
|
332
|
+
} catch {
|
|
333
|
+
// npm CLI failed, try fallback
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Fallback: Direct npm registry API call (Issue #8 fix)
|
|
337
|
+
try {
|
|
338
|
+
const https = await import('https');
|
|
339
|
+
return new Promise((resolve) => {
|
|
340
|
+
const req = https.default.get(
|
|
341
|
+
`https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
|
|
342
|
+
{ timeout: 8000 },
|
|
343
|
+
(res) => {
|
|
344
|
+
let data = '';
|
|
345
|
+
res.on('data', (chunk) => (data += chunk));
|
|
346
|
+
res.on('end', () => {
|
|
347
|
+
try {
|
|
348
|
+
const pkg = JSON.parse(data);
|
|
349
|
+
resolve(pkg.version || null);
|
|
350
|
+
} catch {
|
|
351
|
+
resolve(null);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
req.on('error', () => resolve(null));
|
|
357
|
+
req.on('timeout', () => {
|
|
358
|
+
req.destroy();
|
|
359
|
+
resolve(null);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
327
362
|
} catch {
|
|
328
|
-
// Silently fail - network might be unavailable
|
|
329
363
|
return null;
|
|
330
364
|
}
|
|
331
365
|
}
|
|
@@ -436,17 +470,9 @@ export function shouldShowUpdateNotification(state, latestVersion) {
|
|
|
436
470
|
return false;
|
|
437
471
|
}
|
|
438
472
|
|
|
439
|
-
//
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
// If check is more than 1 day old, don't show notification
|
|
444
|
-
// (user needs to run check again to see new updates)
|
|
445
|
-
if (timeSinceCheck > UPDATE_NOTIFICATION_DURATION) {
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
473
|
+
// Issue #8: Always show notification if update is available
|
|
474
|
+
// The old logic suppressed notifications after 1 day, which was counterproductive
|
|
475
|
+
// Now we always show if there's an update, regardless of cache age
|
|
450
476
|
return true;
|
|
451
477
|
}
|
|
452
478
|
|
|
@@ -197,6 +197,78 @@ gh issue edit [NUMBER] --body "$(gh issue view [NUMBER] --json body -q .body)
|
|
|
197
197
|
|
|
198
198
|
---
|
|
199
199
|
|
|
200
|
+
### Step 7: After Task Completion - Close Issue Prompt
|
|
201
|
+
|
|
202
|
+
**CRITICAL: After ALL TodoWrite tasks are marked complete AND a commit is created, ALWAYS offer to close the issue.**
|
|
203
|
+
|
|
204
|
+
This step triggers when:
|
|
205
|
+
1. All tasks in TodoWrite are marked `completed`
|
|
206
|
+
2. A git commit has been made with changes
|
|
207
|
+
|
|
208
|
+
Display completion summary:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
212
|
+
║ ✅ All Tasks Completed ║
|
|
213
|
+
╠═══════════════════════════════════════════════════════════════╣
|
|
214
|
+
║ ║
|
|
215
|
+
║ Issue: #[NUMBER] - [TITLE] ║
|
|
216
|
+
║ Commit: [SHORT_SHA] - [COMMIT_MSG_FIRST_LINE] ║
|
|
217
|
+
║ Tasks: [X] completed ║
|
|
218
|
+
║ ║
|
|
219
|
+
╠═══════════════════════════════════════════════════════════════╣
|
|
220
|
+
║ [C] Close issue with comment ║
|
|
221
|
+
║ [P] Push to origin + close issue ║
|
|
222
|
+
║ [K] Keep issue open ║
|
|
223
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Then ask:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
header: "Issue"
|
|
230
|
+
question: "All tasks complete. Close issue #[NUMBER]?"
|
|
231
|
+
options:
|
|
232
|
+
- label: "C - Close with comment"
|
|
233
|
+
description: "Add completion summary and close"
|
|
234
|
+
- label: "P - Push + Close"
|
|
235
|
+
description: "Push commit to origin, then close"
|
|
236
|
+
- label: "K - Keep open"
|
|
237
|
+
description: "Leave issue open for follow-up"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Handle Close Actions:**
|
|
241
|
+
|
|
242
|
+
**C (Close with comment):**
|
|
243
|
+
```bash
|
|
244
|
+
gh issue close [NUMBER] --comment "All tasks completed in commit [SHA].
|
|
245
|
+
|
|
246
|
+
## Completed Tasks
|
|
247
|
+
- ✅ Task 1
|
|
248
|
+
- ✅ Task 2
|
|
249
|
+
...
|
|
250
|
+
|
|
251
|
+
Ready for release."
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**P (Push + Close):**
|
|
255
|
+
```bash
|
|
256
|
+
git push origin HEAD
|
|
257
|
+
gh issue close [NUMBER] --comment "All tasks completed and pushed in commit [SHA].
|
|
258
|
+
|
|
259
|
+
## Completed Tasks
|
|
260
|
+
- ✅ Task 1
|
|
261
|
+
- ✅ Task 2
|
|
262
|
+
...
|
|
263
|
+
|
|
264
|
+
Ready for release."
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**K (Keep open):**
|
|
268
|
+
Display: "Issue #[NUMBER] kept open for follow-up."
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
200
272
|
## ERROR HANDLING
|
|
201
273
|
|
|
202
274
|
| Error | Action |
|
|
@@ -874,6 +874,79 @@ After all tasks are complete, display a summary:
|
|
|
874
874
|
|
|
875
875
|
---
|
|
876
876
|
|
|
877
|
+
## CLOSE ISSUE PROMPT (When Working From GitHub Issue)
|
|
878
|
+
|
|
879
|
+
**CRITICAL: If this task list was created for a GitHub issue, ALWAYS offer to close the issue after ALL TodoWrite tasks are marked complete AND a commit is created.**
|
|
880
|
+
|
|
881
|
+
This step triggers when:
|
|
882
|
+
1. The task list originated from a GitHub issue (via `/create-task-list for issue #N` or `/menu-issues-list`)
|
|
883
|
+
2. All tasks in TodoWrite are marked `completed`
|
|
884
|
+
3. A git commit has been made with changes
|
|
885
|
+
|
|
886
|
+
Display completion summary:
|
|
887
|
+
|
|
888
|
+
```
|
|
889
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
890
|
+
║ ✅ All Tasks Completed ║
|
|
891
|
+
╠═══════════════════════════════════════════════════════════════╣
|
|
892
|
+
║ ║
|
|
893
|
+
║ Issue: #[NUMBER] - [TITLE] ║
|
|
894
|
+
║ Commit: [SHORT_SHA] - [COMMIT_MSG_FIRST_LINE] ║
|
|
895
|
+
║ Tasks: [X] completed ║
|
|
896
|
+
║ ║
|
|
897
|
+
╠═══════════════════════════════════════════════════════════════╣
|
|
898
|
+
║ [C] Close issue with comment ║
|
|
899
|
+
║ [P] Push to origin + close issue ║
|
|
900
|
+
║ [K] Keep issue open ║
|
|
901
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
Then ask:
|
|
905
|
+
|
|
906
|
+
```
|
|
907
|
+
header: "Issue"
|
|
908
|
+
question: "All tasks complete. Close issue #[NUMBER]?"
|
|
909
|
+
options:
|
|
910
|
+
- label: "C - Close with comment"
|
|
911
|
+
description: "Add completion summary and close"
|
|
912
|
+
- label: "P - Push + Close"
|
|
913
|
+
description: "Push commit to origin, then close"
|
|
914
|
+
- label: "K - Keep open"
|
|
915
|
+
description: "Leave issue open for follow-up"
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
**Handle Close Actions:**
|
|
919
|
+
|
|
920
|
+
**C (Close with comment):**
|
|
921
|
+
```bash
|
|
922
|
+
gh issue close [NUMBER] --comment "All tasks completed in commit [SHA].
|
|
923
|
+
|
|
924
|
+
## Completed Tasks
|
|
925
|
+
- ✅ Task 1
|
|
926
|
+
- ✅ Task 2
|
|
927
|
+
...
|
|
928
|
+
|
|
929
|
+
Ready for release."
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
**P (Push + Close):**
|
|
933
|
+
```bash
|
|
934
|
+
git push origin HEAD
|
|
935
|
+
gh issue close [NUMBER] --comment "All tasks completed and pushed in commit [SHA].
|
|
936
|
+
|
|
937
|
+
## Completed Tasks
|
|
938
|
+
- ✅ Task 1
|
|
939
|
+
- ✅ Task 2
|
|
940
|
+
...
|
|
941
|
+
|
|
942
|
+
Ready for release."
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
**K (Keep open):**
|
|
946
|
+
Display: "Issue #[NUMBER] kept open for follow-up."
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
877
950
|
## ERROR HANDLING
|
|
878
951
|
|
|
879
952
|
| Situation | Action |
|