@h-rig/run-plugin 0.0.6-alpha.186

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.
Files changed (70) hide show
  1. package/README.md +1 -0
  2. package/dist/src/plugin.d.ts +4 -0
  3. package/dist/src/plugin.js +4319 -0
  4. package/dist/src/read-model/inspect-command.d.ts +19 -0
  5. package/dist/src/read-model/inspect-command.js +341 -0
  6. package/dist/src/read-model/plugin.d.ts +4 -0
  7. package/dist/src/read-model/plugin.js +2550 -0
  8. package/dist/src/read-model/read-model-backend/diagnostics.d.ts +9 -0
  9. package/dist/src/read-model/read-model-backend/diagnostics.js +51 -0
  10. package/dist/src/read-model/read-model-backend/guard.d.ts +4 -0
  11. package/dist/src/read-model/read-model-backend/guard.js +25 -0
  12. package/dist/src/read-model/read-model-backend/inbox.d.ts +23 -0
  13. package/dist/src/read-model/read-model-backend/inbox.js +669 -0
  14. package/dist/src/read-model/read-model-backend/index.d.ts +8 -0
  15. package/dist/src/read-model/read-model-backend/index.js +1163 -0
  16. package/dist/src/read-model/read-model-backend/inspect.d.ts +26 -0
  17. package/dist/src/read-model/read-model-backend/inspect.js +770 -0
  18. package/dist/src/read-model/read-model-backend/projection.d.ts +39 -0
  19. package/dist/src/read-model/read-model-backend/projection.js +669 -0
  20. package/dist/src/read-model/read-model-backend/run-status.d.ts +27 -0
  21. package/dist/src/read-model/read-model-backend/run-status.js +237 -0
  22. package/dist/src/read-model/read-model-backend/stats.d.ts +12 -0
  23. package/dist/src/read-model/read-model-backend/stats.js +800 -0
  24. package/dist/src/read-model/read-model-service.d.ts +2 -0
  25. package/dist/src/read-model/read-model-service.js +1725 -0
  26. package/dist/src/read-model/reconcile.d.ts +23 -0
  27. package/dist/src/read-model/reconcile.js +306 -0
  28. package/dist/src/read-model/run-format.d.ts +23 -0
  29. package/dist/src/read-model/run-format.js +202 -0
  30. package/dist/src/read-model/runs-screen.d.ts +14 -0
  31. package/dist/src/read-model/runs-screen.js +217 -0
  32. package/dist/src/read-model/session-journal.d.ts +26 -0
  33. package/dist/src/read-model/session-journal.js +355 -0
  34. package/dist/src/read-model/stats-command.d.ts +16 -0
  35. package/dist/src/read-model/stats-command.js +88 -0
  36. package/dist/src/read-model/stats-format.d.ts +1 -0
  37. package/dist/src/read-model/stats-format.js +8 -0
  38. package/dist/src/worker/autohost.d.ts +11 -0
  39. package/dist/src/worker/autohost.js +858 -0
  40. package/dist/src/worker/constants.d.ts +3 -0
  41. package/dist/src/worker/constants.js +10 -0
  42. package/dist/src/worker/extension.d.ts +14 -0
  43. package/dist/src/worker/extension.js +881 -0
  44. package/dist/src/worker/host.d.ts +1 -0
  45. package/dist/src/worker/host.js +1 -0
  46. package/dist/src/worker/inbox-command.d.ts +23 -0
  47. package/dist/src/worker/inbox-command.js +163 -0
  48. package/dist/src/worker/index.d.ts +2 -0
  49. package/dist/src/worker/index.js +1767 -0
  50. package/dist/src/worker/local-run-changes.d.ts +3 -0
  51. package/dist/src/worker/local-run-changes.js +65 -0
  52. package/dist/src/worker/notifications.d.ts +1 -0
  53. package/dist/src/worker/notifications.js +27 -0
  54. package/dist/src/worker/notify-cap.d.ts +11 -0
  55. package/dist/src/worker/notify-cap.js +13 -0
  56. package/dist/src/worker/panel-plugin.d.ts +11 -0
  57. package/dist/src/worker/panel-plugin.js +37 -0
  58. package/dist/src/worker/plugin.d.ts +3 -0
  59. package/dist/src/worker/plugin.js +1761 -0
  60. package/dist/src/worker/run-control-service.d.ts +2 -0
  61. package/dist/src/worker/run-control-service.js +210 -0
  62. package/dist/src/worker/session-journal-writer.d.ts +4 -0
  63. package/dist/src/worker/session-journal-writer.js +184 -0
  64. package/dist/src/worker/stall.d.ts +21 -0
  65. package/dist/src/worker/stall.js +55 -0
  66. package/dist/src/worker/utils.d.ts +21 -0
  67. package/dist/src/worker/utils.js +29 -0
  68. package/dist/src/worker/workflow-journal-writer.d.ts +7 -0
  69. package/dist/src/worker/workflow-journal-writer.js +76 -0
  70. package/package.json +47 -0
@@ -0,0 +1,19 @@
1
+ import type { CommandOutcome, RunReadModelDetails, RunRecord, TaskArtifactReadResult } from "@rig/contracts";
2
+ import type { RuntimeCliContext } from "@rig/core/config";
3
+ type MaybePromise<T> = T | Promise<T>;
4
+ type InspectCommandDeps = {
5
+ getRunProjection?: (projectRoot: string, taskId: string) => Promise<RunRecord | null>;
6
+ listRunProjections?: (projectRoot: string) => Promise<readonly RunRecord[]>;
7
+ getRunDetails?: (projectRoot: string, runId: string, options?: {
8
+ includeLogs?: boolean;
9
+ }) => Promise<RunReadModelDetails | null>;
10
+ taskArtifactRead?: (projectRoot: string, filename: string, options?: {
11
+ taskId?: string;
12
+ maxBytes?: number;
13
+ }) => MaybePromise<TaskArtifactReadResult>;
14
+ taskArtifacts?: (projectRoot: string, taskId?: string) => MaybePromise<void>;
15
+ taskDeps?: (projectRoot: string, taskId?: string) => MaybePromise<void>;
16
+ changedFilesForTask?: (projectRoot: string, taskId: string, scoped: boolean) => string[];
17
+ };
18
+ export declare function executeInspect(context: RuntimeCliContext, args: string[], deps?: InspectCommandDeps): Promise<CommandOutcome>;
19
+ export {};
@@ -0,0 +1,341 @@
1
+ // @bun
2
+ // packages/run-plugin/src/read-model/inspect-command.ts
3
+ import { RUN_READ_MODEL, TASK_CLI_DATA_CAPABILITY } from "@rig/contracts";
4
+ import { defineCapability } from "@rig/core/capability";
5
+ import { requireCapabilityForRoot } from "@rig/core/capability-loaders";
6
+ import { CliError, requireNoExtraArgs, requireOption, takeOption } from "@rig/std-shared/cli-args";
7
+ import { printFormattedOutput } from "@rig/std-shared/cli-format";
8
+
9
+ // packages/run-plugin/src/read-model/run-format.ts
10
+ import pc from "picocolors";
11
+ import { formatSection, formatSuccessCard, formatNextSteps } from "@rig/std-shared/cli-format";
12
+ var dim = pc.dim;
13
+ var faintBar = pc.dim("\u2502");
14
+ var accent = pc.cyan;
15
+ var STATUS_ROLES = new Set([
16
+ "success",
17
+ "action-yellow",
18
+ "active-cyan",
19
+ "failure",
20
+ "muted",
21
+ "neutral"
22
+ ]);
23
+ function projectedStatusRole(value) {
24
+ return typeof value === "string" && STATUS_ROLES.has(value) ? value : null;
25
+ }
26
+ function truncate(value, width) {
27
+ return value.length <= width ? value : `${value.slice(0, Math.max(0, width - 1))}\u2026`;
28
+ }
29
+ function pad(value, width) {
30
+ return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
31
+ }
32
+ function colorForRole(role) {
33
+ switch (role) {
34
+ case "success":
35
+ return pc.green;
36
+ case "action-yellow":
37
+ return pc.yellow;
38
+ case "active-cyan":
39
+ return pc.cyan;
40
+ case "failure":
41
+ return pc.red;
42
+ case "muted":
43
+ case "neutral":
44
+ return pc.dim;
45
+ }
46
+ }
47
+ function firstString(record, keys, fallback = "") {
48
+ for (const key of keys) {
49
+ const value = record[key];
50
+ if (typeof value === "string" && value.trim())
51
+ return value;
52
+ }
53
+ return fallback;
54
+ }
55
+ function runIdOf(run) {
56
+ return firstString(run, ["runId", "id"], "(unknown-run)");
57
+ }
58
+ function taskIdOf(run) {
59
+ return firstString(run, ["taskId", "task", "task_id"]);
60
+ }
61
+ function runTitleOf(run) {
62
+ return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
63
+ }
64
+ function runLikeStatusText(run) {
65
+ const record = run;
66
+ const status = typeof record.status === "string" ? record.status.trim() : "";
67
+ return status || "unclassified";
68
+ }
69
+ function runLikeStatusColor(run) {
70
+ const record = run;
71
+ return colorForRole(projectedStatusRole(record.statusRole) ?? "neutral");
72
+ }
73
+ function formatLegacyAutomationSurface() {
74
+ return [];
75
+ }
76
+ function formatRunList(runs, options = {}) {
77
+ if (runs.length === 0) {
78
+ return [
79
+ formatSection("Runs", "none recorded"),
80
+ options.source === "server" ? dim("No runs recorded on the selected server.") : dim("No runs recorded in local state."),
81
+ "",
82
+ ...formatLegacyAutomationSurface()
83
+ ].join(`
84
+ `);
85
+ }
86
+ const body = runs.map((run) => {
87
+ const row = run;
88
+ const runId = runIdOf(row);
89
+ const status = runLikeStatusText(run);
90
+ const runtime = firstString(row, ["runtime", "runtimeAdapter"], "");
91
+ return [
92
+ pc.bold(runId),
93
+ runLikeStatusColor(run)(pad(truncate(status, 12), 12)),
94
+ `${runTitleOf(row)}${runtime ? dim(` ${runtime}`) : ""}`
95
+ ].join(" ");
96
+ });
97
+ return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), ...body, "", ...formatLegacyAutomationSurface()].join(`
98
+ `);
99
+ }
100
+
101
+ // packages/run-plugin/src/read-model/inspect-command.ts
102
+ var RunReadModelCap = defineCapability(RUN_READ_MODEL);
103
+ var TaskCliDataCap = defineCapability(TASK_CLI_DATA_CAPABILITY);
104
+ var taskCliData = (projectRoot) => requireCapabilityForRoot(projectRoot, TaskCliDataCap, "CLI task-data capability unavailable: load @rig/tasks-plugin (default bundle).");
105
+ var INSPECT_USAGE = "rig inspect <logs|artifact|artifacts|run-logs|runs|failures|graph|diff>";
106
+ function inspectHelpText() {
107
+ return [
108
+ `Usage: ${INSPECT_USAGE}`,
109
+ "",
110
+ "Commands:",
111
+ " logs --task <id> Print log lines from a projected run for a task.",
112
+ " artifact --task <id> --file <name>",
113
+ " Preview a single task artifact.",
114
+ " artifacts --task <id> List task artifacts.",
115
+ " run-logs --run <id> Print log lines from a run journal.",
116
+ " runs List projected runs.",
117
+ " diff --task <id> List files changed by a task.",
118
+ " graph [--task <id>] Print the task dependency graph.",
119
+ " failures --task <id> Print run read-model failure summaries for a task."
120
+ ].join(`
121
+ `);
122
+ }
123
+ function printInspectHelp() {
124
+ printFormattedOutput(inspectHelpText());
125
+ }
126
+ function toRunLike(run, classification) {
127
+ return {
128
+ runId: run.runId,
129
+ taskId: run.taskId,
130
+ title: run.title,
131
+ status: classification?.status ?? run.status,
132
+ runStatus: classification?.runStatus,
133
+ statusPhase: classification?.phase,
134
+ statusRole: classification?.role,
135
+ statusRank: classification?.rank,
136
+ isActive: classification?.isActive,
137
+ isTerminal: classification?.isTerminal,
138
+ isNeedsAttention: classification?.isNeedsAttention,
139
+ source: run.source,
140
+ live: run.live,
141
+ stale: run.stale,
142
+ startedAt: run.startedAt,
143
+ updatedAt: run.updatedAt,
144
+ completedAt: run.completedAt,
145
+ joinLink: run.joinLink,
146
+ prUrl: run.prUrl,
147
+ pendingApprovals: run.pendingApprovals,
148
+ pendingInputs: run.pendingInputs,
149
+ steeringCount: run.steeringCount,
150
+ stallCount: run.stallCount
151
+ };
152
+ }
153
+ function requireRunId(value, usage) {
154
+ if (!value || !value.trim())
155
+ throw new CliError(`${usage} requires a run id.`, 2, { hint: "Run `rig inspect runs` to find run ids." });
156
+ return value.trim();
157
+ }
158
+ async function loadRunReadModel(projectRoot) {
159
+ return requireCapabilityForRoot(projectRoot, RunReadModelCap, "RUN_READ_MODEL capability unavailable for this project root: load @rig/run-plugin (standard bundle).");
160
+ }
161
+ async function listRunRecords(projectRoot, deps) {
162
+ return deps.listRunProjections ? deps.listRunProjections(projectRoot) : (await loadRunReadModel(projectRoot)).listRuns({ projectRoot });
163
+ }
164
+ async function getRunRecord(projectRoot, runId, deps) {
165
+ return deps.getRunProjection ? deps.getRunProjection(projectRoot, runId) : (await loadRunReadModel(projectRoot)).getRun({ projectRoot, selector: { id: runId, kind: "any" } });
166
+ }
167
+ async function getRunDetails(projectRoot, runId, deps, options = {}) {
168
+ return deps.getRunDetails ? deps.getRunDetails(projectRoot, runId, options) : (await loadRunReadModel(projectRoot)).getRunDetails({ projectRoot, selector: { id: runId, kind: "any" }, ...options.includeLogs === undefined ? {} : { includeLogs: options.includeLogs } });
169
+ }
170
+ async function runsForTaskId(projectRoot, taskId, deps) {
171
+ try {
172
+ if (!deps.listRunProjections) {
173
+ const runs = await (await loadRunReadModel(projectRoot)).listRuns({ projectRoot, taskId });
174
+ if (runs.length > 0)
175
+ return runs;
176
+ } else {
177
+ const runs = await listRunRecords(projectRoot, deps);
178
+ const filtered = runs.filter((run2) => run2.taskId === taskId || run2.runId === taskId);
179
+ if (filtered.length > 0)
180
+ return filtered;
181
+ }
182
+ } catch {}
183
+ const run = await getRunRecord(projectRoot, taskId, deps);
184
+ return run ? [run] : [];
185
+ }
186
+ async function representativeRunForTaskId(projectRoot, taskId, deps) {
187
+ if (deps.listRunProjections) {
188
+ const runs = await runsForTaskId(projectRoot, taskId, deps);
189
+ for (const run of runs)
190
+ return run;
191
+ return null;
192
+ }
193
+ return (await loadRunReadModel(projectRoot)).getRepresentativeRun({ projectRoot, taskId, purpose: "inspect" });
194
+ }
195
+ function failureLine(failure) {
196
+ return failure.detail ? `${failure.summary} \u2014 ${failure.detail}` : failure.summary;
197
+ }
198
+ async function executeLogs(context, args, deps) {
199
+ const taskResult = takeOption(args, "--task");
200
+ requireNoExtraArgs(taskResult.rest, "rig inspect logs --task <id>");
201
+ const taskId = requireOption(taskResult.value, "--task", "rig inspect logs --task <id>");
202
+ const projection = await representativeRunForTaskId(context.projectRoot, taskId, deps);
203
+ if (!projection)
204
+ throw new CliError(`No projected runs found for task ${taskId}.`, 1, { hint: "Run `rig run list` to confirm the run journal is discoverable." });
205
+ const details = await getRunDetails(context.projectRoot, projection.runId, deps, { includeLogs: true });
206
+ const lines = [...details?.logs ?? []];
207
+ if (context.outputMode === "text") {
208
+ if (lines.length === 0)
209
+ console.log(`No log entries found for task ${taskId}.`);
210
+ else
211
+ for (const line of lines)
212
+ console.log(line);
213
+ }
214
+ return { ok: true, group: "inspect", command: "logs", details: { taskId, runId: projection.runId, count: lines.length, lines } };
215
+ }
216
+ async function executeArtifact(context, args, deps) {
217
+ const taskResult = takeOption(args, "--task");
218
+ const fileResult = takeOption(taskResult.rest, "--file");
219
+ requireNoExtraArgs(fileResult.rest, "rig inspect artifact --task <id> --file <name>");
220
+ const taskId = requireOption(taskResult.value, "--task", "rig inspect artifact --task <id> --file <name>");
221
+ const filename = fileResult.value?.trim();
222
+ if (!filename)
223
+ throw new CliError("rig inspect artifact --task <id> --file <name> requires an artifact file name.", 2);
224
+ const preview = await (deps.taskArtifactRead ?? (await taskCliData(context.projectRoot)).taskArtifactRead)(context.projectRoot, filename, { taskId, maxBytes: 64 * 1024 });
225
+ if (context.outputMode === "text") {
226
+ console.log(preview.contents);
227
+ if (preview.truncated)
228
+ console.log(`
229
+ [truncated at ${preview.maxBytes} bytes; artifact is ${preview.sizeBytes} bytes]`);
230
+ }
231
+ return { ok: true, group: "inspect", command: "artifact", details: { taskId, file: filename, ...preview } };
232
+ }
233
+ async function executeRunLogs(context, args, deps) {
234
+ const runResult = takeOption(args, "--run");
235
+ requireNoExtraArgs(runResult.rest, "rig inspect run-logs --run <id>");
236
+ const runId = requireRunId(runResult.value, "rig inspect run-logs --run <id>");
237
+ const projection = await getRunRecord(context.projectRoot, runId, deps);
238
+ if (!projection)
239
+ throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig inspect runs` to see runs." });
240
+ const details = await getRunDetails(context.projectRoot, projection.runId, deps, { includeLogs: true });
241
+ const lines = [...details?.logs ?? []];
242
+ if (context.outputMode === "text") {
243
+ if (lines.length === 0)
244
+ console.log(`No log entries found for run ${projection.runId}.`);
245
+ else
246
+ for (const line of lines)
247
+ console.log(line);
248
+ }
249
+ return { ok: true, group: "inspect", command: "run-logs", details: { runId: projection.runId, taskId: projection.taskId, count: lines.length, lines } };
250
+ }
251
+ async function executeRuns(context, args, deps) {
252
+ requireNoExtraArgs(args, "rig inspect runs");
253
+ let formatted;
254
+ if (deps.listRunProjections) {
255
+ formatted = (await listRunRecords(context.projectRoot, deps)).map((run) => toRunLike(run));
256
+ } else {
257
+ const readModel = await loadRunReadModel(context.projectRoot);
258
+ const runs = await readModel.listRuns({ projectRoot: context.projectRoot });
259
+ formatted = runs.map((run) => toRunLike(run, readModel.classifyRun(run)));
260
+ }
261
+ if (context.outputMode === "text")
262
+ printFormattedOutput(formatRunList(formatted));
263
+ return { ok: true, group: "inspect", command: "runs", details: { runs: formatted } };
264
+ }
265
+ async function executeArtifacts(context, args, deps) {
266
+ const taskResult = takeOption(args, "--task");
267
+ requireNoExtraArgs(taskResult.rest, "rig inspect artifacts --task <id>");
268
+ const taskId = requireOption(taskResult.value, "--task", "rig inspect artifacts --task <id>");
269
+ if (context.outputMode === "text")
270
+ await (deps.taskArtifacts ?? (await taskCliData(context.projectRoot)).taskArtifacts)(context.projectRoot, taskId);
271
+ return { ok: true, group: "inspect", command: "artifacts", details: { taskId, printed: context.outputMode === "text" } };
272
+ }
273
+ async function executeDiff(context, args, deps) {
274
+ const taskResult = takeOption(args, "--task");
275
+ requireNoExtraArgs(taskResult.rest, "rig inspect diff --task <id>");
276
+ const taskId = requireOption(taskResult.value, "--task", "rig inspect diff --task <id>");
277
+ const files = (deps.changedFilesForTask ?? (await taskCliData(context.projectRoot)).changedFilesForTask)(context.projectRoot, taskId, true);
278
+ if (context.outputMode === "text")
279
+ for (const file of files)
280
+ console.log(file);
281
+ return { ok: true, group: "inspect", command: "diff", details: { taskId, files } };
282
+ }
283
+ async function executeGraph(context, args, deps) {
284
+ const taskResult = takeOption(args, "--task");
285
+ requireNoExtraArgs(taskResult.rest, "rig inspect graph [--task <id>]");
286
+ if (context.outputMode === "text")
287
+ await (deps.taskDeps ?? (await taskCliData(context.projectRoot)).taskDeps)(context.projectRoot, taskResult.value);
288
+ return { ok: true, group: "inspect", command: "graph", details: { taskId: taskResult.value ?? null, printed: context.outputMode === "text" } };
289
+ }
290
+ async function executeFailures(context, args, deps) {
291
+ const taskResult = takeOption(args, "--task");
292
+ requireNoExtraArgs(taskResult.rest, "rig inspect failures --task <id>");
293
+ const taskId = requireOption(taskResult.value, "--task", "rig inspect failures --task <id>");
294
+ const runs = await runsForTaskId(context.projectRoot, taskId, deps);
295
+ const failures = (await Promise.all(runs.map(async (run) => (await getRunDetails(context.projectRoot, run.runId, deps))?.failures ?? []))).flat().map(failureLine);
296
+ if (context.outputMode === "text") {
297
+ if (failures.length === 0)
298
+ console.log(`No failures recorded for task ${taskId}.`);
299
+ else
300
+ for (const failure of failures)
301
+ console.log(failure);
302
+ }
303
+ return { ok: true, group: "inspect", command: "failures", details: { taskId, count: failures.length, failures } };
304
+ }
305
+ function executeAudit(args) {
306
+ requireNoExtraArgs(args, "rig inspect audit");
307
+ throw new CliError("rig inspect audit cannot read the controlled-command audit trail yet: current code only writes audit JSONL and exposes no supported reader API.", 2, { hint: "Use the OMP session history for operator audit context until a controlled-bash audit reader is added." });
308
+ }
309
+ async function executeInspect(context, args, deps = {}) {
310
+ const [command = "failures", ...rest] = args;
311
+ if (command === "--help" || command === "-h" || command === "help") {
312
+ if (context.outputMode === "text")
313
+ printInspectHelp();
314
+ return { ok: true, group: "inspect", command: "help" };
315
+ }
316
+ switch (command) {
317
+ case "logs":
318
+ return executeLogs(context, rest, deps);
319
+ case "artifact":
320
+ return executeArtifact(context, rest, deps);
321
+ case "artifacts":
322
+ return executeArtifacts(context, rest, deps);
323
+ case "run-logs":
324
+ return executeRunLogs(context, rest, deps);
325
+ case "runs":
326
+ return executeRuns(context, rest, deps);
327
+ case "diff":
328
+ return executeDiff(context, rest, deps);
329
+ case "graph":
330
+ return executeGraph(context, rest, deps);
331
+ case "failures":
332
+ return executeFailures(context, rest, deps);
333
+ case "audit":
334
+ return executeAudit(rest);
335
+ default:
336
+ throw new CliError(`Unknown inspect command: ${command}`, 1, { hint: "Run `rig inspect --help` to list inspect commands." });
337
+ }
338
+ }
339
+ export {
340
+ executeInspect
341
+ };
@@ -0,0 +1,4 @@
1
+ import { type RigPlugin } from "@rig/core/config";
2
+ export declare const RUN_READ_MODEL_PLUGIN_NAME = "@rig/run-plugin";
3
+ export declare const runReadModelPlugin: RigPlugin;
4
+ export declare function createRunReadModelPlugin(): RigPlugin;