stitchkit 0.94.1 → 0.95.1

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 (35) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/agent-runtime/provider-origin.d.ts +7 -0
  3. package/dist/agent-runtime/provider-origin.d.ts.map +1 -1
  4. package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
  5. package/dist/application/directory-inbox-contract.d.ts +129 -0
  6. package/dist/application/directory-inbox-contract.d.ts.map +1 -0
  7. package/dist/application/directory-inbox.d.ts +3 -0
  8. package/dist/application/directory-inbox.d.ts.map +1 -0
  9. package/dist/application/process-lifecycle-transitions.d.ts +175 -0
  10. package/dist/application/process-lifecycle-transitions.d.ts.map +1 -0
  11. package/dist/application/process-lifecycle.d.ts +3 -131
  12. package/dist/application/process-lifecycle.d.ts.map +1 -1
  13. package/dist/entrypoints/agent-runtime/harness.js +1 -1
  14. package/dist/entrypoints/agent-runtime.js +1 -1
  15. package/dist/entrypoints/application/directory-inbox.d.ts +11 -0
  16. package/dist/entrypoints/application/directory-inbox.d.ts.map +1 -0
  17. package/dist/entrypoints/application/directory-inbox.js +221 -0
  18. package/dist/entrypoints/application.d.ts +3 -1
  19. package/dist/entrypoints/application.d.ts.map +1 -1
  20. package/dist/entrypoints/application.js +151 -56
  21. package/dist/entrypoints/server.js +6 -219
  22. package/dist/index-5jrd0yng.js +114 -0
  23. package/dist/{index-7f68ghdn.js → index-8zja4pkf.js} +23 -1
  24. package/dist/index-tm88avnj.js +221 -0
  25. package/llms/application-directory-inbox.txt +9 -0
  26. package/llms/application.2.txt +7 -5
  27. package/llms/application.txt +88 -24
  28. package/llms/stitchkit.txt +4 -3
  29. package/llms/{upgrading-0.37.0-0.50.0.txt → upgrading-0.37.0-0.53.0.txt} +25 -3
  30. package/llms/{upgrading-0.53.0-0.67.0.txt → upgrading-0.55.0-0.68.0.txt} +53 -25
  31. package/llms/{upgrading-0.68.0-0.94.0.txt → upgrading-0.69.0-0.95.0.txt} +45 -53
  32. package/llms/upgrading.txt +3 -3
  33. package/llms-full.txt +141 -32
  34. package/llms.txt +6 -5
  35. package/package.json +5 -1
@@ -0,0 +1,221 @@
1
+ import {
2
+ DirectoryInboxStateSchema,
3
+ claimEntry,
4
+ completeEntry,
5
+ emptyDirectoryInboxState,
6
+ forgetMissing,
7
+ releaseEntry,
8
+ withRejection
9
+ } from "../../index-5jrd0yng.js";
10
+ import {
11
+ defineManagedResource
12
+ } from "../../index-2k4yrqkc.js";
13
+ import {
14
+ createFileStateStore
15
+ } from "../../index-tm88avnj.js";
16
+ import {
17
+ backoffDelay
18
+ } from "../../index-ngfhvfpd.js";
19
+ import"../../index-hffjpmq9.js";
20
+
21
+ // src/application/directory-inbox.ts
22
+ import { mkdir, readdir, readFile, rename, stat, unlink } from "node:fs/promises";
23
+ import { join } from "node:path";
24
+ import { z } from "zod";
25
+ var REJECTED = "rejected";
26
+ var ENTRY_NAME = /^[^.].*\.json$/;
27
+ var RETRY_BACKOFF = { minDelayMs: 1000, maxDelayMs: 300000, jitter: 0 };
28
+ var absent = (error) => error instanceof Error && ("code" in error) && error.code === "ENOENT";
29
+ async function quietly(run) {
30
+ try {
31
+ await run();
32
+ } catch (error) {
33
+ if (!absent(error))
34
+ throw error;
35
+ }
36
+ }
37
+ function resolveLimits(config) {
38
+ const integer = z.number().int();
39
+ return {
40
+ pollIntervalMs: integer.min(10).parse(config.pollIntervalMs ?? 1000),
41
+ leaseMs: integer.min(100).parse(config.leaseMs ?? 300000),
42
+ maxAttempts: integer.min(1).max(1e4).parse(config.maxAttempts ?? 20),
43
+ maxEntryBytes: integer.min(1).parse(config.maxEntryBytes ?? 1024 * 1024),
44
+ retain: integer.min(1).max(1e5).parse(config.retain ?? 1000)
45
+ };
46
+ }
47
+ async function entryNames(directory) {
48
+ const entries = await readdir(directory, { withFileTypes: true });
49
+ return entries.filter((entry) => entry.isFile() && ENTRY_NAME.test(entry.name)).map((entry) => entry.name).sort();
50
+ }
51
+ async function readEntry(path, schema, maxEntryBytes) {
52
+ try {
53
+ const { size } = await stat(path);
54
+ if (size > maxEntryBytes) {
55
+ return { reason: "too-large", detail: `${size} bytes over the ${maxEntryBytes} limit` };
56
+ }
57
+ const text = await readFile(path, "utf8");
58
+ let json;
59
+ try {
60
+ json = JSON.parse(text);
61
+ } catch (error) {
62
+ return { reason: "invalid", detail: String(error).slice(0, 1000) };
63
+ }
64
+ const parsed = schema.safeParse(json);
65
+ return parsed.success ? { entry: parsed.data } : { reason: "invalid", detail: z.prettifyError(parsed.error).slice(0, 1000) };
66
+ } catch (error) {
67
+ if (absent(error))
68
+ return null;
69
+ throw error;
70
+ }
71
+ }
72
+ function createDirectoryInbox(config) {
73
+ const limits = resolveLimits(config);
74
+ const clock = config.clock ?? (() => new Date);
75
+ const store = config.store ?? createFileStateStore(join(config.directory, ".inbox-state.json"), {
76
+ schema: DirectoryInboxStateSchema
77
+ });
78
+ const parse = (state) => DirectoryInboxStateSchema.parse(state ?? emptyDirectoryInboxState());
79
+ const update = (transition) => store.update((current) => transition(parse(current)));
80
+ let running = false;
81
+ let admitting = false;
82
+ let timer;
83
+ let forced = new AbortController;
84
+ let tail = Promise.resolve();
85
+ const report = async (error) => {
86
+ try {
87
+ await config.onError?.(error);
88
+ } catch {}
89
+ };
90
+ const setAside = async (key, rejection) => {
91
+ await mkdir(join(config.directory, REJECTED), { recursive: true });
92
+ await quietly(() => rename(join(config.directory, key), join(config.directory, REJECTED, key)));
93
+ if (rejection)
94
+ await config.onRejected?.(rejection);
95
+ };
96
+ const reject = async (key, reason, detail) => {
97
+ const rejection = { key, reason, detail, rejectedAt: clock().toISOString() };
98
+ await update((state) => ({
99
+ state: withRejection(state, rejection, limits.retain),
100
+ result: undefined
101
+ }));
102
+ await setAside(key, rejection);
103
+ };
104
+ const deliver = async (claim) => {
105
+ const path = join(config.directory, claim.key);
106
+ const read = await readEntry(path, config.schema, limits.maxEntryBytes);
107
+ if (read === null)
108
+ return false;
109
+ if ("reason" in read) {
110
+ await reject(claim.key, read.reason, read.detail);
111
+ return false;
112
+ }
113
+ try {
114
+ await config.handle({
115
+ key: claim.key,
116
+ entry: read.entry,
117
+ attempt: claim.attempts,
118
+ signal: forced.signal
119
+ });
120
+ } catch (error) {
121
+ await report(error);
122
+ const retryAt = new Date(clock().getTime() + backoffDelay(RETRY_BACKOFF, claim.attempts));
123
+ await update((state) => ({
124
+ state: releaseEntry(state, claim, retryAt),
125
+ result: undefined
126
+ }));
127
+ return false;
128
+ }
129
+ await update((state) => ({
130
+ state: completeEntry(state, claim.key, clock(), limits.retain),
131
+ result: undefined
132
+ }));
133
+ await quietly(() => unlink(path));
134
+ return true;
135
+ };
136
+ const pass = async () => {
137
+ const names = await entryNames(config.directory);
138
+ await update((state) => ({
139
+ state: forgetMissing(state, new Set(names), clock()),
140
+ result: undefined
141
+ }));
142
+ let handled = 0;
143
+ for (const key of names) {
144
+ if (!admitting && running)
145
+ break;
146
+ const { step } = await update((state) => {
147
+ const next = claimEntry(state, { key, now: clock(), ...limits });
148
+ return { state: next.state, result: next };
149
+ });
150
+ if (step.kind === "remove")
151
+ await quietly(() => unlink(join(config.directory, key)));
152
+ else if (step.kind === "set-aside")
153
+ await setAside(key);
154
+ else if (step.kind === "reject")
155
+ await setAside(key, step.rejection);
156
+ else if (step.kind === "deliver" && await deliver(step.claim))
157
+ handled += 1;
158
+ }
159
+ return handled;
160
+ };
161
+ const flush = () => {
162
+ const result = tail.then(pass, pass);
163
+ tail = result.catch(() => {
164
+ return;
165
+ });
166
+ return result;
167
+ };
168
+ const poll = async () => {
169
+ try {
170
+ await flush();
171
+ } catch (error) {
172
+ await report(error);
173
+ }
174
+ if (admitting)
175
+ timer = setTimeout(() => void poll(), limits.pollIntervalMs);
176
+ };
177
+ const stopAdmitting = () => {
178
+ admitting = false;
179
+ if (timer)
180
+ clearTimeout(timer);
181
+ timer = undefined;
182
+ };
183
+ const inbox = {
184
+ flush,
185
+ async state() {
186
+ return parse(await store.read());
187
+ }
188
+ };
189
+ return defineManagedResource({
190
+ id: config.id,
191
+ ...config.dependsOn && { dependsOn: config.dependsOn },
192
+ async start() {
193
+ await mkdir(config.directory, { recursive: true });
194
+ forced = new AbortController;
195
+ return { value: inbox };
196
+ },
197
+ activate() {
198
+ running = true;
199
+ admitting = true;
200
+ poll();
201
+ },
202
+ stopAdmission() {
203
+ stopAdmitting();
204
+ },
205
+ async drain() {
206
+ await tail;
207
+ },
208
+ async close() {
209
+ stopAdmitting();
210
+ await tail;
211
+ },
212
+ async force() {
213
+ stopAdmitting();
214
+ forced.abort();
215
+ await tail;
216
+ }
217
+ });
218
+ }
219
+ export {
220
+ createDirectoryInbox
221
+ };
@@ -2,6 +2,7 @@ export { type ActivityId, ActivityIdSchema, type ActivityLiveState, ActivityLive
2
2
  export { type BoundedAdmission, type BoundedAdmissionClock, type BoundedAdmissionConfig, type BoundedAdmissionDrainOptions, type BoundedAdmissionDrainResult, type BoundedAdmissionForceResult, type BoundedAdmissionLeaseResult, type BoundedAdmissionPerKeyLimitResolver, type BoundedAdmissionPerKeyLimits, BoundedAdmissionPerKeyLimitsSchema, type BoundedAdmissionPolicy, BoundedAdmissionPolicySchema, BoundedAdmissionRefusalError, type BoundedAdmissionRefusalReason, BoundedAdmissionRefusalReasonSchema, type BoundedAdmissionRefusedResult, type BoundedAdmissionResult, type BoundedAdmissionSnapshot, BoundedAdmissionSnapshotSchema, type BoundedAdmissionState, BoundedAdmissionStateSchema, type BoundedOperationLease, type BoundedOperationRunContext, type BoundedOperationRunOptions, BoundedOperationWaitError, type BoundedRateBudget, BoundedRateBudgetSchema, createBoundedAdmission, } from '../application/admission.js';
3
3
  export { createDecisionPipeline, type DecisionPipeline, type DecisionPipelineConfig, type DecisionPolicy, DecisionPolicyError, type DecisionResult, type DecisionTraceEntry, DecisionUndecidedError, type PolicyDecision, PolicyDecisionSchema, } from '../application/decisions.js';
4
4
  export { type DiagnosticJournal, type DiagnosticJournalCloseResult, DiagnosticJournalCloseResultSchema, type DiagnosticJournalConfig, type DiagnosticJournalFailure, type DiagnosticJournalFailurePhase, DiagnosticJournalFailurePhaseSchema, type DiagnosticJournalFrame, DiagnosticJournalFrameSchema, type DiagnosticJournalLimits, DiagnosticJournalLimitsSchema, type DiagnosticJournalLockDiagnosis, type DiagnosticJournalLockPolicy, DiagnosticJournalLockPolicySchema, type DiagnosticJournalRefusalReason, DiagnosticJournalRefusalReasonSchema, type DiagnosticJournalState, DiagnosticJournalStateSchema, type DiagnosticJournalStatus, DiagnosticJournalStatusSchema, type DiagnosticJournalSubmitResult, DiagnosticJournalSubmitResultSchema, type DiagnosticJournalWaitOptions, type DiagnosticJournalWaitResult, DiagnosticJournalWaitResultSchema, readDiagnosticJournalLockDiagnosis, } from '../application/diagnostic-journal-contract.js';
5
+ export { type DirectoryInbox, type DirectoryInboxConfig, type DirectoryInboxDelivery, type DirectoryInboxRejection, type DirectoryInboxRejectionReason, DirectoryInboxRejectionReasonSchema, type DirectoryInboxResource, type DirectoryInboxState, DirectoryInboxStateSchema, } from '../application/directory-inbox-contract.js';
5
6
  export { type ApplicationEventSink, type ApplicationEventSinkConfig, type ApplicationLifecycleEvent, ApplicationLifecycleEventSchema, applicationLifecycleEvent, createApplicationEventSink, } from '../application/events.js';
6
7
  export { type ApplicationHealthHandlerOptions, ApplicationHealthHandlerOptionsSchema, type ApplicationOperationalHandlers, type ApplicationOperationalHandlersOptions, ApplicationOperationalHandlersOptionsSchema, createApplicationHealthHandler, createApplicationOperationalHandlers, } from '../application/health.js';
7
8
  export { createApplication } from '../application/kernel.js';
@@ -10,7 +11,8 @@ export { defineKeyspace, type KeyspaceBackend, type KeyspaceChange, type Keyspac
10
11
  export { type SqliteKeyspaceBackendConfig, sqliteKeyspaceBackend, } from '../application/keyspace-sqlite.js';
11
12
  export { type ApplicationSnapshotSink, type ApplicationSnapshotSinkConfig, type ApplicationSnapshotSinkError, type ApplicationSnapshotSinkStatus, ApplicationSnapshotSinkStatusSchema, createApplicationSnapshotSink, type RevisionedApplicationSnapshot, } from '../application/latest-sink.js';
12
13
  export { createNotificationOutbox, type DroppedNotification, type EnqueueNotification, type NotificationFailureClassification, type NotificationOutbox, type NotificationOutboxConfig, type NotificationOutboxItem, type NotificationOutboxReceipt, type NotificationOutboxResource, type NotificationOutboxResourceConfig, type NotificationOutboxState, type NotificationSend, notificationOutboxResource, notificationOutboxStateSchema, } from '../application/notification-outbox.js';
13
- export { createProcessLifecycleLedger, type LifecycleLedgerResource, type LifecycleLedgerResourceConfig, type LifecycleRun, LifecycleRunSchema, type LifecycleState, LifecycleStateSchema, type LifecycleTermination, LifecycleTerminationSchema, type LifecycleTransition, lifecycleLedgerResource, type PreviousExit, PreviousExitSchema, type ProcessLifecycleFact, type ProcessLifecycleLedger, type ProcessLifecycleLedgerConfig, type ReadyFact, type SameVersionOverlap, type ShutdownFact, type StartFact, type TransitionReadyInput, type TransitionShutdownInput, type TransitionStartInput, transitionProcessReady, transitionProcessShutdown, transitionProcessStart, } from '../application/process-lifecycle.js';
14
+ export { createProcessLifecycleLedger, type LifecycleLedgerResource, type LifecycleLedgerResourceConfig, lifecycleLedgerResource, type ProcessLifecycleLedger, type ProcessLifecycleLedgerConfig, } from '../application/process-lifecycle.js';
15
+ export { type DrainingFact, type LifecycleRun, LifecycleRunSchema, type LifecycleState, LifecycleStateSchema, type LifecycleTermination, LifecycleTerminationSchema, type LifecycleTransition, type PreviousExit, PreviousExitSchema, type ProcessLifecycleFact, type ReadyFact, type SameVersionOverlap, type ShutdownFact, type StartFact, type TransitionRunInput, type TransitionShutdownInput, type TransitionStartInput, transitionProcessDraining, transitionProcessReady, transitionProcessShutdown, transitionProcessStart, } from '../application/process-lifecycle-transitions.js';
14
16
  export { defineManagedResource, type ManagedResource, type ManagedResourceContext, type ManagedResourceDependency, type ManagedResourcePublished, type ManagedResourcePublishesNoValue, type ManagedResourceStartResult, managedResourceDependencyId, } from '../application/resource.js';
15
17
  export { createRevisionSignal, type RevisionSignal, type RevisionSignalAdvanceResult, RevisionSignalAdvanceResultSchema, type RevisionSignalClock, type RevisionSignalConfig, type RevisionSignalSnapshot, RevisionSignalSnapshotSchema, type RevisionSignalState, RevisionSignalStateSchema, type RevisionSignalTimer, type RevisionSignalWaitOptions, type RevisionSignalWaitOutcome, RevisionSignalWaitOutcomeSchema, type RevisionSignalWaitResult, RevisionSignalWaitResultSchema, } from '../application/revision-signal.js';
16
18
  export { createManagedSchedule, type ManagedSchedule, type ManagedScheduleClock, type ManagedScheduleConfig, type ManagedScheduleDescriptor, ManagedScheduleDescriptorSchema, type ManagedScheduleErrorPolicy, ManagedScheduleErrorPolicySchema, type ManagedScheduleOverlap, ManagedScheduleOverlapSchema, type ManagedScheduleRunContext, type ManagedScheduleStatus, ManagedScheduleStatusSchema, type ManagedScheduleTimer, } from '../application/schedule.js';
@@ -1 +1 @@
1
- {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,10 @@ import {
14
14
  createApplicationSnapshotSink,
15
15
  createManagedSchedule
16
16
  } from "../index-ensd0r74.js";
17
+ import {
18
+ DirectoryInboxRejectionReasonSchema,
19
+ DirectoryInboxStateSchema
20
+ } from "../index-5jrd0yng.js";
17
21
  import {
18
22
  DiagnosticJournalCloseResultSchema,
19
23
  DiagnosticJournalFailurePhaseSchema,
@@ -1068,21 +1072,28 @@ function notificationOutboxResource(outbox, config = {}) {
1068
1072
  });
1069
1073
  }
1070
1074
  // src/application/process-lifecycle.ts
1075
+ import { z as z7 } from "zod";
1076
+
1077
+ // src/application/process-lifecycle-transitions.ts
1071
1078
  import { z as z6 } from "zod";
1072
1079
  var LifecycleTerminationSchema = z6.enum([
1073
1080
  "active",
1081
+ "draining",
1074
1082
  "clean",
1075
1083
  "forced",
1084
+ "startup-failed",
1076
1085
  "hot-reload",
1077
1086
  "abnormal"
1078
1087
  ]);
1088
+ var timestamp = z6.string().datetime({ offset: true });
1079
1089
  var LifecycleRunSchema = z6.object({
1080
1090
  runId: z6.string().min(1).max(128),
1081
1091
  pid: z6.number().int().positive(),
1082
1092
  version: z6.string().min(1).max(256),
1083
- startedAt: z6.string().datetime({ offset: true }),
1084
- readyAt: z6.string().datetime({ offset: true }).nullable(),
1085
- stoppedAt: z6.string().datetime({ offset: true }).nullable(),
1093
+ startedAt: timestamp,
1094
+ readyAt: timestamp.nullable(),
1095
+ unavailableAt: timestamp.nullable().default(null),
1096
+ stoppedAt: timestamp.nullable(),
1086
1097
  termination: LifecycleTerminationSchema
1087
1098
  }).strict();
1088
1099
  var LifecycleStateSchema = z6.object({
@@ -1094,17 +1105,20 @@ var PreviousExitSchema = z6.enum([
1094
1105
  "hot-reload",
1095
1106
  "clean",
1096
1107
  "forced",
1108
+ "startup-failed",
1097
1109
  "handoff",
1098
1110
  "abnormal"
1099
1111
  ]);
1100
1112
  var emptyState = () => ({ schemaVersion: 1, runs: [] });
1101
1113
  var epoch = (value) => Date.parse(value);
1102
1114
  var elapsed = (later, earlier) => Math.max(0, epoch(later) - epoch(earlier));
1103
- function normalize(state, retain) {
1115
+ var isOpenRun = (run) => run.termination === "active" || run.termination === "draining";
1116
+ function normalizeLifecycleState(state, retain) {
1104
1117
  const parsed = LifecycleStateSchema.parse(state ?? emptyState());
1105
1118
  const runs = [...parsed.runs];
1106
1119
  for (let index = runs.length - 1;runs.length > retain && index >= 0; index -= 1) {
1107
- if (runs[index]?.termination !== "active")
1120
+ const run = runs[index];
1121
+ if (run && !isOpenRun(run))
1108
1122
  runs.splice(index, 1);
1109
1123
  }
1110
1124
  return { schemaVersion: 1, runs: runs.slice(0, retain) };
@@ -1113,15 +1127,45 @@ var UNKNOWN_VERSION = "unknown";
1113
1127
  function isVersionChange(previous, next) {
1114
1128
  return previous !== UNKNOWN_VERSION && next !== UNKNOWN_VERSION && previous !== next;
1115
1129
  }
1130
+ var RetainSchema = z6.number().int().min(1).max(1000);
1131
+ function previousExitOf(previous, run, overlap) {
1132
+ if (!previous)
1133
+ return "first-boot";
1134
+ const ended = previous.termination;
1135
+ if (ended !== "active" && ended !== "draining")
1136
+ return ended;
1137
+ if (previous.pid === run.pid)
1138
+ return "hot-reload";
1139
+ if (isVersionChange(previous.version, run.version) || overlap === "handoff")
1140
+ return "handoff";
1141
+ return previous.readyAt === null ? "startup-failed" : "abnormal";
1142
+ }
1143
+ function closeAbandoned(candidate, previous, previousExit, run, overlap) {
1144
+ if (!isOpenRun(candidate))
1145
+ return candidate;
1146
+ const closed = { ...candidate, stoppedAt: run.startedAt };
1147
+ if (candidate.pid === run.pid)
1148
+ return { ...closed, termination: "hot-reload" };
1149
+ if (overlap === "handoff")
1150
+ return candidate;
1151
+ if (candidate.runId === previous?.runId && previousExit === "handoff")
1152
+ return candidate;
1153
+ return {
1154
+ ...closed,
1155
+ termination: candidate.readyAt === null ? "startup-failed" : "abnormal"
1156
+ };
1157
+ }
1116
1158
  function transitionProcessStart(source, input) {
1117
- const retain = z6.number().int().min(1).max(1000).parse(input.retain ?? 20);
1118
- const state = normalize(source, 1000);
1159
+ const retain = RetainSchema.parse(input.retain ?? 20);
1160
+ const overlap = input.sameVersionOverlap ?? "abnormal";
1161
+ const state = normalizeLifecycleState(source, 1000);
1119
1162
  const run = LifecycleRunSchema.parse({
1120
1163
  runId: input.runId,
1121
1164
  pid: input.pid,
1122
1165
  version: input.version,
1123
1166
  startedAt: input.now,
1124
1167
  readyAt: null,
1168
+ unavailableAt: null,
1125
1169
  stoppedAt: null,
1126
1170
  termination: "active"
1127
1171
  });
@@ -1129,31 +1173,10 @@ function transitionProcessStart(source, input) {
1129
1173
  throw new Error(`[stitchkit] lifecycle run id already exists: ${run.runId}`);
1130
1174
  }
1131
1175
  const previous = state.runs[0] ?? null;
1132
- let previousExit = "first-boot";
1133
- let downtimeMs = null;
1134
- if (previous?.stoppedAt) {
1135
- previousExit = previous.termination === "forced" || previous.termination === "abnormal" || previous.termination === "hot-reload" ? previous.termination : "clean";
1136
- downtimeMs = elapsed(run.startedAt, previous.stoppedAt);
1137
- } else if (previous) {
1138
- if (previous.pid === run.pid)
1139
- previousExit = "hot-reload";
1140
- else if (isVersionChange(previous.version, run.version))
1141
- previousExit = "handoff";
1142
- else
1143
- previousExit = input.sameVersionOverlap ?? "abnormal";
1144
- }
1145
- const runs = state.runs.map((candidate) => {
1146
- if (candidate.runId !== previous?.runId || candidate.termination !== "active")
1147
- return candidate;
1148
- if (previousExit === "hot-reload") {
1149
- return { ...candidate, stoppedAt: run.startedAt, termination: "hot-reload" };
1150
- }
1151
- if (previousExit === "abnormal") {
1152
- return { ...candidate, stoppedAt: run.startedAt, termination: "abnormal" };
1153
- }
1154
- return candidate;
1155
- });
1156
- const next = normalize({ schemaVersion: 1, runs: [run, ...runs] }, retain);
1176
+ const previousExit = previousExitOf(previous, run, overlap);
1177
+ const processGapMs = previous && !isOpenRun(previous) && previous.stoppedAt ? elapsed(run.startedAt, previous.stoppedAt) : null;
1178
+ const runs = state.runs.map((candidate) => closeAbandoned(candidate, previous, previousExit, run, overlap));
1179
+ const next = normalizeLifecycleState({ schemaVersion: 1, runs: [run, ...runs] }, retain);
1157
1180
  return {
1158
1181
  state: next,
1159
1182
  fact: {
@@ -1167,15 +1190,30 @@ function transitionProcessStart(source, input) {
1167
1190
  previousPid: previous?.pid ?? null,
1168
1191
  previousVersion: previous?.version ?? null,
1169
1192
  versionChanged: previous !== null && isVersionChange(previous.version, run.version),
1170
- downtimeMs
1193
+ processGapMs
1171
1194
  }
1172
1195
  };
1173
1196
  }
1197
+ function findOpen(state, input) {
1198
+ return state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && isOpenRun(run));
1199
+ }
1200
+ function unavailability(state, target, readyAt) {
1201
+ const older = state.runs.slice(state.runs.indexOf(target) + 1);
1202
+ const served = older.find((run) => run.readyAt !== null);
1203
+ if (!served)
1204
+ return { downtimeMs: null, unavailableSince: null };
1205
+ if (served.unavailableAt !== null) {
1206
+ return {
1207
+ downtimeMs: elapsed(readyAt, served.unavailableAt),
1208
+ unavailableSince: served.unavailableAt
1209
+ };
1210
+ }
1211
+ return isOpenRun(served) ? { downtimeMs: 0, unavailableSince: null } : { downtimeMs: null, unavailableSince: null };
1212
+ }
1174
1213
  function transitionProcessReady(source, input) {
1175
- const retain = input.retain ?? 20;
1176
- const state = normalize(source, retain);
1177
- const target = state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && run.termination === "active");
1178
- if (!target) {
1214
+ const state = normalizeLifecycleState(source, input.retain ?? 20);
1215
+ const target = findOpen(state, input);
1216
+ if (target?.termination !== "active") {
1179
1217
  return {
1180
1218
  state,
1181
1219
  fact: {
@@ -1184,6 +1222,8 @@ function transitionProcessReady(source, input) {
1184
1222
  pid: input.pid,
1185
1223
  readyAt: input.now,
1186
1224
  startupMs: 0,
1225
+ downtimeMs: null,
1226
+ unavailableSince: null,
1187
1227
  recorded: false
1188
1228
  }
1189
1229
  };
@@ -1200,14 +1240,45 @@ function transitionProcessReady(source, input) {
1200
1240
  pid: target.pid,
1201
1241
  readyAt,
1202
1242
  startupMs: elapsed(readyAt, target.startedAt),
1243
+ ...unavailability(state, target, readyAt),
1203
1244
  recorded: target.readyAt === null
1204
1245
  }
1205
1246
  };
1206
1247
  }
1248
+ function transitionProcessDraining(source, input) {
1249
+ const state = normalizeLifecycleState(source, input.retain ?? 20);
1250
+ const target = findOpen(state, input);
1251
+ if (target?.termination !== "active") {
1252
+ return {
1253
+ state,
1254
+ fact: {
1255
+ type: "draining",
1256
+ runId: input.runId,
1257
+ pid: input.pid,
1258
+ unavailableAt: target ? target.unavailableAt : null,
1259
+ recorded: false
1260
+ }
1261
+ };
1262
+ }
1263
+ const unavailableAt = target.readyAt === null ? null : input.now;
1264
+ return {
1265
+ state: {
1266
+ schemaVersion: 1,
1267
+ runs: state.runs.map((run) => run.runId === target.runId ? { ...run, termination: "draining", unavailableAt } : run)
1268
+ },
1269
+ fact: {
1270
+ type: "draining",
1271
+ runId: target.runId,
1272
+ pid: target.pid,
1273
+ unavailableAt,
1274
+ recorded: true
1275
+ }
1276
+ };
1277
+ }
1207
1278
  function transitionProcessShutdown(source, input) {
1208
- const state = normalize(source, input.retain ?? 20);
1209
- const target = state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && run.termination === "active");
1210
- const termination = input.forced ? "forced" : "clean";
1279
+ const state = normalizeLifecycleState(source, input.retain ?? 20);
1280
+ const target = findOpen(state, input);
1281
+ const requested = input.forced ? "forced" : "clean";
1211
1282
  if (!target) {
1212
1283
  return {
1213
1284
  state,
@@ -1217,15 +1288,17 @@ function transitionProcessShutdown(source, input) {
1217
1288
  pid: input.pid,
1218
1289
  stoppedAt: input.now,
1219
1290
  uptimeMs: null,
1220
- termination,
1291
+ termination: requested,
1221
1292
  recorded: false
1222
1293
  }
1223
1294
  };
1224
1295
  }
1296
+ const termination = target.readyAt === null ? "startup-failed" : requested;
1297
+ const unavailableAt = target.unavailableAt ?? (target.readyAt === null ? null : input.now);
1225
1298
  return {
1226
1299
  state: {
1227
1300
  schemaVersion: 1,
1228
- runs: state.runs.map((run) => run.runId === target.runId ? { ...run, stoppedAt: input.now, termination } : run)
1301
+ runs: state.runs.map((run) => run.runId === target.runId ? { ...run, unavailableAt, stoppedAt: input.now, termination } : run)
1229
1302
  },
1230
1303
  fact: {
1231
1304
  type: "stopped",
@@ -1238,10 +1311,12 @@ function transitionProcessShutdown(source, input) {
1238
1311
  }
1239
1312
  };
1240
1313
  }
1314
+
1315
+ // src/application/process-lifecycle.ts
1241
1316
  function createProcessLifecycleLedger(config) {
1242
1317
  const clock = config.clock ?? (() => new Date);
1243
- const pid = z6.number().int().positive().parse(config.pid ?? process.pid);
1244
- const retain = z6.number().int().min(1).max(1000).parse(config.retain ?? 20);
1318
+ const pid = z7.number().int().positive().parse(config.pid ?? process.pid);
1319
+ const retain = z7.number().int().min(1).max(1000).parse(config.retain ?? 20);
1245
1320
  const configuredRunId = config.runId;
1246
1321
  const nextRunId = typeof configuredRunId === "function" ? configuredRunId : configuredRunId === undefined ? () => crypto.randomUUID() : () => configuredRunId;
1247
1322
  let runId = nextRunId();
@@ -1285,6 +1360,20 @@ function createProcessLifecycleLedger(config) {
1285
1360
  publish(fact);
1286
1361
  return fact;
1287
1362
  },
1363
+ async recordDraining() {
1364
+ const fact = await config.store.update((state) => {
1365
+ const transition = transitionProcessDraining(state, {
1366
+ runId,
1367
+ pid,
1368
+ now: clock().toISOString(),
1369
+ retain
1370
+ });
1371
+ return { state: transition.state, result: transition.fact };
1372
+ });
1373
+ if (fact.recorded)
1374
+ publish(fact);
1375
+ return fact;
1376
+ },
1288
1377
  async recordShutdown(input) {
1289
1378
  const fact = await config.store.update((state) => {
1290
1379
  const transition = transitionProcessShutdown(state, {
@@ -1301,11 +1390,11 @@ function createProcessLifecycleLedger(config) {
1301
1390
  return fact;
1302
1391
  },
1303
1392
  async current() {
1304
- const state = normalize(await config.store.read(), retain);
1393
+ const state = normalizeLifecycleState(await config.store.read(), retain);
1305
1394
  return state.runs.find((run) => run.runId === runId && run.pid === pid) ?? null;
1306
1395
  },
1307
1396
  async runs() {
1308
- return normalize(await config.store.read(), retain).runs;
1397
+ return normalizeLifecycleState(await config.store.read(), retain).runs;
1309
1398
  },
1310
1399
  subscribe(listener) {
1311
1400
  listeners.add(listener);
@@ -1340,6 +1429,9 @@ function lifecycleLedgerResource(ledger, config) {
1340
1429
  async activate() {
1341
1430
  await ledger.recordReady();
1342
1431
  },
1432
+ async stopAdmission() {
1433
+ await ledger.recordDraining();
1434
+ },
1343
1435
  async close() {
1344
1436
  await stop(false);
1345
1437
  },
@@ -1349,27 +1441,27 @@ function lifecycleLedgerResource(ledger, config) {
1349
1441
  });
1350
1442
  }
1351
1443
  // src/application/revision-signal.ts
1352
- import { z as z7 } from "zod";
1353
- var NonNegativeSafeIntegerSchema = z7.number().int().nonnegative().safe();
1354
- var PositiveSafeIntegerSchema2 = z7.number().int().positive().safe();
1355
- var TimerDelaySchema = z7.number().int().positive().max(2147483647);
1356
- var RevisionSignalStateSchema = z7.enum(["open", "closed"]);
1357
- var RevisionSignalWaitOutcomeSchema = z7.enum([
1444
+ import { z as z8 } from "zod";
1445
+ var NonNegativeSafeIntegerSchema = z8.number().int().nonnegative().safe();
1446
+ var PositiveSafeIntegerSchema2 = z8.number().int().positive().safe();
1447
+ var TimerDelaySchema = z8.number().int().positive().max(2147483647);
1448
+ var RevisionSignalStateSchema = z8.enum(["open", "closed"]);
1449
+ var RevisionSignalWaitOutcomeSchema = z8.enum([
1358
1450
  "changed",
1359
1451
  "timed-out",
1360
1452
  "aborted",
1361
1453
  "closed",
1362
1454
  "capacity"
1363
1455
  ]);
1364
- var RevisionSignalWaitResultSchema = z7.object({
1456
+ var RevisionSignalWaitResultSchema = z8.object({
1365
1457
  outcome: RevisionSignalWaitOutcomeSchema,
1366
1458
  revision: NonNegativeSafeIntegerSchema
1367
1459
  }).strict().readonly();
1368
- var RevisionSignalAdvanceResultSchema = z7.object({
1369
- outcome: z7.enum(["advanced", "closed"]),
1460
+ var RevisionSignalAdvanceResultSchema = z8.object({
1461
+ outcome: z8.enum(["advanced", "closed"]),
1370
1462
  revision: NonNegativeSafeIntegerSchema
1371
1463
  }).strict().readonly();
1372
- var RevisionSignalSnapshotSchema = z7.object({
1464
+ var RevisionSignalSnapshotSchema = z8.object({
1373
1465
  state: RevisionSignalStateSchema,
1374
1466
  revision: NonNegativeSafeIntegerSchema,
1375
1467
  pending: NonNegativeSafeIntegerSchema,
@@ -1919,6 +2011,7 @@ export {
1919
2011
  transitionProcessStart,
1920
2012
  transitionProcessShutdown,
1921
2013
  transitionProcessReady,
2014
+ transitionProcessDraining,
1922
2015
  sqliteKeyspaceBackend,
1923
2016
  readDiagnosticJournalLockDiagnosis,
1924
2017
  projectApplicationStatus,
@@ -1964,6 +2057,8 @@ export {
1964
2057
  LifecycleTerminationSchema,
1965
2058
  LifecycleStateSchema,
1966
2059
  LifecycleRunSchema,
2060
+ DirectoryInboxStateSchema,
2061
+ DirectoryInboxRejectionReasonSchema,
1967
2062
  DiagnosticJournalWaitResultSchema,
1968
2063
  DiagnosticJournalSubmitResultSchema,
1969
2064
  DiagnosticJournalStatusSchema,