@rajat-rastogi/maestro 0.1.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.
- package/LICENSE +21 -0
- package/README.md +254 -0
- package/defaults/agents/documentation.txt +18 -0
- package/defaults/agents/implementation.txt +16 -0
- package/defaults/agents/quality.txt +19 -0
- package/defaults/agents/simplification.txt +19 -0
- package/defaults/agents/testing.txt +16 -0
- package/defaults/config +46 -0
- package/defaults/plan-tips.md +50 -0
- package/defaults/prompts/finalize.txt +14 -0
- package/defaults/prompts/hint_analysis.txt +38 -0
- package/defaults/prompts/plan_create.txt +36 -0
- package/defaults/prompts/review_first.txt +37 -0
- package/defaults/prompts/review_second.txt +36 -0
- package/defaults/prompts/task.txt +23 -0
- package/dist/backend/backend.d.ts +29 -0
- package/dist/backend/backend.d.ts.map +1 -0
- package/dist/backend/backend.js +9 -0
- package/dist/backend/backend.js.map +1 -0
- package/dist/backend/claude.d.ts +12 -0
- package/dist/backend/claude.d.ts.map +1 -0
- package/dist/backend/claude.js +155 -0
- package/dist/backend/claude.js.map +1 -0
- package/dist/backend/copilot.d.ts +11 -0
- package/dist/backend/copilot.d.ts.map +1 -0
- package/dist/backend/copilot.js +110 -0
- package/dist/backend/copilot.js.map +1 -0
- package/dist/backend/factory.d.ts +4 -0
- package/dist/backend/factory.d.ts.map +1 -0
- package/dist/backend/factory.js +13 -0
- package/dist/backend/factory.js.map +1 -0
- package/dist/config/configserver.d.ts +9 -0
- package/dist/config/configserver.d.ts.map +1 -0
- package/dist/config/configserver.js +141 -0
- package/dist/config/configserver.js.map +1 -0
- package/dist/config/dump.d.ts +2 -0
- package/dist/config/dump.d.ts.map +1 -0
- package/dist/config/dump.js +24 -0
- package/dist/config/dump.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +119 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/prompts.d.ts +19 -0
- package/dist/config/prompts.d.ts.map +1 -0
- package/dist/config/prompts.js +128 -0
- package/dist/config/prompts.js.map +1 -0
- package/dist/config/reset.d.ts +3 -0
- package/dist/config/reset.d.ts.map +1 -0
- package/dist/config/reset.js +23 -0
- package/dist/config/reset.js.map +1 -0
- package/dist/config/template.d.ts +5 -0
- package/dist/config/template.d.ts.map +1 -0
- package/dist/config/template.js +11 -0
- package/dist/config/template.js.map +1 -0
- package/dist/config/types.d.ts +35 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +42 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/write.d.ts +5 -0
- package/dist/config/write.d.ts.map +1 -0
- package/dist/config/write.js +59 -0
- package/dist/config/write.js.map +1 -0
- package/dist/dashboard/assets/config.html +1012 -0
- package/dist/dashboard/assets/dashboard.html +871 -0
- package/dist/dashboard/assets/help.html +657 -0
- package/dist/dashboard/assets.d.ts +2 -0
- package/dist/dashboard/assets.d.ts.map +1 -0
- package/dist/dashboard/assets.js +5 -0
- package/dist/dashboard/assets.js.map +1 -0
- package/dist/dashboard/event-bus.d.ts +11 -0
- package/dist/dashboard/event-bus.d.ts.map +1 -0
- package/dist/dashboard/event-bus.js +4 -0
- package/dist/dashboard/event-bus.js.map +1 -0
- package/dist/dashboard/replay-parser.d.ts +6 -0
- package/dist/dashboard/replay-parser.d.ts.map +1 -0
- package/dist/dashboard/replay-parser.js +56 -0
- package/dist/dashboard/replay-parser.js.map +1 -0
- package/dist/dashboard/server.d.ts +14 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +178 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/dashboard/watcher.d.ts +17 -0
- package/dist/dashboard/watcher.d.ts.map +1 -0
- package/dist/dashboard/watcher.js +73 -0
- package/dist/dashboard/watcher.js.map +1 -0
- package/dist/executor/hints.d.ts +21 -0
- package/dist/executor/hints.d.ts.map +1 -0
- package/dist/executor/hints.js +102 -0
- package/dist/executor/hints.js.map +1 -0
- package/dist/executor/task.d.ts +19 -0
- package/dist/executor/task.d.ts.map +1 -0
- package/dist/executor/task.js +119 -0
- package/dist/executor/task.js.map +1 -0
- package/dist/executor/validation.d.ts +18 -0
- package/dist/executor/validation.d.ts.map +1 -0
- package/dist/executor/validation.js +73 -0
- package/dist/executor/validation.js.map +1 -0
- package/dist/git/branch.d.ts +23 -0
- package/dist/git/branch.d.ts.map +1 -0
- package/dist/git/branch.js +64 -0
- package/dist/git/branch.js.map +1 -0
- package/dist/git/commit.d.ts +21 -0
- package/dist/git/commit.d.ts.map +1 -0
- package/dist/git/commit.js +37 -0
- package/dist/git/commit.js.map +1 -0
- package/dist/git/diff.d.ts +15 -0
- package/dist/git/diff.d.ts.map +1 -0
- package/dist/git/diff.js +26 -0
- package/dist/git/diff.js.map +1 -0
- package/dist/git/git.d.ts +9 -0
- package/dist/git/git.d.ts.map +1 -0
- package/dist/git/git.js +20 -0
- package/dist/git/git.js.map +1 -0
- package/dist/git/gitignore.d.ts +2 -0
- package/dist/git/gitignore.d.ts.map +1 -0
- package/dist/git/gitignore.js +66 -0
- package/dist/git/gitignore.js.map +1 -0
- package/dist/git/worktree.d.ts +3 -0
- package/dist/git/worktree.d.ts.map +1 -0
- package/dist/git/worktree.js +17 -0
- package/dist/git/worktree.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +212 -0
- package/dist/main.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +21 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +218 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/plan/creator.d.ts +27 -0
- package/dist/plan/creator.d.ts.map +1 -0
- package/dist/plan/creator.js +251 -0
- package/dist/plan/creator.js.map +1 -0
- package/dist/plan/parser.d.ts +11 -0
- package/dist/plan/parser.d.ts.map +1 -0
- package/dist/plan/parser.js +151 -0
- package/dist/plan/parser.js.map +1 -0
- package/dist/plan/types.d.ts +23 -0
- package/dist/plan/types.d.ts.map +1 -0
- package/dist/plan/types.js +2 -0
- package/dist/plan/types.js.map +1 -0
- package/dist/plan/updater.d.ts +16 -0
- package/dist/plan/updater.d.ts.map +1 -0
- package/dist/plan/updater.js +59 -0
- package/dist/plan/updater.js.map +1 -0
- package/dist/progress/colors.d.ts +9 -0
- package/dist/progress/colors.d.ts.map +1 -0
- package/dist/progress/colors.js +39 -0
- package/dist/progress/colors.js.map +1 -0
- package/dist/progress/logger.d.ts +17 -0
- package/dist/progress/logger.d.ts.map +1 -0
- package/dist/progress/logger.js +101 -0
- package/dist/progress/logger.js.map +1 -0
- package/dist/progress/notify.d.ts +2 -0
- package/dist/progress/notify.d.ts.map +1 -0
- package/dist/progress/notify.js +37 -0
- package/dist/progress/notify.js.map +1 -0
- package/dist/progress/timestamp.d.ts +5 -0
- package/dist/progress/timestamp.d.ts.map +1 -0
- package/dist/progress/timestamp.js +13 -0
- package/dist/progress/timestamp.js.map +1 -0
- package/dist/review/agents.d.ts +18 -0
- package/dist/review/agents.d.ts.map +1 -0
- package/dist/review/agents.js +43 -0
- package/dist/review/agents.js.map +1 -0
- package/dist/review/pipeline.d.ts +36 -0
- package/dist/review/pipeline.d.ts.map +1 -0
- package/dist/review/pipeline.js +210 -0
- package/dist/review/pipeline.js.map +1 -0
- package/dist/sea.d.ts +19 -0
- package/dist/sea.d.ts.map +1 -0
- package/dist/sea.js +41 -0
- package/dist/sea.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as readline from 'readline';
|
|
4
|
+
import { spawnSync } from 'child_process';
|
|
5
|
+
import { loadPrompt } from '../config/prompts.js';
|
|
6
|
+
import { expandTemplate } from '../config/template.js';
|
|
7
|
+
const GENERATION_PROMPT_SUFFIX = `
|
|
8
|
+
Based on the exploration above and the user's answers, generate a complete maestro plan
|
|
9
|
+
file. Start the plan on its own line with "# Plan:" — everything from that line to the
|
|
10
|
+
end of your response will be saved as the plan file.
|
|
11
|
+
|
|
12
|
+
Use this structure:
|
|
13
|
+
# Plan: [Concise descriptive title]
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
[1–3 sentence goal description]
|
|
17
|
+
|
|
18
|
+
## Validation Commands
|
|
19
|
+
- \`command1\`
|
|
20
|
+
|
|
21
|
+
### Task 1: [Action verb + subject]
|
|
22
|
+
- [ ] [Specific verifiable step]
|
|
23
|
+
|
|
24
|
+
[Continue with 3–10 tasks appropriate to the scope. Each task must have checkboxes.]
|
|
25
|
+
`;
|
|
26
|
+
const REVISION_PROMPT_SUFFIX = `
|
|
27
|
+
Revise the plan according to the requested changes above. Output the complete updated plan
|
|
28
|
+
starting on its own line with "# Plan:" — everything from that line to the end of your
|
|
29
|
+
response will be saved as the plan file.
|
|
30
|
+
`;
|
|
31
|
+
export class PlanCreator {
|
|
32
|
+
config;
|
|
33
|
+
backend;
|
|
34
|
+
logger;
|
|
35
|
+
constructor(config, backend, logger) {
|
|
36
|
+
this.config = config;
|
|
37
|
+
this.backend = backend;
|
|
38
|
+
this.logger = logger;
|
|
39
|
+
}
|
|
40
|
+
async create(description) {
|
|
41
|
+
const cwd = process.cwd();
|
|
42
|
+
// ── Phase 1: exploration + questions ──
|
|
43
|
+
this.logger.info('Exploring codebase and generating questions...\n');
|
|
44
|
+
const exploration = await this.runExploration(description, cwd);
|
|
45
|
+
// ── Collect user answers ──
|
|
46
|
+
const answers = await this.collectAnswers();
|
|
47
|
+
// ── Phase 2: generate plan ──
|
|
48
|
+
this.logger.info('\nGenerating plan...\n');
|
|
49
|
+
const generationPrompt = this.buildGenerationPrompt(description, cwd, exploration, answers);
|
|
50
|
+
const output = await this.runGeneration(generationPrompt);
|
|
51
|
+
// ── Extract and save ──
|
|
52
|
+
const planContent = this.extractPlan(output);
|
|
53
|
+
const filePath = this.savePlan(planContent, description, cwd);
|
|
54
|
+
// ── Post-generation menu ──
|
|
55
|
+
return this.runMenu(planContent, filePath, description, cwd, exploration, answers);
|
|
56
|
+
}
|
|
57
|
+
// ── Menu loop ────────────────────────────────────────────────────────────
|
|
58
|
+
async runMenu(initialPlan, filePath, description, cwd, exploration, answers) {
|
|
59
|
+
let currentPlan = initialPlan;
|
|
60
|
+
while (true) {
|
|
61
|
+
this.printPlan(currentPlan);
|
|
62
|
+
process.stdout.write(`\n─── Plan saved: ${filePath} ───\n`);
|
|
63
|
+
process.stdout.write(' [A] Accept\n');
|
|
64
|
+
process.stdout.write(' [G] Accept and go (run now)\n');
|
|
65
|
+
process.stdout.write(' [E] Edit in editor\n');
|
|
66
|
+
process.stdout.write(' [R] Revise (re-generate with changes)\n');
|
|
67
|
+
process.stdout.write(' [X] Reject and discard\n\n');
|
|
68
|
+
const choice = await this.promptChoice('Choice [A/G/E/R/X]: ', ['a', 'g', 'e', 'r', 'x']);
|
|
69
|
+
if (choice === 'a') {
|
|
70
|
+
return { filePath, runNow: false };
|
|
71
|
+
}
|
|
72
|
+
if (choice === 'g') {
|
|
73
|
+
return { filePath, runNow: true };
|
|
74
|
+
}
|
|
75
|
+
if (choice === 'e') {
|
|
76
|
+
this.openEditor(filePath);
|
|
77
|
+
const runNow = await this.promptYesNo('Run now? [Y/n]: ');
|
|
78
|
+
return { filePath, runNow };
|
|
79
|
+
}
|
|
80
|
+
if (choice === 'r') {
|
|
81
|
+
const revision = await this.collectRevision();
|
|
82
|
+
this.logger.info('\nRevising plan...\n');
|
|
83
|
+
const revisedOutput = await this.runRevision(currentPlan, revision, description, cwd, exploration, answers);
|
|
84
|
+
currentPlan = this.extractPlan(revisedOutput);
|
|
85
|
+
fs.writeFileSync(filePath, currentPlan + '\n', 'utf8');
|
|
86
|
+
// loop back to show menu with updated plan
|
|
87
|
+
}
|
|
88
|
+
if (choice === 'x') {
|
|
89
|
+
try {
|
|
90
|
+
fs.unlinkSync(filePath);
|
|
91
|
+
}
|
|
92
|
+
catch { /* already gone */ }
|
|
93
|
+
this.logger.info('Plan discarded.');
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
99
|
+
printPlan(content) {
|
|
100
|
+
process.stdout.write('\n');
|
|
101
|
+
for (const line of content.split('\n')) {
|
|
102
|
+
this.logger.log(line, 'review');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
openEditor(filePath) {
|
|
106
|
+
const editor = process.env['EDITOR'] ?? process.env['VISUAL']
|
|
107
|
+
?? (process.platform === 'win32' ? 'notepad' : 'vi');
|
|
108
|
+
spawnSync(editor, [filePath], { stdio: 'inherit', shell: process.platform === 'win32' });
|
|
109
|
+
}
|
|
110
|
+
async promptChoice(prompt, valid) {
|
|
111
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
const ask = () => {
|
|
114
|
+
rl.question(prompt, (answer) => {
|
|
115
|
+
const lower = answer.trim().toLowerCase();
|
|
116
|
+
if (valid.includes(lower)) {
|
|
117
|
+
rl.close();
|
|
118
|
+
resolve(lower);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
ask();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
ask();
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async promptYesNo(prompt) {
|
|
129
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
rl.question(prompt, (answer) => {
|
|
132
|
+
rl.close();
|
|
133
|
+
resolve(answer.trim().toLowerCase() !== 'n');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async collectRevision() {
|
|
138
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
139
|
+
process.stdout.write('Describe what to change (blank line to finish):\n> ');
|
|
140
|
+
const lines = [];
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
rl.on('line', (line) => {
|
|
143
|
+
if (line === '') {
|
|
144
|
+
rl.close();
|
|
145
|
+
resolve(lines.join('\n'));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
lines.push(line);
|
|
149
|
+
process.stdout.write('> ');
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
rl.on('close', () => resolve(lines.join('\n')));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// ── AI phases ─────────────────────────────────────────────────────────────
|
|
156
|
+
async runExploration(description, cwd) {
|
|
157
|
+
const template = loadPrompt('plan_create', this.config);
|
|
158
|
+
const prompt = expandTemplate(template, { DESCRIPTION: description, CWD: cwd });
|
|
159
|
+
const lines = [];
|
|
160
|
+
await this.backend.run(prompt, (line) => {
|
|
161
|
+
if (line.type === 'text' && line.text.trim()) {
|
|
162
|
+
for (const l of line.text.split('\n')) {
|
|
163
|
+
this.logger.log(l, 'task');
|
|
164
|
+
lines.push(l);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return lines.join('\n');
|
|
169
|
+
}
|
|
170
|
+
async collectAnswers() {
|
|
171
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
172
|
+
process.stdout.write('\n─── Your answers (blank line to finish) ───\n> ');
|
|
173
|
+
const lines = [];
|
|
174
|
+
return new Promise((resolve) => {
|
|
175
|
+
rl.on('line', (line) => {
|
|
176
|
+
if (line === '') {
|
|
177
|
+
rl.close();
|
|
178
|
+
resolve(lines.join('\n'));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
lines.push(line);
|
|
182
|
+
process.stdout.write('> ');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
rl.on('close', () => resolve(lines.join('\n')));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
buildGenerationPrompt(description, cwd, exploration, answers) {
|
|
189
|
+
return [
|
|
190
|
+
`Developer request: ${description}`,
|
|
191
|
+
`Working directory: ${cwd}`,
|
|
192
|
+
'',
|
|
193
|
+
'Your codebase exploration and questions:',
|
|
194
|
+
exploration,
|
|
195
|
+
'',
|
|
196
|
+
"Developer's answers:",
|
|
197
|
+
answers,
|
|
198
|
+
'',
|
|
199
|
+
GENERATION_PROMPT_SUFFIX,
|
|
200
|
+
].join('\n');
|
|
201
|
+
}
|
|
202
|
+
async runGeneration(prompt) {
|
|
203
|
+
const lines = [];
|
|
204
|
+
await this.backend.run(prompt, (line) => {
|
|
205
|
+
if (line.type === 'text' && line.text.trim()) {
|
|
206
|
+
for (const l of line.text.split('\n')) {
|
|
207
|
+
this.logger.log(l, 'review');
|
|
208
|
+
lines.push(l);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
async runRevision(currentPlan, revision, description, cwd, exploration, answers) {
|
|
215
|
+
const prompt = [
|
|
216
|
+
`Original request: ${description}`,
|
|
217
|
+
`Working directory: ${cwd}`,
|
|
218
|
+
'',
|
|
219
|
+
'Codebase exploration and initial Q&A:',
|
|
220
|
+
exploration,
|
|
221
|
+
'',
|
|
222
|
+
"Developer's original answers:",
|
|
223
|
+
answers,
|
|
224
|
+
'',
|
|
225
|
+
'Current plan:',
|
|
226
|
+
currentPlan,
|
|
227
|
+
'',
|
|
228
|
+
'Requested changes:',
|
|
229
|
+
revision,
|
|
230
|
+
'',
|
|
231
|
+
REVISION_PROMPT_SUFFIX,
|
|
232
|
+
].join('\n');
|
|
233
|
+
return this.runGeneration(prompt);
|
|
234
|
+
}
|
|
235
|
+
extractPlan(output) {
|
|
236
|
+
const idx = output.indexOf('# Plan:');
|
|
237
|
+
if (idx === -1)
|
|
238
|
+
throw new Error('No plan found in output. Re-run with more detail.');
|
|
239
|
+
return output.slice(idx).trim();
|
|
240
|
+
}
|
|
241
|
+
savePlan(content, description, cwd) {
|
|
242
|
+
const plansDir = path.resolve(cwd, this.config.plans_dir);
|
|
243
|
+
fs.mkdirSync(plansDir, { recursive: true });
|
|
244
|
+
const slug = description
|
|
245
|
+
.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/, '').slice(0, 50);
|
|
246
|
+
const filePath = path.join(plansDir, `${slug}.md`);
|
|
247
|
+
fs.writeFileSync(filePath, content + '\n', 'utf8');
|
|
248
|
+
return filePath;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=creator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"creator.js","sourceRoot":"","sources":["../../src/plan/creator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Plan, Task } from './types.js';
|
|
2
|
+
export declare function parsePlanFile(filePath: string): Plan;
|
|
3
|
+
/**
|
|
4
|
+
* Find the first task that has at least one unchecked checkbox.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findFirstIncompleteTask(plan: Plan): Task | null;
|
|
7
|
+
/**
|
|
8
|
+
* Check if all tasks are complete.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isAllTasksComplete(plan: Plan): boolean;
|
|
11
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/plan/parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAY,MAAM,YAAY,CAAC;AASlD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAWpD;AAqID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAQ/D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAEtD"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
// Matches "### Task 1:", "### Task 2.5:", "### Task 2a:", "### Iteration 3:"
|
|
3
|
+
const TASK_HEADER_RE = /^###\s+(?:Task|Iteration)\s+([\d]+(?:\.\d+|[a-z])?)\s*:(.*)$/i;
|
|
4
|
+
const CHECKBOX_RE = /^(\s*)-\s+\[([ xX])\]\s+(.*)$/;
|
|
5
|
+
const VALIDATION_SECTION_RE = /^##\s+Validation\s+Commands\s*$/i;
|
|
6
|
+
const TASK_VALIDATION_RE = /^####\s+Validation\s+Commands\s*$/i;
|
|
7
|
+
const OVERVIEW_SECTION_RE = /^##\s+Overview\s*$/i;
|
|
8
|
+
export function parsePlanFile(filePath) {
|
|
9
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
10
|
+
// Normalize CRLF (Windows) to LF so regexes work correctly on all platforms
|
|
11
|
+
const lines = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
|
|
12
|
+
const title = extractTitle(lines);
|
|
13
|
+
const goal = extractGoal(lines);
|
|
14
|
+
const validationCommands = extractValidationCommands(lines);
|
|
15
|
+
const tasks = extractTasks(lines);
|
|
16
|
+
return { title, goal, validationCommands, tasks, filePath, lines };
|
|
17
|
+
}
|
|
18
|
+
function extractTitle(lines) {
|
|
19
|
+
for (const line of lines) {
|
|
20
|
+
const m = line.match(/^#\s+(.+)$/);
|
|
21
|
+
if (m)
|
|
22
|
+
return m[1].trim();
|
|
23
|
+
}
|
|
24
|
+
return 'Untitled Plan';
|
|
25
|
+
}
|
|
26
|
+
function extractGoal(lines) {
|
|
27
|
+
let inOverview = false;
|
|
28
|
+
const goalLines = [];
|
|
29
|
+
for (const line of lines) {
|
|
30
|
+
if (OVERVIEW_SECTION_RE.test(line)) {
|
|
31
|
+
inOverview = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (inOverview) {
|
|
35
|
+
if (/^#+\s/.test(line))
|
|
36
|
+
break;
|
|
37
|
+
goalLines.push(line);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return goalLines.join('\n').trim();
|
|
41
|
+
}
|
|
42
|
+
function extractValidationCommands(lines) {
|
|
43
|
+
let inSection = false;
|
|
44
|
+
const commands = [];
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
if (VALIDATION_SECTION_RE.test(line)) {
|
|
47
|
+
inSection = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (inSection) {
|
|
51
|
+
// Stop at any heading (##, ###, etc.) — not just same-level
|
|
52
|
+
if (/^#+\s/.test(line))
|
|
53
|
+
break;
|
|
54
|
+
// Skip checkbox lines — they are never commands
|
|
55
|
+
if (/^\s*-\s+\[[ xX]\]/.test(line))
|
|
56
|
+
continue;
|
|
57
|
+
// Extract command from bullet: `- \`command\`` or `- command`
|
|
58
|
+
const m = line.match(/^\s*-\s+`?(.+?)`?\s*$/);
|
|
59
|
+
if (m)
|
|
60
|
+
commands.push(m[1].trim());
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return commands;
|
|
64
|
+
}
|
|
65
|
+
function extractTasks(lines) {
|
|
66
|
+
const tasks = [];
|
|
67
|
+
let currentTask = null;
|
|
68
|
+
let inTaskValidation = false;
|
|
69
|
+
let taskValidationCommands = [];
|
|
70
|
+
for (let i = 0; i < lines.length; i++) {
|
|
71
|
+
const line = lines[i];
|
|
72
|
+
const taskMatch = line.match(TASK_HEADER_RE);
|
|
73
|
+
if (taskMatch) {
|
|
74
|
+
if (currentTask) {
|
|
75
|
+
// Finalize previous task
|
|
76
|
+
tasks.push(buildTask(currentTask, taskValidationCommands, i, lines));
|
|
77
|
+
}
|
|
78
|
+
currentTask = {
|
|
79
|
+
index: taskMatch[1],
|
|
80
|
+
title: taskMatch[2].trim(),
|
|
81
|
+
startLine: i,
|
|
82
|
+
checkboxes: [],
|
|
83
|
+
};
|
|
84
|
+
inTaskValidation = false;
|
|
85
|
+
taskValidationCommands = [];
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (currentTask) {
|
|
89
|
+
if (TASK_VALIDATION_RE.test(line)) {
|
|
90
|
+
inTaskValidation = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (inTaskValidation) {
|
|
94
|
+
if (/^#+\s/.test(line)) {
|
|
95
|
+
inTaskValidation = false;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const m = line.match(/^\s*-\s+`?(.+?)`?\s*$/);
|
|
99
|
+
if (m)
|
|
100
|
+
taskValidationCommands.push(m[1].trim());
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const cbMatch = line.match(CHECKBOX_RE);
|
|
105
|
+
if (cbMatch) {
|
|
106
|
+
currentTask.checkboxes.push({
|
|
107
|
+
text: cbMatch[3].trim(),
|
|
108
|
+
checked: cbMatch[2].toLowerCase() === 'x',
|
|
109
|
+
lineIndex: i,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Finalize last task
|
|
115
|
+
if (currentTask) {
|
|
116
|
+
tasks.push(buildTask(currentTask, taskValidationCommands, lines.length, lines));
|
|
117
|
+
}
|
|
118
|
+
return tasks;
|
|
119
|
+
}
|
|
120
|
+
function buildTask(current, validationCommands, endLine, lines) {
|
|
121
|
+
const rawLines = lines.slice(current.startLine, endLine);
|
|
122
|
+
return {
|
|
123
|
+
index: current.index,
|
|
124
|
+
title: current.title,
|
|
125
|
+
checkboxes: current.checkboxes,
|
|
126
|
+
validationCommands,
|
|
127
|
+
startLine: current.startLine,
|
|
128
|
+
endLine,
|
|
129
|
+
rawText: rawLines.join('\n'),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find the first task that has at least one unchecked checkbox.
|
|
134
|
+
*/
|
|
135
|
+
export function findFirstIncompleteTask(plan) {
|
|
136
|
+
for (const task of plan.tasks) {
|
|
137
|
+
if (task.checkboxes.length === 0)
|
|
138
|
+
continue;
|
|
139
|
+
if (task.checkboxes.some(cb => !cb.checked)) {
|
|
140
|
+
return task;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if all tasks are complete.
|
|
147
|
+
*/
|
|
148
|
+
export function isAllTasksComplete(plan) {
|
|
149
|
+
return findFirstIncompleteTask(plan) === null;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/plan/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface Checkbox {
|
|
2
|
+
text: string;
|
|
3
|
+
checked: boolean;
|
|
4
|
+
lineIndex: number;
|
|
5
|
+
}
|
|
6
|
+
export interface Task {
|
|
7
|
+
index: string;
|
|
8
|
+
title: string;
|
|
9
|
+
checkboxes: Checkbox[];
|
|
10
|
+
validationCommands: string[];
|
|
11
|
+
startLine: number;
|
|
12
|
+
endLine: number;
|
|
13
|
+
rawText: string;
|
|
14
|
+
}
|
|
15
|
+
export interface Plan {
|
|
16
|
+
title: string;
|
|
17
|
+
goal: string;
|
|
18
|
+
validationCommands: string[];
|
|
19
|
+
tasks: Task[];
|
|
20
|
+
filePath: string;
|
|
21
|
+
lines: string[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plan/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plan/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Plan, Task } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mark all checkboxes in a task as checked, writing the change back to the plan file.
|
|
4
|
+
* Mutates plan.lines in-place and writes to disk.
|
|
5
|
+
*/
|
|
6
|
+
export declare function markTaskComplete(plan: Plan, task: Task): void;
|
|
7
|
+
/**
|
|
8
|
+
* Move a completed plan file to docs/plans/completed/ with a timestamp suffix.
|
|
9
|
+
* Returns the new file path.
|
|
10
|
+
*/
|
|
11
|
+
export declare function movePlanToCompleted(plan: Plan, plansDir: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Reload plan from disk (after external modifications).
|
|
14
|
+
*/
|
|
15
|
+
export declare function reloadPlan(plan: Plan): void;
|
|
16
|
+
//# sourceMappingURL=updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../src/plan/updater.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAExC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAa7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAc3C"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Mark all checkboxes in a task as checked, writing the change back to the plan file.
|
|
5
|
+
* Mutates plan.lines in-place and writes to disk.
|
|
6
|
+
*/
|
|
7
|
+
export function markTaskComplete(plan, task) {
|
|
8
|
+
for (const checkbox of task.checkboxes) {
|
|
9
|
+
if (!checkbox.checked) {
|
|
10
|
+
const line = plan.lines[checkbox.lineIndex];
|
|
11
|
+
plan.lines[checkbox.lineIndex] = line.replace(/\[ \]/, '[x]');
|
|
12
|
+
checkbox.checked = true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Also update the task's rawText
|
|
16
|
+
task.rawText = plan.lines.slice(task.startLine, task.endLine).join('\n');
|
|
17
|
+
fs.writeFileSync(plan.filePath, plan.lines.join('\n'), 'utf8');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Move a completed plan file to docs/plans/completed/ with a timestamp suffix.
|
|
21
|
+
* Returns the new file path.
|
|
22
|
+
*/
|
|
23
|
+
export function movePlanToCompleted(plan, plansDir) {
|
|
24
|
+
const now = new Date();
|
|
25
|
+
const ts = formatTimestampForFilename(now);
|
|
26
|
+
const baseName = path.basename(plan.filePath, '.md');
|
|
27
|
+
const completedDir = path.join(plansDir, 'completed');
|
|
28
|
+
fs.mkdirSync(completedDir, { recursive: true });
|
|
29
|
+
const destPath = path.join(completedDir, `${baseName}-${ts}.md`);
|
|
30
|
+
fs.renameSync(plan.filePath, destPath);
|
|
31
|
+
return destPath;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reload plan from disk (after external modifications).
|
|
35
|
+
*/
|
|
36
|
+
export function reloadPlan(plan) {
|
|
37
|
+
const content = fs.readFileSync(plan.filePath, 'utf8');
|
|
38
|
+
const newLines = content.split('\n');
|
|
39
|
+
plan.lines = newLines;
|
|
40
|
+
// Update checkbox state from disk
|
|
41
|
+
for (const task of plan.tasks) {
|
|
42
|
+
for (const checkbox of task.checkboxes) {
|
|
43
|
+
const line = newLines[checkbox.lineIndex];
|
|
44
|
+
if (line !== undefined) {
|
|
45
|
+
checkbox.checked = /\[x\]/i.test(line);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function formatTimestampForFilename(date) {
|
|
51
|
+
const yyyy = date.getFullYear();
|
|
52
|
+
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
|
53
|
+
const dd = String(date.getDate()).padStart(2, '0');
|
|
54
|
+
const hh = String(date.getHours()).padStart(2, '0');
|
|
55
|
+
const min = String(date.getMinutes()).padStart(2, '0');
|
|
56
|
+
const ss = String(date.getSeconds()).padStart(2, '0');
|
|
57
|
+
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.js","sourceRoot":"","sources":["../../src/plan/updater.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Config } from '../config/types.js';
|
|
2
|
+
export type Phase = 'task' | 'review' | 'claude_eval' | 'warn' | 'error' | 'signal' | 'timestamp' | 'info';
|
|
3
|
+
/**
|
|
4
|
+
* Render text with 24-bit ANSI color.
|
|
5
|
+
* Returns plain text when noColor is true or when running in an env that doesn't support colors.
|
|
6
|
+
*/
|
|
7
|
+
export declare function colorize(text: string, hexColor: string, noColor: boolean): string;
|
|
8
|
+
export declare function getPhaseColor(phase: Phase, config: Config): string;
|
|
9
|
+
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/progress/colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAE3G;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAKjF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAYlE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render text with 24-bit ANSI color.
|
|
3
|
+
* Returns plain text when noColor is true or when running in an env that doesn't support colors.
|
|
4
|
+
*/
|
|
5
|
+
export function colorize(text, hexColor, noColor) {
|
|
6
|
+
if (noColor)
|
|
7
|
+
return text;
|
|
8
|
+
const rgb = hexToRgb(hexColor);
|
|
9
|
+
if (!rgb)
|
|
10
|
+
return text;
|
|
11
|
+
return `\x1b[38;2;${rgb.r};${rgb.g};${rgb.b}m${text}\x1b[0m`;
|
|
12
|
+
}
|
|
13
|
+
export function getPhaseColor(phase, config) {
|
|
14
|
+
const map = {
|
|
15
|
+
task: config.color_task,
|
|
16
|
+
review: config.color_review,
|
|
17
|
+
claude_eval: config.color_claude_eval,
|
|
18
|
+
warn: config.color_warn,
|
|
19
|
+
error: config.color_error,
|
|
20
|
+
signal: config.color_signal,
|
|
21
|
+
timestamp: config.color_timestamp,
|
|
22
|
+
info: config.color_info,
|
|
23
|
+
};
|
|
24
|
+
return map[phase] ?? config.color_info;
|
|
25
|
+
}
|
|
26
|
+
function hexToRgb(hex) {
|
|
27
|
+
const cleaned = hex.replace('#', '');
|
|
28
|
+
if (cleaned.length !== 6)
|
|
29
|
+
return null;
|
|
30
|
+
const n = parseInt(cleaned, 16);
|
|
31
|
+
if (isNaN(n))
|
|
32
|
+
return null;
|
|
33
|
+
return {
|
|
34
|
+
r: (n >> 16) & 0xff,
|
|
35
|
+
g: (n >> 8) & 0xff,
|
|
36
|
+
b: n & 0xff,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/progress/colors.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB,EAAE,OAAgB;IACvE,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,aAAa,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,MAAc;IACxD,MAAM,GAAG,GAA0B;QACjC,IAAI,EAAE,MAAM,CAAC,UAAU;QACvB,MAAM,EAAE,MAAM,CAAC,YAAY;QAC3B,WAAW,EAAE,MAAM,CAAC,iBAAiB;QACrC,IAAI,EAAE,MAAM,CAAC,UAAU;QACvB,KAAK,EAAE,MAAM,CAAC,WAAW;QACzB,MAAM,EAAE,MAAM,CAAC,YAAY;QAC3B,SAAS,EAAE,MAAM,CAAC,eAAe;QACjC,IAAI,EAAE,MAAM,CAAC,UAAU;KACxB,CAAC;IACF,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC;AACzC,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO;QACL,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;QACnB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI;QAClB,CAAC,EAAE,CAAC,GAAG,IAAI;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Config } from '../config/types.js';
|
|
2
|
+
import { Phase } from './colors.js';
|
|
3
|
+
import { EventBus } from '../dashboard/event-bus.js';
|
|
4
|
+
export interface Logger {
|
|
5
|
+
log(text: string, phase?: Phase): void;
|
|
6
|
+
header(text: string): void;
|
|
7
|
+
signal(text: string): void;
|
|
8
|
+
error(text: string): void;
|
|
9
|
+
warn(text: string): void;
|
|
10
|
+
info(text: string): void;
|
|
11
|
+
debug(text: string): void;
|
|
12
|
+
setProgressFile(planName: string): void;
|
|
13
|
+
getProgressFilePath(): string;
|
|
14
|
+
setEventBus(bus: EventBus): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function createLogger(config: Config, progressDir: string | undefined): Logger;
|
|
17
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/progress/logger.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAA2B,KAAK,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAY,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,MAAM;IACrB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,mBAAmB,IAAI,MAAM,CAAC;IAC9B,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA6GpF"}
|