@h-rig/run-worker 0.0.6-alpha.132 → 0.0.6-alpha.133

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.
@@ -1,6 +1,7 @@
1
1
  import type { ExtensionAPI, ExtensionContext, AgentEndEvent } from "@oh-my-pi/pi-coding-agent";
2
2
  import { type RigRunTimelineEntry, type RunInboxResolutionSentinel, type RunSessionCustomEntry } from "@rig/contracts";
3
3
  import { projectRunFromSession } from "@rig/runtime/control-plane/run-session-projection";
4
+ import { updateRunTaskSourceLifecycle } from "@rig/runtime/control-plane/tasks/source-lifecycle";
4
5
  import { type RegistryRunProjection } from "@rig/relay-registry";
5
6
  export interface RunProcessWorkerHooks {
6
7
  readonly beforeAgentStart: () => void;
@@ -8,6 +9,18 @@ export interface RunProcessWorkerHooks {
8
9
  readonly agentEnd: (event: AgentEndEvent) => Promise<void>;
9
10
  }
10
11
  export declare const REGISTRY_PROJECTION_TIMELINE_LIMIT = 100;
12
+ type RunTaskSourceLifecycleUpdater = typeof updateRunTaskSourceLifecycle;
13
+ export declare function reflectStoppedRunTaskSource(input: {
14
+ readonly projectRoot: string;
15
+ readonly runId: string;
16
+ readonly taskId?: string | null;
17
+ readonly sourceTask?: unknown;
18
+ readonly worktreePath?: string | null;
19
+ readonly logRoot?: string | null;
20
+ readonly sessionPath?: string | null;
21
+ readonly reason?: string | null;
22
+ readonly updateLifecycle?: RunTaskSourceLifecycleUpdater;
23
+ }): Promise<boolean>;
11
24
  export declare function registryRunProjection(input: {
12
25
  readonly runId: string;
13
26
  readonly folded: ReturnType<typeof projectRunFromSession>;
@@ -32,3 +45,4 @@ export declare function detectRunControlText(text: string, runId: string): {
32
45
  } | null;
33
46
  export declare function maybeStartRunProcessAutohost(api: ExtensionAPI, ctx: ExtensionContext): Promise<RunProcessWorkerHooks | null>;
34
47
  export declare function maybeStartSpikeAutohost(ctx: ExtensionContext): Promise<void>;
48
+ export {};
@@ -1,9 +1,10 @@
1
1
  // @bun
2
2
  // packages/run-worker/src/autohost.ts
3
+ import { runStagedCloseout } from "@rig/bundle-default-lifecycle/staged-closeout";
3
4
  import { latestTimelineEntriesFromCustomEntries, parseInboxResolutionSentinel, parsePauseSentinel, parseResumeSentinel, parseStopSentinel, sessionIdFromSessionFile } from "@rig/contracts";
4
5
  import { Duration, Effect, Fiber, Stream } from "effect";
5
6
  import { createEnvCloseoutRunners } from "@rig/runtime/control-plane/native/closeout-runners";
6
- import { CloseoutValidationError, runInProcessCloseout } from "@rig/runtime/control-plane/native/in-process-closeout";
7
+ import { CloseoutValidationError } from "@rig/runtime/control-plane/native/in-process-closeout";
7
8
  import { projectRunFromSession } from "@rig/runtime/control-plane/run-session-projection";
8
9
  import { localRunChanges } from "@rig/runtime/control-plane/run-discovery-stream";
9
10
  import { updateRunTaskSourceLifecycle } from "@rig/runtime/control-plane/tasks/source-lifecycle";
@@ -11,12 +12,30 @@ import { resolveOwnerNamespaceKey } from "@rig/runtime/control-plane/remote-conf
11
12
  import { resolveRigIdentity } from "@rig/runtime/control-plane/identity";
12
13
  import { connectWorkerProjection, createRegistryClient } from "@rig/relay-registry";
13
14
  import { coerceRegistryStatus } from "@rig/relay-registry/schema";
15
+ import { bootDefaultKernelIntoProcess } from "@rig/kernel/boot-default";
14
16
 
15
17
  // packages/run-worker/src/journal.ts
18
+ import { createJournalSessionProvider } from "@rig/kernel/journal-session-provider";
16
19
  import { RunSessionJournal } from "@rig/runtime/control-plane/run-session-writer";
17
20
  async function createRunJournal(sessionManager, runId) {
18
21
  try {
19
- return new RunSessionJournal(sessionManager, runId);
22
+ const journal = new RunSessionJournal(sessionManager, runId);
23
+ const kernel = createJournalSessionProvider({
24
+ runId,
25
+ store: {
26
+ appendCustomEntry: (customType, data) => sessionManager.appendCustomEntry(customType, data),
27
+ getEntries: () => sessionManager.getEntries?.() ?? sessionManager.getBranch?.() ?? []
28
+ }
29
+ });
30
+ return {
31
+ kernel,
32
+ appendStatus: journal.appendStatus.bind(journal),
33
+ appendTimeline: journal.appendTimeline.bind(journal),
34
+ appendCloseoutPhase: journal.appendCloseoutPhase.bind(journal),
35
+ appendApprovalResolved: journal.appendApprovalResolved.bind(journal),
36
+ appendInputResolved: journal.appendInputResolved.bind(journal),
37
+ appendStall: journal.appendStall.bind(journal)
38
+ };
20
39
  } catch (error) {
21
40
  console.warn(`[rig-run] RunSessionJournal unavailable; run-state arming deferred: ${error instanceof Error ? error.message : String(error)}`);
22
41
  return null;
@@ -111,7 +130,32 @@ function rigRelayUrl() {
111
130
  }
112
131
 
113
132
  // packages/run-worker/src/autohost.ts
133
+ var RIG_PANELS_CUSTOM_MESSAGE_TYPE = "rig-panels";
134
+ var RIG_RUN_STOP_PANEL_ACTION = "rig-run:stop";
135
+ function syntheticRegistryOwner(namespaceKey) {
136
+ const githubUserId = namespaceKey.startsWith("gh:") ? namespaceKey.slice(3) : namespaceKey;
137
+ return {
138
+ githubUserId: githubUserId || "anonymous",
139
+ login: "anonymous",
140
+ namespaceKey
141
+ };
142
+ }
114
143
  var REGISTRY_PROJECTION_TIMELINE_LIMIT = 100;
144
+ async function reflectStoppedRunTaskSource(input) {
145
+ const taskId = input.taskId?.trim();
146
+ if (!taskId)
147
+ return false;
148
+ const reason = input.reason?.trim();
149
+ await (input.updateLifecycle ?? updateRunTaskSourceLifecycle)(input.projectRoot, {
150
+ runId: input.runId,
151
+ taskId,
152
+ sourceTask: input.sourceTask,
153
+ worktreePath: input.worktreePath,
154
+ logRoot: input.logRoot,
155
+ sessionPath: input.sessionPath
156
+ }, "cancelled", reason ? `Rig stopped by operator: ${reason}` : "Rig stopped by operator.");
157
+ return true;
158
+ }
115
159
  function registryRunProjection(input) {
116
160
  const timeline = input.timeline ?? latestTimelineEntriesFromCustomEntries(input.entries, REGISTRY_PROJECTION_TIMELINE_LIMIT);
117
161
  return {
@@ -185,7 +229,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
185
229
  if (!envRunId)
186
230
  throw new Error("RIG_RUN_ID is required when RIG_RUN_PROCESS=1");
187
231
  const runId = sessionIdFromSessionFile(ctx.sessionManager.getSessionFile()) ?? envRunId;
188
- console.log(`[rig-run] session_start hasUI=${ctx.hasUI ? "true" : "false"}`);
189
232
  if (!ctx.hasUI)
190
233
  return null;
191
234
  const collab = ctx.collab;
@@ -194,6 +237,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
194
237
  throw new Error("OMP collab host facade is unavailable for Rig run process.");
195
238
  const identity = resolveRigIdentity(ctx);
196
239
  const journal = await createRunJournal(ctx.sessionManager, runId);
240
+ await bootDefaultKernelIntoProcess({
241
+ entrypoint: "run-worker",
242
+ ...journal ? { journal: journal.kernel } : {}
243
+ });
197
244
  const projectRoot = process.env.PROJECT_RIG_ROOT ?? process.cwd();
198
245
  let runProjection = projectRunFromSession(customEntries(ctx.sessionManager.getBranch()), runId);
199
246
  const taskIdAtStart = process.env.RIG_TASK_ID?.trim() || runProjection.record.taskId;
@@ -212,8 +259,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
212
259
  let runRegistryRoomId = null;
213
260
  let workerProjectionConnection = null;
214
261
  let workerProjectionFiber = null;
215
- const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? null;
216
- const runRegistry = runRegistryNamespace ? createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace }) : null;
262
+ const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? "anonymous";
263
+ const runRegistryOwner = identity?.owner ?? syntheticRegistryOwner(runRegistryNamespace);
264
+ const runRegistryRepo = identity?.selectedRepo ?? "";
265
+ const runRegistry = createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace });
217
266
  let runRegistryLinks = {};
218
267
  const processedControlEntryIds = new Set((ctx.sessionManager.getEntries?.() ?? []).map((entry) => entry && typeof entry === "object" && typeof entry.id === "string" ? entry.id : null).filter((id) => id !== null));
219
268
  const processedControlEntryObjects = new WeakSet;
@@ -251,6 +300,38 @@ async function maybeStartRunProcessAutohost(api, ctx) {
251
300
  timeline
252
301
  });
253
302
  };
303
+ let lastRigPanelsSnapshotJson = "";
304
+ const publishRigPanelsSnapshot = () => {
305
+ const appendCustomMessageEntry = ctx.sessionManager.appendCustomMessageEntry?.bind(ctx.sessionManager);
306
+ if (!appendCustomMessageEntry)
307
+ return;
308
+ const { folded } = currentProjectionParts();
309
+ const status = folded.status ?? "unknown";
310
+ const taskId = folded.record.taskId ?? taskIdAtStart;
311
+ const operatorActive = status === "running" || status === "validating" || status === "closing-out" || status === "needs-attention";
312
+ const frameBody = {
313
+ kind: "snapshot",
314
+ activePanel: "supervisor",
315
+ registrations: [{ id: "supervisor", title: "Supervisor" }],
316
+ supervisor: {
317
+ status,
318
+ currentTask: taskId ? { id: taskId, title: runDisplayTitle } : null,
319
+ processed: folded.closeoutPhases.length,
320
+ succeeded: folded.closeoutPhases.filter((phase) => phase.outcome === "completed").length,
321
+ failed: folded.closeoutPhases.filter((phase) => phase.outcome === "failed").length,
322
+ skipped: 0,
323
+ plannedOrder: taskId ? [{ id: taskId, title: runDisplayTitle, status }] : [],
324
+ idleReason: operatorActive ? null : status,
325
+ stopActionId: operatorActive ? RIG_RUN_STOP_PANEL_ACTION : null,
326
+ closures: []
327
+ }
328
+ };
329
+ const serialized = JSON.stringify(frameBody);
330
+ if (serialized === lastRigPanelsSnapshotJson)
331
+ return;
332
+ lastRigPanelsSnapshotJson = serialized;
333
+ appendCustomMessageEntry(RIG_PANELS_CUSTOM_MESSAGE_TYPE, "", false, { ...frameBody, updatedAt: new Date().toISOString() }, "agent");
334
+ };
254
335
  const pushWorkerProjection = (links = runRegistryLinks) => {
255
336
  if (!workerProjectionConnection)
256
337
  return;
@@ -258,6 +339,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
258
339
  };
259
340
  const publishRunProjection = async (status) => {
260
341
  const projection = buildCurrentRegistryProjection();
342
+ publishRigPanelsSnapshot();
261
343
  if (workerProjectionConnection)
262
344
  workerProjectionConnection.push(projection);
263
345
  if (runRegistry && runRegistryRoomId) {
@@ -360,13 +442,23 @@ async function maybeStartRunProcessAutohost(api, ctx) {
360
442
  };
361
443
  process.once("uncaughtException", publishFatalTerminal);
362
444
  process.once("unhandledRejection", publishFatalTerminal);
445
+ const handlePanelAction = async (input) => {
446
+ if (input.actionId !== RIG_RUN_STOP_PANEL_ACTION && input.actionId !== "stop-supervisor") {
447
+ throw new Error(`Unsupported Rig panel action: ${input.actionId}`);
448
+ }
449
+ pendingStopReason = `operator ${input.from.name} requested stop`;
450
+ journal?.appendTimeline({ type: "interrupted", stage: "panel-action", status: "running", detail: pendingStopReason });
451
+ ctx.abort();
452
+ await publishRunProjection("running");
453
+ };
363
454
  const startRunCollabHost = async () => {
364
455
  try {
365
456
  const projection = await startHost.call(collab, {
366
457
  title: runDisplayTitle,
367
458
  ...identity?.owner ? { owner: identity.owner } : {},
368
459
  ...identity?.selectedRepo ? { selectedRepo: identity.selectedRepo } : {},
369
- relayUrl: rigRelayUrl()
460
+ relayUrl: rigRelayUrl(),
461
+ onPanelAction: handlePanelAction
370
462
  });
371
463
  runRegistryLinks = { joinLink: projection.joinLink, webLink: projection.webLink, relayUrl: projection.relayUrl ?? rigRelayUrl() };
372
464
  const timeline = {
@@ -379,14 +471,15 @@ async function maybeStartRunProcessAutohost(api, ctx) {
379
471
  journal?.appendTimeline(timeline);
380
472
  console.log(`[rig-run] collab-host-started joinLink=${projection.joinLink || "(empty)"} relayUrl=${projection.relayUrl || "(empty)"}`);
381
473
  ctx.ui.notify("Rig run collab host started.", "info");
382
- if (runRegistry && identity?.owner) {
474
+ publishRigPanelsSnapshot();
475
+ if (runRegistry) {
383
476
  try {
384
477
  runRegistryRoomId = projection.sessionId;
385
478
  const initialProjection = buildCurrentRegistryProjection();
386
479
  await runRegistry.registerRoom({
387
480
  roomId: projection.sessionId,
388
- owner: identity.owner,
389
- repo: identity.selectedRepo ?? "",
481
+ owner: runRegistryOwner,
482
+ repo: runRegistryRepo,
390
483
  title: runDisplayTitle,
391
484
  status: "running",
392
485
  joinLink: projection.joinLink ?? "",
@@ -414,9 +507,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
414
507
  console.error(`[rig-run] registry-register-failed ${error instanceof Error ? error.message : String(error)}`);
415
508
  ctx.ui.notify("Rig run could not register to the discovery registry; it may not appear in Runs.", "warning");
416
509
  }
417
- } else {
418
- console.error(`[rig-run] registry-skip namespace=${runRegistryNamespace ? "set" : "MISSING"}`);
419
- ctx.ui.notify("Rig run NOT registered (registry namespace missing) \u2014 it won't appear in Runs.", "warning");
420
510
  }
421
511
  } catch (error) {
422
512
  console.error(`[rig-run] collab-host-start-failed ${error instanceof Error ? error.message : String(error)}`);
@@ -463,6 +553,26 @@ async function maybeStartRunProcessAutohost(api, ctx) {
463
553
  closeoutStarted = true;
464
554
  journal?.appendTimeline({ type: "interrupted", stage: "stopped", status: "stopped", detail: reason });
465
555
  journal?.appendStatus("stopped", { actor: OPERATOR_ACTOR, reason, force: true });
556
+ if (taskIdAtStart) {
557
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "running", detail: "reflecting operator stop to task source" });
558
+ try {
559
+ await reflectStoppedRunTaskSource({
560
+ projectRoot,
561
+ runId,
562
+ taskId: taskIdAtStart,
563
+ sourceTask: runProjection.record.sourceTask,
564
+ worktreePath: process.cwd(),
565
+ logRoot: runProjection.record.logRoot ?? null,
566
+ sessionPath: runProjection.record.sessionPath ?? null,
567
+ reason
568
+ });
569
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "completed", detail: "reflected operator stop" });
570
+ } catch (error) {
571
+ const detail = error instanceof Error ? error.message : String(error);
572
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "failed", detail });
573
+ console.error(`[rig-run] stopped-reflection-failed ${detail}`);
574
+ }
575
+ }
466
576
  await publishRunProjection("stopped");
467
577
  stopRunStallMonitor();
468
578
  stopRunRegistry({ removeRoom: false });
@@ -506,7 +616,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
506
616
  const { command, gitCommand } = createEnvCloseoutRunners(process.env);
507
617
  let closeoutStatusAdvanced = false;
508
618
  try {
509
- await runInProcessCloseout({
619
+ await runStagedCloseout({
510
620
  projectRoot,
511
621
  runId,
512
622
  taskId,
@@ -585,6 +695,7 @@ async function maybeStartSpikeAutohost(ctx) {
585
695
  }
586
696
  export {
587
697
  registryRunProjection,
698
+ reflectStoppedRunTaskSource,
588
699
  maybeStartSpikeAutohost,
589
700
  maybeStartRunProcessAutohost,
590
701
  detectRunControlText,
@@ -1,9 +1,10 @@
1
1
  // @bun
2
2
  // packages/run-worker/src/autohost.ts
3
+ import { runStagedCloseout } from "@rig/bundle-default-lifecycle/staged-closeout";
3
4
  import { latestTimelineEntriesFromCustomEntries, parseInboxResolutionSentinel, parsePauseSentinel, parseResumeSentinel, parseStopSentinel, sessionIdFromSessionFile } from "@rig/contracts";
4
5
  import { Duration, Effect, Fiber, Stream } from "effect";
5
6
  import { createEnvCloseoutRunners } from "@rig/runtime/control-plane/native/closeout-runners";
6
- import { CloseoutValidationError, runInProcessCloseout } from "@rig/runtime/control-plane/native/in-process-closeout";
7
+ import { CloseoutValidationError } from "@rig/runtime/control-plane/native/in-process-closeout";
7
8
  import { projectRunFromSession } from "@rig/runtime/control-plane/run-session-projection";
8
9
  import { localRunChanges } from "@rig/runtime/control-plane/run-discovery-stream";
9
10
  import { updateRunTaskSourceLifecycle } from "@rig/runtime/control-plane/tasks/source-lifecycle";
@@ -11,12 +12,30 @@ import { resolveOwnerNamespaceKey } from "@rig/runtime/control-plane/remote-conf
11
12
  import { resolveRigIdentity } from "@rig/runtime/control-plane/identity";
12
13
  import { connectWorkerProjection, createRegistryClient } from "@rig/relay-registry";
13
14
  import { coerceRegistryStatus } from "@rig/relay-registry/schema";
15
+ import { bootDefaultKernelIntoProcess } from "@rig/kernel/boot-default";
14
16
 
15
17
  // packages/run-worker/src/journal.ts
18
+ import { createJournalSessionProvider } from "@rig/kernel/journal-session-provider";
16
19
  import { RunSessionJournal } from "@rig/runtime/control-plane/run-session-writer";
17
20
  async function createRunJournal(sessionManager, runId) {
18
21
  try {
19
- return new RunSessionJournal(sessionManager, runId);
22
+ const journal = new RunSessionJournal(sessionManager, runId);
23
+ const kernel = createJournalSessionProvider({
24
+ runId,
25
+ store: {
26
+ appendCustomEntry: (customType, data) => sessionManager.appendCustomEntry(customType, data),
27
+ getEntries: () => sessionManager.getEntries?.() ?? sessionManager.getBranch?.() ?? []
28
+ }
29
+ });
30
+ return {
31
+ kernel,
32
+ appendStatus: journal.appendStatus.bind(journal),
33
+ appendTimeline: journal.appendTimeline.bind(journal),
34
+ appendCloseoutPhase: journal.appendCloseoutPhase.bind(journal),
35
+ appendApprovalResolved: journal.appendApprovalResolved.bind(journal),
36
+ appendInputResolved: journal.appendInputResolved.bind(journal),
37
+ appendStall: journal.appendStall.bind(journal)
38
+ };
20
39
  } catch (error) {
21
40
  console.warn(`[rig-run] RunSessionJournal unavailable; run-state arming deferred: ${error instanceof Error ? error.message : String(error)}`);
22
41
  return null;
@@ -111,7 +130,32 @@ function rigRelayUrl() {
111
130
  }
112
131
 
113
132
  // packages/run-worker/src/autohost.ts
133
+ var RIG_PANELS_CUSTOM_MESSAGE_TYPE = "rig-panels";
134
+ var RIG_RUN_STOP_PANEL_ACTION = "rig-run:stop";
135
+ function syntheticRegistryOwner(namespaceKey) {
136
+ const githubUserId = namespaceKey.startsWith("gh:") ? namespaceKey.slice(3) : namespaceKey;
137
+ return {
138
+ githubUserId: githubUserId || "anonymous",
139
+ login: "anonymous",
140
+ namespaceKey
141
+ };
142
+ }
114
143
  var REGISTRY_PROJECTION_TIMELINE_LIMIT = 100;
144
+ async function reflectStoppedRunTaskSource(input) {
145
+ const taskId = input.taskId?.trim();
146
+ if (!taskId)
147
+ return false;
148
+ const reason = input.reason?.trim();
149
+ await (input.updateLifecycle ?? updateRunTaskSourceLifecycle)(input.projectRoot, {
150
+ runId: input.runId,
151
+ taskId,
152
+ sourceTask: input.sourceTask,
153
+ worktreePath: input.worktreePath,
154
+ logRoot: input.logRoot,
155
+ sessionPath: input.sessionPath
156
+ }, "cancelled", reason ? `Rig stopped by operator: ${reason}` : "Rig stopped by operator.");
157
+ return true;
158
+ }
115
159
  function registryRunProjection(input) {
116
160
  const timeline = input.timeline ?? latestTimelineEntriesFromCustomEntries(input.entries, REGISTRY_PROJECTION_TIMELINE_LIMIT);
117
161
  return {
@@ -185,7 +229,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
185
229
  if (!envRunId)
186
230
  throw new Error("RIG_RUN_ID is required when RIG_RUN_PROCESS=1");
187
231
  const runId = sessionIdFromSessionFile(ctx.sessionManager.getSessionFile()) ?? envRunId;
188
- console.log(`[rig-run] session_start hasUI=${ctx.hasUI ? "true" : "false"}`);
189
232
  if (!ctx.hasUI)
190
233
  return null;
191
234
  const collab = ctx.collab;
@@ -194,6 +237,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
194
237
  throw new Error("OMP collab host facade is unavailable for Rig run process.");
195
238
  const identity = resolveRigIdentity(ctx);
196
239
  const journal = await createRunJournal(ctx.sessionManager, runId);
240
+ await bootDefaultKernelIntoProcess({
241
+ entrypoint: "run-worker",
242
+ ...journal ? { journal: journal.kernel } : {}
243
+ });
197
244
  const projectRoot = process.env.PROJECT_RIG_ROOT ?? process.cwd();
198
245
  let runProjection = projectRunFromSession(customEntries(ctx.sessionManager.getBranch()), runId);
199
246
  const taskIdAtStart = process.env.RIG_TASK_ID?.trim() || runProjection.record.taskId;
@@ -212,8 +259,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
212
259
  let runRegistryRoomId = null;
213
260
  let workerProjectionConnection = null;
214
261
  let workerProjectionFiber = null;
215
- const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? null;
216
- const runRegistry = runRegistryNamespace ? createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace }) : null;
262
+ const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? "anonymous";
263
+ const runRegistryOwner = identity?.owner ?? syntheticRegistryOwner(runRegistryNamespace);
264
+ const runRegistryRepo = identity?.selectedRepo ?? "";
265
+ const runRegistry = createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace });
217
266
  let runRegistryLinks = {};
218
267
  const processedControlEntryIds = new Set((ctx.sessionManager.getEntries?.() ?? []).map((entry) => entry && typeof entry === "object" && typeof entry.id === "string" ? entry.id : null).filter((id) => id !== null));
219
268
  const processedControlEntryObjects = new WeakSet;
@@ -251,6 +300,38 @@ async function maybeStartRunProcessAutohost(api, ctx) {
251
300
  timeline
252
301
  });
253
302
  };
303
+ let lastRigPanelsSnapshotJson = "";
304
+ const publishRigPanelsSnapshot = () => {
305
+ const appendCustomMessageEntry = ctx.sessionManager.appendCustomMessageEntry?.bind(ctx.sessionManager);
306
+ if (!appendCustomMessageEntry)
307
+ return;
308
+ const { folded } = currentProjectionParts();
309
+ const status = folded.status ?? "unknown";
310
+ const taskId = folded.record.taskId ?? taskIdAtStart;
311
+ const operatorActive = status === "running" || status === "validating" || status === "closing-out" || status === "needs-attention";
312
+ const frameBody = {
313
+ kind: "snapshot",
314
+ activePanel: "supervisor",
315
+ registrations: [{ id: "supervisor", title: "Supervisor" }],
316
+ supervisor: {
317
+ status,
318
+ currentTask: taskId ? { id: taskId, title: runDisplayTitle } : null,
319
+ processed: folded.closeoutPhases.length,
320
+ succeeded: folded.closeoutPhases.filter((phase) => phase.outcome === "completed").length,
321
+ failed: folded.closeoutPhases.filter((phase) => phase.outcome === "failed").length,
322
+ skipped: 0,
323
+ plannedOrder: taskId ? [{ id: taskId, title: runDisplayTitle, status }] : [],
324
+ idleReason: operatorActive ? null : status,
325
+ stopActionId: operatorActive ? RIG_RUN_STOP_PANEL_ACTION : null,
326
+ closures: []
327
+ }
328
+ };
329
+ const serialized = JSON.stringify(frameBody);
330
+ if (serialized === lastRigPanelsSnapshotJson)
331
+ return;
332
+ lastRigPanelsSnapshotJson = serialized;
333
+ appendCustomMessageEntry(RIG_PANELS_CUSTOM_MESSAGE_TYPE, "", false, { ...frameBody, updatedAt: new Date().toISOString() }, "agent");
334
+ };
254
335
  const pushWorkerProjection = (links = runRegistryLinks) => {
255
336
  if (!workerProjectionConnection)
256
337
  return;
@@ -258,6 +339,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
258
339
  };
259
340
  const publishRunProjection = async (status) => {
260
341
  const projection = buildCurrentRegistryProjection();
342
+ publishRigPanelsSnapshot();
261
343
  if (workerProjectionConnection)
262
344
  workerProjectionConnection.push(projection);
263
345
  if (runRegistry && runRegistryRoomId) {
@@ -360,13 +442,23 @@ async function maybeStartRunProcessAutohost(api, ctx) {
360
442
  };
361
443
  process.once("uncaughtException", publishFatalTerminal);
362
444
  process.once("unhandledRejection", publishFatalTerminal);
445
+ const handlePanelAction = async (input) => {
446
+ if (input.actionId !== RIG_RUN_STOP_PANEL_ACTION && input.actionId !== "stop-supervisor") {
447
+ throw new Error(`Unsupported Rig panel action: ${input.actionId}`);
448
+ }
449
+ pendingStopReason = `operator ${input.from.name} requested stop`;
450
+ journal?.appendTimeline({ type: "interrupted", stage: "panel-action", status: "running", detail: pendingStopReason });
451
+ ctx.abort();
452
+ await publishRunProjection("running");
453
+ };
363
454
  const startRunCollabHost = async () => {
364
455
  try {
365
456
  const projection = await startHost.call(collab, {
366
457
  title: runDisplayTitle,
367
458
  ...identity?.owner ? { owner: identity.owner } : {},
368
459
  ...identity?.selectedRepo ? { selectedRepo: identity.selectedRepo } : {},
369
- relayUrl: rigRelayUrl()
460
+ relayUrl: rigRelayUrl(),
461
+ onPanelAction: handlePanelAction
370
462
  });
371
463
  runRegistryLinks = { joinLink: projection.joinLink, webLink: projection.webLink, relayUrl: projection.relayUrl ?? rigRelayUrl() };
372
464
  const timeline = {
@@ -379,14 +471,15 @@ async function maybeStartRunProcessAutohost(api, ctx) {
379
471
  journal?.appendTimeline(timeline);
380
472
  console.log(`[rig-run] collab-host-started joinLink=${projection.joinLink || "(empty)"} relayUrl=${projection.relayUrl || "(empty)"}`);
381
473
  ctx.ui.notify("Rig run collab host started.", "info");
382
- if (runRegistry && identity?.owner) {
474
+ publishRigPanelsSnapshot();
475
+ if (runRegistry) {
383
476
  try {
384
477
  runRegistryRoomId = projection.sessionId;
385
478
  const initialProjection = buildCurrentRegistryProjection();
386
479
  await runRegistry.registerRoom({
387
480
  roomId: projection.sessionId,
388
- owner: identity.owner,
389
- repo: identity.selectedRepo ?? "",
481
+ owner: runRegistryOwner,
482
+ repo: runRegistryRepo,
390
483
  title: runDisplayTitle,
391
484
  status: "running",
392
485
  joinLink: projection.joinLink ?? "",
@@ -414,9 +507,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
414
507
  console.error(`[rig-run] registry-register-failed ${error instanceof Error ? error.message : String(error)}`);
415
508
  ctx.ui.notify("Rig run could not register to the discovery registry; it may not appear in Runs.", "warning");
416
509
  }
417
- } else {
418
- console.error(`[rig-run] registry-skip namespace=${runRegistryNamespace ? "set" : "MISSING"}`);
419
- ctx.ui.notify("Rig run NOT registered (registry namespace missing) \u2014 it won't appear in Runs.", "warning");
420
510
  }
421
511
  } catch (error) {
422
512
  console.error(`[rig-run] collab-host-start-failed ${error instanceof Error ? error.message : String(error)}`);
@@ -463,6 +553,26 @@ async function maybeStartRunProcessAutohost(api, ctx) {
463
553
  closeoutStarted = true;
464
554
  journal?.appendTimeline({ type: "interrupted", stage: "stopped", status: "stopped", detail: reason });
465
555
  journal?.appendStatus("stopped", { actor: OPERATOR_ACTOR, reason, force: true });
556
+ if (taskIdAtStart) {
557
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "running", detail: "reflecting operator stop to task source" });
558
+ try {
559
+ await reflectStoppedRunTaskSource({
560
+ projectRoot,
561
+ runId,
562
+ taskId: taskIdAtStart,
563
+ sourceTask: runProjection.record.sourceTask,
564
+ worktreePath: process.cwd(),
565
+ logRoot: runProjection.record.logRoot ?? null,
566
+ sessionPath: runProjection.record.sessionPath ?? null,
567
+ reason
568
+ });
569
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "completed", detail: "reflected operator stop" });
570
+ } catch (error) {
571
+ const detail = error instanceof Error ? error.message : String(error);
572
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "failed", detail });
573
+ console.error(`[rig-run] stopped-reflection-failed ${detail}`);
574
+ }
575
+ }
466
576
  await publishRunProjection("stopped");
467
577
  stopRunStallMonitor();
468
578
  stopRunRegistry({ removeRoom: false });
@@ -506,7 +616,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
506
616
  const { command, gitCommand } = createEnvCloseoutRunners(process.env);
507
617
  let closeoutStatusAdvanced = false;
508
618
  try {
509
- await runInProcessCloseout({
619
+ await runStagedCloseout({
510
620
  projectRoot,
511
621
  runId,
512
622
  taskId,
package/dist/src/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  // @bun
2
2
  // packages/run-worker/src/autohost.ts
3
+ import { runStagedCloseout } from "@rig/bundle-default-lifecycle/staged-closeout";
3
4
  import { latestTimelineEntriesFromCustomEntries, parseInboxResolutionSentinel, parsePauseSentinel, parseResumeSentinel, parseStopSentinel, sessionIdFromSessionFile } from "@rig/contracts";
4
5
  import { Duration, Effect, Fiber, Stream } from "effect";
5
6
  import { createEnvCloseoutRunners } from "@rig/runtime/control-plane/native/closeout-runners";
6
- import { CloseoutValidationError, runInProcessCloseout } from "@rig/runtime/control-plane/native/in-process-closeout";
7
+ import { CloseoutValidationError } from "@rig/runtime/control-plane/native/in-process-closeout";
7
8
  import { projectRunFromSession } from "@rig/runtime/control-plane/run-session-projection";
8
9
  import { localRunChanges } from "@rig/runtime/control-plane/run-discovery-stream";
9
10
  import { updateRunTaskSourceLifecycle } from "@rig/runtime/control-plane/tasks/source-lifecycle";
@@ -11,12 +12,30 @@ import { resolveOwnerNamespaceKey } from "@rig/runtime/control-plane/remote-conf
11
12
  import { resolveRigIdentity } from "@rig/runtime/control-plane/identity";
12
13
  import { connectWorkerProjection, createRegistryClient } from "@rig/relay-registry";
13
14
  import { coerceRegistryStatus } from "@rig/relay-registry/schema";
15
+ import { bootDefaultKernelIntoProcess } from "@rig/kernel/boot-default";
14
16
 
15
17
  // packages/run-worker/src/journal.ts
18
+ import { createJournalSessionProvider } from "@rig/kernel/journal-session-provider";
16
19
  import { RunSessionJournal } from "@rig/runtime/control-plane/run-session-writer";
17
20
  async function createRunJournal(sessionManager, runId) {
18
21
  try {
19
- return new RunSessionJournal(sessionManager, runId);
22
+ const journal = new RunSessionJournal(sessionManager, runId);
23
+ const kernel = createJournalSessionProvider({
24
+ runId,
25
+ store: {
26
+ appendCustomEntry: (customType, data) => sessionManager.appendCustomEntry(customType, data),
27
+ getEntries: () => sessionManager.getEntries?.() ?? sessionManager.getBranch?.() ?? []
28
+ }
29
+ });
30
+ return {
31
+ kernel,
32
+ appendStatus: journal.appendStatus.bind(journal),
33
+ appendTimeline: journal.appendTimeline.bind(journal),
34
+ appendCloseoutPhase: journal.appendCloseoutPhase.bind(journal),
35
+ appendApprovalResolved: journal.appendApprovalResolved.bind(journal),
36
+ appendInputResolved: journal.appendInputResolved.bind(journal),
37
+ appendStall: journal.appendStall.bind(journal)
38
+ };
20
39
  } catch (error) {
21
40
  console.warn(`[rig-run] RunSessionJournal unavailable; run-state arming deferred: ${error instanceof Error ? error.message : String(error)}`);
22
41
  return null;
@@ -111,7 +130,32 @@ function rigRelayUrl() {
111
130
  }
112
131
 
113
132
  // packages/run-worker/src/autohost.ts
133
+ var RIG_PANELS_CUSTOM_MESSAGE_TYPE = "rig-panels";
134
+ var RIG_RUN_STOP_PANEL_ACTION = "rig-run:stop";
135
+ function syntheticRegistryOwner(namespaceKey) {
136
+ const githubUserId = namespaceKey.startsWith("gh:") ? namespaceKey.slice(3) : namespaceKey;
137
+ return {
138
+ githubUserId: githubUserId || "anonymous",
139
+ login: "anonymous",
140
+ namespaceKey
141
+ };
142
+ }
114
143
  var REGISTRY_PROJECTION_TIMELINE_LIMIT = 100;
144
+ async function reflectStoppedRunTaskSource(input) {
145
+ const taskId = input.taskId?.trim();
146
+ if (!taskId)
147
+ return false;
148
+ const reason = input.reason?.trim();
149
+ await (input.updateLifecycle ?? updateRunTaskSourceLifecycle)(input.projectRoot, {
150
+ runId: input.runId,
151
+ taskId,
152
+ sourceTask: input.sourceTask,
153
+ worktreePath: input.worktreePath,
154
+ logRoot: input.logRoot,
155
+ sessionPath: input.sessionPath
156
+ }, "cancelled", reason ? `Rig stopped by operator: ${reason}` : "Rig stopped by operator.");
157
+ return true;
158
+ }
115
159
  function registryRunProjection(input) {
116
160
  const timeline = input.timeline ?? latestTimelineEntriesFromCustomEntries(input.entries, REGISTRY_PROJECTION_TIMELINE_LIMIT);
117
161
  return {
@@ -185,7 +229,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
185
229
  if (!envRunId)
186
230
  throw new Error("RIG_RUN_ID is required when RIG_RUN_PROCESS=1");
187
231
  const runId = sessionIdFromSessionFile(ctx.sessionManager.getSessionFile()) ?? envRunId;
188
- console.log(`[rig-run] session_start hasUI=${ctx.hasUI ? "true" : "false"}`);
189
232
  if (!ctx.hasUI)
190
233
  return null;
191
234
  const collab = ctx.collab;
@@ -194,6 +237,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
194
237
  throw new Error("OMP collab host facade is unavailable for Rig run process.");
195
238
  const identity = resolveRigIdentity(ctx);
196
239
  const journal = await createRunJournal(ctx.sessionManager, runId);
240
+ await bootDefaultKernelIntoProcess({
241
+ entrypoint: "run-worker",
242
+ ...journal ? { journal: journal.kernel } : {}
243
+ });
197
244
  const projectRoot = process.env.PROJECT_RIG_ROOT ?? process.cwd();
198
245
  let runProjection = projectRunFromSession(customEntries(ctx.sessionManager.getBranch()), runId);
199
246
  const taskIdAtStart = process.env.RIG_TASK_ID?.trim() || runProjection.record.taskId;
@@ -212,8 +259,10 @@ async function maybeStartRunProcessAutohost(api, ctx) {
212
259
  let runRegistryRoomId = null;
213
260
  let workerProjectionConnection = null;
214
261
  let workerProjectionFiber = null;
215
- const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? null;
216
- const runRegistry = runRegistryNamespace ? createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace }) : null;
262
+ const runRegistryNamespace = identity?.owner?.namespaceKey ?? resolveOwnerNamespaceKey(rigProjectRoot()) ?? "anonymous";
263
+ const runRegistryOwner = identity?.owner ?? syntheticRegistryOwner(runRegistryNamespace);
264
+ const runRegistryRepo = identity?.selectedRepo ?? "";
265
+ const runRegistry = createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey: runRegistryNamespace });
217
266
  let runRegistryLinks = {};
218
267
  const processedControlEntryIds = new Set((ctx.sessionManager.getEntries?.() ?? []).map((entry) => entry && typeof entry === "object" && typeof entry.id === "string" ? entry.id : null).filter((id) => id !== null));
219
268
  const processedControlEntryObjects = new WeakSet;
@@ -251,6 +300,38 @@ async function maybeStartRunProcessAutohost(api, ctx) {
251
300
  timeline
252
301
  });
253
302
  };
303
+ let lastRigPanelsSnapshotJson = "";
304
+ const publishRigPanelsSnapshot = () => {
305
+ const appendCustomMessageEntry = ctx.sessionManager.appendCustomMessageEntry?.bind(ctx.sessionManager);
306
+ if (!appendCustomMessageEntry)
307
+ return;
308
+ const { folded } = currentProjectionParts();
309
+ const status = folded.status ?? "unknown";
310
+ const taskId = folded.record.taskId ?? taskIdAtStart;
311
+ const operatorActive = status === "running" || status === "validating" || status === "closing-out" || status === "needs-attention";
312
+ const frameBody = {
313
+ kind: "snapshot",
314
+ activePanel: "supervisor",
315
+ registrations: [{ id: "supervisor", title: "Supervisor" }],
316
+ supervisor: {
317
+ status,
318
+ currentTask: taskId ? { id: taskId, title: runDisplayTitle } : null,
319
+ processed: folded.closeoutPhases.length,
320
+ succeeded: folded.closeoutPhases.filter((phase) => phase.outcome === "completed").length,
321
+ failed: folded.closeoutPhases.filter((phase) => phase.outcome === "failed").length,
322
+ skipped: 0,
323
+ plannedOrder: taskId ? [{ id: taskId, title: runDisplayTitle, status }] : [],
324
+ idleReason: operatorActive ? null : status,
325
+ stopActionId: operatorActive ? RIG_RUN_STOP_PANEL_ACTION : null,
326
+ closures: []
327
+ }
328
+ };
329
+ const serialized = JSON.stringify(frameBody);
330
+ if (serialized === lastRigPanelsSnapshotJson)
331
+ return;
332
+ lastRigPanelsSnapshotJson = serialized;
333
+ appendCustomMessageEntry(RIG_PANELS_CUSTOM_MESSAGE_TYPE, "", false, { ...frameBody, updatedAt: new Date().toISOString() }, "agent");
334
+ };
254
335
  const pushWorkerProjection = (links = runRegistryLinks) => {
255
336
  if (!workerProjectionConnection)
256
337
  return;
@@ -258,6 +339,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
258
339
  };
259
340
  const publishRunProjection = async (status) => {
260
341
  const projection = buildCurrentRegistryProjection();
342
+ publishRigPanelsSnapshot();
261
343
  if (workerProjectionConnection)
262
344
  workerProjectionConnection.push(projection);
263
345
  if (runRegistry && runRegistryRoomId) {
@@ -360,13 +442,23 @@ async function maybeStartRunProcessAutohost(api, ctx) {
360
442
  };
361
443
  process.once("uncaughtException", publishFatalTerminal);
362
444
  process.once("unhandledRejection", publishFatalTerminal);
445
+ const handlePanelAction = async (input) => {
446
+ if (input.actionId !== RIG_RUN_STOP_PANEL_ACTION && input.actionId !== "stop-supervisor") {
447
+ throw new Error(`Unsupported Rig panel action: ${input.actionId}`);
448
+ }
449
+ pendingStopReason = `operator ${input.from.name} requested stop`;
450
+ journal?.appendTimeline({ type: "interrupted", stage: "panel-action", status: "running", detail: pendingStopReason });
451
+ ctx.abort();
452
+ await publishRunProjection("running");
453
+ };
363
454
  const startRunCollabHost = async () => {
364
455
  try {
365
456
  const projection = await startHost.call(collab, {
366
457
  title: runDisplayTitle,
367
458
  ...identity?.owner ? { owner: identity.owner } : {},
368
459
  ...identity?.selectedRepo ? { selectedRepo: identity.selectedRepo } : {},
369
- relayUrl: rigRelayUrl()
460
+ relayUrl: rigRelayUrl(),
461
+ onPanelAction: handlePanelAction
370
462
  });
371
463
  runRegistryLinks = { joinLink: projection.joinLink, webLink: projection.webLink, relayUrl: projection.relayUrl ?? rigRelayUrl() };
372
464
  const timeline = {
@@ -379,14 +471,15 @@ async function maybeStartRunProcessAutohost(api, ctx) {
379
471
  journal?.appendTimeline(timeline);
380
472
  console.log(`[rig-run] collab-host-started joinLink=${projection.joinLink || "(empty)"} relayUrl=${projection.relayUrl || "(empty)"}`);
381
473
  ctx.ui.notify("Rig run collab host started.", "info");
382
- if (runRegistry && identity?.owner) {
474
+ publishRigPanelsSnapshot();
475
+ if (runRegistry) {
383
476
  try {
384
477
  runRegistryRoomId = projection.sessionId;
385
478
  const initialProjection = buildCurrentRegistryProjection();
386
479
  await runRegistry.registerRoom({
387
480
  roomId: projection.sessionId,
388
- owner: identity.owner,
389
- repo: identity.selectedRepo ?? "",
481
+ owner: runRegistryOwner,
482
+ repo: runRegistryRepo,
390
483
  title: runDisplayTitle,
391
484
  status: "running",
392
485
  joinLink: projection.joinLink ?? "",
@@ -414,9 +507,6 @@ async function maybeStartRunProcessAutohost(api, ctx) {
414
507
  console.error(`[rig-run] registry-register-failed ${error instanceof Error ? error.message : String(error)}`);
415
508
  ctx.ui.notify("Rig run could not register to the discovery registry; it may not appear in Runs.", "warning");
416
509
  }
417
- } else {
418
- console.error(`[rig-run] registry-skip namespace=${runRegistryNamespace ? "set" : "MISSING"}`);
419
- ctx.ui.notify("Rig run NOT registered (registry namespace missing) \u2014 it won't appear in Runs.", "warning");
420
510
  }
421
511
  } catch (error) {
422
512
  console.error(`[rig-run] collab-host-start-failed ${error instanceof Error ? error.message : String(error)}`);
@@ -463,6 +553,26 @@ async function maybeStartRunProcessAutohost(api, ctx) {
463
553
  closeoutStarted = true;
464
554
  journal?.appendTimeline({ type: "interrupted", stage: "stopped", status: "stopped", detail: reason });
465
555
  journal?.appendStatus("stopped", { actor: OPERATOR_ACTOR, reason, force: true });
556
+ if (taskIdAtStart) {
557
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "running", detail: "reflecting operator stop to task source" });
558
+ try {
559
+ await reflectStoppedRunTaskSource({
560
+ projectRoot,
561
+ runId,
562
+ taskId: taskIdAtStart,
563
+ sourceTask: runProjection.record.sourceTask,
564
+ worktreePath: process.cwd(),
565
+ logRoot: runProjection.record.logRoot ?? null,
566
+ sessionPath: runProjection.record.sessionPath ?? null,
567
+ reason
568
+ });
569
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "completed", detail: "reflected operator stop" });
570
+ } catch (error) {
571
+ const detail = error instanceof Error ? error.message : String(error);
572
+ journal?.appendTimeline({ type: "stage", stage: "Task-source", status: "failed", detail });
573
+ console.error(`[rig-run] stopped-reflection-failed ${detail}`);
574
+ }
575
+ }
466
576
  await publishRunProjection("stopped");
467
577
  stopRunStallMonitor();
468
578
  stopRunRegistry({ removeRoom: false });
@@ -506,7 +616,7 @@ async function maybeStartRunProcessAutohost(api, ctx) {
506
616
  const { command, gitCommand } = createEnvCloseoutRunners(process.env);
507
617
  let closeoutStatusAdvanced = false;
508
618
  try {
509
- await runInProcessCloseout({
619
+ await runStagedCloseout({
510
620
  projectRoot,
511
621
  runId,
512
622
  taskId,
@@ -611,6 +721,7 @@ export {
611
721
  timestampMs,
612
722
  startRunProcessStallMonitor,
613
723
  registryRunProjection,
724
+ reflectStoppedRunTaskSource,
614
725
  maybeStartSpikeAutohost,
615
726
  maybeStartRunProcessAutohost,
616
727
  dispatchRunNotifications,
@@ -1,6 +1,8 @@
1
1
  import type { ExtensionContext } from "@oh-my-pi/pi-coding-agent";
2
2
  import type { ApprovalDecision, RunActor, RunCloseoutPhase, RunCloseoutPhaseOutcome, RunStatus } from "@rig/contracts";
3
+ import { type JournalSessionProvider } from "@rig/kernel/journal-session-provider";
3
4
  export type RunJournal = {
5
+ readonly kernel: JournalSessionProvider;
4
6
  appendStatus(to: RunStatus, opts?: {
5
7
  reason?: string | null;
6
8
  actor?: RunActor;
@@ -1,9 +1,26 @@
1
1
  // @bun
2
2
  // packages/run-worker/src/journal.ts
3
+ import { createJournalSessionProvider } from "@rig/kernel/journal-session-provider";
3
4
  import { RunSessionJournal } from "@rig/runtime/control-plane/run-session-writer";
4
5
  async function createRunJournal(sessionManager, runId) {
5
6
  try {
6
- return new RunSessionJournal(sessionManager, runId);
7
+ const journal = new RunSessionJournal(sessionManager, runId);
8
+ const kernel = createJournalSessionProvider({
9
+ runId,
10
+ store: {
11
+ appendCustomEntry: (customType, data) => sessionManager.appendCustomEntry(customType, data),
12
+ getEntries: () => sessionManager.getEntries?.() ?? sessionManager.getBranch?.() ?? []
13
+ }
14
+ });
15
+ return {
16
+ kernel,
17
+ appendStatus: journal.appendStatus.bind(journal),
18
+ appendTimeline: journal.appendTimeline.bind(journal),
19
+ appendCloseoutPhase: journal.appendCloseoutPhase.bind(journal),
20
+ appendApprovalResolved: journal.appendApprovalResolved.bind(journal),
21
+ appendInputResolved: journal.appendInputResolved.bind(journal),
22
+ appendStall: journal.appendStall.bind(journal)
23
+ };
7
24
  } catch (error) {
8
25
  console.warn(`[rig-run] RunSessionJournal unavailable; run-state arming deferred: ${error instanceof Error ? error.message : String(error)}`);
9
26
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/run-worker",
3
- "version": "0.0.6-alpha.132",
3
+ "version": "0.0.6-alpha.133",
4
4
  "type": "module",
5
5
  "description": "Rig package",
6
6
  "license": "UNLICENSED",
@@ -26,9 +26,11 @@
26
26
  ]
27
27
  },
28
28
  "dependencies": {
29
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.132",
30
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.132",
31
- "@rig/relay-registry": "npm:@h-rig/relay-registry@0.0.6-alpha.132",
29
+ "@rig/bundle-default-lifecycle": "npm:@h-rig/bundle-default-lifecycle@0.0.6-alpha.133",
30
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.133",
31
+ "@rig/kernel": "npm:@h-rig/kernel@0.0.6-alpha.133",
32
+ "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.133",
33
+ "@rig/relay-registry": "npm:@h-rig/relay-registry@0.0.6-alpha.133",
32
34
  "@oh-my-pi/pi-coding-agent": "16.0.4",
33
35
  "effect": "4.0.0-beta.78"
34
36
  }