@fractary/faber-cli 1.6.2 → 1.6.3
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/dist/commands/runs.d.ts.map +1 -1
- package/dist/commands/runs.js +57 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,iBAAiB,IAAI,OAAO,CAoM3C"}
|
package/dist/commands/runs.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* - Contains the run ID of the currently active workflow in this worktree
|
|
13
13
|
*/
|
|
14
14
|
import { Command } from 'commander';
|
|
15
|
+
import * as fs from 'fs';
|
|
15
16
|
import { FABER_RUNS_DIR, ACTIVE_RUN_ID_FILE, getRunsDir, getRunDir, getPlanPath, getStatePath, getActiveRunIdPath, RELATIVE_PATHS, } from '@fractary/faber';
|
|
16
17
|
export function createRunsCommand() {
|
|
17
18
|
const runsCmd = new Command('runs')
|
|
@@ -150,5 +151,61 @@ export function createRunsCommand() {
|
|
|
150
151
|
console.log(` Active Run ID File: ${RELATIVE_PATHS.ACTIVE_RUN_ID_FILE}`);
|
|
151
152
|
}
|
|
152
153
|
});
|
|
154
|
+
runsCmd
|
|
155
|
+
.command('verify-complete')
|
|
156
|
+
.description('Verify that all phases and steps in a run are completed or skipped')
|
|
157
|
+
.argument('<run_id>', 'Run ID to verify')
|
|
158
|
+
.option('--json', 'Output as JSON')
|
|
159
|
+
.action((runId, options) => {
|
|
160
|
+
try {
|
|
161
|
+
const statePath = getStatePath(runId);
|
|
162
|
+
if (!fs.existsSync(statePath)) {
|
|
163
|
+
console.error(`Error: State file not found: ${statePath}`);
|
|
164
|
+
process.exit(2);
|
|
165
|
+
}
|
|
166
|
+
const state = JSON.parse(fs.readFileSync(statePath, 'utf-8'));
|
|
167
|
+
const pending = [];
|
|
168
|
+
// Check each phase and its steps
|
|
169
|
+
if (state.phases && typeof state.phases === 'object') {
|
|
170
|
+
for (const [phaseName, phase] of Object.entries(state.phases)) {
|
|
171
|
+
if (phase.enabled === false)
|
|
172
|
+
continue;
|
|
173
|
+
if (phase.steps && typeof phase.steps === 'object') {
|
|
174
|
+
for (const [stepId, step] of Object.entries(phase.steps)) {
|
|
175
|
+
const status = step.status || 'pending';
|
|
176
|
+
if (status !== 'completed' && status !== 'success' && status !== 'skipped') {
|
|
177
|
+
pending.push(`${phaseName}:${stepId} (${status})`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// Phase without steps — check phase-level status
|
|
183
|
+
const phaseStatus = phase.status || 'pending';
|
|
184
|
+
if (phaseStatus !== 'completed' && phaseStatus !== 'success' && phaseStatus !== 'skipped') {
|
|
185
|
+
pending.push(`${phaseName} (${phaseStatus})`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const pass = pending.length === 0;
|
|
191
|
+
if (options.json) {
|
|
192
|
+
console.log(JSON.stringify({ pass, pending }, null, 2));
|
|
193
|
+
}
|
|
194
|
+
else if (pass) {
|
|
195
|
+
console.log('✓ All phases and steps are completed');
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(`✗ ${pending.length} item(s) still pending:`);
|
|
199
|
+
for (const item of pending) {
|
|
200
|
+
console.log(` - ${item}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
process.exit(pass ? 0 : 1);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
207
|
+
process.exit(2);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
153
210
|
return runsCmd;
|
|
154
211
|
}
|