@claudexor/control-api 3.0.4 → 3.1.0

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 (56) hide show
  1. package/dist/artifact-serve-routes.d.ts +46 -1
  2. package/dist/artifact-serve-routes.d.ts.map +1 -1
  3. package/dist/artifact-serve-routes.js +172 -8
  4. package/dist/artifact-serve-routes.js.map +1 -1
  5. package/dist/candidates.d.ts.map +1 -1
  6. package/dist/candidates.js +14 -1
  7. package/dist/candidates.js.map +1 -1
  8. package/dist/daemon-server.d.ts +67 -3
  9. package/dist/daemon-server.d.ts.map +1 -1
  10. package/dist/daemon-server.js +349 -50
  11. package/dist/daemon-server.js.map +1 -1
  12. package/dist/operation-catalog.d.ts +10 -1
  13. package/dist/operation-catalog.d.ts.map +1 -1
  14. package/dist/operation-catalog.js +150 -18
  15. package/dist/operation-catalog.js.map +1 -1
  16. package/dist/operation-parameters.d.ts +34 -0
  17. package/dist/operation-parameters.d.ts.map +1 -0
  18. package/dist/operation-parameters.js +52 -0
  19. package/dist/operation-parameters.js.map +1 -0
  20. package/dist/problem-response.d.ts +43 -0
  21. package/dist/problem-response.d.ts.map +1 -1
  22. package/dist/problem-response.js +192 -0
  23. package/dist/problem-response.js.map +1 -1
  24. package/dist/project-routes.d.ts +1 -0
  25. package/dist/project-routes.d.ts.map +1 -1
  26. package/dist/project-routes.js +18 -1
  27. package/dist/project-routes.js.map +1 -1
  28. package/dist/run-apply-routes.d.ts +6 -1
  29. package/dist/run-apply-routes.d.ts.map +1 -1
  30. package/dist/run-apply-routes.js +32 -2
  31. package/dist/run-apply-routes.js.map +1 -1
  32. package/dist/run-events-stream.d.ts.map +1 -1
  33. package/dist/run-events-stream.js +99 -64
  34. package/dist/run-events-stream.js.map +1 -1
  35. package/dist/run-list.d.ts +74 -0
  36. package/dist/run-list.d.ts.map +1 -0
  37. package/dist/run-list.js +156 -0
  38. package/dist/run-list.js.map +1 -0
  39. package/dist/run-retry-routes.d.ts.map +1 -1
  40. package/dist/run-retry-routes.js +38 -1
  41. package/dist/run-retry-routes.js.map +1 -1
  42. package/dist/run-start.d.ts +14 -1
  43. package/dist/run-start.d.ts.map +1 -1
  44. package/dist/run-start.js +50 -1
  45. package/dist/run-start.js.map +1 -1
  46. package/dist/run-timeline.d.ts +44 -3
  47. package/dist/run-timeline.d.ts.map +1 -1
  48. package/dist/run-timeline.js +143 -24
  49. package/dist/run-timeline.js.map +1 -1
  50. package/dist/thread-projection.d.ts.map +1 -1
  51. package/dist/thread-projection.js +6 -0
  52. package/dist/thread-projection.js.map +1 -1
  53. package/dist/thread-turn-routes.d.ts.map +1 -1
  54. package/dist/thread-turn-routes.js +20 -23
  55. package/dist/thread-turn-routes.js.map +1 -1
  56. package/package.json +6 -6
@@ -1,3 +1,180 @@
1
+ import { redactSecrets } from "@claudexor/util";
2
+ /** Bounds for the request-validation projection (QA-053). Redact-first, then
3
+ * truncate; never split a redaction marker; disclose omitted counts. */
4
+ const ZOD_MAX_ISSUES = 25;
5
+ const ZOD_MAX_PER_FIELD = 3;
6
+ const ZOD_MAX_PATH_BYTES = 256;
7
+ const ZOD_MAX_MESSAGE_BYTES = 512;
8
+ /** Structural ZodError detection — deliberately NOT `instanceof`, which is
9
+ * unreliable across duplicated `zod` package copies. A request-boundary
10
+ * validation failure carries an `issues` array of `{path,message}`. */
11
+ function structuralZodIssues(error) {
12
+ if (!error || typeof error !== "object")
13
+ return null;
14
+ const issues = error.issues;
15
+ if (!Array.isArray(issues) || issues.length === 0)
16
+ return null;
17
+ const out = [];
18
+ for (const raw of issues) {
19
+ if (!raw || typeof raw !== "object")
20
+ return null;
21
+ const issue = raw;
22
+ if (!Array.isArray(issue["path"]) || typeof issue["message"] !== "string")
23
+ return null;
24
+ out.push(issue);
25
+ }
26
+ return out;
27
+ }
28
+ function truncateBytes(text, maxBytes) {
29
+ if (Buffer.byteLength(text, "utf8") <= maxBytes)
30
+ return text;
31
+ // Truncate on a whole UTF-16 code point boundary, then trim to the byte cap.
32
+ let sliced = text;
33
+ while (Buffer.byteLength(sliced, "utf8") > maxBytes && sliced.length > 0) {
34
+ sliced = sliced.slice(0, -1);
35
+ }
36
+ return sliced;
37
+ }
38
+ /** JSON Pointer (RFC 9457-style) for one issue path, without echoing an
39
+ * unrecognized key verbatim when it is unsafe. */
40
+ function issuePointer(path) {
41
+ if (path.length === 0)
42
+ return "/";
43
+ const parts = path.map((seg) => typeof seg === "number"
44
+ ? String(seg)
45
+ : redactSecrets(seg).replaceAll("~", "~0").replaceAll("/", "~1"));
46
+ return truncateBytes("/" + parts.join("/"), ZOD_MAX_PATH_BYTES);
47
+ }
48
+ /** A concise, safe per-issue message that never echoes a raw RECEIVED value
49
+ * (type names and schema-declared enums/literals are safe; the actual input
50
+ * value and attacker-supplied keys are not). */
51
+ function safeIssueMessage(issue) {
52
+ const code = issue.code;
53
+ let text;
54
+ switch (code) {
55
+ case "invalid_type":
56
+ // `expected`/`received` are TYPE names here (e.g. "object"), not values.
57
+ text = `Expected ${String(issue.expected)}, received ${String(issue.received)}.`;
58
+ break;
59
+ case "invalid_enum_value":
60
+ case "invalid_literal": {
61
+ const options = Array.isArray(issue.options)
62
+ ? issue.options.map((o) => JSON.stringify(o)).join(", ")
63
+ : issue.expected !== undefined
64
+ ? JSON.stringify(issue.expected)
65
+ : "";
66
+ text = options ? `Expected one of: ${options}.` : "Value is not an accepted option.";
67
+ break;
68
+ }
69
+ case "unrecognized_keys":
70
+ text = "Unrecognized key(s) in object.";
71
+ break;
72
+ case "invalid_union":
73
+ text = "Value does not match any accepted shape.";
74
+ break;
75
+ default:
76
+ // Other Zod codes (too_small/too_big/invalid_string/custom) carry
77
+ // schema-derived messages that do not echo the input value.
78
+ text = issue.message;
79
+ }
80
+ return truncateBytes(redactSecrets(text), ZOD_MAX_MESSAGE_BYTES);
81
+ }
82
+ /**
83
+ * QA-053: turn a request-boundary ZodError into a machine-readable problem —
84
+ * structured `fieldErrors` (JSON Pointer -> messages), a short single-line human
85
+ * `message`, and bounded `context` counts — instead of copying Zod's multiline
86
+ * issue-array serialization into `message` with an empty `fieldErrors`.
87
+ *
88
+ * Returns a normalized typed error the shared `problemBody` projection already
89
+ * knows how to serialize (code/message/fieldErrors/context). A non-ZodError, or
90
+ * a typed error that already owns `code`/`fieldErrors` (idempotency_key_required,
91
+ * inline_secret_rejected, invalid JSON body, 413), is returned UNCHANGED — this
92
+ * only normalizes structural validation exceptions at the request boundary and
93
+ * never reinterprets a service-output or internal error as a user field error.
94
+ */
95
+ export function normalizeRequestValidationError(error) {
96
+ // A typed error that already carries a product code is authoritative.
97
+ if (error &&
98
+ typeof error === "object" &&
99
+ typeof error.code === "string") {
100
+ return error;
101
+ }
102
+ const issues = structuralZodIssues(error);
103
+ if (!issues)
104
+ return error;
105
+ const fieldErrors = {};
106
+ let used = 0;
107
+ let omitted = 0;
108
+ const push = (pointer, message) => {
109
+ if (used >= ZOD_MAX_ISSUES) {
110
+ omitted += 1;
111
+ return;
112
+ }
113
+ const bucket = (fieldErrors[pointer] ??= []);
114
+ if (bucket.length >= ZOD_MAX_PER_FIELD) {
115
+ omitted += 1;
116
+ return;
117
+ }
118
+ bucket.push(message);
119
+ used += 1;
120
+ };
121
+ for (const issue of issues) {
122
+ // Unrecognized keys: surface WHICH field is unexpected via the pointer
123
+ // (the client's own field name, redacted) — the value is never echoed. This
124
+ // is the RFC 9457 pattern and is more useful than a bare root message.
125
+ if (issue.code === "unrecognized_keys" && Array.isArray(issue.keys) && issue.keys.length > 0) {
126
+ for (const key of issue.keys) {
127
+ if (typeof key !== "string")
128
+ continue;
129
+ push(issuePointer([...issue.path, key]), "Unexpected field; not part of this request.");
130
+ }
131
+ continue;
132
+ }
133
+ push(issuePointer(issue.path), safeIssueMessage(issue));
134
+ }
135
+ const fieldCount = Object.keys(fieldErrors).length;
136
+ const message = `Request validation failed for ${fieldCount} field${fieldCount === 1 ? "" : "s"}.`;
137
+ return Object.assign(new Error(message), {
138
+ status: 400,
139
+ code: "invalid_request",
140
+ retryable: false,
141
+ fieldErrors,
142
+ context: { issueCount: issues.length, omittedIssueCount: omitted },
143
+ });
144
+ }
145
+ /** Max bytes of vendor (Git) stderr retained as revert-refusal evidence. */
146
+ const REVERT_DETAIL_MAX_BYTES = 2000;
147
+ /**
148
+ * QA-051 / W3: map a workspace revert refusal to a stable, locale-independent
149
+ * English message + typed reason code, keeping the original (redacted, bounded)
150
+ * vendor stderr as context evidence rather than the semantic message.
151
+ *
152
+ * The class is decided by the PRODUCER: `reasonCode` comes straight from
153
+ * `RevertResult.reasonCode` (which branch failed), NOT from regexing the human
154
+ * `reason`. The English-prefix regex survives only as a conservative fallback
155
+ * for a legacy-shaped result that carries no typed code.
156
+ */
157
+ export function revertRefusedProblem(rawReason, reasonCode) {
158
+ const raw = rawReason ?? "revert refused";
159
+ // Prefer the producer's typed class; fall back to the English-prefix match
160
+ // only when a legacy caller supplied no code.
161
+ const reason = reasonCode ??
162
+ (/postimage no longer matches/.test(raw) ? "postimage_diverged" : "reverse_apply_failed");
163
+ const message = reason === "postimage_diverged"
164
+ ? "Revert is no longer available because the affected files changed after this turn."
165
+ : "Revert could not be applied to the current project tree.";
166
+ let detail = redactSecrets(raw);
167
+ if (Buffer.byteLength(detail, "utf8") > REVERT_DETAIL_MAX_BYTES) {
168
+ // Prefix-slice FIRST (code units >= bytes wanted), then trim at most a few
169
+ // trailing code units for multi-byte alignment — a character-by-character
170
+ // loop over megabytes of git stderr is O(N²) on the daemon's event loop.
171
+ detail = detail.slice(0, REVERT_DETAIL_MAX_BYTES);
172
+ while (Buffer.byteLength(detail, "utf8") > REVERT_DETAIL_MAX_BYTES && detail.length > 0) {
173
+ detail = detail.slice(0, -1);
174
+ }
175
+ }
176
+ return { message, context: { reason, detail } };
177
+ }
1
178
  const RESERVED_FIELDS = new Set([
2
179
  "error",
3
180
  "message",
@@ -25,4 +202,19 @@ export function controlProblemError(status, body) {
25
202
  context,
26
203
  });
27
204
  }
205
+ /**
206
+ * The problem `code` for a THROWN service error: a typed code the service
207
+ * chose (e.g. settings-service `config_error`) reaches the wire verbatim so
208
+ * clients can key remediation on it; only an untyped throw is the generic
209
+ * `internal_error` (BACKLOG N1 — the catch paths used to stamp every throw
210
+ * `internal_error`, erasing the typed taxonomy the same body carried).
211
+ */
212
+ export function thrownProblemCode(error) {
213
+ if (error && typeof error === "object" && "code" in error) {
214
+ const value = error.code;
215
+ if (typeof value === "string" && /^[a-z][a-z0-9_]{2,63}$/.test(value))
216
+ return value;
217
+ }
218
+ return "internal_error";
219
+ }
28
220
  //# sourceMappingURL=problem-response.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"problem-response.js","sourceRoot":"","sources":["../src/problem-response.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,OAAO;IACP,SAAS;IACT,MAAM;IACN,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,cAAc;CACf,CAAC,CAAC;AAWH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,IAAa;IAC/D,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAgC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzF,MAAM,OAAO,GACX,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,QAAQ;QACjC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QACjB,CAAC,CAAC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ;YACrC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;YACnB,CAAC,CAAC,8BAA8B,MAAM,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC;IACpF,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CACpE,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE;QACvC,IAAI;QACJ,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,IAAI;QACvC,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC;QAClC,eAAe,EAAE,MAAM,CAAC,iBAAiB,CAAC;QAC1C,YAAY,EAAE,MAAM,CAAC,cAAc,CAAC;QACpC,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"problem-response.js","sourceRoot":"","sources":["../src/problem-response.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ export interface ProjectRouteContext {
10
10
  clientId: string;
11
11
  }) => Promise<unknown>;
12
12
  relinkProject?: (id: string, root: string) => Promise<unknown>;
13
+ removeProject?: (id: string) => Promise<unknown>;
13
14
  };
14
15
  readBody(req: IncomingMessage): Promise<unknown>;
15
16
  json(res: ServerResponse, status: number, body: unknown): void;
@@ -1 +1 @@
1
- {"version":3,"file":"project-routes.d.ts","sourceRoot":"","sources":["../src/project-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAUjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE;QACT,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;YAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;SAAE,CAAC,CAAC;QACtD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;YACxB,IAAI,EAAE,MAAM,CAAC;YACb,cAAc,EAAE,MAAM,CAAC;YACvB,QAAQ,EAAE,MAAM,CAAC;SAClB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAChE,CAAC;IACF,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/D,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACzD;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CA6ClB"}
1
+ {"version":3,"file":"project-routes.d.ts","sourceRoot":"","sources":["../src/project-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAWjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE;QACT,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;YAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;SAAE,CAAC,CAAC;QACtD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;YACxB,IAAI,EAAE,MAAM,CAAC;YACb,cAAc,EAAE,MAAM,CAAC;YACvB,QAAQ,EAAE,MAAM,CAAC;SAClB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/D,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAClD,CAAC;IACF,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/D,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACzD;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CA6DlB"}
@@ -1,4 +1,4 @@
1
- import { ControlProject, ControlProjectListResponse, ControlProjectRegisterRequest, ControlProjectRelinkRequest, } from "@claudexor/schema";
1
+ import { ControlProject, ControlProjectListResponse, ControlProjectRegisterRequest, ControlProjectRelinkRequest, ControlProjectRemoveReceipt, } from "@claudexor/schema";
2
2
  import { assertNoInlineSecretValues } from "@claudexor/util";
3
3
  import { requiredIdempotencyKey } from "./run-start.js";
4
4
  export async function handleProjectRoute(ctx, method, path, req, res) {
@@ -49,6 +49,23 @@ export async function handleProjectRoute(ctx, method, path, req, res) {
49
49
  }
50
50
  return true;
51
51
  }
52
+ // QA-049: DELETE /projects/:id — retire a durable project (registry entry +
53
+ // journal-partition archival), typed-fenced against non-purged threads and
54
+ // live/queued runs. Not a relink match, so it lives after that branch.
55
+ const projectDeleteMatch = /^\/projects\/([^/]+)$/.exec(path);
56
+ if (method === "DELETE" && projectDeleteMatch) {
57
+ const service = ctx.services?.removeProject;
58
+ if (!service)
59
+ return unsupported(ctx, res);
60
+ try {
61
+ const receipt = await service(decodeURIComponent(projectDeleteMatch[1]));
62
+ ctx.json(res, 200, ControlProjectRemoveReceipt.parse(receipt));
63
+ }
64
+ catch (error) {
65
+ ctx.requestError(res, error);
66
+ }
67
+ return true;
68
+ }
52
69
  return false;
53
70
  }
54
71
  function unsupported(ctx, res) {
@@ -1 +1 @@
1
- {"version":3,"file":"project-routes.js","sourceRoot":"","sources":["../src/project-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-routes.js","sourceRoot":"","sources":["../src/project-routes.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { verifyAndDeliver } from "@claudexor/delivery";
3
- import { ControlApplyCheckRequest, ControlApplyRequest, type FinalVerifyRecord } from "@claudexor/schema";
3
+ import { ControlApplyCheckRequest, ControlApplyRequest, type FinalVerifyRecord, type RunApplyState } from "@claudexor/schema";
4
4
  import type { DaemonRunRecord } from "./daemon-server.js";
5
5
  export interface DeliveryCommandServices {
6
6
  beginDelivery?: (params: unknown, input: {
@@ -41,6 +41,11 @@ export interface RunApplyRouteContext {
41
41
  /** Persist applyState=applied on the run's delivery-state artifact after a
42
42
  * delivery reports applied=true (round-15 #2) — idempotent, best-effort. */
43
43
  markApplied(record: DaemonRunRecord): void;
44
+ /** The run's effective MUTABLE delivery/apply state (delivery_state overlay →
45
+ * work_product snapshot) — the same authority that projects
46
+ * summary.result.applyState. An already-delivered run answers apply/check as
47
+ * a typed idempotent no-op instead of "patch does not apply" (#26). */
48
+ deliveredApplyState(record: DaemonRunRecord): RunApplyState;
44
49
  }
45
50
  /** Own the generic manual run apply/check routes outside the daemon server shell. */
46
51
  export declare function handleRunApplyRoutes(ctx: RunApplyRouteContext, method: string, path: string, req: IncomingMessage, res: ServerResponse): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"run-apply-routes.d.ts","sourceRoot":"","sources":["../src/run-apply-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-apply-routes.d.ts","sourceRoot":"","sources":["../src/run-apply-routes.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { checkPatch, verifyAndDeliver } from "@claudexor/delivery";
1
+ import { checkPatch, checkPatchReverse, verifyAndDeliver } from "@claudexor/delivery";
2
2
  import { ControlApplyCheckRequest, ControlApplyCheckResponse, ControlApplyRequest, ControlDeliveryResponse, } from "@claudexor/schema";
3
3
  import { assertNoInlineSecretValues, containsSecretLikeToken, sha256 } from "@claudexor/util";
4
4
  import { requiredIdempotencyKey, validateAbsoluteRepoRoot } from "./run-start.js";
@@ -82,6 +82,23 @@ export async function handleRunApplyRoutes(ctx, method, path, req, res) {
82
82
  const rootError = validateAbsoluteRepoRoot(root);
83
83
  if (rootError)
84
84
  throw Object.assign(new Error(rootError), { status: 400 });
85
+ // Idempotent replay (#26 dry-run): an already-delivered run cannot pass a
86
+ // forward `git apply --check` (the tree is the postimage), which would
87
+ // read as "patch does not apply". When the recorded delivery state says
88
+ // the change is in place AND the reverse check confirms the tree is this
89
+ // patch's exact postimage, report the safe already-applied no-op instead
90
+ // of a false conflict. A diverged tree falls through to the honest gate.
91
+ const applyState = ctx.deliveredApplyState(record);
92
+ if ((applyState === "applied" || applyState === "applied_review_blocked") &&
93
+ (await checkPatchReverse(root, patch)).ok) {
94
+ ctx.json(res, 200, ControlApplyCheckResponse.parse({
95
+ ok: true,
96
+ code: 0,
97
+ stderr: "already applied; idempotent no-op (no files would change)",
98
+ alreadyApplied: true,
99
+ }));
100
+ return true;
101
+ }
85
102
  const gateError = ctx.gateError(record, patch, root);
86
103
  if (gateError)
87
104
  throw Object.assign(new Error(gateError), { status: 409 });
@@ -141,7 +158,20 @@ export async function handleRunApplyRoutes(ctx, method, path, req, res) {
141
158
  // actionable and preserves the run indefinitely.
142
159
  if (delivered.applied)
143
160
  ctx.markApplied(record);
144
- ctx.json(res, 200, ControlDeliveryResponse.parse(delivered));
161
+ // #26: type the coarse delivery disposition on the wire so a consumer reads
162
+ // the outcome without parsing `detail` prose. `alreadyApplied` rides on the
163
+ // receipt already; deliveryStatus is its enum projection.
164
+ const deliveryStatus = delivered.refused
165
+ ? "refused"
166
+ : delivered.alreadyApplied
167
+ ? "already_applied"
168
+ : delivered.applied
169
+ ? "applied"
170
+ : undefined;
171
+ ctx.json(res, 200, ControlDeliveryResponse.parse({
172
+ ...delivered,
173
+ ...(deliveryStatus ? { deliveryStatus } : {}),
174
+ }));
145
175
  }
146
176
  catch (error) {
147
177
  ctx.requestError(res, error);
@@ -1 +1 @@
1
- {"version":3,"file":"run-apply-routes.js","sourceRoot":"","sources":["../src/run-apply-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9F,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAkBlF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAA6C,EAC7C,KAMC;IAED,MAAM,KAAK,GAAG,QAAQ,EAAE,aAAa,CAAC;IACtC,MAAM,QAAQ,GAAG,QAAQ,EAAE,gBAAgB,CAAC;IAC5C,MAAM,IAAI,GAAG,QAAQ,EAAE,YAAY,CAAC;IACpC,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE;QACxC,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,aAAa;QACrB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,IAAI,OAAO,CAAC,KAAK,KAAK,WAAW;YAAE,OAAO,OAAO,CAAC,MAAW,CAAC;QAC9D,IAAI,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,OAAO,GACX,OAAO,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;gBAClD,CAAC,CAAE,OAAO,CAAC,MAAkC;gBAC7C,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,iBAAiB,CAAC,EAAE;gBACjE,MAAM,EAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG;gBACvE,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,iBAAiB;aAChE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CACP,OAAO,CAAC,KAAK,KAAK,aAAa;YAC7B,CAAC,CAAC,2EAA2E;YAC7E,CAAC,CAAC,2DAA2D,CAChE,EACD;YACE,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,OAAO,CAAC,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,sBAAsB;SACxF,CACF,CAAC;IACJ,CAAC;IACD,IAAI,MAAS,CAAC;IACd,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,sEAAsE;QACtE,oEAAoE;QACpE,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CAAC,+DAA+D,CAAC,EAC1E;YACE,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,8BAA8B;YACpC,KAAK,EAAE,KAAK;SACb,CACF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AA2BD,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAyB,EACzB,MAAc,EACd,IAAY,EACZ,GAAoB,EACpB,GAAmB;IAEnB,MAAM,UAAU,GAAG,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,IAAI,MAAM,KAAK,MAAM,IAAI,UAAU,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACpC,0BAA0B,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,wBAAwB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,KAAK,KAAK,IAAI;gBAChB,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACpF,IAAI,uBAAuB,CAAC,KAAK,CAAC;gBAChC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wDAAwD,CAAC,EAAE;oBACvF,MAAM,EAAE,GAAG;iBACZ,CAAC,CAAC;YACL,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI;gBACP,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9F,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,SAAS;gBAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1E,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACrD,IAAI,SAAS;gBAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1E,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,yBAAyB,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC;IAC9E,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACpB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpC,0BAA0B,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,IAAI;YAChB,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpF,IAAI,uBAAuB,CAAC,KAAK,CAAC;YAChC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,EAAE;gBACjF,MAAM,EAAE,GAAG;aACZ,CAAC,CAAC;QACL,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI;YACP,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oCAAoC,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACxF,MAAM,SAAS,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,SAAS;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,CACrD,qBAAqB,CAAC,GAAG,CAAC,QAAQ,EAAE;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG;YACH,SAAS,EAAE,WAAW;YACtB,OAAO,EAAE;gBACP,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE;gBAChC,IAAI;gBACJ,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC;gBAC1B,QAAQ,EAAE,IAAI;aACf;YACD,IAAI,EAAE,GAAG,EAAE,CACT,gBAAgB,CACd,IAAI,EACJ,KAAK,EACL,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAC/D,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,EACrB,CAAC,WAAW,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,CACjE;SACJ,CAAC,CACH,CAAC;QACF,IAAI,SAAS,CAAC,OAAO;YACnB,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,IAAI,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,sEAAsE;QACtE,yEAAyE;QACzE,gEAAgE;QAChE,iDAAiD;QACjD,IAAI,SAAS,CAAC,OAAO;YAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,uBAAuB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"run-apply-routes.js","sourceRoot":"","sources":["../src/run-apply-routes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-events-stream.d.ts","sourceRoot":"","sources":["../src/run-events-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACjE,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAChE,IAAI,EAAE;QACJ,MAAM,EAAE;YAAE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;SAAE,CAAC;QACzD,GAAG,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;SAAE,GAAG,SAAS,CAAC;QACtF,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,eAAe,EACpB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Hf"}
1
+ {"version":3,"file":"run-events-stream.d.ts","sourceRoot":"","sources":["../src/run-events-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACjE,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAChE,IAAI,EAAE;QACJ,MAAM,EAAE;YAAE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;SAAE,CAAC;QACzD,GAAG,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE;gBAAE,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;SAAE,GAAG,SAAS,CAAC;QACtF,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,eAAe,EACpB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA0Jf"}
@@ -44,87 +44,122 @@ export async function streamRunEvents(ctx, id, lastEventId, req, res) {
44
44
  }, ctx.opts.heartbeatMs ?? 15_000);
45
45
  heartbeat.unref?.();
46
46
  let draining = false;
47
+ // Lost-wakeup latch (QA-018 / backlog C2): a bus push or poll tick that
48
+ // arrives while a drain pass already holds `draining` must not be dropped as
49
+ // a no-op — it records a pending re-check the drain loop honors before it
50
+ // concludes. The durable file stays the single ordered source; this bit only
51
+ // guarantees the tailer looks again.
52
+ let pending = false;
47
53
  const writeAvailable = async () => {
48
- if (closed || draining)
54
+ if (closed)
49
55
  return;
56
+ if (draining) {
57
+ pending = true;
58
+ return;
59
+ }
50
60
  // The re-entrancy guard must cover the QUEUED-phase status await too:
51
61
  // with drain-await backpressure in the replay loop, two triggers (poll
52
62
  // timer + bus push) passing this point concurrently could interleave
53
63
  // out-of-order seq writes. One flag spans the whole invocation.
54
64
  draining = true;
55
- if (!eventsPath) {
56
- // Still queued: poll the job until the run binds its dir (then tail
57
- // it) or the job goes terminal without one (validation failure — a
58
- // run that never materialized ends the stream honestly).
59
- const latest = await ctx.opts.daemon.status(rec.id).catch(() => rec);
60
- if (latest.runDir) {
61
- eventsPath = join(latest.runDir, "events.jsonl");
62
- }
63
- else if (TERMINAL_STATES.has(latest.state)) {
64
- res.write("event: end\ndata: {}\n\n");
65
- res.end();
66
- cleanup();
67
- return;
68
- }
69
- else {
70
- draining = false;
71
- return;
72
- }
73
- }
74
- if (!existsSync(eventsPath)) {
75
- draining = false;
76
- return;
77
- }
78
65
  try {
79
- const { lines, nextOffset, rest } = readNewLines(eventsPath, offset, carry);
80
- offset = nextOffset;
81
- carry = rest;
82
- for (const raw of lines) {
83
- lineNo += 1;
84
- // Durable cursor: the event's own persisted seq. Legacy lines without
85
- // one fall back to their line number (matching EventLog's counter
86
- // init), so resume ids stay consistent either way.
87
- let seq = lineNo;
88
- let type = "run";
89
- try {
90
- const parsed = JSON.parse(raw);
91
- type = String(parsed.type ?? "run");
92
- if (typeof parsed.seq === "number" && Number.isFinite(parsed.seq))
93
- seq = parsed.seq;
66
+ // Drain-until-stable: re-read the file after every productive pass and
67
+ // after any pending wakeup, so a terminal tail appended between a read and
68
+ // the status probe is never left undelivered.
69
+ for (;;) {
70
+ pending = false;
71
+ if (!eventsPath) {
72
+ // Still queued: poll the job until the run binds its dir (then tail
73
+ // it) or the job goes terminal without one (validation failure — a
74
+ // run that never materialized ends the stream honestly).
75
+ const latest = await ctx.opts.daemon.status(rec.id).catch(() => rec);
76
+ if (latest.runDir) {
77
+ eventsPath = join(latest.runDir, "events.jsonl");
78
+ }
79
+ else if (TERMINAL_STATES.has(latest.state)) {
80
+ res.write("event: end\ndata: {}\n\n");
81
+ res.end();
82
+ cleanup();
83
+ return;
84
+ }
85
+ else {
86
+ if (pending)
87
+ continue;
88
+ return;
89
+ }
94
90
  }
95
- catch {
96
- type = "malformed";
91
+ if (!existsSync(eventsPath)) {
92
+ if (pending)
93
+ continue;
94
+ return;
97
95
  }
98
- if (seq <= lastEventId)
99
- continue;
100
- // Backpressure: a large replay into a slow client must not balloon
101
- // the socket buffer — pause the tail until the kernel drains it
102
- // (or the client goes away, which resolves via `close`).
103
- if (!res.write(`id: ${seq}\nevent: ${type}\ndata: ${redactedSseLine(raw)}\n\n`)) {
104
- await new Promise((resolve) => {
105
- const done = () => {
106
- res.off("drain", done);
107
- res.off("close", done);
108
- resolve();
109
- };
110
- res.once("drain", done);
111
- res.once("close", done);
112
- });
113
- if (closed)
96
+ const { lines, nextOffset, rest } = readNewLines(eventsPath, offset, carry);
97
+ offset = nextOffset;
98
+ carry = rest;
99
+ for (const raw of lines) {
100
+ lineNo += 1;
101
+ // Durable cursor: the event's own persisted seq. Legacy lines without
102
+ // one fall back to their line number (matching EventLog's counter
103
+ // init), so resume ids stay consistent either way.
104
+ let seq = lineNo;
105
+ let type = "run";
106
+ try {
107
+ const parsed = JSON.parse(raw);
108
+ type = String(parsed.type ?? "run");
109
+ if (typeof parsed.seq === "number" && Number.isFinite(parsed.seq))
110
+ seq = parsed.seq;
111
+ }
112
+ catch {
113
+ type = "malformed";
114
+ }
115
+ if (seq <= lastEventId)
116
+ continue;
117
+ // Backpressure: a large replay into a slow client must not balloon
118
+ // the socket buffer — pause the tail until the kernel drains it
119
+ // (or the client goes away, which resolves via `close`).
120
+ if (!res.write(`id: ${seq}\nevent: ${type}\ndata: ${redactedSseLine(raw)}\n\n`)) {
121
+ await new Promise((resolve) => {
122
+ const done = () => {
123
+ res.off("drain", done);
124
+ res.off("close", done);
125
+ resolve();
126
+ };
127
+ res.once("drain", done);
128
+ res.once("close", done);
129
+ });
130
+ if (closed)
131
+ return;
132
+ }
133
+ if (type === "run.completed" || type === "run.failed" || type === "run.blocked") {
134
+ res.write("event: end\ndata: {}\n\n");
135
+ res.end();
136
+ cleanup();
114
137
  return;
138
+ }
115
139
  }
116
- if (type === "run.completed" || type === "run.failed" || type === "run.blocked") {
140
+ // A productive pass may have surfaced only a PREFIX of the tail: loop to
141
+ // re-read from the advanced cursor before deciding anything.
142
+ if (lines.length > 0)
143
+ continue;
144
+ const latest = await ctx.opts.daemon.status(rec.id).catch(() => rec);
145
+ if (TERMINAL_STATES.has(latest.state)) {
146
+ // A materialized run appends its canonical terminal event to the file
147
+ // BEFORE the daemon commits terminal job state, so once status is
148
+ // terminal the terminal event is durably readable. Re-check the file
149
+ // cursor: only conclude `end` when the file yields nothing new AND a
150
+ // wakeup is not already pending — otherwise loop and deliver the tail,
151
+ // whose canonical terminal ends the stream through the branch above.
152
+ const tail = readNewLines(eventsPath, offset, carry);
153
+ if (tail.lines.length > 0 || pending)
154
+ continue;
117
155
  res.write("event: end\ndata: {}\n\n");
118
156
  res.end();
119
157
  cleanup();
120
158
  return;
121
159
  }
122
- }
123
- const latest = await ctx.opts.daemon.status(rec.id).catch(() => rec);
124
- if (TERMINAL_STATES.has(latest.state)) {
125
- res.write("event: end\ndata: {}\n\n");
126
- res.end();
127
- cleanup();
160
+ if (pending)
161
+ continue;
162
+ return;
128
163
  }
129
164
  }
130
165
  finally {