mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-09-15 06:25:32 +02:00
* refactor(cli): list workspaces natively instead of via the worker image * feat(cli): preflight that Docker is installed and running * feat(cli): stop scans by workspace or --all, terminating their Temporal workflows * fix(worker): abort the running agent on cancellation so Temporal cancel takes effect * refactor(cli): split destructive teardown out of stop into a reset command * refactor(cli): centralise flag parsing and confirmation across commands * fix(cli): pass provider credentials to docker by name to keep secrets out of argv * feat(cli): add per-command help via <command> --help/-h and help <command> * feat(cli): replace raw docker output with clack spinners for infra and scan teardown * fix(cli): verify scan stop by re-querying container and workflow state instead of assuming success * fix(cli): resolve running state before prompting on stop and report no-op stops honestly * refactor(cli): show splash first and drive start with one spinner resolving to a clean line * fix(cli): validate --url up front so a bad value fails cleanly instead of a late crash * refactor(cli): centralize error reporting with fail() for expected errors and a crash handler that logs the stack and links the issue tracker * feat(cli): add --json/--plain machine-readable output to workspaces and status * refactor(cli): remove the workspaces command * refactor(cli): remove the status command * feat(cli): add 'progress <workspace>' — live scan progress from Temporal * fix(cli): mark metric-less agents as skipped in progress, not done * feat(cli): animate running agents in progress with a clack-style spinner * feat(cli): rename progress->status, reveal agents as they run, show live per-agent elapsed * fix(cli): mark passed-over phases as skipped live, not pending * style(cli): rename status footer 'Wall-clock' to 'Time Taken', drop the parenthetical * style(cli): drop '(sum of agents)' from status total cost line * style(cli): green filled circle for completed, Shannon gold for running * style(cli): use Shannon gold in place of green in status * feat(cli): suggest closest command or flag on typo * refactor(cli): single-source start help and drop ./repos bare-name shortcut * feat(cli): name providers and fix in multi-provider credential error * feat(cli): support --flag=value syntax and expand leading ~ in paths * refactor(cli): centralize ANSI color codes in colors.ts * feat(cli): add scans command listing completed scans with cost and duration * fix(cli): keep stdout clean off-TTY for logs and start * feat(cli): add repo link to top-level help * feat(worker): record auth-validation metrics and register resume attempts early * refactor(cli): share resume-aware workflow-id resolution and surface root-cause failures * feat(cli): add status --json, auth phase, dashboard link, and stable live redraw * refactor(cli): drop cost from status and scans output * feat(worker): surface both PDF and markdown report at run root * refactor(cli): normalize error/warning prefixing through fail and warn * feat(cli): add version --json for machine-readable output * refactor(cli): rename start --debug to --keep-container * refactor(cli): point start's progress hint at status instead of the Temporal dashboard * refactor(cli): centralize the mode-aware command prefix * refactor(cli): trim start and logs output to durable facts off-TTY * feat(cli): require typed confirmation for reset instead of --yes reset permanently wipes all Temporal data and volumes — a severe, irreversible action. Replace its default y/N confirm (bypassable with --yes) with a typed-word confirmation that has no bypass, so the wipe can only be triggered by a deliberate interactive answer. * feat(cli): surface logs and status hints after start on a TTY * feat(cli): exit 2 on usage errors, distinct from operational failures * feat(cli): add start --follow to stream logs and exit on scan outcome * refactor(cli): redesign splash with sunset-gradient wordmark and truecolor * refactor(cli): remove the uninstall command * docs: sync CLI docs with removed uninstall/workspaces, new scans and --follow * docs: fix reset confirmation — typed confirm, not --yes/-y * style(cli): restructure status footer with divider, aligned Logs/Temporal rows * feat(cli): show splash in the status command * fix(worker): validate auth-state shape, not entry count * docs: correct reset confirmation and add markdown report to run-root docs
69 lines
2.7 KiB
TypeScript
69 lines
2.7 KiB
TypeScript
/**
|
|
* Machine-readable snapshot of one scan, for `shannon status --json`.
|
|
*
|
|
* A point-in-time view built from the same derivation the human progress tree uses
|
|
* (derive.ts), so the JSON and the rendered tree can never disagree about an agent's
|
|
* state. One invocation is one snapshot — callers that want to track progress poll it.
|
|
*/
|
|
|
|
import type { DerivedPhase } from './derive.js';
|
|
import { derivePipeline, isTerminal, scanElapsedMs } from './derive.js';
|
|
import type { RenderInput } from './render.js';
|
|
|
|
/** Coarse scan status token, mirroring the human status badge in machine-friendly form. */
|
|
export type ScanStatus = 'running' | 'completed' | 'partial' | 'failed' | 'stopped' | 'cancelled' | 'timed_out';
|
|
|
|
export interface StatusJson {
|
|
readonly workspace: string;
|
|
/** Temporal workflow id backing this scan (differs from workspace on a resume). */
|
|
readonly workflowId?: string;
|
|
/** Coarse outcome: `running` until the scan closes, then its terminal status. */
|
|
readonly status: ScanStatus;
|
|
/** Raw Temporal WorkflowExecutionStatusName, for callers that need the source status. */
|
|
readonly temporalStatus: string;
|
|
/** Wall-clock elapsed ms (live for a running scan, final for a closed one), or null when unknown. */
|
|
readonly elapsedMs: number | null;
|
|
readonly startedAt?: string;
|
|
readonly endedAt?: string;
|
|
/** Failure text when a failed scan left no readable state. */
|
|
readonly failureMessage?: string;
|
|
readonly phases: readonly DerivedPhase[];
|
|
}
|
|
|
|
/** Map the raw Temporal status (and workflow status) onto the coarse machine token. */
|
|
function deriveStatus(input: RenderInput): ScanStatus {
|
|
if (!isTerminal(input.temporalStatus)) return 'running';
|
|
if (input.state?.status === 'partial') return 'partial';
|
|
|
|
switch (input.temporalStatus) {
|
|
case 'COMPLETED':
|
|
return 'completed';
|
|
case 'TERMINATED':
|
|
return 'stopped';
|
|
case 'CANCELLED':
|
|
case 'CANCELED':
|
|
return 'cancelled';
|
|
case 'TIMED_OUT':
|
|
return 'timed_out';
|
|
default:
|
|
return 'failed';
|
|
}
|
|
}
|
|
|
|
/** Build the JSON snapshot for a scan at instant `now`. */
|
|
export function toStatusJson(input: RenderInput, now: number): StatusJson {
|
|
const elapsedMs = scanElapsedMs(input, now);
|
|
|
|
return {
|
|
workspace: input.workspace,
|
|
...(input.workflowId !== undefined && { workflowId: input.workflowId }),
|
|
status: deriveStatus(input),
|
|
temporalStatus: input.temporalStatus,
|
|
elapsedMs: elapsedMs ?? null,
|
|
...(input.startedAt !== undefined && { startedAt: new Date(input.startedAt).toISOString() }),
|
|
...(input.endedAt !== undefined && { endedAt: new Date(input.endedAt).toISOString() }),
|
|
...(input.failureMessage !== undefined && { failureMessage: input.failureMessage }),
|
|
phases: derivePipeline(input, now),
|
|
};
|
|
}
|