akm-cli 0.9.0-rc.13 → 0.9.0-rc.15
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/CHANGELOG.md +162 -23
- package/dist/akm-migrate +3 -1
- package/dist/assets/hints/cli-hints-full.md +3 -4
- package/dist/assets/hints/cli-hints-short.md +5 -5
- package/dist/assets/workflows/workflow-template.md +4 -3
- package/dist/cli/invocation.js +3 -2
- package/dist/cli/retired-commands.js +5 -0
- package/dist/cli/unknown-flags.js +226 -0
- package/dist/cli.js +19 -35
- package/dist/commands/agent/agent-dispatch.js +7 -3
- package/dist/commands/agent/contribute-cli.js +15 -3
- package/dist/commands/feedback-cli.js +6 -3
- package/dist/commands/health/checks.js +6 -3
- package/dist/commands/improve/collapse-detector.js +2 -3
- package/dist/commands/improve/reflect.js +5 -3
- package/dist/commands/lint/base-linter.js +4 -16
- package/dist/commands/lint/index.js +13 -13
- package/dist/commands/log.js +6 -1
- package/dist/commands/migration-tool.js +4 -5
- package/dist/commands/observability-cli.js +1 -1
- package/dist/commands/proposal/propose.js +5 -3
- package/dist/commands/proposal/repository.js +5 -5
- package/dist/commands/read/knowledge.js +2 -0
- package/dist/commands/registry-cli.js +5 -3
- package/dist/commands/sources/add-cli.js +6 -6
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/self-update.js +30 -7
- package/dist/commands/sources/source-add.js +17 -2
- package/dist/commands/tasks/tasks.js +10 -10
- package/dist/commands/workflow-cli.js +133 -259
- package/dist/core/adapter/adapters/akm-lint.js +17 -13
- package/dist/core/adapter/adapters/akm-task-adapter.js +14 -11
- package/dist/core/asset/akm-markdown.js +41 -8
- package/dist/core/asset/frontmatter.js +22 -0
- package/dist/core/asset/resolve-ref.js +23 -3
- package/dist/core/common.js +45 -2
- package/dist/core/config/config-schema.js +8 -0
- package/dist/core/config/schema/experimental.js +0 -17
- package/dist/core/config/schema/sources-bundles.js +11 -0
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/errors.js +5 -1
- package/dist/core/logs-db.js +2 -1
- package/dist/core/parse.js +4 -1
- package/dist/core/state/migrations.js +11 -14
- package/dist/core/state-db.js +4 -6
- package/dist/core/subprocess.js +6 -4
- package/dist/core/type-presentation.js +1 -1
- package/dist/indexer/indexer.js +16 -1
- package/dist/indexer/search/search-source.js +1 -1
- package/dist/indexer/walk/matchers.js +3 -1
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/spawn.js +1 -2
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/lockfile.js +11 -56
- package/dist/output/shapes/passthrough.js +0 -6
- package/dist/output/text/command-format.js +3 -3
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/show-directives.js +4 -6
- package/dist/output/text/workflow-format.js +15 -181
- package/dist/output/text/workflow.js +1 -6
- package/dist/scripts/akm-migrate-node.js +58666 -0
- package/dist/scripts/akm-migrate.js +33976 -11498
- package/dist/setup/detect.js +42 -15
- package/dist/setup/setup.js +1 -1
- package/dist/sources/providers/git-stash.js +4 -2
- package/dist/sources/providers/website.js +5 -0
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +370 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +40 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +199 -0
- package/dist/sources/snapshot-fetchers/registry.js +10 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +279 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +488 -257
- package/dist/sources/snapshot-fetchers/x.js +193 -0
- package/dist/storage/engines/sqlite-migrations.js +22 -107
- package/dist/storage/repositories/workflow-runs-repository.js +9 -23
- package/dist/tasks/runner.js +43 -19
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/validator.js +6 -2
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +44 -28
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +122 -60
- package/dist/workflows/exec/step-work.js +64 -175
- package/dist/workflows/exec/unit-dispatch.js +4 -0
- package/dist/workflows/ir/compile.js +2 -2
- package/dist/workflows/ir/freeze.js +29 -9
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +6 -2
- package/dist/workflows/renderer.js +2 -2
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/runs.js +72 -92
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/validate-summary.js +30 -14
- package/docs/migration/release-notes/0.9.0.md +31 -4
- package/docs/migration/v0.8-to-v0.9.md +70 -100
- package/docs/reference/data-and-telemetry.md +5 -5
- package/package.json +7 -3
- package/schemas/akm-config.json +24 -6
- package/schemas/akm-workflow.json +1 -1
- package/dist/workflows/cli.js +0 -33
- package/dist/workflows/exec/brief.js +0 -450
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/workflow-engine-gate.js +0 -67
|
@@ -5,33 +5,14 @@
|
|
|
5
5
|
* Plain-text renderers for `akm workflow *` commands.
|
|
6
6
|
*
|
|
7
7
|
* Split out of `helpers.ts` (formerly 1418 lines / 59 fns) as its own
|
|
8
|
-
* sibling module: the workflow run/
|
|
8
|
+
* sibling module: the workflow list/status/run/create/resume renderers form a
|
|
9
9
|
* cohesive, self-contained cluster (they call only each other, never
|
|
10
10
|
* formatters from other domains).
|
|
11
11
|
*/
|
|
12
|
-
/**
|
|
13
|
-
* Plain-text rendering for a step-completion that was rejected by the
|
|
14
|
-
* summary-validation gate (#506): the step stays pending and the agent gets
|
|
15
|
-
* corrective feedback on what to finish/fix.
|
|
16
|
-
*/
|
|
17
|
-
export function formatWorkflowCompleteRejectedPlain(r) {
|
|
18
|
-
const stepId = String(r.stepId ?? "?");
|
|
19
|
-
const feedback = typeof r.feedback === "string" ? r.feedback : "";
|
|
20
|
-
const missing = Array.isArray(r.missing) ? r.missing.map((m) => String(m)) : [];
|
|
21
|
-
const lines = [`workflow complete: rejected — step "${stepId}" does not meet its completion criteria`];
|
|
22
|
-
if (feedback)
|
|
23
|
-
lines.push(` feedback: ${feedback}`);
|
|
24
|
-
if (missing.length > 0) {
|
|
25
|
-
lines.push(" outstanding:");
|
|
26
|
-
for (const m of missing)
|
|
27
|
-
lines.push(` - ${m}`);
|
|
28
|
-
}
|
|
29
|
-
return lines.join("\n");
|
|
30
|
-
}
|
|
31
12
|
export function formatWorkflowListPlain(result) {
|
|
32
13
|
const runs = Array.isArray(result.runs) ? result.runs : [];
|
|
33
14
|
if (runs.length === 0) {
|
|
34
|
-
return "No workflow runs in the current working scope. Start one with `akm workflow
|
|
15
|
+
return "No workflow runs in the current working scope. Start one with `akm workflow run workflows/<name>` or author one with `akm workflow create <name>`.";
|
|
35
16
|
}
|
|
36
17
|
return runs
|
|
37
18
|
.map((run) => {
|
|
@@ -89,8 +70,8 @@ export function formatWorkflowStatusPlain(result) {
|
|
|
89
70
|
const suffix = attempts !== undefined && attempts > 1 ? `, attempt ${attempts}` : "";
|
|
90
71
|
lines.push(` - ${id} [${node}] (${status}${suffix})`);
|
|
91
72
|
// Codex round-3 finding B: a `running` claim gone silent past the check-in
|
|
92
|
-
// window — the
|
|
93
|
-
// human can reclaim/re-run the unit
|
|
73
|
+
// window — the process holding it likely died. Surface it (with the claim
|
|
74
|
+
// holder) so a human can reclaim/re-run the unit.
|
|
94
75
|
if (unit.stale === true) {
|
|
95
76
|
const holder = typeof unit.claimHolder === "string" && unit.claimHolder.trim() ? ` claimed by ${unit.claimHolder}` : "";
|
|
96
77
|
lines.push(` stale: claim went silent past the check-in window${holder} — its driver may have died`);
|
|
@@ -117,7 +98,7 @@ export function formatWorkflowStatusPlain(result) {
|
|
|
117
98
|
}
|
|
118
99
|
/**
|
|
119
100
|
* Render the stalled-run check-in directive (#506) when present on a
|
|
120
|
-
* workflow-
|
|
101
|
+
* workflow-status result. Returns null when the run is healthy.
|
|
121
102
|
*/
|
|
122
103
|
function formatWorkflowCheckinLine(result) {
|
|
123
104
|
const checkin = typeof result.checkin === "object" && result.checkin !== null
|
|
@@ -127,52 +108,16 @@ function formatWorkflowCheckinLine(result) {
|
|
|
127
108
|
return null;
|
|
128
109
|
return checkin.directive.trim();
|
|
129
110
|
}
|
|
130
|
-
export function formatWorkflowNextPlain(result) {
|
|
131
|
-
const base = formatWorkflowStatusPlain(result);
|
|
132
|
-
const step = typeof result.step === "object" && result.step !== null ? result.step : undefined;
|
|
133
|
-
if (!step)
|
|
134
|
-
return base;
|
|
135
|
-
const lines = base ? [base, "", "next:"] : ["next:"];
|
|
136
|
-
lines.push(` ${String(step.title ?? "Untitled step")} [${String(step.id ?? "unknown")}]`);
|
|
137
|
-
if (typeof step.instructions === "string" && step.instructions.trim()) {
|
|
138
|
-
const instrLines = step.instructions.trim().split("\n");
|
|
139
|
-
lines.push(` instructions: ${instrLines[0]}`);
|
|
140
|
-
for (const instrLine of instrLines.slice(1))
|
|
141
|
-
lines.push(` ${instrLine}`);
|
|
142
|
-
}
|
|
143
|
-
const completion = Array.isArray(step.completionCriteria) ? step.completionCriteria : [];
|
|
144
|
-
if (completion.length > 0) {
|
|
145
|
-
lines.push(" completion:");
|
|
146
|
-
for (const criterion of completion) {
|
|
147
|
-
lines.push(` - ${String(criterion)}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// T2-3: surface run-id as labeled field
|
|
151
|
-
const run = typeof result.run === "object" && result.run !== null ? result.run : undefined;
|
|
152
|
-
const runId = typeof run?.id === "string" ? run.id : null;
|
|
153
|
-
const stepId = typeof step?.id === "string" ? step.id : null;
|
|
154
|
-
if (runId) {
|
|
155
|
-
lines.push("");
|
|
156
|
-
lines.push(`runId: ${runId}`);
|
|
157
|
-
}
|
|
158
|
-
// T1-6: complete command
|
|
159
|
-
if (runId && stepId) {
|
|
160
|
-
lines.push("");
|
|
161
|
-
lines.push("COMPLETE THIS STEP:");
|
|
162
|
-
lines.push(` akm workflow complete '${runId}' --step '${stepId}'`);
|
|
163
|
-
}
|
|
164
|
-
else if (runId) {
|
|
165
|
-
lines.push("");
|
|
166
|
-
lines.push("COMPLETE THIS STEP:");
|
|
167
|
-
lines.push(` akm workflow complete '${runId}' --step '<step-id>'`);
|
|
168
|
-
}
|
|
169
|
-
return lines.join("\n");
|
|
170
|
-
}
|
|
171
111
|
export function formatWorkflowRunPlain(result) {
|
|
172
112
|
const run = typeof result.run === "object" && result.run !== null ? result.run : undefined;
|
|
173
113
|
if (!run)
|
|
174
114
|
return null;
|
|
175
115
|
const lines = [`run: ${String(run.id ?? "unknown")}`, `status: ${String(run.status ?? "unknown")}`];
|
|
116
|
+
// Creation-time notices (e.g. the implicit engine fallback) must survive the
|
|
117
|
+
// text renderer: JSON/YAML pass them through, and dropping them here would
|
|
118
|
+
// hide the announcement from the DEFAULT output mode — where it matters most.
|
|
119
|
+
for (const warning of Array.isArray(result.warnings) ? result.warnings : [])
|
|
120
|
+
lines.push(`! ${String(warning)}`);
|
|
176
121
|
const executed = Array.isArray(result.executed) ? result.executed : [];
|
|
177
122
|
if (executed.length === 0) {
|
|
178
123
|
lines.push("executed: (no steps — run was already done or blocked)");
|
|
@@ -197,126 +142,15 @@ export function formatWorkflowRunPlain(result) {
|
|
|
197
142
|
for (const item of missing)
|
|
198
143
|
lines.push(` missing: ${String(item)}`);
|
|
199
144
|
}
|
|
145
|
+
if (result.aborted === true) {
|
|
146
|
+
lines.push(result.timedOut === true
|
|
147
|
+
? "workflow timed out; the run remains resumable."
|
|
148
|
+
: "workflow interrupted; the run remains resumable.");
|
|
149
|
+
}
|
|
200
150
|
if (result.done === true)
|
|
201
151
|
lines.push("workflow completed.");
|
|
202
152
|
return lines.join("\n");
|
|
203
153
|
}
|
|
204
|
-
export function formatWorkflowBriefPlain(result) {
|
|
205
|
-
const run = typeof result.run === "object" && result.run !== null ? result.run : undefined;
|
|
206
|
-
if (!run)
|
|
207
|
-
return null;
|
|
208
|
-
const lines = [];
|
|
209
|
-
lines.push(`# Workflow brief: ${String(run.id ?? "unknown")}`);
|
|
210
|
-
lines.push(`workflow: ${String(run.workflowRef ?? "?")} (${String(run.workflowTitle ?? "")})`);
|
|
211
|
-
lines.push(`status: ${String(run.status ?? "?")}`);
|
|
212
|
-
if (typeof result.message === "string")
|
|
213
|
-
lines.push(result.message);
|
|
214
|
-
const lease = typeof result.engineLease === "object" && result.engineLease !== null
|
|
215
|
-
? result.engineLease
|
|
216
|
-
: undefined;
|
|
217
|
-
if (lease) {
|
|
218
|
-
const live = lease.live === true ? "LIVE" : "expired";
|
|
219
|
-
lines.push(`engine lease: ${String(lease.holder ?? "?")} (until ${String(lease.until ?? "?")}) [${live}]`);
|
|
220
|
-
}
|
|
221
|
-
const warnings = Array.isArray(result.warnings) ? result.warnings : [];
|
|
222
|
-
for (const w of warnings)
|
|
223
|
-
lines.push(`! ${String(w)}`);
|
|
224
|
-
if (result.done === true) {
|
|
225
|
-
lines.push("");
|
|
226
|
-
lines.push("This run is completed — no work remains.");
|
|
227
|
-
return lines.join("\n");
|
|
228
|
-
}
|
|
229
|
-
const step = typeof result.step === "object" && result.step !== null ? result.step : undefined;
|
|
230
|
-
if (!step) {
|
|
231
|
-
return lines.join("\n");
|
|
232
|
-
}
|
|
233
|
-
const gate = typeof step.gate === "object" && step.gate !== null ? step.gate : undefined;
|
|
234
|
-
lines.push("");
|
|
235
|
-
lines.push(`## Active step: ${String(step.stepId ?? "?")} — ${String(step.title ?? "")} [${String(step.kind ?? "execute")}]`);
|
|
236
|
-
if (gate) {
|
|
237
|
-
const criteria = Array.isArray(gate.criteria) ? gate.criteria : [];
|
|
238
|
-
lines.push(`gate: loop ${String(gate.currentLoop ?? 1)} of max ${String(gate.maxLoops ?? 1)}` +
|
|
239
|
-
(criteria.length > 0 ? `; criteria: ${criteria.map(String).join("; ")}` : "; no completion criteria") +
|
|
240
|
-
(gate.judgesArtifact === true ? " (artifact-judged)" : ""));
|
|
241
|
-
}
|
|
242
|
-
if (step.outputSchema !== undefined)
|
|
243
|
-
lines.push("outputSchema: declared (see JSON output)");
|
|
244
|
-
const feedback = typeof result.gateFeedback === "object" && result.gateFeedback !== null
|
|
245
|
-
? result.gateFeedback
|
|
246
|
-
: undefined;
|
|
247
|
-
if (feedback) {
|
|
248
|
-
lines.push(`gate feedback (previous loop rejected): ${String(feedback.feedback ?? "")}`);
|
|
249
|
-
const missing = Array.isArray(feedback.missing) ? feedback.missing : [];
|
|
250
|
-
for (const m of missing)
|
|
251
|
-
lines.push(` - missing: ${String(m)}`);
|
|
252
|
-
}
|
|
253
|
-
const route = typeof result.route === "object" && result.route !== null ? result.route : undefined;
|
|
254
|
-
if (route) {
|
|
255
|
-
lines.push("");
|
|
256
|
-
lines.push(`## Route contract on ${String(route.input ?? "?")}`);
|
|
257
|
-
const when = typeof route.when === "object" && route.when !== null ? route.when : {};
|
|
258
|
-
for (const [value, target] of Object.entries(when))
|
|
259
|
-
lines.push(` when "${value}" → ${String(target)}`);
|
|
260
|
-
if (route.defaultStepId !== undefined)
|
|
261
|
-
lines.push(` default → ${String(route.defaultStepId)}`);
|
|
262
|
-
const decision = typeof route.decision === "object" && route.decision !== null
|
|
263
|
-
? route.decision
|
|
264
|
-
: undefined;
|
|
265
|
-
if (decision)
|
|
266
|
-
lines.push(` decision NOW: value "${String(decision.value)}" → ${String(decision.selected)}`);
|
|
267
|
-
else if (typeof route.decisionError === "string")
|
|
268
|
-
lines.push(` decision error: ${route.decisionError}`);
|
|
269
|
-
else
|
|
270
|
-
lines.push(" decision: pending this step's output (evaluated after units complete)");
|
|
271
|
-
}
|
|
272
|
-
const workList = typeof result.workList === "object" && result.workList !== null
|
|
273
|
-
? result.workList
|
|
274
|
-
: undefined;
|
|
275
|
-
const units = workList && Array.isArray(workList.units) ? workList.units : [];
|
|
276
|
-
if (workList?.error) {
|
|
277
|
-
lines.push("");
|
|
278
|
-
lines.push(`work-list error: ${String(workList.error)}`);
|
|
279
|
-
}
|
|
280
|
-
else if (units.length > 0) {
|
|
281
|
-
lines.push("");
|
|
282
|
-
lines.push(`## Units (${units.length})`);
|
|
283
|
-
for (const u of units) {
|
|
284
|
-
const model = u.model ? ` model=${String(u.model)}` : "";
|
|
285
|
-
const journaled = typeof u.journaled === "object" && u.journaled !== null ? u.journaled : undefined;
|
|
286
|
-
const jstatus = journaled ? ` [journaled: ${String(journaled.status)}]` : "";
|
|
287
|
-
lines.push(`- ${String(u.unitId)} (runner=${String(u.runner)}${model})${jstatus}`);
|
|
288
|
-
const env = Array.isArray(u.env) ? u.env : [];
|
|
289
|
-
if (env.length > 0)
|
|
290
|
-
lines.push(` env (names): ${env.map(String).join(", ")}`);
|
|
291
|
-
if (u.outputSchema !== undefined)
|
|
292
|
-
lines.push(" outputSchema: declared (see JSON output)");
|
|
293
|
-
const resolved = typeof u.resolved === "object" && u.resolved !== null ? u.resolved : undefined;
|
|
294
|
-
if (resolved && resolved.ok === false)
|
|
295
|
-
lines.push(` RESOLUTION ERROR: ${String(resolved.error)}`);
|
|
296
|
-
if (typeof u.report === "string")
|
|
297
|
-
lines.push(` report: ${u.report}`);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
// Finding D: a non-dispatching step (route-only / empty / all-unresolvable)
|
|
301
|
-
// advances via the `--settle` verb, surfaced so a driver can advance the spine.
|
|
302
|
-
if (typeof result.settleCommand === "string") {
|
|
303
|
-
lines.push("");
|
|
304
|
-
lines.push("## Advance (no reportable units)");
|
|
305
|
-
lines.push(`settle: ${result.settleCommand}`);
|
|
306
|
-
}
|
|
307
|
-
const guidance = typeof result.reportGuidance === "object" && result.reportGuidance !== null
|
|
308
|
-
? result.reportGuidance
|
|
309
|
-
: undefined;
|
|
310
|
-
if (guidance) {
|
|
311
|
-
lines.push("");
|
|
312
|
-
lines.push("## Reporting");
|
|
313
|
-
if (typeof guidance.checkin === "string")
|
|
314
|
-
lines.push(`heartbeat: ${guidance.checkin}`);
|
|
315
|
-
if (typeof guidance.failure === "string")
|
|
316
|
-
lines.push(`on failure: ${guidance.failure}`);
|
|
317
|
-
}
|
|
318
|
-
return lines.join("\n");
|
|
319
|
-
}
|
|
320
154
|
export function formatWorkflowCreatePlain(r) {
|
|
321
155
|
// `workflow create --print`: no file is written, just the template text
|
|
322
156
|
// (dropped `workflow template`'s output, moved onto this shape).
|
|
@@ -2,17 +2,12 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
// Output text formatters for all `akm workflow *` commands.
|
|
5
|
-
import {
|
|
5
|
+
import { formatWorkflowCreatePlain, formatWorkflowListPlain, formatWorkflowResumePlain, formatWorkflowRunPlain, formatWorkflowStatusPlain, } from "./helpers.js";
|
|
6
6
|
export const workflowFormatters = [
|
|
7
|
-
{ command: "workflow-start", handler: (r) => formatWorkflowStatusPlain(r) },
|
|
8
7
|
{ command: "workflow-status", handler: (r) => formatWorkflowStatusPlain(r) },
|
|
9
|
-
{ command: "workflow-complete", handler: (r) => formatWorkflowStatusPlain(r) },
|
|
10
|
-
{ command: "workflow-complete-rejected", handler: (r) => formatWorkflowCompleteRejectedPlain(r) },
|
|
11
|
-
{ command: "workflow-next", handler: (r) => formatWorkflowNextPlain(r) },
|
|
12
8
|
{ command: "workflow-list", handler: (r) => formatWorkflowListPlain(r) },
|
|
13
9
|
{ command: "workflow-create", handler: (r) => formatWorkflowCreatePlain(r) },
|
|
14
10
|
{ command: "workflow-resume", handler: (r) => formatWorkflowResumePlain(r) },
|
|
15
11
|
{ command: "workflow-abandon", handler: (r) => formatWorkflowStatusPlain(r) },
|
|
16
12
|
{ command: "workflow-run", handler: (r) => formatWorkflowRunPlain(r) },
|
|
17
|
-
{ command: "workflow-brief", handler: (r) => formatWorkflowBriefPlain(r) },
|
|
18
13
|
];
|