feat(cli): add --latest, --debug, --role flags to live command (#37 Phase 2)

- --latest: auto-find most recent thread by start timestamp
- --debug: display .info.jsonl debug log with tags
- --role: filter output to specific role
- Add live-argv.ts for flag parsing
- Add fixtures and test coverage for all flags

Testing: #50
This commit is contained in:
2026-05-07 21:34:04 +08:00
parent 990200230b
commit 8fe26417cf
12 changed files with 651 additions and 77 deletions
+5 -3
View File
@@ -1,6 +1,6 @@
import { normalizeRefsField } from "./refs-field.js";
import { err, ok, type Result } from "./result.js";
import type { RoleOutput, WorkflowResult } from "./types.js";
import type { RoleOutput, WorkflowCompletion } from "./types.js";
/** Role steps replayed from `.data.jsonl`, including persisted timestamps. */
export type ForkHistoricalStep = RoleOutput & { timestamp: number };
@@ -14,8 +14,10 @@ export type ParsedThreadStartRecord = {
depth: number;
};
/** Recognizes a persisted workflow completion line (no `role`; has numeric `returnCode` and string `summary`). */
export function tryParseWorkflowResultRecord(obj: Record<string, unknown>): WorkflowResult | null {
/** Recognizes a persisted workflow completion line (no `role`; has numeric `returnCode` and string `summary`). Omits `rootHash` when absent. */
export function tryParseWorkflowResultRecord(
obj: Record<string, unknown>,
): WorkflowCompletion | null {
if (obj.role !== undefined) {
return null;
}
+1 -1
View File
@@ -422,7 +422,7 @@ async function main(): Promise<void> {
} catch (e) {
const message = e instanceof Error ? e.message : String(e);
bootLog("Q3MN8YKW", `thread ${threadId} failed: ${message}`);
const failure: WorkflowResult = { returnCode: 1, summary: message };
const failure: WorkflowResult = { returnCode: 1, summary: message, rootHash: "" };
await appendFile(dataJsonlPath, `${JSON.stringify(failure)}\n`, "utf8").catch(() => {});
} finally {
threads.delete(threadId);