@sift-wiki/conductor 0.2.0-beta.1 → 0.2.0-beta.2

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 (94) hide show
  1. package/dist/adapters/claudeAgent.js +1 -0
  2. package/dist/adapters/claudeAgent.js.map +1 -1
  3. package/dist/adapters/codexAgent.js +1 -0
  4. package/dist/adapters/codexAgent.js.map +1 -1
  5. package/dist/adapters/fakeAgent.js +1 -0
  6. package/dist/adapters/fakeAgent.js.map +1 -1
  7. package/dist/adapters/httpAgent.js +1 -0
  8. package/dist/adapters/httpAgent.js.map +1 -1
  9. package/dist/adapters/processAgent.js +4 -0
  10. package/dist/adapters/processAgent.js.map +1 -1
  11. package/dist/adapters/provider/runProvider.js +4 -0
  12. package/dist/adapters/provider/runProvider.js.map +1 -1
  13. package/dist/adapters/provider/store.js +3 -4
  14. package/dist/adapters/provider/store.js.map +1 -1
  15. package/dist/adapters/types.d.ts +9 -0
  16. package/dist/cli.d.ts +6 -0
  17. package/dist/cli.js +16 -4
  18. package/dist/cli.js.map +1 -1
  19. package/dist/conductorClient.d.ts +56 -19
  20. package/dist/conductorClient.js +91 -40
  21. package/dist/conductorClient.js.map +1 -1
  22. package/dist/config.js +4 -5
  23. package/dist/config.js.map +1 -1
  24. package/dist/daemon.d.ts +19 -6
  25. package/dist/daemon.js +160 -122
  26. package/dist/daemon.js.map +1 -1
  27. package/dist/desktop/app/controller.d.ts +1 -1
  28. package/dist/desktop/app/runtimeController.d.ts +7 -0
  29. package/dist/desktop/app/runtimeController.js +12 -1
  30. package/dist/desktop/app/runtimeController.js.map +1 -1
  31. package/dist/localApi/contracts.d.ts +15 -4
  32. package/dist/localApi/contracts.js +19 -1
  33. package/dist/localApi/contracts.js.map +1 -1
  34. package/dist/localApi/recovery.d.ts +66 -0
  35. package/dist/localApi/recovery.js +115 -0
  36. package/dist/localApi/recovery.js.map +1 -0
  37. package/dist/localApi/server.js +3 -1
  38. package/dist/localApi/server.js.map +1 -1
  39. package/dist/localApp/service.js +16 -4
  40. package/dist/localApp/service.js.map +1 -1
  41. package/dist/protocol/fenced.d.ts +135 -0
  42. package/dist/protocol/fenced.js +142 -0
  43. package/dist/protocol/fenced.js.map +1 -0
  44. package/dist/redaction.js +2 -0
  45. package/dist/redaction.js.map +1 -1
  46. package/dist/runtime/atomicFile.d.ts +6 -0
  47. package/dist/runtime/atomicFile.js +78 -0
  48. package/dist/runtime/atomicFile.js.map +1 -0
  49. package/dist/runtime/daemonCapabilities.d.ts +7 -0
  50. package/dist/runtime/daemonCapabilities.js +24 -0
  51. package/dist/runtime/daemonCapabilities.js.map +1 -0
  52. package/dist/runtime/eventOutbox.d.ts +100 -0
  53. package/dist/runtime/eventOutbox.js +206 -0
  54. package/dist/runtime/eventOutbox.js.map +1 -0
  55. package/dist/runtime/executionJournal.d.ts +102 -0
  56. package/dist/runtime/executionJournal.js +209 -0
  57. package/dist/runtime/executionJournal.js.map +1 -0
  58. package/dist/runtime/executionSafety.d.ts +76 -0
  59. package/dist/runtime/executionSafety.js +207 -0
  60. package/dist/runtime/executionSafety.js.map +1 -0
  61. package/dist/runtime/fencedExecutionState.d.ts +43 -0
  62. package/dist/runtime/fencedExecutionState.js +158 -0
  63. package/dist/runtime/fencedExecutionState.js.map +1 -0
  64. package/dist/runtime/leaseManager.d.ts +38 -0
  65. package/dist/runtime/leaseManager.js +102 -0
  66. package/dist/runtime/leaseManager.js.map +1 -0
  67. package/dist/runtime/localRunQueue.d.ts +1 -1
  68. package/dist/runtime/localRunQueue.js +8 -0
  69. package/dist/runtime/localRunQueue.js.map +1 -1
  70. package/dist/runtime/localSessionCache.d.ts +1 -1
  71. package/dist/runtime/localSessionCache.js.map +1 -1
  72. package/dist/runtime/process.d.ts +13 -1
  73. package/dist/runtime/process.js +39 -9
  74. package/dist/runtime/process.js.map +1 -1
  75. package/dist/runtime/recoveryCoordinator.d.ts +19 -0
  76. package/dist/runtime/recoveryCoordinator.js +183 -0
  77. package/dist/runtime/recoveryCoordinator.js.map +1 -0
  78. package/dist/runtime/runtimeLock.d.ts +33 -0
  79. package/dist/runtime/runtimeLock.js +140 -0
  80. package/dist/runtime/runtimeLock.js.map +1 -0
  81. package/dist/runtime/runtimeService.d.ts +6 -1
  82. package/dist/runtime/runtimeService.js +54 -20
  83. package/dist/runtime/runtimeService.js.map +1 -1
  84. package/dist/runtime/taskExecution.d.ts +2 -0
  85. package/dist/runtime/taskExecution.js +18 -12
  86. package/dist/runtime/taskExecution.js.map +1 -1
  87. package/dist/types.d.ts +28 -13
  88. package/dist/version.d.ts +1 -1
  89. package/dist/version.js +1 -1
  90. package/dist/workTypes.d.ts +5 -5
  91. package/dist-web/assets/index-CWAdDb9V.js +72 -0
  92. package/dist-web/index.html +2 -2
  93. package/package.json +1 -1
  94. package/dist-web/assets/index-D5X9InfE.js +0 -72
@@ -0,0 +1,102 @@
1
+ import { z } from "zod";
2
+ import { type AttemptAuthority } from "../protocol/fenced.js";
3
+ import { type AtomicWriteOptions } from "./atomicFile.js";
4
+ export declare const JOURNAL_SCHEMA_VERSION = 1;
5
+ declare const processIdentitySchema: z.ZodObject<{
6
+ pid: z.ZodNumber;
7
+ startMarker: z.ZodString;
8
+ }, z.core.$strict>;
9
+ declare const journalPhaseSchema: z.ZodEnum<{
10
+ superseded: "superseded";
11
+ claimed: "claimed";
12
+ starting: "starting";
13
+ running: "running";
14
+ authority_uncertain: "authority_uncertain";
15
+ recovering: "recovering";
16
+ interrupted: "interrupted";
17
+ overtime: "overtime";
18
+ terminal: "terminal";
19
+ }>;
20
+ export declare const executionJournalSchema: z.ZodObject<{
21
+ schemaVersion: z.ZodLiteral<1>;
22
+ attemptId: z.ZodString;
23
+ jobId: z.ZodString;
24
+ runId: z.ZodString;
25
+ taskRecordId: z.ZodOptional<z.ZodString>;
26
+ localKey: z.ZodString;
27
+ adapterType: z.ZodString;
28
+ authority: z.ZodObject<{
29
+ attemptId: z.ZodString;
30
+ leaseGeneration: z.ZodNumber;
31
+ leaseExpiresAt: z.ZodISODateTime;
32
+ mustStopAt: z.ZodISODateTime;
33
+ }, z.core.$strict>;
34
+ accessMode: z.ZodEnum<{
35
+ inspect: "inspect";
36
+ write: "write";
37
+ }>;
38
+ phase: z.ZodEnum<{
39
+ superseded: "superseded";
40
+ claimed: "claimed";
41
+ starting: "starting";
42
+ running: "running";
43
+ authority_uncertain: "authority_uncertain";
44
+ recovering: "recovering";
45
+ interrupted: "interrupted";
46
+ overtime: "overtime";
47
+ terminal: "terminal";
48
+ }>;
49
+ leaseHealth: z.ZodOptional<z.ZodEnum<{
50
+ healthy: "healthy";
51
+ retrying: "retrying";
52
+ "authority-uncertain": "authority-uncertain";
53
+ lost: "lost";
54
+ }>>;
55
+ provider: z.ZodObject<{
56
+ resumeSupported: z.ZodBoolean;
57
+ sessionId: z.ZodOptional<z.ZodString>;
58
+ processIdentity: z.ZodOptional<z.ZodObject<{
59
+ pid: z.ZodNumber;
60
+ startMarker: z.ZodString;
61
+ }, z.core.$strict>>;
62
+ }, z.core.$strict>;
63
+ lastAcknowledgedClientSequence: z.ZodNumber;
64
+ nextClientSequence: z.ZodNumber;
65
+ settlementIdempotencyKey: z.ZodOptional<z.ZodString>;
66
+ lastProgressAt: z.ZodOptional<z.ZodISODateTime>;
67
+ noProgressObservedAt: z.ZodOptional<z.ZodISODateTime>;
68
+ updatedAt: z.ZodISODateTime;
69
+ interruptionReason: z.ZodOptional<z.ZodString>;
70
+ terminalResult: z.ZodOptional<z.ZodObject<{
71
+ status: z.ZodEnum<{
72
+ cancelled: "cancelled";
73
+ completed: "completed";
74
+ failed: "failed";
75
+ overtime: "overtime";
76
+ }>;
77
+ summary: z.ZodString;
78
+ }, z.core.$strict>>;
79
+ }, z.core.$strict>;
80
+ export type SafeProcessIdentity = z.infer<typeof processIdentitySchema>;
81
+ export type ExecutionJournal = z.infer<typeof executionJournalSchema>;
82
+ export type ExecutionJournalPhase = z.infer<typeof journalPhaseSchema>;
83
+ export type JournalReadResult = {
84
+ journal: ExecutionJournal;
85
+ recoveredFromLastGood: boolean;
86
+ migrated: boolean;
87
+ };
88
+ export declare class ExecutionJournalStore {
89
+ readonly directory: string;
90
+ private readonly writeOptions;
91
+ constructor(directory?: string, writeOptions?: AtomicWriteOptions);
92
+ write(journal: ExecutionJournal): Promise<void>;
93
+ read(attemptId: string): Promise<JournalReadResult | undefined>;
94
+ listUnfinished(): Promise<JournalReadResult[]>;
95
+ list(): Promise<JournalReadResult[]>;
96
+ delete(attemptId: string): Promise<void>;
97
+ private pathFor;
98
+ private enforceRetention;
99
+ }
100
+ export declare function defaultExecutionJournalDirectory(env?: NodeJS.ProcessEnv): string;
101
+ export declare function authorityFromJournal(journal: ExecutionJournal): AttemptAuthority;
102
+ export {};
@@ -0,0 +1,209 @@
1
+ import { readFile, readdir, rename, rm } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { z } from "zod";
4
+ import { defaultConfigPath } from "../config.js";
5
+ import { attemptAuthoritySchema } from "../protocol/fenced.js";
6
+ import { redactSecrets } from "../redaction.js";
7
+ import { atomicWriteOwnerOnly, isNodeError } from "./atomicFile.js";
8
+ export const JOURNAL_SCHEMA_VERSION = 1;
9
+ const MAX_JOURNAL_BYTES = 64 * 1024;
10
+ const MAX_JOURNALS = 100;
11
+ const processIdentitySchema = z.object({
12
+ pid: z.number().int().positive(),
13
+ startMarker: z.string().min(1).max(500),
14
+ }).strict();
15
+ const journalPhaseSchema = z.enum([
16
+ "claimed",
17
+ "starting",
18
+ "running",
19
+ "authority_uncertain",
20
+ "recovering",
21
+ "interrupted",
22
+ "overtime",
23
+ "superseded",
24
+ "terminal",
25
+ ]);
26
+ const terminalResultSchema = z.object({
27
+ status: z.enum(["completed", "failed", "cancelled", "overtime"]),
28
+ summary: z.string().min(1).max(4_000),
29
+ }).strict();
30
+ export const executionJournalSchema = z.object({
31
+ schemaVersion: z.literal(JOURNAL_SCHEMA_VERSION),
32
+ attemptId: z.string().min(1),
33
+ jobId: z.string().min(1),
34
+ runId: z.string().min(1),
35
+ taskRecordId: z.string().min(1).optional(),
36
+ localKey: z.string().min(1),
37
+ adapterType: z.string().min(1),
38
+ authority: attemptAuthoritySchema,
39
+ accessMode: z.enum(["inspect", "write"]),
40
+ phase: journalPhaseSchema,
41
+ leaseHealth: z.enum(["healthy", "retrying", "authority-uncertain", "lost"]).optional(),
42
+ provider: z.object({
43
+ resumeSupported: z.boolean(),
44
+ sessionId: z.string().min(1).max(500).optional(),
45
+ processIdentity: processIdentitySchema.optional(),
46
+ }).strict(),
47
+ lastAcknowledgedClientSequence: z.number().int().nonnegative(),
48
+ nextClientSequence: z.number().int().positive(),
49
+ settlementIdempotencyKey: z.string().min(1).max(200).optional(),
50
+ lastProgressAt: z.iso.datetime().optional(),
51
+ noProgressObservedAt: z.iso.datetime().optional(),
52
+ updatedAt: z.iso.datetime(),
53
+ interruptionReason: z.string().min(1).max(1_000).optional(),
54
+ terminalResult: terminalResultSchema.optional(),
55
+ }).strict();
56
+ const legacyJournalSchema = executionJournalSchema.omit({ schemaVersion: true }).extend({
57
+ schemaVersion: z.literal(0),
58
+ }).strict();
59
+ export class ExecutionJournalStore {
60
+ directory;
61
+ writeOptions;
62
+ constructor(directory = defaultExecutionJournalDirectory(), writeOptions = {}) {
63
+ this.directory = directory;
64
+ this.writeOptions = writeOptions;
65
+ }
66
+ async write(journal) {
67
+ const parsed = executionJournalSchema.parse(sanitizeJournal(journal));
68
+ const contents = serializeBounded(parsed, MAX_JOURNAL_BYTES, "Execution journal");
69
+ await this.enforceRetention(parsed.attemptId);
70
+ await atomicWriteOwnerOnly(this.pathFor(parsed.attemptId), contents, {
71
+ ...this.writeOptions,
72
+ backup: true,
73
+ });
74
+ }
75
+ async read(attemptId) {
76
+ const filePath = this.pathFor(attemptId);
77
+ const primary = await readOptional(filePath);
78
+ if (primary === undefined)
79
+ return undefined;
80
+ const parsed = parseJournal(primary);
81
+ if (parsed !== undefined) {
82
+ if (parsed.migrated)
83
+ await this.write(parsed.journal);
84
+ return { ...parsed, recoveredFromLastGood: false };
85
+ }
86
+ const backup = await readOptional(`${filePath}.last-good`);
87
+ const recovered = backup === undefined ? undefined : parseJournal(backup);
88
+ if (recovered === undefined) {
89
+ await quarantine(filePath);
90
+ throw new Error("Execution recovery state is corrupt and has no valid last-good snapshot.");
91
+ }
92
+ await this.write(recovered.journal);
93
+ return { ...recovered, recoveredFromLastGood: true };
94
+ }
95
+ async listUnfinished() {
96
+ return (await this.list()).filter((result) => activeRecoveryPhase(result.journal.phase));
97
+ }
98
+ async list() {
99
+ let names;
100
+ try {
101
+ names = await readdir(this.directory);
102
+ }
103
+ catch (error) {
104
+ if (isNodeError(error) && error.code === "ENOENT")
105
+ return [];
106
+ throw error;
107
+ }
108
+ const results = [];
109
+ for (const name of names.filter((candidate) => candidate.endsWith(".json")).sort()) {
110
+ const attemptId = decodeURIComponent(name.slice(0, -5));
111
+ const result = await this.read(attemptId);
112
+ if (result !== undefined)
113
+ results.push(result);
114
+ }
115
+ return results;
116
+ }
117
+ async delete(attemptId) {
118
+ await rm(this.pathFor(attemptId), { force: true });
119
+ await rm(`${this.pathFor(attemptId)}.last-good`, { force: true });
120
+ }
121
+ pathFor(attemptId) {
122
+ return path.join(this.directory, `${encodeURIComponent(attemptId)}.json`);
123
+ }
124
+ async enforceRetention(currentAttemptId) {
125
+ let names;
126
+ try {
127
+ names = await readdir(this.directory);
128
+ }
129
+ catch (error) {
130
+ if (isNodeError(error) && error.code === "ENOENT")
131
+ return;
132
+ throw error;
133
+ }
134
+ const journals = names.filter((name) => name.endsWith(".json"));
135
+ if (journals.length >= MAX_JOURNALS && !journals.includes(`${encodeURIComponent(currentAttemptId)}.json`)) {
136
+ throw new Error(`Execution journal retention limit of ${String(MAX_JOURNALS)} was reached.`);
137
+ }
138
+ }
139
+ }
140
+ export function defaultExecutionJournalDirectory(env = process.env) {
141
+ return path.join(path.dirname(defaultConfigPath(env)), "runtime", "executions");
142
+ }
143
+ function parseJournal(contents) {
144
+ let raw;
145
+ try {
146
+ raw = JSON.parse(contents);
147
+ }
148
+ catch {
149
+ return undefined;
150
+ }
151
+ const current = executionJournalSchema.safeParse(raw);
152
+ if (current.success)
153
+ return { journal: current.data, migrated: false };
154
+ const legacy = legacyJournalSchema.safeParse(raw);
155
+ if (!legacy.success)
156
+ return undefined;
157
+ return {
158
+ journal: { ...legacy.data, schemaVersion: JOURNAL_SCHEMA_VERSION },
159
+ migrated: true,
160
+ };
161
+ }
162
+ function sanitizeJournal(journal) {
163
+ return {
164
+ ...journal,
165
+ ...(journal.interruptionReason === undefined
166
+ ? {}
167
+ : { interruptionReason: redactSecrets(journal.interruptionReason) }),
168
+ ...(journal.terminalResult === undefined
169
+ ? {}
170
+ : { terminalResult: { ...journal.terminalResult, summary: redactSecrets(journal.terminalResult.summary) } }),
171
+ };
172
+ }
173
+ function serializeBounded(value, maxBytes, label) {
174
+ const contents = `${JSON.stringify(value, null, 2)}\n`;
175
+ if (Buffer.byteLength(contents, "utf8") > maxBytes) {
176
+ throw new Error(`${label} exceeds its ${String(maxBytes)} byte limit.`);
177
+ }
178
+ return contents;
179
+ }
180
+ async function readOptional(filePath) {
181
+ try {
182
+ return await readFile(filePath, "utf8");
183
+ }
184
+ catch (error) {
185
+ if (isNodeError(error) && error.code === "ENOENT")
186
+ return undefined;
187
+ throw error;
188
+ }
189
+ }
190
+ async function quarantine(filePath) {
191
+ try {
192
+ await rename(filePath, `${filePath}.corrupt-${String(Date.now())}`);
193
+ }
194
+ catch (error) {
195
+ if (!isNodeError(error) || error.code !== "ENOENT")
196
+ throw error;
197
+ }
198
+ }
199
+ export function authorityFromJournal(journal) {
200
+ return journal.authority;
201
+ }
202
+ function activeRecoveryPhase(phase) {
203
+ return phase === "claimed"
204
+ || phase === "starting"
205
+ || phase === "running"
206
+ || phase === "authority_uncertain"
207
+ || phase === "recovering";
208
+ }
209
+ //# sourceMappingURL=executionJournal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executionJournal.js","sourceRoot":"","sources":["../../src/runtime/executionJournal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { LocalAgentAdapter, Sleep } from "../adapters/types.js";
2
+ import type { DaemonClient, DaemonTimer } from "../daemon.js";
3
+ import type { ClaimedJob, JsonObject, LeaseRefresh, RunEventInput } from "../types.js";
4
+ import type { LocalLogSpool } from "./localLogSpool.js";
5
+ import type { RunEventRetryBuffer } from "./runEventRetryBuffer.js";
6
+ import type { DurableEventOutbox } from "./eventOutbox.js";
7
+ import type { ExecutionJournalStore } from "./executionJournal.js";
8
+ import { FencedExecutionState } from "./fencedExecutionState.js";
9
+ import type { LocalRuntimeSessionCache, LocalRuntimeSessionStatus } from "./localSessionCache.js";
10
+ export type ActiveLeaseState = {
11
+ done: boolean;
12
+ cancelRequested: boolean;
13
+ timedOut: boolean;
14
+ hardStop: boolean;
15
+ authorityUncertain: boolean;
16
+ };
17
+ export type NoProgressObserver = {
18
+ recordProgress(): void;
19
+ stop(): Promise<void>;
20
+ };
21
+ export declare const defaultDaemonTimer: DaemonTimer;
22
+ export declare function createFencedState(input: {
23
+ job: ClaimedJob;
24
+ adapter: LocalAgentAdapter | undefined;
25
+ journalStore?: ExecutionJournalStore | undefined;
26
+ eventOutbox?: DurableEventOutbox | undefined;
27
+ now: () => Date;
28
+ }): Promise<FencedExecutionState | undefined>;
29
+ export declare function emitRunEvent(input: {
30
+ client: DaemonClient;
31
+ credential: string;
32
+ job: ClaimedJob;
33
+ event: RunEventInput;
34
+ buffer?: RunEventRetryBuffer | undefined;
35
+ logSpool?: LocalLogSpool | undefined;
36
+ fencedState?: FencedExecutionState | undefined;
37
+ progressObserver?: NoProgressObserver | undefined;
38
+ }): Promise<void>;
39
+ export declare function observeRunProgress(input: {
40
+ job: ClaimedJob;
41
+ timer: DaemonTimer;
42
+ fencedState?: FencedExecutionState | undefined;
43
+ logSpool?: LocalLogSpool | undefined;
44
+ now: () => Date;
45
+ }): NoProgressObserver;
46
+ export declare function rejectExhaustedClaim(job: ClaimedJob, fencedState: FencedExecutionState | undefined): Promise<boolean>;
47
+ export declare function refreshLeaseUntilDone(input: {
48
+ client: DaemonClient;
49
+ credential: string;
50
+ jobId: string;
51
+ sleep: Sleep;
52
+ sleepSignal: AbortSignal;
53
+ adapterAbort: AbortController;
54
+ state: ActiveLeaseState;
55
+ leaseRefreshMs: number;
56
+ fencedState?: FencedExecutionState | undefined;
57
+ monotonicNowMs?: (() => number) | undefined;
58
+ random?: (() => number) | undefined;
59
+ nowMs?: (() => number) | undefined;
60
+ continueInspectOnly?: boolean | undefined;
61
+ }): Promise<void>;
62
+ export declare function renewFencedLease(input: {
63
+ client: DaemonClient;
64
+ credential: string;
65
+ jobId: string;
66
+ fencedState: FencedExecutionState;
67
+ sleep: Sleep;
68
+ signal?: AbortSignal | undefined;
69
+ nowMs?: (() => number) | undefined;
70
+ monotonicNowMs?: (() => number) | undefined;
71
+ random?: (() => number) | undefined;
72
+ }): Promise<LeaseRefresh>;
73
+ export declare function scheduleRunTimeout(job: ClaimedJob, timer: DaemonTimer, adapterAbort: AbortController, state: {
74
+ timedOut: boolean;
75
+ }, now: () => Date): unknown;
76
+ export declare function updateLocalSession(cache: LocalRuntimeSessionCache | undefined, job: ClaimedJob, status: LocalRuntimeSessionStatus, errorSummary?: JsonObject): void;
@@ -0,0 +1,207 @@
1
+ import { FencedExecutionState } from "./fencedExecutionState.js";
2
+ import { LeaseAuthorityError, LeaseManager } from "./leaseManager.js";
3
+ import { isAbortError } from "./sleep.js";
4
+ const DEFAULT_NO_PROGRESS_MS = 5 * 60_000;
5
+ export const defaultDaemonTimer = {
6
+ schedule: (callback, ms) => setTimeout(callback, ms),
7
+ cancel: (handle) => clearTimeout(handle),
8
+ };
9
+ export async function createFencedState(input) {
10
+ if (input.job.authority === undefined)
11
+ return undefined;
12
+ if (input.journalStore === undefined || input.eventOutbox === undefined) {
13
+ throw new Error("Fenced claims require durable journal and outbox persistence before execution.");
14
+ }
15
+ return FencedExecutionState.create({
16
+ job: { ...input.job, authority: input.job.authority },
17
+ adapter: input.adapter,
18
+ store: input.journalStore,
19
+ outbox: input.eventOutbox,
20
+ now: input.now,
21
+ });
22
+ }
23
+ export async function emitRunEvent(input) {
24
+ if (input.event.eventType === "progress")
25
+ input.progressObserver?.recordProgress();
26
+ const summary = input.event.payload?.["summary"];
27
+ if (typeof summary === "string") {
28
+ input.logSpool?.append({
29
+ runId: input.job.runId,
30
+ message: summary,
31
+ stream: input.event.eventType === "log" ? "stdout" : "system",
32
+ occurredAt: input.event.occurredAt,
33
+ });
34
+ }
35
+ if (input.fencedState !== undefined) {
36
+ await input.fencedState.emit((event) => input.client.appendRunEvent(input.credential, input.job.runId, event), input.event);
37
+ return;
38
+ }
39
+ try {
40
+ await input.client.appendRunEvent(input.credential, input.job.runId, input.event);
41
+ }
42
+ catch (error) {
43
+ if (input.buffer === undefined)
44
+ throw error;
45
+ input.buffer.enqueue({ runId: input.job.runId, event: input.event, error });
46
+ }
47
+ }
48
+ export function observeRunProgress(input) {
49
+ const thresholdMs = noProgressThresholdMs(input.job);
50
+ let stopped = false;
51
+ let generation = 0;
52
+ let handle;
53
+ let pending = Promise.resolve();
54
+ const schedule = () => {
55
+ const scheduledGeneration = ++generation;
56
+ handle = input.timer.schedule(() => {
57
+ if (stopped || scheduledGeneration !== generation)
58
+ return;
59
+ handle = undefined;
60
+ const observedAt = input.now().toISOString();
61
+ pending = pending.then(async () => {
62
+ await input.fencedState?.recordNoProgress(observedAt);
63
+ input.logSpool?.append({
64
+ runId: input.job.runId,
65
+ occurredAt: observedAt,
66
+ stream: "system",
67
+ message: "No provider progress was observed during the configured interval.",
68
+ });
69
+ });
70
+ }, thresholdMs);
71
+ };
72
+ schedule();
73
+ return {
74
+ recordProgress() {
75
+ if (stopped)
76
+ return;
77
+ generation += 1;
78
+ if (handle !== undefined)
79
+ input.timer.cancel(handle);
80
+ schedule();
81
+ },
82
+ async stop() {
83
+ stopped = true;
84
+ generation += 1;
85
+ if (handle !== undefined)
86
+ input.timer.cancel(handle);
87
+ await pending;
88
+ },
89
+ };
90
+ }
91
+ export async function rejectExhaustedClaim(job, fencedState) {
92
+ if (job.maxAttempts === undefined || job.attempts <= job.maxAttempts)
93
+ return false;
94
+ await fencedState?.updatePhase("interrupted", "Sift returned a claim after its maximum attempt count was exhausted.");
95
+ return true;
96
+ }
97
+ export async function refreshLeaseUntilDone(input) {
98
+ for (;;) {
99
+ if (leaseDone(input.state))
100
+ return;
101
+ try {
102
+ await input.sleep(input.leaseRefreshMs, input.sleepSignal);
103
+ }
104
+ catch (error) {
105
+ if (isAbortError(error))
106
+ return;
107
+ throw error;
108
+ }
109
+ if (leaseDone(input.state))
110
+ return;
111
+ let refresh;
112
+ try {
113
+ refresh = input.fencedState === undefined
114
+ ? await input.client.refreshLease(input.credential, input.jobId)
115
+ : await renewFencedLease({
116
+ client: input.client,
117
+ credential: input.credential,
118
+ jobId: input.jobId,
119
+ fencedState: input.fencedState,
120
+ sleep: input.sleep,
121
+ signal: input.sleepSignal,
122
+ nowMs: input.nowMs,
123
+ monotonicNowMs: input.monotonicNowMs,
124
+ random: input.random,
125
+ });
126
+ }
127
+ catch (error) {
128
+ if (error instanceof LeaseAuthorityError && input.fencedState !== undefined) {
129
+ input.state.authorityUncertain = true;
130
+ await input.fencedState.updatePhase("authority_uncertain", error.message);
131
+ if (input.continueInspectOnly !== true)
132
+ input.adapterAbort.abort();
133
+ return;
134
+ }
135
+ throw error;
136
+ }
137
+ if (refresh.cancelRequested) {
138
+ input.state.cancelRequested = true;
139
+ input.adapterAbort.abort();
140
+ return;
141
+ }
142
+ }
143
+ }
144
+ export async function renewFencedLease(input) {
145
+ const manager = new LeaseManager({
146
+ sleep: input.sleep,
147
+ nowMs: input.nowMs,
148
+ monotonicNowMs: input.monotonicNowMs,
149
+ random: input.random,
150
+ onHealth: (health) => input.fencedState.updateLeaseHealth(health),
151
+ });
152
+ const refresh = await manager.renew({
153
+ authority: input.fencedState.authority(),
154
+ signal: input.signal,
155
+ refresh: () => input.client.refreshLease(input.credential, input.jobId, input.fencedState.authority()),
156
+ });
157
+ if (refresh.authority === undefined) {
158
+ throw new LeaseAuthorityError("authority_uncertain", "Fenced renewal omitted authority.");
159
+ }
160
+ await input.fencedState.updateAuthority(refresh.authority);
161
+ return refresh;
162
+ }
163
+ export function scheduleRunTimeout(job, timer, adapterAbort, state, now) {
164
+ if (job.authority !== undefined) {
165
+ const delay = Date.parse(job.authority.mustStopAt) - now().getTime();
166
+ return timer.schedule(() => {
167
+ state.timedOut = true;
168
+ adapterAbort.abort();
169
+ }, Math.max(0, delay));
170
+ }
171
+ const maxRunMinutes = job.wakeEnvelope?.limits.maxRunMinutes;
172
+ if (maxRunMinutes === undefined)
173
+ return undefined;
174
+ return timer.schedule(() => {
175
+ state.timedOut = true;
176
+ adapterAbort.abort();
177
+ }, maxRunMinutes * 60_000);
178
+ }
179
+ export function updateLocalSession(cache, job, status, errorSummary) {
180
+ if (cache === undefined)
181
+ return;
182
+ const previous = cache.read(job.runId);
183
+ const now = new Date().toISOString();
184
+ cache.upsert({
185
+ runId: job.runId,
186
+ adapterType: job.adapterType,
187
+ localKey: job.localKey,
188
+ status,
189
+ localOnly: true,
190
+ updatedAt: now,
191
+ startedAt: previous?.startedAt ?? now,
192
+ ...(status === "running" || status === "starting" ? {} : { stoppedAt: now }),
193
+ taskKey: job.taskRecordId ?? job.wakeEnvelope?.task.id,
194
+ cancelRequested: status === "cancelled",
195
+ ...(errorSummary === undefined ? {} : { errorSummary }),
196
+ });
197
+ }
198
+ function leaseDone(state) {
199
+ return state.done;
200
+ }
201
+ function noProgressThresholdMs(job) {
202
+ const minutes = job.limits["noProgressMinutes"];
203
+ return typeof minutes === "number" && Number.isFinite(minutes) && minutes > 0
204
+ ? minutes * 60_000
205
+ : DEFAULT_NO_PROGRESS_MS;
206
+ }
207
+ //# sourceMappingURL=executionSafety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executionSafety.js","sourceRoot":"","sources":["../../src/runtime/executionSafety.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { LocalAgentAdapter } from "../adapters/types.js";
2
+ import type { AttemptMutationOptions } from "../protocol/fenced.js";
3
+ import type { ClaimedJob, JsonObject, RunEventAppendResult, RunEventDeliveryInput, RunEventInput } from "../types.js";
4
+ import type { DurableEventOutbox } from "./eventOutbox.js";
5
+ import { type ExecutionJournal, type ExecutionJournalPhase, type ExecutionJournalStore } from "./executionJournal.js";
6
+ import type { LeaseHealth } from "./leaseManager.js";
7
+ export declare class FencedExecutionState {
8
+ private journal;
9
+ private readonly store;
10
+ private readonly outbox;
11
+ private readonly now;
12
+ private eventChain;
13
+ private updateChain;
14
+ private constructor();
15
+ static create(input: {
16
+ job: ClaimedJob & {
17
+ authority: NonNullable<ClaimedJob["authority"]>;
18
+ };
19
+ adapter: LocalAgentAdapter | undefined;
20
+ store: ExecutionJournalStore;
21
+ outbox: DurableEventOutbox;
22
+ now?: (() => Date) | undefined;
23
+ createId?: (() => string) | undefined;
24
+ }): Promise<FencedExecutionState>;
25
+ authority(): {
26
+ attemptId: string;
27
+ leaseGeneration: number;
28
+ leaseExpiresAt: string;
29
+ mustStopAt: string;
30
+ };
31
+ accessMode(): "inspect" | "write";
32
+ settlementOptions(): AttemptMutationOptions;
33
+ updateAuthority(authority: ExecutionJournal["authority"]): Promise<void>;
34
+ updateLeaseHealth(leaseHealth: LeaseHealth): Promise<void>;
35
+ updatePhase(phase: ExecutionJournalPhase, interruptionReason?: string): Promise<void>;
36
+ recordProcessIdentity(processIdentity: NonNullable<ExecutionJournal["provider"]["processIdentity"]>): Promise<void>;
37
+ recordProviderSession(sessionId: string): Promise<void>;
38
+ recordNoProgress(observedAt: string): Promise<void>;
39
+ recordTerminal(status: NonNullable<ExecutionJournal["terminalResult"]>["status"], summary: JsonObject, phase?: ExecutionJournalPhase): Promise<void>;
40
+ emit(deliver: (event: RunEventDeliveryInput) => Promise<RunEventAppendResult>, event: RunEventInput): Promise<void>;
41
+ private emitInSequence;
42
+ private update;
43
+ }