mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 05:56:21 -10:00
rig workflow trace gains --full, which passes ?full=true to the daemon's existing GET /api/workflow/<id>/trace route; there is no new daemon route. Without the flag the request has no query, as before. --json prints the daemon payload unchanged. Human output adds one line naming the --full command when the trail came back with trailCompleteness recent. docs/as-built/cli-reference.md lists the option.
This commit is contained in:
1 parent
642be39e5b
commit
a34cb55ad7
3 files changed
+63
-4
No files matched your search
@@ -600,7 +600,7 @@ Herdr session per request, including session-bound previews and window reuse.
|
||||
| `rig workflow specs` | — | `--json` |
|
||||
| `rig workflow guidance <instanceId>` | — | `--packet <id>`<br>`--component <id>`<br>`--full`<br>`--json` |
|
||||
| `rig workflow show <instanceId>` | — | `--json` |
|
||||
| `rig workflow trace <instanceId>` | — | `--json` |
|
||||
| `rig workflow trace <instanceId>` | — | `--full`<br>`--json` |
|
||||
| `rig workflow continue <instanceId>` | — | `--json` |
|
||||
| `rig workflow run <specPath>` | — | `--root-objective <text>` **required**<br>`--created-by <session>` **required**<br>`--entry-owner <session>`<br>`--rig <name>`<br>`--project <id>`<br>`--mission <id>`<br>`--slice <id>`<br>`--tags <tags>`<br>`--json` |
|
||||
| `rig workflow watch <instanceId>` | — | `--json` |
|
||||
|
||||
@@ -639,17 +639,22 @@ exception routes only. Existing obligations keep their owners and evidence.
|
||||
cmd
|
||||
.command("trace <instanceId>")
|
||||
.description("Show one workflow instance + its append-only step trail (audit-only verdict)")
|
||||
.option("--full", "Return the complete step trail instead of the 50 most recent closures (trailCompleteness: complete)")
|
||||
.option("--json", "JSON output for agents")
|
||||
.addHelpText("after", `
|
||||
The default trail holds the 50 most recent closures; trailCompleteness says
|
||||
"recent" when older ones were left out. --full asks the daemon for all of them.
|
||||
|
||||
Examples:
|
||||
$ rig workflow trace WF01ABC
|
||||
$ rig workflow trace WF01ABC --json | jq '.trail[] | {step, actor, exit}'
|
||||
$ rig workflow trace WF01ABC --full --json | jq '.trailCompleteness, (.trail | length)'
|
||||
`)
|
||||
.action(async (instanceId: string, opts: { json?: boolean }) => {
|
||||
.action(async (instanceId: string, opts: { json?: boolean; full?: boolean }) => {
|
||||
const deps = getDeps();
|
||||
await withClient(deps, async (client) => {
|
||||
const res = await client.get<{ instance?: unknown; reconciliation?: unknown; trail?: unknown[]; frontier?: unknown[]; failures?: unknown[]; boundaryObligations?: unknown[]; unknowns?: string[] }>(
|
||||
`/api/workflow/${encodeURIComponent(instanceId)}/trace`,
|
||||
const res = await client.get<{ instance?: unknown; reconciliation?: unknown; trail?: unknown[]; trailCompleteness?: string; frontier?: unknown[]; failures?: unknown[]; boundaryObligations?: unknown[]; unknowns?: string[] }>(
|
||||
`/api/workflow/${encodeURIComponent(instanceId)}/trace${opts.full ? "?full=true" : ""}`,
|
||||
);
|
||||
// WF3 FR-2: human mode renders the per-step tree (mini-req 2's
|
||||
// one-screen bar); --json byte-identical (BR-2).
|
||||
@@ -667,6 +672,9 @@ Examples:
|
||||
} as Parameters<typeof renderTraceTree>[0];
|
||||
const trail = (res.data.trail ?? []) as Parameters<typeof renderTraceTree>[1];
|
||||
for (const line of renderTraceTree(instance, trail)) console.log(line);
|
||||
if (res.data.trailCompleteness === "recent") {
|
||||
console.log(` (the ${trail.length} most recent closures; older ones left out - all of them: rig workflow trace ${instanceId} --full)`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -331,6 +331,57 @@ describe("rig workflow CLI (PL-004 Phase D)", () => {
|
||||
expect(calls.find((c) => c.path === "/api/workflow/inst-1/trace")).toBeDefined();
|
||||
});
|
||||
|
||||
it("trace without --full keeps the daemon's default (no ?full=true)", async () => {
|
||||
const { deps, calls } = makeDeps({
|
||||
routes: { "GET /api/workflow/inst-1/trace": { status: 200, data: { instance: {}, trail: [], trailCompleteness: "recent" } } },
|
||||
});
|
||||
const program = createProgram({ workflowDeps: deps });
|
||||
program.exitOverride();
|
||||
await program.parseAsync(["node", "rig", "workflow", "trace", "inst-1", "--json"]);
|
||||
expect(calls.map((c) => c.path)).toEqual(["/api/workflow/inst-1/trace"]);
|
||||
});
|
||||
|
||||
it("trace --full passes ?full=true through and prints the complete trail", async () => {
|
||||
const trail = Array.from({ length: 52 }, (_, i) => ({ stepId: `s${i}`, actorSession: "a@r", closureReason: "done" }));
|
||||
const { deps, calls } = makeDeps({
|
||||
routes: { "GET /api/workflow/inst-1/trace?full=true": { status: 200, data: { instance: {}, trail, trailCompleteness: "complete" } } },
|
||||
});
|
||||
const logs: string[] = [];
|
||||
const spy = vi.spyOn(console, "log").mockImplementation((...a: unknown[]) => { logs.push(a.join(" ")); });
|
||||
try {
|
||||
const program = createProgram({ workflowDeps: deps });
|
||||
program.exitOverride();
|
||||
await program.parseAsync(["node", "rig", "workflow", "trace", "inst-1", "--full", "--json"]);
|
||||
} finally {
|
||||
spy.mockRestore();
|
||||
}
|
||||
expect(calls.map((c) => c.path)).toEqual(["/api/workflow/inst-1/trace?full=true"]);
|
||||
const out = JSON.parse(logs.join("\n")) as { trail: unknown[]; trailCompleteness: string };
|
||||
expect(out.trailCompleteness).toBe("complete");
|
||||
expect(out.trail).toHaveLength(52);
|
||||
});
|
||||
|
||||
it("trace in human mode says when the trail was cut and how to get all of it", async () => {
|
||||
const { deps } = makeDeps({
|
||||
routes: {
|
||||
"GET /api/workflow/inst-1/trace": {
|
||||
status: 200,
|
||||
data: { instance: { instanceId: "inst-1", status: "active" }, trail: [], trailCompleteness: "recent" },
|
||||
},
|
||||
},
|
||||
});
|
||||
const logs: string[] = [];
|
||||
const spy = vi.spyOn(console, "log").mockImplementation((...a: unknown[]) => { logs.push(a.join(" ")); });
|
||||
try {
|
||||
const program = createProgram({ workflowDeps: deps });
|
||||
program.exitOverride();
|
||||
await program.parseAsync(["node", "rig", "workflow", "trace", "inst-1"]);
|
||||
} finally {
|
||||
spy.mockRestore();
|
||||
}
|
||||
expect(logs.join("\n")).toContain("rig workflow trace inst-1 --full");
|
||||
});
|
||||
|
||||
it("continue POSTs /api/workflow/:instanceId/continue", async () => {
|
||||
const { deps, calls } = makeDeps({
|
||||
routes: { "POST /api/workflow/inst-1/continue": { status: 200, data: { instance: {}, trail: [] } } },
|
||||
|
||||
Reference in new issue
Block a user