claude-cli-advanced-starter-pack 1.1.0 → 1.8.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.
Files changed (56) hide show
  1. package/OVERVIEW.md +5 -1
  2. package/README.md +241 -132
  3. package/bin/gtask.js +53 -0
  4. package/package.json +1 -1
  5. package/src/cli/menu.js +27 -0
  6. package/src/commands/explore-mcp/mcp-registry.js +99 -0
  7. package/src/commands/init.js +306 -77
  8. package/src/commands/install-panel-hook.js +108 -0
  9. package/src/commands/install-scripts.js +232 -0
  10. package/src/commands/install-skill.js +220 -0
  11. package/src/commands/panel.js +297 -0
  12. package/src/commands/setup-wizard.js +4 -3
  13. package/src/commands/test-setup.js +4 -5
  14. package/src/data/releases.json +164 -0
  15. package/src/panel/queue.js +188 -0
  16. package/templates/commands/ask-claude.template.md +118 -0
  17. package/templates/commands/ccasp-panel.template.md +72 -0
  18. package/templates/commands/ccasp-setup.template.md +470 -79
  19. package/templates/commands/create-smoke-test.template.md +186 -0
  20. package/templates/commands/project-impl.template.md +9 -113
  21. package/templates/commands/refactor-check.template.md +112 -0
  22. package/templates/commands/refactor-cleanup.template.md +144 -0
  23. package/templates/commands/refactor-prep.template.md +192 -0
  24. package/templates/docs/AI_ARCHITECTURE_CONSTITUTION.template.md +198 -0
  25. package/templates/docs/DETAILED_GOTCHAS.template.md +347 -0
  26. package/templates/docs/PHASE-DEV-CHECKLIST.template.md +241 -0
  27. package/templates/docs/PROGRESS_JSON_TEMPLATE.json +117 -0
  28. package/templates/docs/background-agent.template.md +264 -0
  29. package/templates/hooks/autonomous-decision-logger.template.js +207 -0
  30. package/templates/hooks/branch-merge-checker.template.js +272 -0
  31. package/templates/hooks/git-commit-tracker.template.js +267 -0
  32. package/templates/hooks/issue-completion-detector.template.js +205 -0
  33. package/templates/hooks/panel-queue-reader.template.js +83 -0
  34. package/templates/hooks/phase-validation-gates.template.js +307 -0
  35. package/templates/hooks/session-id-generator.template.js +236 -0
  36. package/templates/hooks/token-usage-monitor.template.js +193 -0
  37. package/templates/patterns/README.md +129 -0
  38. package/templates/patterns/l1-l2-orchestration.md +189 -0
  39. package/templates/patterns/multi-phase-orchestration.md +258 -0
  40. package/templates/patterns/two-tier-query-pipeline.md +192 -0
  41. package/templates/scripts/README.md +109 -0
  42. package/templates/scripts/analyze-delegation-log.js +299 -0
  43. package/templates/scripts/autonomous-decision-logger.js +277 -0
  44. package/templates/scripts/git-history-analyzer.py +269 -0
  45. package/templates/scripts/phase-validation-gates.js +307 -0
  46. package/templates/scripts/poll-deployment-status.js +260 -0
  47. package/templates/scripts/roadmap-scanner.js +263 -0
  48. package/templates/scripts/validate-deployment.js +293 -0
  49. package/templates/skills/agent-creator/skill.json +18 -0
  50. package/templates/skills/agent-creator/skill.md +335 -0
  51. package/templates/skills/hook-creator/skill.json +18 -0
  52. package/templates/skills/hook-creator/skill.md +318 -0
  53. package/templates/skills/panel/skill.json +18 -0
  54. package/templates/skills/panel/skill.md +90 -0
  55. package/templates/skills/rag-agent-creator/skill.json +18 -0
  56. package/templates/skills/rag-agent-creator/skill.md +307 -0
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Phase Validation Gates Hook
4
+ *
5
+ * 5-gate validation system for phased development.
6
+ * Ensures quality standards are met before auto-chaining to next phase.
7
+ *
8
+ * Event: PostToolUse (custom trigger)
9
+ * Trigger: Phase completion markers
10
+ *
11
+ * Configuration: Reads from .claude/config/hooks-config.json
12
+ *
13
+ * Gates:
14
+ * 1. Tasks Complete - All phase tasks marked done
15
+ * 2. Files Created - Expected output files exist
16
+ * 3. Tests Passing - Required tests pass (if configured)
17
+ * 4. No Errors - No blocking errors detected
18
+ * 5. Token Budget - Within configured token limits
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ // Default configuration
25
+ const DEFAULT_CONFIG = {
26
+ enabled: true,
27
+ gates: {
28
+ tasks_complete: { enabled: true, required: true },
29
+ files_created: { enabled: true, required: false },
30
+ tests_passing: { enabled: true, required: false },
31
+ no_errors: { enabled: true, required: true },
32
+ token_budget: { enabled: true, required: false },
33
+ },
34
+ auto_chain_on_pass: false, // Automatically start next phase
35
+ report_failures: true, // Log detailed failure reports
36
+ };
37
+
38
+ // Paths
39
+ const CONFIG_PATH = path.join(process.cwd(), '.claude', 'config', 'hooks-config.json');
40
+ const STATE_FILE = path.join(process.cwd(), '.claude', 'hooks', 'config', 'phase-validation-state.json');
41
+
42
+ /**
43
+ * Load configuration
44
+ */
45
+ function loadConfig() {
46
+ try {
47
+ if (fs.existsSync(CONFIG_PATH)) {
48
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
49
+ return { ...DEFAULT_CONFIG, ...(config.phase_validation || {}) };
50
+ }
51
+ } catch (e) {
52
+ // Use defaults
53
+ }
54
+ return DEFAULT_CONFIG;
55
+ }
56
+
57
+ /**
58
+ * Load validation state
59
+ */
60
+ function loadState() {
61
+ try {
62
+ if (fs.existsSync(STATE_FILE)) {
63
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
64
+ }
65
+ } catch (e) {
66
+ // Use defaults
67
+ }
68
+ return {
69
+ last_validation: null,
70
+ gate_results: {},
71
+ phases_validated: [],
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Save validation state
77
+ */
78
+ function saveState(state) {
79
+ try {
80
+ const dir = path.dirname(STATE_FILE);
81
+ if (!fs.existsSync(dir)) {
82
+ fs.mkdirSync(dir, { recursive: true });
83
+ }
84
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
85
+ } catch (e) {
86
+ console.error(`[phase-validation] Error saving state: ${e.message}`);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Gate 1: Check if all tasks are complete
92
+ */
93
+ async function checkTasksComplete(phase, result) {
94
+ const tasks = phase.tasks || [];
95
+ const completed = tasks.filter(t => t.status === 'completed');
96
+
97
+ const passed = completed.length >= tasks.length;
98
+ const message = passed
99
+ ? `All tasks complete (${tasks.length}/${tasks.length})`
100
+ : `${tasks.length - completed.length} tasks incomplete`;
101
+
102
+ return { passed, message, completed: completed.length, total: tasks.length };
103
+ }
104
+
105
+ /**
106
+ * Gate 2: Check if expected files were created
107
+ */
108
+ async function checkFilesCreated(phase, result) {
109
+ const expectedFiles = phase.expectedOutputFiles || [];
110
+ const actualFiles = result?.filesCreated || [];
111
+
112
+ if (expectedFiles.length === 0) {
113
+ return { passed: true, message: 'No expected files specified', expected: 0, found: 0 };
114
+ }
115
+
116
+ const missingFiles = expectedFiles.filter(file => {
117
+ const fullPath = path.resolve(file);
118
+ return !fs.existsSync(fullPath) && !actualFiles.includes(file);
119
+ });
120
+
121
+ const passed = missingFiles.length === 0;
122
+ const message = passed
123
+ ? `All expected files created (${expectedFiles.length})`
124
+ : `Missing files: ${missingFiles.slice(0, 3).join(', ')}${missingFiles.length > 3 ? '...' : ''}`;
125
+
126
+ return { passed, message, expected: expectedFiles.length, missing: missingFiles };
127
+ }
128
+
129
+ /**
130
+ * Gate 3: Check if tests are passing
131
+ */
132
+ async function checkTestsPassing(phase, result) {
133
+ if (!phase.requireTests) {
134
+ return { passed: true, message: 'Tests not required for this phase' };
135
+ }
136
+
137
+ const testResults = result?.testResults || { passed: 0, failed: 0, total: 0 };
138
+
139
+ if (testResults.total === 0) {
140
+ return { passed: false, message: 'No tests executed (requireTests=true)', testResults };
141
+ }
142
+
143
+ const passed = testResults.failed === 0;
144
+ const message = passed
145
+ ? `All tests passing (${testResults.passed}/${testResults.total})`
146
+ : `${testResults.failed} tests failed`;
147
+
148
+ return { passed, message, testResults };
149
+ }
150
+
151
+ /**
152
+ * Gate 4: Check for errors
153
+ */
154
+ async function checkNoErrors(phase, result) {
155
+ const errors = result?.errors || [];
156
+
157
+ const passed = errors.length === 0;
158
+ const message = passed
159
+ ? 'No errors detected'
160
+ : `${errors.length} error(s) detected`;
161
+
162
+ return { passed, message, errors: errors.slice(0, 5) };
163
+ }
164
+
165
+ /**
166
+ * Gate 5: Check token budget
167
+ */
168
+ async function checkTokenBudget(phase, result) {
169
+ const budget = phase.tokenBudget || Infinity;
170
+ const used = result?.tokens || 0;
171
+
172
+ if (budget === Infinity) {
173
+ return { passed: true, message: `No token budget specified (used: ${used.toLocaleString()})`, used };
174
+ }
175
+
176
+ const passed = used <= budget;
177
+ const percentage = Math.round((used / budget) * 100);
178
+ const message = passed
179
+ ? `Within budget: ${used.toLocaleString()}/${budget.toLocaleString()} (${percentage}%)`
180
+ : `Budget exceeded: ${used.toLocaleString()}/${budget.toLocaleString()} (${percentage}%)`;
181
+
182
+ return { passed, message, used, budget, percentage };
183
+ }
184
+
185
+ /**
186
+ * Run all validation gates
187
+ */
188
+ async function validatePhase(phase, result, config) {
189
+ const gateConfig = config.gates;
190
+ const gateResults = {};
191
+ let allPassed = true;
192
+ let requiredPassed = true;
193
+
194
+ const gates = [
195
+ { id: 'tasks_complete', name: 'Tasks Complete', fn: checkTasksComplete },
196
+ { id: 'files_created', name: 'Files Created', fn: checkFilesCreated },
197
+ { id: 'tests_passing', name: 'Tests Passing', fn: checkTestsPassing },
198
+ { id: 'no_errors', name: 'No Errors', fn: checkNoErrors },
199
+ { id: 'token_budget', name: 'Token Budget', fn: checkTokenBudget },
200
+ ];
201
+
202
+ console.log(`\n[phase-validation] Running validation gates for Phase ${phase.phase_number || '?'}`);
203
+ console.log('─'.repeat(60));
204
+
205
+ for (const gate of gates) {
206
+ const gateSettings = gateConfig[gate.id] || { enabled: true, required: false };
207
+
208
+ if (!gateSettings.enabled) {
209
+ gateResults[gate.id] = { skipped: true, message: 'Gate disabled' };
210
+ console.log(`⏭️ ${gate.name}: Skipped (disabled)`);
211
+ continue;
212
+ }
213
+
214
+ const gateResult = await gate.fn(phase, result);
215
+ gateResults[gate.id] = gateResult;
216
+
217
+ if (gateResult.passed) {
218
+ console.log(`✅ ${gate.name}: ${gateResult.message}`);
219
+ } else {
220
+ console.log(`❌ ${gate.name}: ${gateResult.message}`);
221
+ allPassed = false;
222
+ if (gateSettings.required) {
223
+ requiredPassed = false;
224
+ }
225
+ }
226
+ }
227
+
228
+ console.log('─'.repeat(60));
229
+
230
+ if (allPassed) {
231
+ console.log('✅ All gates passed\n');
232
+ } else if (requiredPassed) {
233
+ console.log('⚠️ Some optional gates failed (required gates passed)\n');
234
+ } else {
235
+ console.log('❌ Required gates failed\n');
236
+ }
237
+
238
+ return {
239
+ allPassed,
240
+ requiredPassed,
241
+ gateResults,
242
+ phase_number: phase.phase_number,
243
+ timestamp: new Date().toISOString(),
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Main hook handler
249
+ */
250
+ module.exports = async function phaseValidationGates(context) {
251
+ const approve = () => ({ continue: true });
252
+
253
+ try {
254
+ const config = loadConfig();
255
+
256
+ if (!config.enabled) {
257
+ return approve();
258
+ }
259
+
260
+ // This hook is typically called programmatically with phase data
261
+ // For now, return approve and let the caller use validatePhase directly
262
+ return approve();
263
+ } catch (error) {
264
+ console.error(`[phase-validation] Error: ${error.message}`);
265
+ return approve();
266
+ }
267
+ };
268
+
269
+ // Export validation functions for programmatic use
270
+ module.exports.validatePhase = validatePhase;
271
+ module.exports.gates = {
272
+ checkTasksComplete,
273
+ checkFilesCreated,
274
+ checkTestsPassing,
275
+ checkNoErrors,
276
+ checkTokenBudget,
277
+ };
278
+
279
+ // Direct execution support
280
+ if (require.main === module) {
281
+ const config = loadConfig();
282
+
283
+ // Example phase for testing
284
+ const testPhase = {
285
+ phase_number: 1,
286
+ tasks: [
287
+ { id: 'T1', status: 'completed' },
288
+ { id: 'T2', status: 'completed' },
289
+ { id: 'T3', status: 'pending' },
290
+ ],
291
+ expectedOutputFiles: [],
292
+ requireTests: false,
293
+ tokenBudget: 50000,
294
+ };
295
+
296
+ const testResult = {
297
+ tokens: 25000,
298
+ errors: [],
299
+ filesCreated: [],
300
+ testResults: { passed: 0, failed: 0, total: 0 },
301
+ };
302
+
303
+ validatePhase(testPhase, testResult, config).then(result => {
304
+ console.log('\nValidation Result:');
305
+ console.log(JSON.stringify(result, null, 2));
306
+ });
307
+ }
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Session ID Generator Hook
4
+ *
5
+ * Generates unique session IDs with PID-keyed registry for parallel session isolation.
6
+ * Enables multiple Claude Code sessions without interference.
7
+ *
8
+ * Event: SessionStart
9
+ *
10
+ * Configuration: Reads from .claude/config/hooks-config.json
11
+ *
12
+ * Features:
13
+ * - UUID session generation
14
+ * - PID-keyed registry (handles PID reuse)
15
+ * - Stale session cleanup
16
+ * - Cross-platform process detection
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const crypto = require('crypto');
22
+
23
+ // Default configuration
24
+ const DEFAULT_CONFIG = {
25
+ enabled: true,
26
+ retention_hours: 24, // Keep session records for 24 hours
27
+ cleanup_on_start: true, // Clean stale sessions on startup
28
+ registry_enabled: true, // Enable PID-keyed registry
29
+ };
30
+
31
+ // Paths
32
+ const CONFIG_PATH = path.join(process.cwd(), '.claude', 'config', 'hooks-config.json');
33
+ const CONFIG_DIR = path.join(process.cwd(), '.claude', 'hooks', 'config');
34
+ const SESSION_FILE = path.join(CONFIG_DIR, 'current-session.json');
35
+ const REGISTRY_FILE = path.join(CONFIG_DIR, 'session-registry.json');
36
+ const SESSIONS_DIR = path.join(process.cwd(), '.claude', 'sessions');
37
+
38
+ /**
39
+ * Load configuration
40
+ */
41
+ function loadConfig() {
42
+ try {
43
+ if (fs.existsSync(CONFIG_PATH)) {
44
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
45
+ return { ...DEFAULT_CONFIG, ...(config.session_generator || {}) };
46
+ }
47
+ } catch (e) {
48
+ // Use defaults
49
+ }
50
+ return DEFAULT_CONFIG;
51
+ }
52
+
53
+ /**
54
+ * Check if a process is still running (cross-platform)
55
+ */
56
+ function isProcessRunning(pid) {
57
+ try {
58
+ process.kill(pid, 0);
59
+ return true;
60
+ } catch (error) {
61
+ // EPERM means process exists but we don't have permission
62
+ // ESRCH means process doesn't exist
63
+ return error.code === 'EPERM';
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Clean stale entries from the session registry
69
+ */
70
+ function cleanStaleRegistryEntries(registry) {
71
+ const cleaned = {};
72
+ for (const [key, data] of Object.entries(registry)) {
73
+ if (isProcessRunning(data.pid)) {
74
+ cleaned[key] = data;
75
+ }
76
+ }
77
+ return cleaned;
78
+ }
79
+
80
+ /**
81
+ * Read the session registry
82
+ */
83
+ function readRegistry() {
84
+ try {
85
+ if (fs.existsSync(REGISTRY_FILE)) {
86
+ return JSON.parse(fs.readFileSync(REGISTRY_FILE, 'utf8'));
87
+ }
88
+ } catch (e) {
89
+ // Registry corrupt or unreadable - start fresh
90
+ }
91
+ return {};
92
+ }
93
+
94
+ /**
95
+ * Write the session registry atomically
96
+ */
97
+ function writeRegistry(registry) {
98
+ const tempFile = REGISTRY_FILE + '.tmp';
99
+ try {
100
+ fs.writeFileSync(tempFile, JSON.stringify(registry, null, 2));
101
+ fs.renameSync(tempFile, REGISTRY_FILE);
102
+ } catch (e) {
103
+ // Fallback: direct write if rename fails (Windows)
104
+ try {
105
+ fs.writeFileSync(REGISTRY_FILE, JSON.stringify(registry, null, 2));
106
+ } catch (err) {
107
+ // Silent fail - registry is not critical
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Cleanup old session files
114
+ */
115
+ function cleanupOldSessions(config) {
116
+ const retentionMs = config.retention_hours * 60 * 60 * 1000;
117
+
118
+ try {
119
+ if (!fs.existsSync(SESSIONS_DIR)) return;
120
+
121
+ const now = Date.now();
122
+ const files = fs.readdirSync(SESSIONS_DIR);
123
+
124
+ for (const file of files) {
125
+ if (!file.endsWith('-task.json') && !file.endsWith('-session.json')) continue;
126
+
127
+ const filePath = path.join(SESSIONS_DIR, file);
128
+ const stat = fs.statSync(filePath);
129
+
130
+ if (now - stat.mtimeMs > retentionMs) {
131
+ fs.unlinkSync(filePath);
132
+ console.log(`[session-generator] Cleaned old session: ${file}`);
133
+ }
134
+ }
135
+ } catch (e) {
136
+ // Silent fail - cleanup is non-critical
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Main hook handler
142
+ */
143
+ module.exports = async function sessionIdGenerator(context) {
144
+ const approve = () => ({ continue: true });
145
+
146
+ try {
147
+ const config = loadConfig();
148
+
149
+ if (!config.enabled) {
150
+ return approve();
151
+ }
152
+
153
+ // Cleanup on start if enabled
154
+ if (config.cleanup_on_start) {
155
+ cleanupOldSessions(config);
156
+ }
157
+
158
+ // Generate UUID for this session
159
+ const sessionId = crypto.randomUUID();
160
+ const startTime = Date.now();
161
+ const pid = process.pid;
162
+
163
+ // Create session data
164
+ const sessionData = {
165
+ session_id: sessionId,
166
+ pid: pid,
167
+ start_time: startTime,
168
+ started_at: new Date().toISOString(),
169
+ cwd: process.cwd(),
170
+ node_version: process.version,
171
+ platform: process.platform,
172
+ };
173
+
174
+ // Ensure config directory exists
175
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
176
+
177
+ // Update session registry if enabled
178
+ if (config.registry_enabled) {
179
+ let registry = readRegistry();
180
+ registry = cleanStaleRegistryEntries(registry);
181
+
182
+ // Create composite key: pid-startTime (handles PID reuse)
183
+ const registryKey = `${pid}-${startTime}`;
184
+ registry[registryKey] = sessionData;
185
+
186
+ writeRegistry(registry);
187
+ }
188
+
189
+ // Write current-session.json (backwards compatibility)
190
+ fs.writeFileSync(SESSION_FILE, JSON.stringify(sessionData, null, 2));
191
+
192
+ // Set environment variable for downstream hooks
193
+ process.env.CLAUDE_SESSION_ID = sessionId;
194
+
195
+ console.log(`[session-generator] Session started: ${sessionId.substring(0, 8)}...`);
196
+
197
+ return approve();
198
+ } catch (error) {
199
+ console.error(`[session-generator] Error: ${error.message}`);
200
+ return approve();
201
+ }
202
+ };
203
+
204
+ // Direct execution support
205
+ if (require.main === module) {
206
+ const config = loadConfig();
207
+
208
+ if (config.cleanup_on_start) {
209
+ cleanupOldSessions(config);
210
+ }
211
+
212
+ const sessionId = crypto.randomUUID();
213
+ const startTime = Date.now();
214
+ const pid = process.pid;
215
+
216
+ const sessionData = {
217
+ session_id: sessionId,
218
+ pid: pid,
219
+ start_time: startTime,
220
+ started_at: new Date().toISOString(),
221
+ cwd: process.cwd(),
222
+ };
223
+
224
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
225
+
226
+ if (config.registry_enabled) {
227
+ let registry = readRegistry();
228
+ registry = cleanStaleRegistryEntries(registry);
229
+ registry[`${pid}-${startTime}`] = sessionData;
230
+ writeRegistry(registry);
231
+ }
232
+
233
+ fs.writeFileSync(SESSION_FILE, JSON.stringify(sessionData, null, 2));
234
+
235
+ console.log(JSON.stringify({ result: 'continue' }));
236
+ }