yuurei 0.0.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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/dist/artifact/collector.d.ts +15 -0
  4. package/dist/artifact/collector.d.ts.map +1 -0
  5. package/dist/artifact/collector.js +87 -0
  6. package/dist/artifact/collector.js.map +1 -0
  7. package/dist/artifact/types.d.ts +10 -0
  8. package/dist/artifact/types.d.ts.map +1 -0
  9. package/dist/artifact/types.js +2 -0
  10. package/dist/artifact/types.js.map +1 -0
  11. package/dist/cell/digest.d.ts +10 -0
  12. package/dist/cell/digest.d.ts.map +1 -0
  13. package/dist/cell/digest.js +13 -0
  14. package/dist/cell/digest.js.map +1 -0
  15. package/dist/cell/resolver.d.ts +18 -0
  16. package/dist/cell/resolver.d.ts.map +1 -0
  17. package/dist/cell/resolver.js +41 -0
  18. package/dist/cell/resolver.js.map +1 -0
  19. package/dist/cell/types.d.ts +48 -0
  20. package/dist/cell/types.d.ts.map +1 -0
  21. package/dist/cell/types.js +2 -0
  22. package/dist/cell/types.js.map +1 -0
  23. package/dist/cli/clean.d.ts +16 -0
  24. package/dist/cli/clean.d.ts.map +1 -0
  25. package/dist/cli/clean.js +24 -0
  26. package/dist/cli/clean.js.map +1 -0
  27. package/dist/cli/doctor.d.ts +29 -0
  28. package/dist/cli/doctor.d.ts.map +1 -0
  29. package/dist/cli/doctor.js +160 -0
  30. package/dist/cli/doctor.js.map +1 -0
  31. package/dist/cli/exit-codes.d.ts +15 -0
  32. package/dist/cli/exit-codes.d.ts.map +1 -0
  33. package/dist/cli/exit-codes.js +18 -0
  34. package/dist/cli/exit-codes.js.map +1 -0
  35. package/dist/cli/init.d.ts +32 -0
  36. package/dist/cli/init.d.ts.map +1 -0
  37. package/dist/cli/init.js +143 -0
  38. package/dist/cli/init.js.map +1 -0
  39. package/dist/cli/inspect.d.ts +4 -0
  40. package/dist/cli/inspect.d.ts.map +1 -0
  41. package/dist/cli/inspect.js +24 -0
  42. package/dist/cli/inspect.js.map +1 -0
  43. package/dist/cli/output.d.ts +5 -0
  44. package/dist/cli/output.d.ts.map +1 -0
  45. package/dist/cli/output.js +5 -0
  46. package/dist/cli/output.js.map +1 -0
  47. package/dist/cli/profile-list.d.ts +3 -0
  48. package/dist/cli/profile-list.d.ts.map +1 -0
  49. package/dist/cli/profile-list.js +14 -0
  50. package/dist/cli/profile-list.js.map +1 -0
  51. package/dist/cli/run.d.ts +22 -0
  52. package/dist/cli/run.d.ts.map +1 -0
  53. package/dist/cli/run.js +95 -0
  54. package/dist/cli/run.js.map +1 -0
  55. package/dist/cli/trace-show.d.ts +3 -0
  56. package/dist/cli/trace-show.d.ts.map +1 -0
  57. package/dist/cli/trace-show.js +22 -0
  58. package/dist/cli/trace-show.js.map +1 -0
  59. package/dist/config/discovery.d.ts +3 -0
  60. package/dist/config/discovery.d.ts.map +1 -0
  61. package/dist/config/discovery.js +18 -0
  62. package/dist/config/discovery.js.map +1 -0
  63. package/dist/config/schema.d.ts +21 -0
  64. package/dist/config/schema.d.ts.map +1 -0
  65. package/dist/config/schema.js +19 -0
  66. package/dist/config/schema.js.map +1 -0
  67. package/dist/config/yuurei-config.d.ts +4 -0
  68. package/dist/config/yuurei-config.d.ts.map +1 -0
  69. package/dist/config/yuurei-config.js +10 -0
  70. package/dist/config/yuurei-config.js.map +1 -0
  71. package/dist/cost/noop.d.ts +7 -0
  72. package/dist/cost/noop.d.ts.map +1 -0
  73. package/dist/cost/noop.js +10 -0
  74. package/dist/cost/noop.js.map +1 -0
  75. package/dist/cost/types.d.ts +21 -0
  76. package/dist/cost/types.d.ts.map +1 -0
  77. package/dist/cost/types.js +2 -0
  78. package/dist/cost/types.js.map +1 -0
  79. package/dist/index.d.ts +3 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +111 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/isolation/config-root.d.ts +9 -0
  84. package/dist/isolation/config-root.d.ts.map +1 -0
  85. package/dist/isolation/config-root.js +10 -0
  86. package/dist/isolation/config-root.js.map +1 -0
  87. package/dist/isolation/env.d.ts +2 -0
  88. package/dist/isolation/env.d.ts.map +1 -0
  89. package/dist/isolation/env.js +17 -0
  90. package/dist/isolation/env.js.map +1 -0
  91. package/dist/isolation/index.d.ts +9 -0
  92. package/dist/isolation/index.d.ts.map +1 -0
  93. package/dist/isolation/index.js +21 -0
  94. package/dist/isolation/index.js.map +1 -0
  95. package/dist/isolation/level0.d.ts +20 -0
  96. package/dist/isolation/level0.d.ts.map +1 -0
  97. package/dist/isolation/level0.js +51 -0
  98. package/dist/isolation/level0.js.map +1 -0
  99. package/dist/isolation/level1.d.ts +13 -0
  100. package/dist/isolation/level1.d.ts.map +1 -0
  101. package/dist/isolation/level1.js +58 -0
  102. package/dist/isolation/level1.js.map +1 -0
  103. package/dist/isolation/tempdir.d.ts +53 -0
  104. package/dist/isolation/tempdir.d.ts.map +1 -0
  105. package/dist/isolation/tempdir.js +87 -0
  106. package/dist/isolation/tempdir.js.map +1 -0
  107. package/dist/isolation/types.d.ts +37 -0
  108. package/dist/isolation/types.d.ts.map +1 -0
  109. package/dist/isolation/types.js +2 -0
  110. package/dist/isolation/types.js.map +1 -0
  111. package/dist/profile/loader.d.ts +9 -0
  112. package/dist/profile/loader.d.ts.map +1 -0
  113. package/dist/profile/loader.js +95 -0
  114. package/dist/profile/loader.js.map +1 -0
  115. package/dist/profile/manifest.d.ts +29 -0
  116. package/dist/profile/manifest.d.ts.map +1 -0
  117. package/dist/profile/manifest.js +28 -0
  118. package/dist/profile/manifest.js.map +1 -0
  119. package/dist/profile/types.d.ts +31 -0
  120. package/dist/profile/types.d.ts.map +1 -0
  121. package/dist/profile/types.js +2 -0
  122. package/dist/profile/types.js.map +1 -0
  123. package/dist/run/id.d.ts +7 -0
  124. package/dist/run/id.d.ts.map +1 -0
  125. package/dist/run/id.js +15 -0
  126. package/dist/run/id.js.map +1 -0
  127. package/dist/run/layout.d.ts +27 -0
  128. package/dist/run/layout.d.ts.map +1 -0
  129. package/dist/run/layout.js +45 -0
  130. package/dist/run/layout.js.map +1 -0
  131. package/dist/run/pipeline.d.ts +45 -0
  132. package/dist/run/pipeline.d.ts.map +1 -0
  133. package/dist/run/pipeline.js +246 -0
  134. package/dist/run/pipeline.js.map +1 -0
  135. package/dist/run/signals.d.ts +53 -0
  136. package/dist/run/signals.d.ts.map +1 -0
  137. package/dist/run/signals.js +74 -0
  138. package/dist/run/signals.js.map +1 -0
  139. package/dist/runtime/claude-code/args.d.ts +8 -0
  140. package/dist/runtime/claude-code/args.d.ts.map +1 -0
  141. package/dist/runtime/claude-code/args.js +13 -0
  142. package/dist/runtime/claude-code/args.js.map +1 -0
  143. package/dist/runtime/claude-code/index.d.ts +11 -0
  144. package/dist/runtime/claude-code/index.d.ts.map +1 -0
  145. package/dist/runtime/claude-code/index.js +167 -0
  146. package/dist/runtime/claude-code/index.js.map +1 -0
  147. package/dist/runtime/claude-code/paths.d.ts +3 -0
  148. package/dist/runtime/claude-code/paths.d.ts.map +1 -0
  149. package/dist/runtime/claude-code/paths.js +6 -0
  150. package/dist/runtime/claude-code/paths.js.map +1 -0
  151. package/dist/runtime/codex/args.d.ts +21 -0
  152. package/dist/runtime/codex/args.d.ts.map +1 -0
  153. package/dist/runtime/codex/args.js +35 -0
  154. package/dist/runtime/codex/args.js.map +1 -0
  155. package/dist/runtime/codex/index.d.ts +13 -0
  156. package/dist/runtime/codex/index.d.ts.map +1 -0
  157. package/dist/runtime/codex/index.js +299 -0
  158. package/dist/runtime/codex/index.js.map +1 -0
  159. package/dist/runtime/codex/paths.d.ts +3 -0
  160. package/dist/runtime/codex/paths.d.ts.map +1 -0
  161. package/dist/runtime/codex/paths.js +6 -0
  162. package/dist/runtime/codex/paths.js.map +1 -0
  163. package/dist/runtime/detect.d.ts +5 -0
  164. package/dist/runtime/detect.d.ts.map +1 -0
  165. package/dist/runtime/detect.js +42 -0
  166. package/dist/runtime/detect.js.map +1 -0
  167. package/dist/runtime/exec.d.ts +24 -0
  168. package/dist/runtime/exec.d.ts.map +1 -0
  169. package/dist/runtime/exec.js +132 -0
  170. package/dist/runtime/exec.js.map +1 -0
  171. package/dist/runtime/registry.d.ts +4 -0
  172. package/dist/runtime/registry.d.ts.map +1 -0
  173. package/dist/runtime/registry.js +23 -0
  174. package/dist/runtime/registry.js.map +1 -0
  175. package/dist/runtime/reserved-paths.d.ts +22 -0
  176. package/dist/runtime/reserved-paths.d.ts.map +1 -0
  177. package/dist/runtime/reserved-paths.js +30 -0
  178. package/dist/runtime/reserved-paths.js.map +1 -0
  179. package/dist/runtime/types.d.ts +105 -0
  180. package/dist/runtime/types.d.ts.map +1 -0
  181. package/dist/runtime/types.js +2 -0
  182. package/dist/runtime/types.js.map +1 -0
  183. package/dist/trace/reader.d.ts +4 -0
  184. package/dist/trace/reader.d.ts.map +1 -0
  185. package/dist/trace/reader.js +9 -0
  186. package/dist/trace/reader.js.map +1 -0
  187. package/dist/trace/redact.d.ts +22 -0
  188. package/dist/trace/redact.d.ts.map +1 -0
  189. package/dist/trace/redact.js +124 -0
  190. package/dist/trace/redact.js.map +1 -0
  191. package/dist/trace/schema.d.ts +49 -0
  192. package/dist/trace/schema.d.ts.map +1 -0
  193. package/dist/trace/schema.js +53 -0
  194. package/dist/trace/schema.js.map +1 -0
  195. package/dist/trace/writer.d.ts +17 -0
  196. package/dist/trace/writer.d.ts.map +1 -0
  197. package/dist/trace/writer.js +45 -0
  198. package/dist/trace/writer.js.map +1 -0
  199. package/dist/util/fs.d.ts +17 -0
  200. package/dist/util/fs.d.ts.map +1 -0
  201. package/dist/util/fs.js +61 -0
  202. package/dist/util/fs.js.map +1 -0
  203. package/dist/util/hash.d.ts +3 -0
  204. package/dist/util/hash.d.ts.map +1 -0
  205. package/dist/util/hash.js +7 -0
  206. package/dist/util/hash.js.map +1 -0
  207. package/dist/util/json.d.ts +8 -0
  208. package/dist/util/json.d.ts.map +1 -0
  209. package/dist/util/json.js +24 -0
  210. package/dist/util/json.js.map +1 -0
  211. package/dist/util/logger.d.ts +8 -0
  212. package/dist/util/logger.d.ts.map +1 -0
  213. package/dist/util/logger.js +16 -0
  214. package/dist/util/logger.js.map +1 -0
  215. package/dist/version.d.ts +24 -0
  216. package/dist/version.d.ts.map +1 -0
  217. package/dist/version.js +26 -0
  218. package/dist/version.js.map +1 -0
  219. package/docs/assets/yuurei-top.jpg +0 -0
  220. package/package.json +61 -0
@@ -0,0 +1,246 @@
1
+ import { rm, writeFile } from 'node:fs/promises';
2
+ import { NoopCostModel } from '../cost/noop.js';
3
+ import { installSignalCleanup } from './signals.js';
4
+ import { resolveCell } from '../cell/resolver.js';
5
+ import { collectArtifacts, DEFAULT_ARTIFACT_MAX_BYTES, writeArtifactManifest, } from '../artifact/collector.js';
6
+ import { createIsolation, createVerifiedIsolation } from '../isolation/index.js';
7
+ import { toProfileManifest } from '../profile/manifest.js';
8
+ import { getRuntime } from '../runtime/registry.js';
9
+ import { writeTrace } from '../trace/writer.js';
10
+ import { redactFile } from '../trace/redact.js';
11
+ import { TRACE_SCHEMA_VERSION } from '../trace/schema.js';
12
+ import { createUniqueRunLayout } from './layout.js';
13
+ /**
14
+ * The single place that orders a run's execution:
15
+ * resolve → isolate → verify (fail-closed) → prepare → execute →
16
+ * normalize → write trace → collect artifacts. No other module should
17
+ * re-implement this ordering (design doc §12.2 fail-closed principle).
18
+ */
19
+ export async function runPipeline(input) {
20
+ const cell = await resolveCell(input);
21
+ const { runId, layout } = await createUniqueRunLayout(input.yuureiDir);
22
+ const isolation = (input.createIsolation ?? createIsolation)(input.isolationStrategy);
23
+ let context;
24
+ try {
25
+ context = await createVerifiedIsolation(isolation, cell);
26
+ }
27
+ catch (error) {
28
+ // Isolation verification failed (§12.2 fail-closed). The run dir was
29
+ // already created; remove it so no partial directory is left behind.
30
+ await rm(layout.runDir, { recursive: true, force: true }).catch(() => { });
31
+ throw error;
32
+ }
33
+ context.keep = input.keep;
34
+ let prepared;
35
+ let scrubbed = false;
36
+ let disposed = false;
37
+ let traceWritten = false;
38
+ let runDirRemoved = false;
39
+ const warn = (message) => input.onWarning?.(message);
40
+ /**
41
+ * Every credential path an adapter writes during `prepare()` is registered
42
+ * here at the moment of the write. The scrub reads from this sink rather
43
+ * than from `prepared.credentialFilePaths`, which only exists once
44
+ * prepare() has returned — so a signal or throw between the write and the
45
+ * return no longer strands credential material (design doc §9.2, audit
46
+ * Finding 1).
47
+ */
48
+ const registeredCredentialPaths = new Set();
49
+ const scrubCredentials = async () => {
50
+ // Credential material should never survive a run, even under `--keep` —
51
+ // `--keep` preserves config/logs for debugging, never bridged auth
52
+ // material. Best-effort, not a guarantee: a failed deletion is reported
53
+ // via onWarning (naming the residual path) rather than silently
54
+ // swallowed. Shared by the finally block and the signal handler, guarded
55
+ // so a signal arriving mid-cleanup can't double-scrub and double-report.
56
+ if (scrubbed)
57
+ return;
58
+ scrubbed = true;
59
+ await Promise.all([...registeredCredentialPaths].map(async (path) => {
60
+ try {
61
+ await rm(path, { force: true });
62
+ }
63
+ catch (error) {
64
+ warn(`failed to scrub credential file, it may still be present on disk: ${path} (${error instanceof Error ? error.message : String(error)})`);
65
+ }
66
+ }));
67
+ };
68
+ /**
69
+ * `discardKept` overrides the context's own `keep` for this disposal only.
70
+ * Passed as a value rather than written back onto `context`, so the decision
71
+ * is visible at the call site instead of as a side effect on shared state.
72
+ */
73
+ const disposeContext = async (discardKept = false) => {
74
+ if (disposed)
75
+ return;
76
+ disposed = true;
77
+ await isolation.dispose(discardKept ? { ...context, keep: false } : context);
78
+ };
79
+ const removeRunDir = async () => {
80
+ if (runDirRemoved)
81
+ return;
82
+ runDirRemoved = true;
83
+ try {
84
+ await rm(layout.runDir, { recursive: true, force: true });
85
+ }
86
+ catch (error) {
87
+ warn(`failed to remove partial run directory: ${layout.runDir} (${error instanceof Error ? error.message : String(error)})`);
88
+ }
89
+ };
90
+ /**
91
+ * The actual cleanup lifecycle, run exactly once. `cleanup` below memoizes
92
+ * this promise so that every caller — the finally block and the signal
93
+ * handler — awaits the *same* in-flight lifecycle. Without the memoization,
94
+ * a caller arriving while another caller's scrub/dispose is mid-await would
95
+ * short-circuit through the boolean guards (`scrubbed`/`disposed` are set
96
+ * before their awaits complete), return immediately, and let the signal
97
+ * handler's `process.exit()` fire before the first caller's in-flight
98
+ * rm/dispose had settled.
99
+ */
100
+ const runCleanup = async () => {
101
+ // Scrub before dispose() so this runs regardless of which branch above
102
+ // threw, and so a signal killing the process mid-dispose never leaves
103
+ // credential material behind.
104
+ await scrubCredentials();
105
+ // `prepared` only exists once prepare() has returned. If the run ended
106
+ // before that point AND the adapter registered no credential paths, we
107
+ // cannot rule out an unregistered credential write — removing the whole
108
+ // root is the only safe choice under `--keep` (§9.2). Once a path is
109
+ // registered the scrub handled it above, so the rest of the root may be
110
+ // kept for debugging.
111
+ const startedRuntime = prepared !== undefined;
112
+ const cannotIdentifyCredentials = !startedRuntime && registeredCredentialPaths.size === 0;
113
+ if (cannotIdentifyCredentials && context.keep) {
114
+ warn(`run ended before the runtime started; removing the isolation directory despite --keep, because credential material written during setup cannot be identified: ${context.rootDir}`);
115
+ }
116
+ // If no trace was written (signal-interrupted or threw before writeTrace),
117
+ // remove the partial run directory so no undocumented directory is left
118
+ // that cannot be consumed by `yuurei trace show`. This must run even when
119
+ // isolation.dispose() rejects: a disposal failure must not strand the run
120
+ // directory as if the run were complete (review #116). disposeContext
121
+ // itself never throws from here — its rejection propagates out of
122
+ // runCleanup after the run directory has been handled.
123
+ try {
124
+ await disposeContext(cannotIdentifyCredentials);
125
+ }
126
+ finally {
127
+ if (!traceWritten) {
128
+ await removeRunDir();
129
+ }
130
+ }
131
+ };
132
+ let cleanupPromise = null;
133
+ const cleanup = () => {
134
+ cleanupPromise ??= runCleanup();
135
+ return cleanupPromise;
136
+ };
137
+ const signalCleanup = installSignalCleanup({ cleanup });
138
+ let primaryError;
139
+ try {
140
+ const runtime = (input.resolveRuntime ?? getRuntime)(cell.runtimeId);
141
+ prepared = await runtime.prepare(cell, context, (path) => registeredCredentialPaths.add(path));
142
+ const result = await runtime.execute(prepared, input.timeoutMs ?? null);
143
+ const fragment = await runtime.normalize(result, { runtimeVersion: prepared.runtimeVersion });
144
+ for (const w of fragment.warnings ?? [])
145
+ warn(w);
146
+ const costModel = new NoopCostModel();
147
+ const costEstimate = await costModel.estimate({
148
+ runtimeId: cell.runtimeId,
149
+ model: cell.requestedModel,
150
+ tokensIn: fragment.usage['input_tokens'] ?? null,
151
+ tokensOut: fragment.usage['output_tokens'] ?? null,
152
+ });
153
+ const knownCredentialValues = prepared.credentialValuesToRedact;
154
+ const maxArtifactBytes = input.maxArtifactBytes ?? DEFAULT_ARTIFACT_MAX_BYTES;
155
+ const redactLog = async (inputPath, outputPath) => {
156
+ try {
157
+ return await redactFile(inputPath, outputPath, knownCredentialValues, maxArtifactBytes);
158
+ }
159
+ catch (err) {
160
+ if (err.code === 'ENOENT') {
161
+ await writeFile(outputPath, '', 'utf8');
162
+ return false;
163
+ }
164
+ throw err;
165
+ }
166
+ };
167
+ const [stdoutTruncated, stderrTruncated] = await Promise.all([
168
+ redactLog(result.stdoutPath, layout.stdoutPath),
169
+ redactLog(result.stderrPath, layout.stderrPath),
170
+ ]);
171
+ // Collect artifacts and persist every durable output BEFORE the trace is
172
+ // written. trace.json is the completion marker: it is written last, so a
173
+ // failure in any step above leaves a run directory with no trace.json,
174
+ // which cleanup removes and `yuurei trace show` cannot consume. The
175
+ // artifact list in the trace is derived from the manifest, so the two can
176
+ // never disagree (#111).
177
+ const manifest = await collectArtifacts(layout.runDir, ['stdout.log', 'stderr.log'], {
178
+ maxBytes: maxArtifactBytes,
179
+ truncatedPaths: [
180
+ ...(stdoutTruncated ? ['stdout.log'] : []),
181
+ ...(stderrTruncated ? ['stderr.log'] : []),
182
+ ],
183
+ });
184
+ await writeArtifactManifest(layout.runDir, manifest);
185
+ // Identity, not content: §10.1 records a digest of the profile content,
186
+ // and §10.2 keeps a profile's own secrets out of the durable run dir.
187
+ await writeFile(layout.resolvedProfilePath, JSON.stringify(toProfileManifest(cell.resolvedProfile), null, 2), 'utf8');
188
+ const trace = {
189
+ schema_version: TRACE_SCHEMA_VERSION,
190
+ run_id: runId,
191
+ started_at: result.startedAt,
192
+ finished_at: result.finishedAt,
193
+ runtime: fragment.runtime,
194
+ model: { requested: cell.requestedModel, resolved: fragment.model.resolved },
195
+ profile: { name: cell.resolvedProfile.name, digest: cell.resolvedProfile.digest },
196
+ task: { source: cell.resolvedTask.source, digest: cell.resolvedTask.digest },
197
+ isolation: { strategy: context.strategy, verified: true },
198
+ execution: {
199
+ exit_code: fragment.execution.exitCode,
200
+ signal: fragment.execution.signal,
201
+ duration_ms: fragment.execution.durationMs,
202
+ timed_out: result.timedOut,
203
+ },
204
+ usage: fragment.usage,
205
+ cost: costEstimate.amount === null
206
+ ? null
207
+ : { amount: costEstimate.amount, currency: costEstimate.currency ?? 'USD' },
208
+ // The actual artifacts just collected — mirrors artifacts.json rather
209
+ // than a placeholder empty list.
210
+ artifacts: manifest.artifacts.map(({ path, kind }) => ({ path, kind })),
211
+ };
212
+ await writeTrace(layout.runDir, trace);
213
+ traceWritten = true;
214
+ return { runId, runDir: layout.runDir, cell, trace };
215
+ }
216
+ catch (error) {
217
+ primaryError = error;
218
+ throw error;
219
+ }
220
+ finally {
221
+ // The finally block and the signal handler share ONE memoized cleanup
222
+ // promise (see `cleanup` above), so a signal arriving while this block is
223
+ // mid-cleanup joins the in-flight lifecycle instead of starting a second
224
+ // one: the handler's `await options.cleanup()` waits for the same
225
+ // scrub/dispose this block is awaiting, and its `process.exit()` fires
226
+ // only after both have settled. The handler stays installed until the
227
+ // cleanup has finished so a signal in that window is caught rather than
228
+ // taking the default disposition mid-rm; it is uninstalled last, closing
229
+ // the tiny post-completion window where an unrelated signal would be a
230
+ // no-op handler on an already-finished run.
231
+ try {
232
+ if (primaryError !== undefined) {
233
+ // The run already failed; a cleanup failure must not mask the primary
234
+ // error — report it via onWarning and let the original error propagate.
235
+ await cleanup().catch((cleanupError) => warn(`cleanup failed after the run failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`));
236
+ }
237
+ else {
238
+ await cleanup();
239
+ }
240
+ }
241
+ finally {
242
+ signalCleanup.uninstall();
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/run/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAA4B,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAoCpD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEvE,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,eAAe,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACtF,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qEAAqE;QACrE,qEAAqE;QACrE,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1E,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAE1B,IAAI,QAAiC,CAAC;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;IAE7D;;;;;;;OAOG;IACH,MAAM,yBAAyB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpD,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAClC,wEAAwE;QACxE,mEAAmE;QACnE,wEAAwE;QACxE,gEAAgE;QAChE,yEAAyE;QACzE,yEAAyE;QACzE,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,GAAG,yBAAyB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAChD,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CACF,qEAAqE,IAAI,KACvE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,GAAG,CACJ,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF;;;;OAIG;IACH,MAAM,cAAc,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,EAAE,EAAE;QACnD,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/E,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC9B,IAAI,aAAa;YAAE,OAAO;QAC1B,aAAa,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CACF,2CAA2C,MAAM,CAAC,MAAM,KACtD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;;;;;;;;OASG;IACH,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,uEAAuE;QACvE,sEAAsE;QACtE,8BAA8B;QAC9B,MAAM,gBAAgB,EAAE,CAAC;QACzB,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,sBAAsB;QACtB,MAAM,cAAc,GAAG,QAAQ,KAAK,SAAS,CAAC;QAC9C,MAAM,yBAAyB,GAAG,CAAC,cAAc,IAAI,yBAAyB,CAAC,IAAI,KAAK,CAAC,CAAC;QAC1F,IAAI,yBAAyB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,CACF,iKAAiK,OAAO,CAAC,OAAO,EAAE,CACnL,CAAC;QACJ,CAAC;QACD,2EAA2E;QAC3E,wEAAwE;QACxE,0EAA0E;QAC1E,0EAA0E;QAC1E,sEAAsE;QACtE,kEAAkE;QAClE,uDAAuD;QACvD,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,YAAY,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,cAAc,GAAyB,IAAI,CAAC;IAChD,MAAM,OAAO,GAAG,GAAkB,EAAE;QAClC,cAAc,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,oBAAoB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACxD,IAAI,YAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,cAAc,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrE,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;QAC9F,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE;YAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAEjD,MAAM,SAAS,GAAG,IAAI,aAAa,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;YAC5C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,cAAc;YAC1B,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,IAAI;YAChD,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,IAAI;SACnD,CAAC,CAAC;QAEH,MAAM,qBAAqB,GAAG,QAAQ,CAAC,wBAAwB,CAAC;QAChE,MAAM,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;QAC9E,MAAM,SAAS,GAAG,KAAK,EAAE,SAAiB,EAAE,UAAkB,EAAoB,EAAE;YAClF,IAAI,CAAC;gBACH,OAAO,MAAM,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,CAAC,CAAC;YAC1F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACrD,MAAM,SAAS,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;oBACxC,OAAO,KAAK,CAAC;gBACf,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC3D,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;YAC/C,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;SAChD,CAAC,CAAC;QAEH,yEAAyE;QACzE,yEAAyE;QACzE,uEAAuE;QACvE,oEAAoE;QACpE,0EAA0E;QAC1E,yBAAyB;QACzB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE;YACnF,QAAQ,EAAE,gBAAgB;YAC1B,cAAc,EAAE;gBACd,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1C,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3C;SACF,CAAC,CAAC;QACH,MAAM,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrD,wEAAwE;QACxE,sEAAsE;QACtE,MAAM,SAAS,CACb,MAAM,CAAC,mBAAmB,EAC1B,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAChE,MAAM,CACP,CAAC;QAEF,MAAM,KAAK,GAAU;YACnB,cAAc,EAAE,oBAAoB;YACpC,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,MAAM,CAAC,SAAS;YAC5B,WAAW,EAAE,MAAM,CAAC,UAAU;YAC9B,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC5E,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;YACjF,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YAC5E,SAAS,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;YACzD,SAAS,EAAE;gBACT,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,QAAQ;gBACtC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM;gBACjC,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,UAAU;gBAC1C,SAAS,EAAE,MAAM,CAAC,QAAQ;aAC3B;YACD,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,IAAI,EACF,YAAY,CAAC,MAAM,KAAK,IAAI;gBAC1B,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,IAAI,KAAK,EAAE;YAC/E,sEAAsE;YACtE,iCAAiC;YACjC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;SACxE,CAAC;QAEF,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvC,YAAY,GAAG,IAAI,CAAC;QAEpB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,GAAG,KAAK,CAAC;QACrB,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,sEAAsE;QACtE,0EAA0E;QAC1E,yEAAyE;QACzE,kEAAkE;QAClE,uEAAuE;QACvE,sEAAsE;QACtE,wEAAwE;QACxE,yEAAyE;QACzE,uEAAuE;QACvE,4CAA4C;QAC5C,IAAI,CAAC;YACH,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC/B,sEAAsE;gBACtE,wEAAwE;gBACxE,MAAM,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,EAAE,CACrC,IAAI,CACF,wCACE,YAAY,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAC5E,EAAE,CACH,CACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,OAAO,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,SAAS,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Exit codes for dying to a caught signal, using the shell convention of
3
+ * 128 + signal number (SIGINT is 2, SIGTERM is 15). A parent shell or CI
4
+ * runner watching `yuurei run` sees the same code it would see for a
5
+ * normally-killed child, rather than yuurei reporting its own error code for
6
+ * an interruption it handled itself.
7
+ */
8
+ export declare const SIGNAL_EXIT_CODES: Record<string, number>;
9
+ /**
10
+ * Maps a signal name to the shell-convention exit code (128 + signal number).
11
+ * Handles SIGINT (130) and SIGTERM (143) by the well-known table; falls back
12
+ * to 128 for any other signal so the process never exits 0 for a killed run.
13
+ */
14
+ export declare function exitCodeForSignal(signal: string): number;
15
+ export interface SignalCleanupOptions {
16
+ /**
17
+ * Cleans up the active run (credential scrub + isolation dispose) and
18
+ * reports any non-fatal failure via the same warning channel the normal
19
+ * finally block uses. Must be safe to call more than once.
20
+ */
21
+ cleanup: () => Promise<void>;
22
+ }
23
+ export interface SignalCleanupHandle {
24
+ /**
25
+ * Removes both handlers so a signal arriving after the run completed
26
+ * normally hits the default disposition instead of re-entering the
27
+ * cleanup/exit path. The pipeline calls this from its finally block.
28
+ */
29
+ uninstall(): void;
30
+ }
31
+ /**
32
+ * Installs best-effort cleanup on SIGINT/SIGTERM for the duration of the
33
+ * active run. The handler runs the same guarded cleanup the pipeline's
34
+ * finally block runs, then exits with the shell-convention code for the
35
+ * received signal (130 for SIGINT, 143 for SIGTERM). This is what makes a
36
+ * signal-killed run clean up credential material and the isolation temp dir
37
+ * that an async try/finally alone would leave behind — the finally block
38
+ * cannot be entered once the signal's default action fires.
39
+ *
40
+ * The pipeline's finally block awaits the same cleanup promise before it
41
+ * returns, so the handler's `process.exit()` never preempts an in-flight
42
+ * dispose — the exit fires only after the cleanup has run. The first signal
43
+ * to arrive removes both handlers before cleaning up, so a second signal
44
+ * during cleanup keeps the default disposition (genuinely kills the process)
45
+ * rather than racing a second `process.exit()`; the finally block's
46
+ * `uninstall()` removes both handlers after a normal completion so an
47
+ * unrelated signal arriving after the run hits the default disposition.
48
+ *
49
+ * Deliberately not a guarantee: SIGKILL (and power loss / hard crash) still
50
+ * bypasses this, which is tracked separately.
51
+ */
52
+ export declare function installSignalCleanup(options: SignalCleanupOptions): SignalCleanupHandle;
53
+ //# sourceMappingURL=signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/run/signals.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGpD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CAiCvF"}
@@ -0,0 +1,74 @@
1
+ import process from 'node:process';
2
+ /**
3
+ * Exit codes for dying to a caught signal, using the shell convention of
4
+ * 128 + signal number (SIGINT is 2, SIGTERM is 15). A parent shell or CI
5
+ * runner watching `yuurei run` sees the same code it would see for a
6
+ * normally-killed child, rather than yuurei reporting its own error code for
7
+ * an interruption it handled itself.
8
+ */
9
+ export const SIGNAL_EXIT_CODES = {
10
+ SIGINT: 130,
11
+ SIGTERM: 143,
12
+ };
13
+ /**
14
+ * Maps a signal name to the shell-convention exit code (128 + signal number).
15
+ * Handles SIGINT (130) and SIGTERM (143) by the well-known table; falls back
16
+ * to 128 for any other signal so the process never exits 0 for a killed run.
17
+ */
18
+ export function exitCodeForSignal(signal) {
19
+ return SIGNAL_EXIT_CODES[signal] ?? 128;
20
+ }
21
+ /**
22
+ * Installs best-effort cleanup on SIGINT/SIGTERM for the duration of the
23
+ * active run. The handler runs the same guarded cleanup the pipeline's
24
+ * finally block runs, then exits with the shell-convention code for the
25
+ * received signal (130 for SIGINT, 143 for SIGTERM). This is what makes a
26
+ * signal-killed run clean up credential material and the isolation temp dir
27
+ * that an async try/finally alone would leave behind — the finally block
28
+ * cannot be entered once the signal's default action fires.
29
+ *
30
+ * The pipeline's finally block awaits the same cleanup promise before it
31
+ * returns, so the handler's `process.exit()` never preempts an in-flight
32
+ * dispose — the exit fires only after the cleanup has run. The first signal
33
+ * to arrive removes both handlers before cleaning up, so a second signal
34
+ * during cleanup keeps the default disposition (genuinely kills the process)
35
+ * rather than racing a second `process.exit()`; the finally block's
36
+ * `uninstall()` removes both handlers after a normal completion so an
37
+ * unrelated signal arriving after the run hits the default disposition.
38
+ *
39
+ * Deliberately not a guarantee: SIGKILL (and power loss / hard crash) still
40
+ * bypasses this, which is tracked separately.
41
+ */
42
+ export function installSignalCleanup(options) {
43
+ const handlers = new Map();
44
+ const uninstall = () => {
45
+ for (const [signal, handler] of handlers) {
46
+ process.off(signal, handler);
47
+ }
48
+ handlers.clear();
49
+ };
50
+ for (const [signal, exitCode] of Object.entries(SIGNAL_EXIT_CODES)) {
51
+ const handler = async () => {
52
+ // First signal wins: removing both handlers here means a second signal
53
+ // during cleanup keeps the default action (kills the process) instead
54
+ // of being re-entered or racing a second process.exit().
55
+ uninstall();
56
+ try {
57
+ // cleanup is memoized, so this awaits the same lifecycle the
58
+ // pipeline's finally block is awaiting — process.exit() below cannot
59
+ // preempt an in-flight scrub/dispose.
60
+ await options.cleanup();
61
+ }
62
+ finally {
63
+ // Exit with the signal code regardless of whether cleanup itself
64
+ // failed (a failed cleanup reports its own onWarning; the run was
65
+ // still killed by the signal).
66
+ process.exit(exitCode);
67
+ }
68
+ };
69
+ handlers.set(signal, handler);
70
+ process.on(signal, handler);
71
+ }
72
+ return { uninstall };
73
+ }
74
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/run/signals.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,GAAG;CACb,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,iBAAiB,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;AAC1C,CAAC;AAoBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA6B;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAExD,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,CAAC;QACD,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC;IAEF,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnE,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;YACzB,uEAAuE;YACvE,sEAAsE;YACtE,yDAAyD;YACzD,SAAS,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,6DAA6D;gBAC7D,qEAAqE;gBACrE,sCAAsC;gBACtC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YAC1B,CAAC;oBAAS,CAAC;gBACT,iEAAiE;gBACjE,kEAAkE;gBAClE,+BAA+B;gBAC/B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ResolvedCell } from '../../cell/types.js';
2
+ /**
3
+ * Builds the non-interactive CLI invocation for Claude Code. Kept isolated
4
+ * from the rest of the codebase so a future CLI flag change only touches
5
+ * this file (design doc §6.1: adapter-internal conventions must not leak).
6
+ */
7
+ export declare function buildClaudeCodeArgs(cell: ResolvedCell): string[];
8
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/runtime/claude-code/args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,EAAE,CAMhE"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Builds the non-interactive CLI invocation for Claude Code. Kept isolated
3
+ * from the rest of the codebase so a future CLI flag change only touches
4
+ * this file (design doc §6.1: adapter-internal conventions must not leak).
5
+ */
6
+ export function buildClaudeCodeArgs(cell) {
7
+ const args = ['--print', '--output-format', 'json', cell.resolvedTask.content];
8
+ if (cell.requestedModel) {
9
+ args.push('--model', cell.requestedModel);
10
+ }
11
+ return args;
12
+ }
13
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/runtime/claude-code/args.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAkB;IACpD,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { IsolationContext } from '../../isolation/types.js';
2
+ import type { ResolvedCell } from '../../cell/types.js';
3
+ import type { NormalizationContext, NormalizedTraceFragment, PreparedRun, RegisterCredentialPath, Runtime, RuntimeDetection, RuntimeResult } from '../types.js';
4
+ export declare class ClaudeCodeRuntime implements Runtime {
5
+ id(): string;
6
+ detect(): Promise<RuntimeDetection>;
7
+ prepare(cell: ResolvedCell, isolation: IsolationContext, _registerCredentialPath: RegisterCredentialPath): Promise<PreparedRun>;
8
+ execute(run: PreparedRun, timeoutMs: number | null): Promise<RuntimeResult>;
9
+ normalize(result: RuntimeResult, context: NormalizationContext): Promise<NormalizedTraceFragment>;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/claude-code/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,sBAAsB,EACtB,OAAO,EACP,gBAAgB,EAChB,aAAa,EACd,MAAM,aAAa,CAAC;AA4CrB,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,EAAE,IAAI,MAAM;IAIN,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAsBnC,OAAO,CACX,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,gBAAgB,EAC3B,uBAAuB,EAAE,sBAAsB,GAC9C,OAAO,CAAC,WAAW,CAAC;IAmCjB,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAY3E,SAAS,CACb,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,uBAAuB,CAAC;CA2DpC"}
@@ -0,0 +1,167 @@
1
+ import { mkdir, readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { configRootOf } from '../../isolation/config-root.js';
4
+ import { detectViaVersionFlag, isVersionAtLeast } from '../detect.js';
5
+ import { execCapture } from '../exec.js';
6
+ import { writeFileTree } from '../../util/fs.js';
7
+ import { assertNoReservedConfigPath } from '../reserved-paths.js';
8
+ import { buildClaudeCodeArgs } from './args.js';
9
+ import { claudeConfigDir } from './paths.js';
10
+ const RUNTIME_ID = 'claude-code';
11
+ const COMMAND = 'claude';
12
+ const MIN_SUPPORTED_VERSION = [2, 0, 0];
13
+ /**
14
+ * Claude Code resolves its credential store to `<config dir>/.credentials.json`
15
+ * (verified against 2.1.267: a token planted there is read, parsed and sent to
16
+ * the API). Unlike Codex there is no bridged credential *file* of yuurei's own
17
+ * to protect -- the reservation exists because the isolated run holds no
18
+ * credential at all under subscription login, so a profile-supplied one would
19
+ * be used unconditionally.
20
+ */
21
+ const CLAUDE_RESERVED_CONFIG_PATHS = ['.credentials.json'];
22
+ const CLAUDE_CREDENTIAL_ENV_KEYS = ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN'];
23
+ /**
24
+ * Approved method (design doc §9.2) for Claude Code: forward an explicitly-set
25
+ * API key or long-lived token from the parent environment. There is no
26
+ * credential *file* to reference — the interactive session token lives in the
27
+ * OS keychain, which §10.2 forbids reading. Operators who authenticated via
28
+ * subscription login run `claude setup-token` once and export the result.
29
+ * Never reads the keychain, never copies any part of the real ~/.claude.
30
+ * Returns the values actually forwarded, so the pipeline can redact them
31
+ * from persisted logs without needing to know their env var names.
32
+ */
33
+ function bridgeClaudeCredentials(env) {
34
+ const forwardedValues = [];
35
+ for (const key of CLAUDE_CREDENTIAL_ENV_KEYS) {
36
+ const value = process.env[key];
37
+ if (value) {
38
+ env[key] = value;
39
+ forwardedValues.push(value);
40
+ }
41
+ }
42
+ return forwardedValues;
43
+ }
44
+ export class ClaudeCodeRuntime {
45
+ id() {
46
+ return RUNTIME_ID;
47
+ }
48
+ async detect() {
49
+ const detection = await detectViaVersionFlag(COMMAND);
50
+ const authUsable = detection.installed && CLAUDE_CREDENTIAL_ENV_KEYS.some((key) => Boolean(process.env[key]));
51
+ return {
52
+ ...detection,
53
+ versionSupported: isVersionAtLeast(detection.version, MIN_SUPPORTED_VERSION),
54
+ authUsable,
55
+ ...(detection.installed && authUsable === false
56
+ ? {
57
+ authGuidance: 'Claude Code uses the OS credential store for interactive login, which yuurei never reads (design doc §9.2/§10.2). ' +
58
+ 'For subscription login, run `claude setup-token` once, then in this shell export the result as ANTHROPIC_AUTH_TOKEN. ' +
59
+ 'Re-run `yuurei doctor` and look for authUsable: true. ' +
60
+ 'Note: `claude auth status` may report loggedIn: true while yuurei reports authUsable: false — those check different stores. ' +
61
+ 'A shell export applies only to that shell and its child processes; do not persist the token in a profile, task, or committed file. ' +
62
+ 'Verify the variable is set without printing its value: [ -n "$ANTHROPIC_AUTH_TOKEN" ] && echo present || echo absent',
63
+ }
64
+ : {}),
65
+ };
66
+ }
67
+ async prepare(cell, isolation, _registerCredentialPath) {
68
+ const env = { ...isolation.env };
69
+ const configDir = claudeConfigDir(configRootOf(isolation));
70
+ await mkdir(configDir, { recursive: true, mode: 0o700 });
71
+ // Reject before anything is written, rather than relying on write order to
72
+ // paper over the collision (§9.2). Claude Code resolves its credential
73
+ // store from CLAUDE_CONFIG_DIR, which is exactly the directory the profile
74
+ // is materialized into.
75
+ assertNoReservedConfigPath(configDir, cell.resolvedProfile.content.configFiles, CLAUDE_RESERVED_CONFIG_PATHS);
76
+ await writeFileTree(configDir, cell.resolvedProfile.content.configFiles);
77
+ const credentialValuesToRedact = bridgeClaudeCredentials(env);
78
+ env['CLAUDE_CONFIG_DIR'] = configDir;
79
+ const detection = await this.detect();
80
+ return {
81
+ runtimeId: RUNTIME_ID,
82
+ command: COMMAND,
83
+ args: buildClaudeCodeArgs(cell),
84
+ env,
85
+ cwd: isolation.rootDir,
86
+ isolation,
87
+ cell,
88
+ runtimeVersion: detection.version,
89
+ // Credentials here are env vars only (bridgeClaudeCredentials above) —
90
+ // nothing is ever written to disk, so there is no path to register for
91
+ // the scrub.
92
+ credentialValuesToRedact,
93
+ };
94
+ }
95
+ async execute(run, timeoutMs) {
96
+ return execCapture({
97
+ command: run.command,
98
+ args: run.args,
99
+ env: run.env,
100
+ cwd: run.cwd,
101
+ stdoutPath: join(run.isolation.rootDir, 'stdout.log'),
102
+ stderrPath: join(run.isolation.rootDir, 'stderr.log'),
103
+ ...(timeoutMs !== null ? { timeoutMs } : {}),
104
+ });
105
+ }
106
+ async normalize(result, context) {
107
+ const durationMs = new Date(result.finishedAt).getTime() - new Date(result.startedAt).getTime();
108
+ let usage = {};
109
+ const warnings = [];
110
+ try {
111
+ const stdout = await readFile(result.stdoutPath, 'utf8');
112
+ let parsed;
113
+ try {
114
+ parsed = JSON.parse(stdout.trim());
115
+ }
116
+ catch {
117
+ warnings.push('claude-code: stdout was not valid JSON — usage unobserved');
118
+ parsed = undefined;
119
+ }
120
+ if (parsed !== undefined) {
121
+ if (typeof parsed === 'object' && parsed !== null) {
122
+ const obj = parsed;
123
+ const usageRaw = obj['usage'];
124
+ if (typeof usageRaw === 'object' && usageRaw !== null) {
125
+ const u = usageRaw;
126
+ const pick = (key) => {
127
+ const v = u[key];
128
+ return typeof v === 'number' ? v : null;
129
+ };
130
+ usage = {
131
+ input_tokens: pick('input_tokens'),
132
+ output_tokens: pick('output_tokens'),
133
+ cache_creation_input_tokens: pick('cache_creation_input_tokens'),
134
+ cache_read_input_tokens: pick('cache_read_input_tokens'),
135
+ };
136
+ }
137
+ else {
138
+ warnings.push('claude-code: stdout JSON had no usage field — usage unobserved');
139
+ }
140
+ }
141
+ else {
142
+ warnings.push('claude-code: stdout JSON was not an object — usage unobserved');
143
+ }
144
+ }
145
+ }
146
+ catch (err) {
147
+ const code = err.code;
148
+ if (code === 'ENOENT') {
149
+ // Missing stdout is expected for killed/timed-out runs; warn only on normal exit
150
+ if (result.exitCode === 0 && result.signal === null && !result.timedOut) {
151
+ warnings.push('claude-code: stdout absent after normal exit — usage unobserved');
152
+ }
153
+ }
154
+ else {
155
+ warnings.push(`claude-code: stdout unreadable (${err instanceof Error ? err.message : String(err)}) — usage unobserved`);
156
+ }
157
+ }
158
+ return {
159
+ runtime: { id: RUNTIME_ID, version: context.runtimeVersion },
160
+ model: { requested: '', resolved: null },
161
+ execution: { exitCode: result.exitCode, signal: result.signal, durationMs },
162
+ usage,
163
+ ...(warnings.length > 0 ? { warnings } : {}),
164
+ };
165
+ }
166
+ }
167
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/claude-code/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Claude Code's config root under a given HOME directory (real or isolated). */
2
+ export declare function claudeConfigDir(homeDir: string): string;
3
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/runtime/claude-code/paths.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,6 @@
1
+ import { join } from 'node:path';
2
+ /** Claude Code's config root under a given HOME directory (real or isolated). */
3
+ export function claudeConfigDir(homeDir) {
4
+ return join(homeDir, '.claude');
5
+ }
6
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/runtime/claude-code/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC"}