cc-dev-template 0.1.32 → 0.1.34
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/install.js +5 -9
- package/package.json +1 -1
- package/src/commands/done.md +52 -0
- package/src/commands/prime.md +40 -4
- package/src/skills/initialize-project/SKILL.md +84 -0
- package/src/agents/adr-agent.md +0 -167
- package/src/agents/claude-md-agent.md +0 -124
- package/src/agents/decomposition-agent.md +0 -170
- package/src/agents/execution-agent.md +0 -232
- package/src/agents/rca-agent.md +0 -192
- package/src/agents/tdd-agent.md +0 -205
- package/src/commands/create-agent-skill.md +0 -11
- package/src/commands/finalize.md +0 -48
- package/src/commands/heal-skill.md +0 -69
- package/src/hooks/orchestration-guidance.sh +0 -56
- package/src/hooks/orchestration-hook.json +0 -14
- package/src/scripts/adr-list.js +0 -298
- package/src/scripts/adr-tags.js +0 -242
- package/src/scripts/validate-yaml.js +0 -142
- package/src/scripts/yaml-validation-hook.json +0 -15
- package/src/skills/orchestration/SKILL.md +0 -161
- package/src/skills/orchestration/references/debugging/describe.md +0 -144
- package/src/skills/orchestration/references/debugging/fix.md +0 -117
- package/src/skills/orchestration/references/debugging/learn.md +0 -185
- package/src/skills/orchestration/references/debugging/rca.md +0 -92
- package/src/skills/orchestration/references/debugging/verify.md +0 -102
- package/src/skills/orchestration/references/execution/complete.md +0 -175
- package/src/skills/orchestration/references/execution/start.md +0 -77
- package/src/skills/orchestration/references/execution/tasks.md +0 -114
- package/src/skills/orchestration/references/planning/draft.md +0 -269
- package/src/skills/orchestration/references/planning/explore.md +0 -160
- package/src/skills/orchestration/references/planning/finalize.md +0 -184
- package/src/skills/orchestration/references/planning/start.md +0 -119
- package/src/skills/orchestration/scripts/plan-status.js +0 -355
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# Planning Phase 1: Requirements
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
Transform a vague idea into a crystal clear understanding of WHAT we're building and what SUCCESS looks like.
|
|
6
|
-
|
|
7
|
-
This phase is about understanding the problem, not solving it. Stay focused on goals, success criteria, and removing ambiguity. Implementation details (the HOW) come later in exploration and drafting phases.
|
|
8
|
-
|
|
9
|
-
**Success looks like**: You can articulate exactly what the user wants to build, why it matters, and how we'll know when it's done—with zero ambiguity.
|
|
10
|
-
|
|
11
|
-
## What To Do
|
|
12
|
-
|
|
13
|
-
Complete each step in order before proceeding to the next.
|
|
14
|
-
|
|
15
|
-
<steps>
|
|
16
|
-
|
|
17
|
-
<step name="Ask What They Want to Plan">
|
|
18
|
-
Start with a simple, open-ended question. Let the user describe their idea in their own words.
|
|
19
|
-
|
|
20
|
-
Just ask: **"What do you want to plan?"**
|
|
21
|
-
|
|
22
|
-
Let them write freely here (save AskUserQuestion for the clarifying questions). They'll dump out their thoughts, context, and initial ideas. Your job is to listen and absorb.
|
|
23
|
-
</step>
|
|
24
|
-
|
|
25
|
-
<step name="Probe for Clarity">
|
|
26
|
-
After the user describes what they want, your job is to remove all ambiguity. Use `AskUserQuestion` to dig into anything that's unclear.
|
|
27
|
-
|
|
28
|
-
**Focus on these areas:**
|
|
29
|
-
|
|
30
|
-
1. **Goals**: What are they trying to achieve? What problem does this solve?
|
|
31
|
-
2. **Success criteria**: How will we know when this is done? What does "working" look like?
|
|
32
|
-
3. **Scope boundaries**: What's included? What's explicitly NOT included?
|
|
33
|
-
4. **Submodule scope**: If in a repo with submodules, which submodules does this work affect?
|
|
34
|
-
5. **Ambiguities**: Anything in their description that could be interpreted multiple ways
|
|
35
|
-
|
|
36
|
-
**Ask only what the user alone can answer.** Questions about goals, preferences, success criteria, and scope belong here. Questions about codebase state (what exists, how things work) belong in exploration (Phase 2)—discover those yourself by reading the code.
|
|
37
|
-
|
|
38
|
-
**Ask one clarifying question at a time.** After each answer, assess: Is there still ambiguity? If yes, ask another question. If no, move on.
|
|
39
|
-
|
|
40
|
-
**Example clarifying questions:**
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
"You mentioned [X]. What specifically should happen when [X]?"
|
|
44
|
-
|
|
45
|
-
"What does success look like for this? How will you know it's working?"
|
|
46
|
-
|
|
47
|
-
"Is [Y] part of this work, or should we consider that out of scope?"
|
|
48
|
-
|
|
49
|
-
"When you say [Z], do you mean [interpretation A] or [interpretation B]?"
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Always include an escape hatch** in your AskUserQuestion options—something like "Something else" or "Let me explain" so the user can provide context that doesn't fit your options.
|
|
53
|
-
</step>
|
|
54
|
-
|
|
55
|
-
<step name="Keep Going Until Clear">
|
|
56
|
-
Continue asking clarifying questions until ONE of these is true:
|
|
57
|
-
|
|
58
|
-
- **You have no more questions**: Every aspect of what they want is crystal clear
|
|
59
|
-
- **The user says stop**: They indicate they've clarified enough ("I think that covers it", "Let's move on", etc.)
|
|
60
|
-
|
|
61
|
-
Take your time here. Ambiguity discovered now is cheap to resolve. Ambiguity discovered during implementation is expensive.
|
|
62
|
-
</step>
|
|
63
|
-
|
|
64
|
-
<step name="Summarize What You Learned">
|
|
65
|
-
Before moving on, summarize your understanding back to the user:
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
## Here's what I understand:
|
|
69
|
-
|
|
70
|
-
**What we're building**: [1-2 sentence summary]
|
|
71
|
-
|
|
72
|
-
**Goals**:
|
|
73
|
-
- [Goal 1]
|
|
74
|
-
- [Goal 2]
|
|
75
|
-
|
|
76
|
-
**Success criteria** (how we'll know it's done):
|
|
77
|
-
- [Criterion 1]
|
|
78
|
-
- [Criterion 2]
|
|
79
|
-
|
|
80
|
-
**Scope**:
|
|
81
|
-
- Includes: [what's in]
|
|
82
|
-
- Excludes: [what's out]
|
|
83
|
-
- Submodules affected: [list submodules if relevant, or "N/A"]
|
|
84
|
-
|
|
85
|
-
**Type**: [feature / enhancement / refactor / bug fix]
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Then confirm:
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
AskUserQuestion:
|
|
92
|
-
Question: "Does this capture what you want to build?"
|
|
93
|
-
Options:
|
|
94
|
-
- "Yes, that's right" - Proceed to codebase exploration
|
|
95
|
-
- "Mostly, but..." - I'll clarify what needs adjustment
|
|
96
|
-
- "No, let's try again" - Start over with a fresh description
|
|
97
|
-
```
|
|
98
|
-
</step>
|
|
99
|
-
|
|
100
|
-
<checkpoint>
|
|
101
|
-
Before proceeding to the next phase:
|
|
102
|
-
- User has described what they want
|
|
103
|
-
- All ambiguities have been clarified
|
|
104
|
-
- Summary has been presented and confirmed
|
|
105
|
-
</checkpoint>
|
|
106
|
-
|
|
107
|
-
</steps>
|
|
108
|
-
|
|
109
|
-
## Key Principles
|
|
110
|
-
|
|
111
|
-
**Stay focused on WHAT, not HOW.** Keep questions about goals, success criteria, and scope. Save implementation questions ("Which framework? What database?") for later phases.
|
|
112
|
-
|
|
113
|
-
**Ask when uncertain.** If something is unclear, ask. Let the user fill in the blanks rather than assuming.
|
|
114
|
-
|
|
115
|
-
**Invest time here.** This phase sets the foundation. A few extra minutes of clarity now saves hours of rework later.
|
|
116
|
-
|
|
117
|
-
<transition>
|
|
118
|
-
When the user confirms your summary is accurate, read `references/planning/explore.md` to continue to codebase exploration.
|
|
119
|
-
</transition>
|
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* plan-status.js - List active plans and debug sessions in the project
|
|
5
|
-
*
|
|
6
|
-
* This CLI script scans .claude/plans/ and .claude/debug/ for active work
|
|
7
|
-
* and outputs structured information. Completed items are filtered out
|
|
8
|
-
* since they're no longer actionable. Designed to support /prime command
|
|
9
|
-
* by quickly surfacing "where are we" and "what can we do" without manual
|
|
10
|
-
* file scanning.
|
|
11
|
-
*
|
|
12
|
-
* Usage:
|
|
13
|
-
* node ~/.claude/skills/orchestration/scripts/plan-status.js
|
|
14
|
-
*
|
|
15
|
-
* Output:
|
|
16
|
-
* JSON object to stdout:
|
|
17
|
-
* {
|
|
18
|
-
* "plans": [
|
|
19
|
-
* {
|
|
20
|
-
* "id": "plan-feature-auth",
|
|
21
|
-
* "title": "Authentication Feature",
|
|
22
|
-
* "status": "approved",
|
|
23
|
-
* "path": ".claude/plans/feature-auth/"
|
|
24
|
-
* }
|
|
25
|
-
* ],
|
|
26
|
-
* "debugSessions": [
|
|
27
|
-
* {
|
|
28
|
-
* "id": "debug-001",
|
|
29
|
-
* "title": "Avatar not updating",
|
|
30
|
-
* "status": "investigating",
|
|
31
|
-
* "phase": "rca",
|
|
32
|
-
* "path": ".claude/debug/avatar-not-updating/"
|
|
33
|
-
* }
|
|
34
|
-
* ]
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* Directory structure:
|
|
38
|
-
* .claude/plans/[slug]/
|
|
39
|
-
* plan.md - Plan definition with YAML frontmatter (preferred)
|
|
40
|
-
* plan.yaml - Plan definition (legacy, fallback)
|
|
41
|
-
* manifest.yaml - Task manifest with completion status (optional)
|
|
42
|
-
*
|
|
43
|
-
* .claude/debug/[slug]/
|
|
44
|
-
* debug.md - Debug session with YAML frontmatter (preferred)
|
|
45
|
-
* debug.yaml - Debug session (legacy, fallback)
|
|
46
|
-
*
|
|
47
|
-
* Note: This script uses process.cwd() to find project-local files, since
|
|
48
|
-
* scripts install globally to ~/.claude/scripts/ but need to access the
|
|
49
|
-
* project's .claude/ directories.
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
const fs = require('fs');
|
|
53
|
-
const path = require('path');
|
|
54
|
-
const yaml = require('js-yaml');
|
|
55
|
-
|
|
56
|
-
// Directories are in the project's .claude/ directory (relative to CWD)
|
|
57
|
-
const PLANS_DIR = path.join(process.cwd(), '.claude', 'plans');
|
|
58
|
-
const DEBUG_DIR = path.join(process.cwd(), '.claude', 'debug');
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Read and parse a YAML file
|
|
62
|
-
* @param {string} filePath - Absolute path to the YAML file
|
|
63
|
-
* @returns {object | null} - Parsed YAML data or null on error
|
|
64
|
-
*/
|
|
65
|
-
function parseYamlFile(filePath) {
|
|
66
|
-
try {
|
|
67
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
68
|
-
return yaml.load(content);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
// Log to stderr so it doesn't pollute JSON output
|
|
71
|
-
console.error(`Warning: Failed to parse ${filePath}: ${error.message}`);
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Parse YAML frontmatter from Markdown content
|
|
78
|
-
* Frontmatter is delimited by --- at start and end
|
|
79
|
-
* @param {string} content - File content as string
|
|
80
|
-
* @returns {object | null} - Parsed YAML object or null if no frontmatter
|
|
81
|
-
*/
|
|
82
|
-
function parseFrontmatter(content) {
|
|
83
|
-
if (!content || typeof content !== 'string') {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Frontmatter must start at the beginning of the file with ---
|
|
88
|
-
if (!content.startsWith('---')) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Find the closing ---
|
|
93
|
-
const endIndex = content.indexOf('\n---', 3);
|
|
94
|
-
if (endIndex === -1) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Extract the YAML content between the delimiters
|
|
99
|
-
const frontmatterContent = content.slice(4, endIndex).trim();
|
|
100
|
-
if (!frontmatterContent) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
return yaml.load(frontmatterContent);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error(`Warning: Failed to parse frontmatter: ${error.message}`);
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Read and parse a Markdown file with YAML frontmatter
|
|
114
|
-
* @param {string} filePath - Absolute path to the Markdown file
|
|
115
|
-
* @returns {object | null} - Parsed frontmatter data or null on error
|
|
116
|
-
*/
|
|
117
|
-
function parseMarkdownFile(filePath) {
|
|
118
|
-
try {
|
|
119
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
120
|
-
return parseFrontmatter(content);
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error(`Warning: Failed to read ${filePath}: ${error.message}`);
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Count completed and total tasks from a manifest
|
|
129
|
-
* @param {object} manifest - Parsed manifest.yaml data
|
|
130
|
-
* @returns {{ total: number, completed: number } | null}
|
|
131
|
-
*/
|
|
132
|
-
function countTasks(manifest) {
|
|
133
|
-
if (!manifest || !Array.isArray(manifest.tasks)) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const total = manifest.tasks.length;
|
|
138
|
-
const completed = manifest.tasks.filter(task => task.status === 'completed').length;
|
|
139
|
-
|
|
140
|
-
return { total, completed };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Get plan information from a plan directory
|
|
145
|
-
* Prefers plan.md (Markdown with frontmatter), falls back to plan.yaml
|
|
146
|
-
* @param {string} planDir - Absolute path to the plan directory
|
|
147
|
-
* @param {string} slug - Directory name (slug)
|
|
148
|
-
* @returns {object | null} - Plan info object or null if invalid
|
|
149
|
-
*/
|
|
150
|
-
function getPlanInfo(planDir, slug) {
|
|
151
|
-
const planMdPath = path.join(planDir, 'plan.md');
|
|
152
|
-
const planYamlPath = path.join(planDir, 'plan.yaml');
|
|
153
|
-
const manifestPath = path.join(planDir, 'manifest.yaml');
|
|
154
|
-
|
|
155
|
-
// Try plan.md first (preferred format), fall back to plan.yaml
|
|
156
|
-
let plan = null;
|
|
157
|
-
if (fs.existsSync(planMdPath)) {
|
|
158
|
-
plan = parseMarkdownFile(planMdPath);
|
|
159
|
-
} else if (fs.existsSync(planYamlPath)) {
|
|
160
|
-
plan = parseYamlFile(planYamlPath);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (!plan) {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Build plan info object
|
|
168
|
-
const planInfo = {
|
|
169
|
-
id: plan.id || `plan-${slug}`,
|
|
170
|
-
title: plan.title || '',
|
|
171
|
-
status: plan.status || 'unknown',
|
|
172
|
-
path: `.claude/plans/${slug}/`
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// Include affected_submodules if present in the plan
|
|
176
|
-
if (Array.isArray(plan.affected_submodules) && plan.affected_submodules.length > 0) {
|
|
177
|
-
planInfo.affected_submodules = plan.affected_submodules;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// If manifest exists, use its status and add task counts
|
|
181
|
-
// The manifest represents actual execution progress, so it overrides plan.yaml status
|
|
182
|
-
if (fs.existsSync(manifestPath)) {
|
|
183
|
-
const manifest = parseYamlFile(manifestPath);
|
|
184
|
-
|
|
185
|
-
// Use manifest status if present (represents actual progress)
|
|
186
|
-
if (manifest && manifest.status) {
|
|
187
|
-
planInfo.status = manifest.status;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Add task counts from manifest
|
|
191
|
-
const taskCounts = countTasks(manifest);
|
|
192
|
-
if (taskCounts) {
|
|
193
|
-
planInfo.tasks = taskCounts;
|
|
194
|
-
|
|
195
|
-
// Derive completion status: if all tasks are completed, the plan is completed
|
|
196
|
-
if (taskCounts.total > 0 && taskCounts.completed === taskCounts.total) {
|
|
197
|
-
planInfo.status = 'completed';
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return planInfo;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Scan plans directory and collect all plan information
|
|
207
|
-
* @returns {Array<object>} - Array of plan info objects
|
|
208
|
-
*/
|
|
209
|
-
function collectPlans() {
|
|
210
|
-
const plans = [];
|
|
211
|
-
|
|
212
|
-
// Check if plans directory exists - return empty array if not
|
|
213
|
-
if (!fs.existsSync(PLANS_DIR)) {
|
|
214
|
-
return plans;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Get all subdirectories in plans directory
|
|
218
|
-
let entries;
|
|
219
|
-
try {
|
|
220
|
-
entries = fs.readdirSync(PLANS_DIR, { withFileTypes: true });
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.error(`Warning: Failed to read plans directory: ${error.message}`);
|
|
223
|
-
return plans;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Process each plan directory
|
|
227
|
-
const planDirs = entries
|
|
228
|
-
.filter(entry => entry.isDirectory())
|
|
229
|
-
.map(entry => entry.name)
|
|
230
|
-
.sort(); // Sort alphabetically for consistent ordering
|
|
231
|
-
|
|
232
|
-
for (const slug of planDirs) {
|
|
233
|
-
const planDir = path.join(PLANS_DIR, slug);
|
|
234
|
-
const planInfo = getPlanInfo(planDir, slug);
|
|
235
|
-
|
|
236
|
-
// Only include non-completed plans
|
|
237
|
-
if (planInfo && planInfo.status !== 'completed') {
|
|
238
|
-
plans.push(planInfo);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return plans;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Determine which debug phase based on debug.yaml state
|
|
247
|
-
* @param {object} debug - Parsed debug.yaml data
|
|
248
|
-
* @returns {string} - Phase name (describe, rca, verify, fix, learn)
|
|
249
|
-
*/
|
|
250
|
-
function determineDebugPhase(debug) {
|
|
251
|
-
if (!debug || debug.status === 'closed') {
|
|
252
|
-
return 'closed';
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const hypotheses = debug.hypotheses || [];
|
|
256
|
-
if (hypotheses.length === 0) {
|
|
257
|
-
return 'rca';
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Check the latest hypothesis status
|
|
261
|
-
const latest = hypotheses[hypotheses.length - 1];
|
|
262
|
-
switch (latest.status) {
|
|
263
|
-
case 'investigating':
|
|
264
|
-
return 'rca';
|
|
265
|
-
case 'verified':
|
|
266
|
-
return 'fix';
|
|
267
|
-
case 'disproven':
|
|
268
|
-
return 'rca';
|
|
269
|
-
case 'fixed':
|
|
270
|
-
return 'learn';
|
|
271
|
-
default:
|
|
272
|
-
return 'rca';
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Get debug session information from a debug directory
|
|
278
|
-
* Prefers debug.md (Markdown with frontmatter), falls back to debug.yaml
|
|
279
|
-
* @param {string} debugDir - Absolute path to the debug directory
|
|
280
|
-
* @param {string} slug - Directory name (slug)
|
|
281
|
-
* @returns {object | null} - Debug info object or null if invalid
|
|
282
|
-
*/
|
|
283
|
-
function getDebugInfo(debugDir, slug) {
|
|
284
|
-
const debugMdPath = path.join(debugDir, 'debug.md');
|
|
285
|
-
const debugYamlPath = path.join(debugDir, 'debug.yaml');
|
|
286
|
-
|
|
287
|
-
// Try debug.md first (preferred format), fall back to debug.yaml
|
|
288
|
-
let debug = null;
|
|
289
|
-
if (fs.existsSync(debugMdPath)) {
|
|
290
|
-
debug = parseMarkdownFile(debugMdPath);
|
|
291
|
-
} else if (fs.existsSync(debugYamlPath)) {
|
|
292
|
-
debug = parseYamlFile(debugYamlPath);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (!debug) {
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return {
|
|
300
|
-
id: debug.id || `debug-${slug}`,
|
|
301
|
-
title: debug.title || '',
|
|
302
|
-
status: debug.status || 'unknown',
|
|
303
|
-
phase: determineDebugPhase(debug),
|
|
304
|
-
path: `.claude/debug/${slug}/`
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Scan debug directory and collect all active debug sessions
|
|
310
|
-
* @returns {Array<object>} - Array of debug info objects
|
|
311
|
-
*/
|
|
312
|
-
function collectDebugSessions() {
|
|
313
|
-
const sessions = [];
|
|
314
|
-
|
|
315
|
-
if (!fs.existsSync(DEBUG_DIR)) {
|
|
316
|
-
return sessions;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
let entries;
|
|
320
|
-
try {
|
|
321
|
-
entries = fs.readdirSync(DEBUG_DIR, { withFileTypes: true });
|
|
322
|
-
} catch (error) {
|
|
323
|
-
console.error(`Warning: Failed to read debug directory: ${error.message}`);
|
|
324
|
-
return sessions;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const debugDirs = entries
|
|
328
|
-
.filter(entry => entry.isDirectory())
|
|
329
|
-
.map(entry => entry.name)
|
|
330
|
-
.sort();
|
|
331
|
-
|
|
332
|
-
for (const slug of debugDirs) {
|
|
333
|
-
const debugDir = path.join(DEBUG_DIR, slug);
|
|
334
|
-
const debugInfo = getDebugInfo(debugDir, slug);
|
|
335
|
-
|
|
336
|
-
// Only include non-closed sessions
|
|
337
|
-
if (debugInfo && debugInfo.status !== 'closed') {
|
|
338
|
-
sessions.push(debugInfo);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return sessions;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Main execution
|
|
346
|
-
function main() {
|
|
347
|
-
const plans = collectPlans();
|
|
348
|
-
const debugSessions = collectDebugSessions();
|
|
349
|
-
|
|
350
|
-
// Output JSON to stdout
|
|
351
|
-
const output = { plans, debugSessions };
|
|
352
|
-
console.log(JSON.stringify(output, null, 2));
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
main();
|