@zhivex-ai/harness 1.4.0 → 1.4.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 (117) hide show
  1. package/CHANGELOG.md +29 -10
  2. package/README.md +7 -5
  3. package/SUPPORT.md +2 -2
  4. package/contracts/client-protocol-v1.schema.json +593 -0
  5. package/contracts/engine-api.json +156 -0
  6. package/contracts/public-api.json +12 -0
  7. package/contracts/stable-api-signatures.json +33 -33
  8. package/dist/acp-cli.js +54 -20
  9. package/dist/audit/index.d.ts +3 -0
  10. package/dist/audit/index.js +482 -0
  11. package/dist/audit/pack.d.ts +72 -0
  12. package/dist/audit-pack-e4vaq7np.js +532 -0
  13. package/dist/cli/arguments.d.ts +3 -1
  14. package/dist/cli/audit-pack.d.ts +24 -0
  15. package/dist/cli/cli-credentials.d.ts +6 -0
  16. package/dist/cli/cli-profiles.d.ts +4 -2
  17. package/dist/cli/node-engine.d.ts +2 -0
  18. package/dist/{cli-2h37qyvg.js → cli-1cf4dcnj.js} +245 -642
  19. package/dist/{cli-entry-w0hterjs.js → cli-entry-3s63zn4w.js} +40 -13
  20. package/dist/cli-entry-7f0cen32.js +9990 -0
  21. package/dist/cli-entry-a890x3kq.js +10348 -0
  22. package/dist/{cli-entry-20w6nh0k.js → cli-entry-hdtfef27.js} +439 -19
  23. package/dist/cli-entry-rgs6bxmy.js +484 -0
  24. package/dist/cli.js +27 -2
  25. package/dist/client/json-contracts.d.ts +4 -0
  26. package/dist/client/protocol.d.ts +133 -0
  27. package/dist/client/task-control-host.d.ts +400 -0
  28. package/dist/client/task-projection-host.d.ts +12 -0
  29. package/dist/client/task-projection.d.ts +168 -0
  30. package/dist/compat/code-support.js +28 -22
  31. package/dist/{config-qt69hkqj.js → config-r9fdhce6.js} +3 -3
  32. package/dist/{config-j9624t6t.js → config-vyajmksy.js} +1 -1
  33. package/dist/engine/acp.js +15 -11
  34. package/dist/engine/client.js +14 -10
  35. package/dist/engine/desktop-providers-v1.d.ts +2 -0
  36. package/dist/engine/desktop-providers-v1.js +23 -3
  37. package/dist/engine/desktop-state-v1.js +11 -8
  38. package/dist/engine/index.d.ts +3 -0
  39. package/dist/engine/index.js +101 -554
  40. package/dist/engine/mcp-stdio-v1.js +8 -6
  41. package/dist/engine/models.js +76 -4
  42. package/dist/engine/protocol.d.ts +2 -0
  43. package/dist/engine/protocol.js +110 -0
  44. package/dist/engine/service.js +15 -11
  45. package/dist/hostile-repository-demo.js +1095 -505
  46. package/dist/{index-937cb7y8.js → index-02pqtbbg.js} +559 -33
  47. package/dist/{index-pp474137.js → index-0zs2dz26.js} +766 -931
  48. package/dist/{index-8zjmnyw5.js → index-1265j7t2.js} +73 -6
  49. package/dist/index-4fx5f3k5.js +269 -0
  50. package/dist/{index-nmjdwd4p.js → index-4gt045j0.js} +109 -1
  51. package/dist/{index-6dft2vev.js → index-6599mpmy.js} +5 -3
  52. package/dist/{index-tfzta544.js → index-74kkpyqk.js} +9 -7
  53. package/dist/{index-61gthdz6.js → index-8sm2a1wa.js} +1 -1
  54. package/dist/index-c39197wq.js +552 -0
  55. package/dist/{index-5jhgatga.js → index-crta5wzv.js} +7 -6
  56. package/dist/{index-m34q25jj.js → index-d9zkmhz3.js} +143 -824
  57. package/dist/{index-pdmevfxv.js → index-dtb2c6ds.js} +5 -259
  58. package/dist/index-f6mqa5gk.js +1535 -0
  59. package/dist/index-j6zxnc8m.js +490 -0
  60. package/dist/{index-rkbf7dqg.js → index-mv8sb1ns.js} +5 -3
  61. package/dist/{index-xqxeypt5.js → index-mzydbzp8.js} +76 -4
  62. package/dist/{index-wg1sd3at.js → index-qfsrrnz6.js} +1 -1
  63. package/dist/{index-m82cfspw.js → index-sk3cap35.js} +877 -963
  64. package/dist/index-sstgcsr0.js +511 -0
  65. package/dist/index-wm9xeq1n.js +329 -0
  66. package/dist/index-xdbkcccf.js +719 -0
  67. package/dist/{index-s2k2edts.js → index-zxg4ve4j.js} +41 -1548
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.js +93 -77
  70. package/dist/internal/desktop/providers.d.ts +2 -0
  71. package/dist/models/catalog.d.ts +2 -0
  72. package/dist/persistence/sqlite-database.d.ts +1 -0
  73. package/dist/providers/azure-openai.d.ts +14 -0
  74. package/dist/providers/bedrock.d.ts +23 -0
  75. package/dist/providers/providers.d.ts +1 -1
  76. package/dist/runtime/durable-review-group.d.ts +33 -0
  77. package/dist/runtime/harness.d.ts +11 -0
  78. package/dist/runtime/run-interruption.d.ts +7 -0
  79. package/dist/runtime/shared-budget.d.ts +30 -0
  80. package/dist/runtime/task-continuity.d.ts +300 -77
  81. package/dist/service-cli.js +15 -11
  82. package/dist/{service-client-cli-fn54ev6w.js → service-client-cli-eqrdc9zq.js} +400 -305
  83. package/dist/verify-historical-migrations.js +1095 -505
  84. package/dist/zhx.js +27 -2
  85. package/docs/AUDIT_PACK.md +99 -0
  86. package/docs/AZURE_OPENAI.md +53 -0
  87. package/docs/BEDROCK.md +56 -0
  88. package/docs/CLI.md +15 -0
  89. package/docs/CLIENT_PROTOCOL.md +178 -0
  90. package/docs/CODE_RELEASE.md +31 -1
  91. package/docs/CODE_WEB_TASKS.md +116 -0
  92. package/docs/CONTEXT_ENGINEERING.md +59 -0
  93. package/docs/CREDENTIALS.md +21 -0
  94. package/docs/DURABLE_OPERATIONS.md +93 -1
  95. package/docs/ENGINE_API.md +5 -2
  96. package/docs/EXTENSIBILITY.md +2 -2
  97. package/docs/FIRST_USE.md +6 -6
  98. package/docs/MINIMUM_TASK_AUTHORITY.md +3 -3
  99. package/docs/PROJECT_MEMORY.md +1 -1
  100. package/docs/README.md +6 -1
  101. package/docs/STABILITY.md +3 -1
  102. package/docs/SUPPORT_MATRIX.md +1 -1
  103. package/docs/SUPPORT_MATRIX_1_1.md +1 -1
  104. package/docs/USAGE.md +3 -1
  105. package/docs/VERTEX.md +2 -2
  106. package/docs/WEB_LIMITS.md +4 -3
  107. package/docs/adr/0002-isolated-mcp-stdio.md +6 -3
  108. package/docs/support-matrix-1.1.json +3 -1
  109. package/docs/support-matrix.json +6 -4
  110. package/evaluations/code-task-ui.json +20 -0
  111. package/evaluations/representative-assembly-matrix.json +10 -1
  112. package/evaluations/task-projection.json +10 -0
  113. package/evaluations/task-recovery-lab.json +60 -0
  114. package/examples/README.md +3 -3
  115. package/package.json +23 -13
  116. package/dist/cli-entry-4ngptr62.js +0 -19900
  117. package/dist/index-m49jx72n.js +0 -220
@@ -1,6 +1,26 @@
1
1
  import {
2
2
  HARNESS_EXECUTION_POLICY_VERSION
3
- } from "./index-8zjmnyw5.js";
3
+ } from "./index-1265j7t2.js";
4
+ import {
5
+ FileSizeLimitError,
6
+ MAX_EDIT_CHANGES,
7
+ MAX_EDIT_PROPOSAL_BYTES,
8
+ SqliteDatabase,
9
+ UnsafeFileTypeError,
10
+ assertTaskAcceptanceImport,
11
+ confirmTaskAcceptanceImport,
12
+ createEditProposal,
13
+ fileDigestSchema,
14
+ moveFileInputSchema,
15
+ mutationAuditEntrySchema,
16
+ quarantineFileInputSchema,
17
+ readRegularFileNoFollow,
18
+ restoreFileInputSchema,
19
+ statRegularFileNoFollow,
20
+ taskAcceptanceChecks,
21
+ validateEditProposal,
22
+ workspaceFilePathSchema
23
+ } from "./index-xdbkcccf.js";
4
24
  import {
5
25
  HarnessError,
6
26
  HarnessExecutionError,
@@ -8,517 +28,9 @@ import {
8
28
  HarnessWorkspaceError
9
29
  } from "./index-bpc596v3.js";
10
30
 
11
- // src/workspace/edit-contracts.ts
12
- import { createHash } from "node:crypto";
13
- import path from "node:path";
14
- import { z } from "zod";
15
- var EDIT_CONTRACT_SCHEMA_VERSION = 1;
16
- var EDIT_DIGEST_ALGORITHM = "sha256";
17
- var MAX_EDIT_CHANGES = 50;
18
- var MAX_EDIT_FILE_BYTES = 1024 * 1024;
19
- var MAX_EDIT_PROPOSAL_BYTES = 4 * 1024 * 1024;
20
- var SHA256_DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/;
21
- var fileDigestSchema = z.string().regex(SHA256_DIGEST_PATTERN, "Digest must use the format sha256:<64 lowercase hexadecimal characters>.");
22
- var expectedEditDigestSchema = fileDigestSchema.nullable().describe("Required. Use the inspected sha256 digest for an existing file, or explicit JSON null for a create-only target. Never omit this field.");
23
- var workspaceFilePathSchema = z.string().min(1).max(1024).refine((value) => !value.includes("\x00"), "Path cannot contain a NUL byte.").refine((value) => !path.isAbsolute(value) && !/^[A-Za-z]:[\\/]/.test(value), "Path must be relative.").refine((value) => {
24
- const segments = value.split(/[\\/]+/);
25
- return segments.every((segment) => segment !== "" && segment !== "." && segment !== "..");
26
- }, "Path must be normalized and cannot contain empty, dot, or parent segments.");
27
- var editChangeSchema = z.strictObject({
28
- path: workspaceFilePathSchema,
29
- expectedDigest: expectedEditDigestSchema,
30
- content: z.string()
31
- }).superRefine((change, context) => {
32
- if (Buffer.byteLength(change.content, "utf8") > MAX_EDIT_FILE_BYTES) {
33
- context.addIssue({
34
- code: "custom",
35
- path: ["content"],
36
- message: `Content exceeds the ${MAX_EDIT_FILE_BYTES}-byte per-file limit.`
37
- });
38
- }
39
- });
40
- var editChangesSchema = z.array(editChangeSchema).min(1).max(MAX_EDIT_CHANGES).superRefine((changes, context) => {
41
- const paths = new Set;
42
- let totalBytes = 0;
43
- for (let index = 0;index < changes.length; index += 1) {
44
- const change = changes[index];
45
- if (!change) {
46
- continue;
47
- }
48
- if (paths.has(change.path)) {
49
- context.addIssue({
50
- code: "custom",
51
- path: [index, "path"],
52
- message: `Duplicate target path: ${change.path}.`
53
- });
54
- }
55
- paths.add(change.path);
56
- totalBytes += Buffer.byteLength(change.content, "utf8");
57
- }
58
- if (totalBytes > MAX_EDIT_PROPOSAL_BYTES) {
59
- context.addIssue({
60
- code: "custom",
61
- message: `Proposal exceeds the ${MAX_EDIT_PROPOSAL_BYTES}-byte aggregate limit.`
62
- });
63
- }
64
- });
65
- var editProposalInputSchema = z.strictObject({
66
- changes: editChangesSchema
67
- });
68
- var editProposalChangeSchema = z.strictObject({
69
- path: workspaceFilePathSchema,
70
- expectedDigest: expectedEditDigestSchema,
71
- contentDigest: fileDigestSchema,
72
- bytes: z.number().int().min(0).max(MAX_EDIT_FILE_BYTES)
73
- });
74
- var editProposalSchema = z.strictObject({
75
- schemaVersion: z.literal(EDIT_CONTRACT_SCHEMA_VERSION),
76
- kind: z.literal("edit-proposal"),
77
- proposalId: fileDigestSchema,
78
- digestAlgorithm: z.literal(EDIT_DIGEST_ALGORITHM),
79
- changes: z.array(editProposalChangeSchema).min(1).max(MAX_EDIT_CHANGES)
80
- });
81
- var applyEditProposalInputSchema = z.strictObject({
82
- proposalId: fileDigestSchema,
83
- changes: editChangesSchema
84
- }).superRefine((input, context) => {
85
- if (!editProposalInputSchema.safeParse({ changes: input.changes }).success)
86
- return;
87
- if (createEditProposal({ changes: input.changes }).proposalId !== input.proposalId) {
88
- context.addIssue({
89
- code: "custom",
90
- path: ["proposalId"],
91
- message: "proposalId does not match the supplied paths, preconditions, and content. Read proposalId from the matching propose_edits result; do not invent it."
92
- });
93
- }
94
- });
95
- var moveFileInputSchema = z.strictObject({
96
- source: workspaceFilePathSchema,
97
- destination: workspaceFilePathSchema,
98
- expectedDigest: fileDigestSchema
99
- }).refine((input) => input.source !== input.destination, {
100
- path: ["destination"],
101
- message: "Move destination must differ from source."
102
- });
103
- var quarantineFileInputSchema = z.strictObject({
104
- path: workspaceFilePathSchema,
105
- expectedDigest: fileDigestSchema
106
- });
107
- var restoreFileInputSchema = z.strictObject({
108
- quarantineId: z.string().min(1).max(200).regex(/^[A-Za-z0-9._:-]+$/),
109
- destination: workspaceFilePathSchema.optional(),
110
- expectedDigest: fileDigestSchema.optional()
111
- });
112
- var mutationOperationSchema = z.enum(["create", "update", "move", "quarantine", "restore"]);
113
- var mutationAuditEntrySchema = z.strictObject({
114
- id: z.string().min(1).max(200),
115
- operation: mutationOperationSchema,
116
- path: workspaceFilePathSchema,
117
- destination: workspaceFilePathSchema.optional(),
118
- beforeDigest: fileDigestSchema.optional(),
119
- afterDigest: fileDigestSchema.optional(),
120
- timestamp: z.iso.datetime(),
121
- quarantineId: z.string().min(1).max(200).optional()
122
- });
123
- var digest = (value) => `sha256:${createHash("sha256").update(value).digest("hex")}`;
124
- var canonicalProposalPayload = (changes) => ({
125
- schemaVersion: EDIT_CONTRACT_SCHEMA_VERSION,
126
- kind: "edit-proposal",
127
- digestAlgorithm: EDIT_DIGEST_ALGORITHM,
128
- changes: [...changes].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0).map((change) => ({
129
- path: change.path,
130
- expectedDigest: change.expectedDigest,
131
- contentDigest: digest(change.content),
132
- bytes: Buffer.byteLength(change.content, "utf8")
133
- }))
134
- });
135
- var createEditProposal = (input) => {
136
- const parsed = editProposalInputSchema.parse(input);
137
- const payload = canonicalProposalPayload(parsed.changes);
138
- return editProposalSchema.parse({
139
- ...payload,
140
- proposalId: digest(JSON.stringify(payload))
141
- });
142
- };
143
- var validateEditProposal = (input) => {
144
- const parsed = applyEditProposalInputSchema.parse(input);
145
- const proposal = createEditProposal({ changes: parsed.changes });
146
- if (proposal.proposalId !== parsed.proposalId) {
147
- throw new Error("proposalId does not match the supplied paths, preconditions, and content.");
148
- }
149
- return parsed;
150
- };
151
- var editContractDocument = (kind, result) => ({
152
- schemaVersion: EDIT_CONTRACT_SCHEMA_VERSION,
153
- kind,
154
- result
155
- });
156
-
157
- // src/persistence/persistence-secrets.ts
158
- var protectedValues = new Set;
159
- function protectPersistenceSecret(secret) {
160
- if (!secret)
161
- return;
162
- protectedValues.add(secret);
163
- protectedValues.add(JSON.stringify(secret).slice(1, -1));
164
- }
165
- function assertNoPersistenceSecret(value) {
166
- if (!protectedValues.size)
167
- return;
168
- const seen = new WeakSet;
169
- const visit = (item) => {
170
- if (typeof item === "string") {
171
- for (const secret of protectedValues)
172
- if (item.includes(secret))
173
- throw new Error("PERSISTENCE_SECRET_REJECTED");
174
- } else if (item instanceof Uint8Array) {
175
- const bytes = Buffer.from(item.buffer, item.byteOffset, item.byteLength);
176
- for (const secret of protectedValues)
177
- if (bytes.includes(Buffer.from(secret)))
178
- throw new Error("PERSISTENCE_SECRET_REJECTED");
179
- } else if (item && typeof item === "object" && !seen.has(item)) {
180
- seen.add(item);
181
- for (const [key, entry] of Object.entries(item)) {
182
- visit(key);
183
- visit(entry);
184
- }
185
- }
186
- };
187
- visit(value);
188
- }
189
-
190
- // src/persistence/sqlite-access.ts
191
- import { closeSync, constants, fchmodSync, fstatSync, lstatSync, openSync, realpathSync } from "node:fs";
192
- import path2 from "node:path";
193
- var O_SHLOCK = 16;
194
- var O_EXLOCK = 32;
195
- var held = new WeakMap;
196
- var activeDescriptors = new Set;
197
- function filename(databasePath) {
198
- const directory = realpathSync(path2.dirname(path2.resolve(databasePath)));
199
- return path2.join(directory, `.${path2.basename(databasePath)}.access-lock`);
200
- }
201
- function releaseDescriptor(state) {
202
- closeSync(state.fd);
203
- activeDescriptors.delete(state.fd);
204
- }
205
- function makeLease(lock, fd, exclusive) {
206
- const state = { filename: lock, fd, closed: false, borrowers: 0, exclusive };
207
- const lease = Object.freeze({ fd, close() {
208
- if (!state.closed) {
209
- state.closed = true;
210
- if (state.borrowers === 0)
211
- releaseDescriptor(state);
212
- }
213
- } });
214
- held.set(lease, state);
215
- activeDescriptors.add(fd);
216
- return lease;
217
- }
218
- function acquireSqliteAccess(databasePath, exclusive = false) {
219
- if (databasePath === ":memory:" || process.platform !== "darwin")
220
- return;
221
- let fd;
222
- try {
223
- const lock = filename(databasePath);
224
- fd = openSync(lock, constants.O_RDWR | constants.O_CREAT | constants.O_NOFOLLOW | constants.O_NONBLOCK | (exclusive ? O_EXLOCK : O_SHLOCK), 384);
225
- const info = fstatSync(fd);
226
- const current = lstatSync(lock);
227
- if (!info.isFile() || info.nlink !== 1 || info.uid !== process.getuid?.() || info.size !== 0 || current.isSymbolicLink() || current.dev !== info.dev || current.ino !== info.ino)
228
- throw new Error;
229
- if (info.mode & 63)
230
- fchmodSync(fd, 384);
231
- if (fstatSync(fd).mode & 63)
232
- throw new Error;
233
- return makeLease(lock, fd, exclusive);
234
- } catch {
235
- if (fd !== undefined)
236
- closeSync(fd);
237
- throw new Error("SQLITE_ACCESS_UNAVAILABLE");
238
- }
239
- }
240
- function retainSqliteAccess(lease, databasePath) {
241
- validateSqliteAccess(lease, databasePath);
242
- const state = held.get(lease);
243
- state.borrowers++;
244
- let released = false;
245
- return () => {
246
- if (!released) {
247
- released = true;
248
- state.borrowers--;
249
- if (state.closed && state.borrowers === 0)
250
- releaseDescriptor(state);
251
- }
252
- };
253
- }
254
- function exclusiveSqliteAccessDescriptor(lease, databasePath) {
255
- validateSqliteAccess(lease, databasePath);
256
- const state = held.get(lease);
257
- if (!state.exclusive || state.borrowers !== 0)
258
- throw new Error("SQLITE_ACCESS_UNAVAILABLE");
259
- return state.fd;
260
- }
261
- function adoptExclusiveSqliteAccess(databasePath, fd) {
262
- try {
263
- if (process.platform !== "darwin" || !Number.isInteger(fd) || fd < 4 || fd > 603 || activeDescriptors.has(fd))
264
- throw new Error;
265
- const lock = filename(databasePath), current = lstatSync(lock), owned = fstatSync(fd);
266
- if (!owned.isFile() || owned.nlink !== 1 || owned.uid !== process.getuid?.() || owned.mode & 63 || owned.size !== 0 || current.isSymbolicLink() || current.dev !== owned.dev || current.ino !== owned.ino)
267
- throw new Error;
268
- return makeLease(lock, fd, true);
269
- } catch {
270
- throw new Error("SQLITE_ACCESS_UNAVAILABLE");
271
- }
272
- }
273
- function validateSqliteAccess(lease, databasePath) {
274
- try {
275
- const state = held.get(lease);
276
- if (!state || state.closed || state.filename !== filename(databasePath))
277
- throw new Error;
278
- const current = lstatSync(state.filename), owned = fstatSync(state.fd);
279
- if (current.isSymbolicLink() || !current.isFile() || current.nlink !== 1 || current.dev !== owned.dev || current.ino !== owned.ino)
280
- throw new Error;
281
- } catch {
282
- throw new Error("SQLITE_ACCESS_UNAVAILABLE");
283
- }
284
- }
285
-
286
- // src/persistence/sqlite-database.ts
287
- import { createRequire } from "node:module";
288
- var require2 = createRequire(process.execPath);
289
- var DatabaseSyncConstructor;
290
- var loadDatabaseSync = () => {
291
- DatabaseSyncConstructor ??= require2("node:sqlite").DatabaseSync;
292
- return DatabaseSyncConstructor;
293
- };
294
- var normalizeNumberedParameters = (sql) => {
295
- const indexes = new Set;
296
- const normalizedSql = sql.replace(/\?([1-9]\d*)/g, (_match, rawIndex) => {
297
- const index = Number(rawIndex);
298
- indexes.add(index);
299
- return `$__zhivex_${index}`;
300
- });
301
- return {
302
- sql: normalizedSql,
303
- indexes: [...indexes].sort((left, right) => left - right)
304
- };
305
- };
306
- var numberedBindings = (indexes, parameters) => {
307
- if (indexes.length === 0)
308
- return;
309
- const maximumIndex = indexes.at(-1);
310
- if (parameters.length !== maximumIndex) {
311
- throw new Error(`SQLite numbered parameters require exactly ${maximumIndex} binding${maximumIndex === 1 ? "" : "s"}; received ${parameters.length}.`);
312
- }
313
- return Object.fromEntries(indexes.map((index) => [`$__zhivex_${index}`, parameters[index - 1]]));
314
- };
315
-
316
- class SqliteDatabase {
317
- #database;
318
- #access;
319
- #ownedAccess;
320
- #releaseBorrowed;
321
- #databasePath;
322
- constructor(databasePath, options = {}) {
323
- options.create;
324
- options.strict;
325
- if (options.accessLease)
326
- validateSqliteAccess(options.accessLease, databasePath);
327
- this.#access = options.accessLease ?? acquireSqliteAccess(databasePath);
328
- this.#ownedAccess = options.accessLease === undefined;
329
- this.#databasePath = databasePath;
330
- this.#releaseBorrowed = options.accessLease ? retainSqliteAccess(options.accessLease, databasePath) : undefined;
331
- try {
332
- const DatabaseSync = loadDatabaseSync();
333
- this.#database = new DatabaseSync(databasePath, {
334
- ...options.readonly === undefined ? {} : { readOnly: options.readonly }
335
- });
336
- } catch (error) {
337
- if (this.#ownedAccess)
338
- this.#access?.close();
339
- this.#releaseBorrowed?.();
340
- throw error;
341
- }
342
- }
343
- exec(sql) {
344
- if (this.#access)
345
- validateSqliteAccess(this.#access, this.#databasePath);
346
- assertNoPersistenceSecret(sql);
347
- this.#database.exec(sql);
348
- }
349
- query(sql) {
350
- assertNoPersistenceSecret(sql);
351
- if (this.#access)
352
- validateSqliteAccess(this.#access, this.#databasePath);
353
- const normalized = normalizeNumberedParameters(sql);
354
- const statement = this.#database.prepare(normalized.sql);
355
- const invoke = (method, parameters) => {
356
- if (this.#access)
357
- validateSqliteAccess(this.#access, this.#databasePath);
358
- assertNoPersistenceSecret(sql);
359
- assertNoPersistenceSecret(parameters);
360
- const bindings = numberedBindings(normalized.indexes, parameters);
361
- return bindings ? method(bindings) : method(...parameters);
362
- };
363
- return {
364
- run: (...parameters) => invoke(statement.run.bind(statement), parameters),
365
- get: (...parameters) => invoke(statement.get.bind(statement), parameters),
366
- all: (...parameters) => invoke(statement.all.bind(statement), parameters)
367
- };
368
- }
369
- close(throwOnError = true) {
370
- try {
371
- this.#database.close();
372
- if (this.#ownedAccess)
373
- this.#access?.close();
374
- this.#releaseBorrowed?.();
375
- } catch (error) {
376
- if (throwOnError) {
377
- throw error;
378
- }
379
- }
380
- }
381
- }
382
-
383
- // src/workspace/file-security.ts
384
- import { constants as fsConstants } from "node:fs";
385
- import { open } from "node:fs/promises";
386
- import path3 from "node:path";
387
- var sameOpenFile = (before, after) => before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs && before.mode === after.mode && before.nlink === after.nlink;
388
-
389
- class UnsafeFileTypeError extends Error {
390
- constructor(label) {
391
- super(`${label} must be a regular file and must not be a symbolic link.`);
392
- this.name = "UnsafeFileTypeError";
393
- }
394
- }
395
-
396
- class FileSizeLimitError extends Error {
397
- label;
398
- maxBytes;
399
- constructor(label, maxBytes) {
400
- super(`${label} exceeds the ${maxBytes}-byte limit.`);
401
- this.label = label;
402
- this.maxBytes = maxBytes;
403
- this.name = "FileSizeLimitError";
404
- }
405
- }
406
-
407
- class FileChangedWhileReadingError extends Error {
408
- constructor(label) {
409
- super(`${label} changed while it was being read.`);
410
- this.name = "FileChangedWhileReadingError";
411
- }
412
- }
413
- var invalidFileError = (label) => new UnsafeFileTypeError(label);
414
- var openRegularFileNoFollow = async (target, label) => {
415
- try {
416
- const flags = fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | fsConstants.O_NONBLOCK;
417
- let absolute = path3.resolve(target);
418
- if (process.platform === "darwin") {
419
- absolute = absolute.replace(/^\/(tmp|var|etc)(\/|$)/, "/private/$1$2");
420
- return await open(absolute, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | 536870912, 384);
421
- }
422
- if (process.platform !== "linux")
423
- throw new Error("Safe descriptor-relative reads require Linux or macOS.");
424
- const segments = absolute.split("/").filter(Boolean);
425
- const leaf = segments.pop();
426
- if (!leaf)
427
- throw invalidFileError(label);
428
- let directory = await open("/", fsConstants.O_RDONLY | fsConstants.O_DIRECTORY);
429
- try {
430
- for (const segment of segments) {
431
- const next = await open(`/proc/self/fd/${directory.fd}/${segment}`, fsConstants.O_RDONLY | fsConstants.O_DIRECTORY | fsConstants.O_NOFOLLOW);
432
- await directory.close();
433
- directory = next;
434
- }
435
- return await open(`/proc/self/fd/${directory.fd}/${leaf}`, flags);
436
- } finally {
437
- await directory.close();
438
- }
439
- } catch (error) {
440
- const code = error.code;
441
- if (code === "ELOOP" || code === "EMLINK" || code === "ENOTDIR")
442
- throw invalidFileError(label);
443
- throw error;
444
- }
445
- };
446
- var statRegularFileNoFollow = async (target, options) => {
447
- const handle = await openRegularFileNoFollow(target, options.label);
448
- try {
449
- const stat = await handle.stat();
450
- if (!stat.isFile() || options.requireSingleLink && stat.nlink !== 1) {
451
- throw invalidFileError(options.label);
452
- }
453
- return stat;
454
- } finally {
455
- await handle.close();
456
- }
457
- };
458
- var readRegularFileNoFollow = async (target, options) => {
459
- const handle = await openRegularFileNoFollow(target, options.label);
460
- try {
461
- const before = await handle.stat();
462
- if (!before.isFile() || options.requireSingleLink && before.nlink !== 1) {
463
- throw invalidFileError(options.label);
464
- }
465
- if (!Number.isSafeInteger(before.size) || before.size < 0) {
466
- throw new Error(`${options.label} has an unsupported size.`);
467
- }
468
- if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 0) {
469
- throw new Error(`${options.label} has an invalid byte limit.`);
470
- }
471
- if (before.size > options.maxBytes) {
472
- throw new FileSizeLimitError(options.label, options.maxBytes);
473
- }
474
- const contents = Buffer.alloc(before.size);
475
- let offset = 0;
476
- while (offset < contents.byteLength) {
477
- const { bytesRead } = await handle.read(contents, offset, contents.byteLength - offset, offset);
478
- if (bytesRead === 0)
479
- break;
480
- offset += bytesRead;
481
- }
482
- const probe = Buffer.allocUnsafe(1);
483
- const { bytesRead: extraBytes } = await handle.read(probe, 0, 1, before.size);
484
- const after = await handle.stat();
485
- if (offset !== before.size || extraBytes !== 0 || !sameOpenFile(before, after) || options.requireSingleLink && after.nlink !== 1) {
486
- throw new FileChangedWhileReadingError(options.label);
487
- }
488
- return { contents, stat: after };
489
- } finally {
490
- await handle.close();
491
- }
492
- };
493
- async function* readRegularFileChunksNoFollow(target, options) {
494
- const handle = await openRegularFileNoFollow(target, options.label);
495
- try {
496
- const before = await handle.stat();
497
- if (!before.isFile() || options.requireSingleLink && before.nlink !== 1)
498
- throw invalidFileError(options.label);
499
- if (options.requirePrivate && (before.mode & 63) !== 0)
500
- throw new Error(`${options.label} permissions must not grant group or other access.`);
501
- let offset = 0;
502
- while (offset < before.size) {
503
- const buffer = Buffer.allocUnsafe(Math.min(64 * 1024, before.size - offset));
504
- const { bytesRead: bytesRead2 } = await handle.read(buffer, 0, buffer.length, offset);
505
- if (!bytesRead2)
506
- throw new FileChangedWhileReadingError(options.label);
507
- offset += bytesRead2;
508
- yield buffer.subarray(0, bytesRead2);
509
- }
510
- const probe = Buffer.allocUnsafe(1);
511
- const { bytesRead } = await handle.read(probe, 0, 1, offset);
512
- if (bytesRead || !sameOpenFile(before, await handle.stat()))
513
- throw new FileChangedWhileReadingError(options.label);
514
- } finally {
515
- await handle.close();
516
- }
517
- }
518
-
519
31
  // src/execution/package-manager.ts
520
32
  import { lstat } from "node:fs/promises";
521
- import path4 from "node:path";
33
+ import path from "node:path";
522
34
  var HARNESS_PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
523
35
  var LOCKFILES = {
524
36
  npm: ["package-lock.json", "npm-shrinkwrap.json"],
@@ -547,7 +59,7 @@ var existingLockfiles = async (root) => {
547
59
  for (const manager of HARNESS_PACKAGE_MANAGERS) {
548
60
  for (const file of LOCKFILES[manager]) {
549
61
  try {
550
- const entry = await lstat(path4.join(root, file));
62
+ const entry = await lstat(path.join(root, file));
551
63
  if (entry.isSymbolicLink()) {
552
64
  throw new Error(`Package-manager lockfile must not be a symbolic link: ${file}.`);
553
65
  }
@@ -793,10 +305,10 @@ var runPortableProcess = async (command, options = {}) => {
793
305
  };
794
306
 
795
307
  // src/workspace/workspace-mutation-lock.ts
796
- import { createHash as createHash2 } from "node:crypto";
308
+ import { createHash } from "node:crypto";
797
309
  import { AsyncLocalStorage } from "node:async_hooks";
798
- import { lstat as lstat2, mkdir, open as open2, realpath } from "node:fs/promises";
799
- import path5 from "node:path";
310
+ import { lstat as lstat2, mkdir, open, realpath } from "node:fs/promises";
311
+ import path2 from "node:path";
800
312
  import { setTimeout as delay } from "node:timers/promises";
801
313
  var ownership = new AsyncLocalStorage;
802
314
  var withWorkspaceMutation = async (root, operation) => {
@@ -808,7 +320,7 @@ var withWorkspaceMutation = async (root, operation) => {
808
320
  if (uid === undefined || !["darwin", "linux"].includes(process.platform)) {
809
321
  throw new HarnessWorkspaceError("Workspace mutation locks require Linux or macOS user identity.");
810
322
  }
811
- const directory = path5.join(process.platform === "darwin" ? "/private/tmp" : "/tmp", `zhivex-harness-mutation-locks-${uid}`);
323
+ const directory = path2.join(process.platform === "darwin" ? "/private/tmp" : "/tmp", `zhivex-harness-mutation-locks-${uid}`);
812
324
  await mkdir(directory, { mode: 448 }).catch((error) => {
813
325
  if (error.code !== "EEXIST")
814
326
  throw error;
@@ -817,22 +329,22 @@ var withWorkspaceMutation = async (root, operation) => {
817
329
  if (!entry.isDirectory() || entry.isSymbolicLink() || entry.uid !== uid || (entry.mode & 63) !== 0 || await realpath(directory) !== directory) {
818
330
  throw new HarnessWorkspaceError("Workspace mutation lock requires a real state directory without symbolic links.");
819
331
  }
820
- const filename2 = path5.join(directory, `${createHash2("sha256").update(root).digest("hex")}.sqlite`);
332
+ const filename = path2.join(directory, `${createHash("sha256").update(root).digest("hex")}.sqlite`);
821
333
  try {
822
- const created = await open2(filename2, "wx", 384);
334
+ const created = await open(filename, "wx", 384);
823
335
  await created.close();
824
336
  } catch (error) {
825
337
  if (error.code !== "EEXIST")
826
338
  throw error;
827
339
  }
828
- const before = await statRegularFileNoFollow(filename2, { label: "Workspace mutation lock", requireSingleLink: true });
340
+ const before = await statRegularFileNoFollow(filename, { label: "Workspace mutation lock", requireSingleLink: true });
829
341
  if (before.uid !== uid || (before.mode & 63) !== 0)
830
342
  throw new HarnessWorkspaceError("Workspace mutation lock must be owner-only.");
831
- const database = new SqliteDatabase(filename2, { create: false });
343
+ const database = new SqliteDatabase(filename, { create: false });
832
344
  let acquired = false;
833
345
  const token = { active: true };
834
346
  try {
835
- const after = await statRegularFileNoFollow(filename2, { label: "Workspace mutation lock", requireSingleLink: true });
347
+ const after = await statRegularFileNoFollow(filename, { label: "Workspace mutation lock", requireSingleLink: true });
836
348
  if (before.dev !== after.dev || before.ino !== after.ino) {
837
349
  throw new HarnessWorkspaceError("Workspace mutation lock changed while opening.");
838
350
  }
@@ -865,12 +377,12 @@ var withWorkspaceMutation = async (root, operation) => {
865
377
  };
866
378
 
867
379
  // src/workspace/replacement-edits.ts
868
- import { z as z2 } from "zod";
869
- var replacementEditSchema = z2.strictObject({
380
+ import { z } from "zod";
381
+ var replacementEditSchema = z.strictObject({
870
382
  path: workspaceFilePathSchema,
871
383
  expectedDigest: fileDigestSchema,
872
- oldText: z2.string().min(1).max(64000),
873
- newText: z2.string().max(64000)
384
+ oldText: z.string().min(1).max(64000),
385
+ newText: z.string().max(64000)
874
386
  });
875
387
 
876
388
  // src/workspace/bounded-reads.ts
@@ -887,9 +399,9 @@ async function* boundedBatches(items, operation, concurrency = 8) {
887
399
  }
888
400
 
889
401
  // src/workspace/workspace.ts
890
- import { createHash as createHash3, randomUUID } from "node:crypto";
891
- import { link, lstat as lstat3, mkdir as mkdir2, open as open3, readdir, realpath as realpath2, rename, stat, unlink } from "node:fs/promises";
892
- import path6 from "node:path";
402
+ import { createHash as createHash2, randomUUID } from "node:crypto";
403
+ import { link, lstat as lstat3, mkdir as mkdir2, open as open2, readdir, realpath as realpath2, rename, stat, unlink } from "node:fs/promises";
404
+ import path3 from "node:path";
893
405
 
894
406
  // src/workspace/path-policy.ts
895
407
  var HARD_IGNORES = new Set([".git", ".next", ".turbo", ".zhivex-harness", "coverage", "dist", "node_modules"]);
@@ -925,11 +437,11 @@ var MAX_GIT_DIFF_PATHS = 2048;
925
437
  var MAX_GIT_DIFF_ARGV_CHARACTERS = 128000;
926
438
  var GIT_SAFE_PREFIX = ["git", "-c", "core.fsmonitor=false"];
927
439
  var isInside = (root, candidate) => {
928
- const relative = path6.relative(root, candidate);
929
- return relative === "" || !relative.startsWith(`..${path6.sep}`) && relative !== ".." && !path6.isAbsolute(relative);
440
+ const relative = path3.relative(root, candidate);
441
+ return relative === "" || !relative.startsWith(`..${path3.sep}`) && relative !== ".." && !path3.isAbsolute(relative);
930
442
  };
931
- var wirePath = (value) => value.split(path6.sep).join("/");
932
- var digestBytes = (value) => `sha256:${createHash3("sha256").update(value).digest("hex")}`;
443
+ var wirePath = (value) => value.split(path3.sep).join("/");
444
+ var digestBytes = (value) => `sha256:${createHash2("sha256").update(value).digest("hex")}`;
933
445
  var truncate = (value, maxLength = MAX_TOOL_OUTPUT) => value.length <= maxLength ? value : `${value.slice(0, maxLength)}
934
446
  … output truncated (${value.length - maxLength} characters omitted)`;
935
447
  var cursorEncode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
@@ -1058,7 +570,7 @@ var nulFields = (result, label) => {
1058
570
  };
1059
571
  var safeGitPath = (candidate) => {
1060
572
  const normalized = wirePath(candidate);
1061
- return normalized !== "" && normalized !== "." && !path6.isAbsolute(candidate) && !normalized.startsWith("../") && !isHardIgnored(normalized);
573
+ return normalized !== "" && normalized !== "." && !path3.isAbsolute(candidate) && !normalized.startsWith("../") && !isHardIgnored(normalized);
1062
574
  };
1063
575
  var renderGitPath = (candidate) => /[\0\r\n\t]/.test(candidate) ? JSON.stringify(candidate) : candidate;
1064
576
  var filteredGitStatus = (result) => {
@@ -1145,7 +657,7 @@ class Workspace {
1145
657
  }
1146
658
  static async open(root, options = {}) {
1147
659
  try {
1148
- const resolved = await realpath2(path6.resolve(root));
660
+ const resolved = await realpath2(path3.resolve(root));
1149
661
  if (!(await stat(resolved)).isDirectory()) {
1150
662
  throw new HarnessWorkspaceError(`The workspace is not a directory: ${root}`);
1151
663
  }
@@ -1172,10 +684,10 @@ class Workspace {
1172
684
  lexicalPath(relativePath) {
1173
685
  if (!relativePath || relativePath.includes("\x00"))
1174
686
  throw new HarnessWorkspaceError("The path must be a valid relative path.");
1175
- const candidate = path6.resolve(this.root, relativePath);
687
+ const candidate = path3.resolve(this.root, relativePath);
1176
688
  if (!isInside(this.root, candidate))
1177
689
  throw new HarnessWorkspaceError(`The path escapes the workspace: ${relativePath}`);
1178
- const relative = wirePath(path6.relative(this.root, candidate));
690
+ const relative = wirePath(path3.relative(this.root, candidate));
1179
691
  if (relative && isHardIgnored(relative)) {
1180
692
  const blocked = relative.split("/").find((segment) => HARD_IGNORES.has(segment.toLocaleLowerCase()) || isSensitiveName(segment));
1181
693
  throw new HarnessWorkspaceError(`The path is protected by the harness policy: ${blocked}`);
@@ -1186,10 +698,10 @@ class Workspace {
1186
698
  const candidate = this.lexicalPath(relativePath);
1187
699
  if (candidate === this.root && options.requireFile)
1188
700
  throw new HarnessWorkspaceError("The workspace root is not a regular file.");
1189
- const segments = path6.relative(this.root, candidate).split(path6.sep).filter(Boolean);
701
+ const segments = path3.relative(this.root, candidate).split(path3.sep).filter(Boolean);
1190
702
  let current = this.root;
1191
703
  for (let index = 0;index < segments.length; index += 1) {
1192
- current = path6.join(current, segments[index]);
704
+ current = path3.join(current, segments[index]);
1193
705
  const leaf = index === segments.length - 1;
1194
706
  if (leaf && options.skipLeafValidation)
1195
707
  continue;
@@ -1223,14 +735,14 @@ class Workspace {
1223
735
  if (!allowBinary && contents.includes(0))
1224
736
  throw new HarnessWorkspaceError("The file appears to be binary and cannot be read as text.");
1225
737
  return {
1226
- path: wirePath(path6.relative(this.root, safe.path)),
738
+ path: wirePath(path3.relative(this.root, safe.path)),
1227
739
  absolutePath: safe.path,
1228
740
  contents,
1229
741
  digest: digestBytes(contents),
1230
742
  mode: file.stat.mode & 511
1231
743
  };
1232
744
  }
1233
- fingerprint(relativePath, kind, entry, digest2) {
745
+ fingerprint(relativePath, kind, entry, digest) {
1234
746
  return {
1235
747
  path: relativePath || ".",
1236
748
  kind,
@@ -1239,7 +751,7 @@ class Workspace {
1239
751
  size: entry.size,
1240
752
  mtimeMs: entry.mtimeMs,
1241
753
  ctimeMs: entry.ctimeMs,
1242
- ...digest2 ? { digest: digest2 } : {}
754
+ ...digest ? { digest } : {}
1243
755
  };
1244
756
  }
1245
757
  sameFingerprint(entry, fingerprint) {
@@ -1247,20 +759,20 @@ class Workspace {
1247
759
  }
1248
760
  async rulesForDirectory(directory, base, inherited, ignoreFiles) {
1249
761
  const rules = [...inherited];
1250
- for (const filename2 of IGNORE_FILES) {
762
+ for (const filename of IGNORE_FILES) {
1251
763
  try {
1252
- const ignorePath = path6.join(directory, filename2);
764
+ const ignorePath = path3.join(directory, filename);
1253
765
  const inspected = await statRegularFileNoFollow(ignorePath, { label: "The ignore file" });
1254
766
  if (inspected.size > MAX_FILE_BYTES) {
1255
- ignoreFiles.push(this.fingerprint(wirePath(path6.relative(this.root, ignorePath)), "ignore-file", inspected));
767
+ ignoreFiles.push(this.fingerprint(wirePath(path3.relative(this.root, ignorePath)), "ignore-file", inspected));
1256
768
  continue;
1257
769
  }
1258
770
  const file = await readRegularFileNoFollow(ignorePath, {
1259
771
  label: "The ignore file",
1260
772
  maxBytes: MAX_FILE_BYTES
1261
773
  });
1262
- const digest2 = digestBytes(file.contents);
1263
- ignoreFiles.push(this.fingerprint(wirePath(path6.relative(this.root, ignorePath)), "ignore-file", file.stat, digest2));
774
+ const digest = digestBytes(file.contents);
775
+ ignoreFiles.push(this.fingerprint(wirePath(path3.relative(this.root, ignorePath)), "ignore-file", file.stat, digest));
1264
776
  rules.push(...parseIgnoreRules(file.contents.toString("utf8"), base));
1265
777
  } catch (error) {
1266
778
  if (error.code !== "ENOENT" && !(error instanceof UnsafeFileTypeError))
@@ -1291,7 +803,7 @@ class Workspace {
1291
803
  if (isHardIgnored(relative) || entry.isSymbolicLink() || isIgnoredByRules(relative, entry.isDirectory(), rules))
1292
804
  continue;
1293
805
  if (entry.isDirectory())
1294
- children.push({ directory: path6.join(directory, entry.name), base: relative, inherited: rules });
806
+ children.push({ directory: path3.join(directory, entry.name), base: relative, inherited: rules });
1295
807
  else if (entry.isFile())
1296
808
  files.push({ path: relative });
1297
809
  }
@@ -1309,14 +821,14 @@ class Workspace {
1309
821
  async isWorkspaceIndexFresh(index) {
1310
822
  try {
1311
823
  for await (const batch of boundedBatches(index.directories, async (fingerprint) => {
1312
- const absolute = fingerprint.path === "." ? this.root : path6.join(this.root, fingerprint.path);
824
+ const absolute = fingerprint.path === "." ? this.root : path3.join(this.root, fingerprint.path);
1313
825
  const entry = await lstat3(absolute);
1314
826
  return !entry.isSymbolicLink() && entry.isDirectory() && this.sameFingerprint(entry, fingerprint);
1315
827
  }))
1316
828
  if (batch.some((fresh) => !fresh))
1317
829
  return false;
1318
830
  for await (const batch of boundedBatches(index.ignoreFiles, async (fingerprint) => {
1319
- const absolute = path6.join(this.root, fingerprint.path);
831
+ const absolute = path3.join(this.root, fingerprint.path);
1320
832
  if (fingerprint.digest) {
1321
833
  const file = await readRegularFileNoFollow(absolute, {
1322
834
  label: "The ignore file",
@@ -1412,7 +924,7 @@ class Workspace {
1412
924
  const start = await this.safePath(relativePath);
1413
925
  if (!(await lstat3(start.path)).isDirectory())
1414
926
  throw new HarnessWorkspaceError("list_files requires a directory.");
1415
- const requestPath = wirePath(path6.relative(this.root, start.path)) || ".";
927
+ const requestPath = wirePath(path3.relative(this.root, start.path)) || ".";
1416
928
  const input = typeof options === "number" ? { limit: options } : options;
1417
929
  const limit = input.limit ?? 200;
1418
930
  const includeDigests = input.includeDigests ?? true;
@@ -1517,7 +1029,7 @@ class Workspace {
1517
1029
  }
1518
1030
  const ordered = requests.map((request) => ({
1519
1031
  ...request,
1520
- path: wirePath(path6.relative(this.root, this.lexicalPath(request.path)))
1032
+ path: wirePath(path3.relative(this.root, this.lexicalPath(request.path)))
1521
1033
  })).sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0) || (a.startLine ?? 1) - (b.startLine ?? 1) || (a.endLine ?? 0) - (b.endLine ?? 0));
1522
1034
  for (const request of ordered) {
1523
1035
  if (!Number.isSafeInteger(request.startLine ?? 1) || (request.startLine ?? 1) < 1 || request.endLine !== undefined && (!Number.isSafeInteger(request.endLine) || request.endLine < (request.startLine ?? 1))) {
@@ -1554,7 +1066,7 @@ class Workspace {
1554
1066
  throw new HarnessWorkspaceError("The search query must be between 1 and 200 characters.");
1555
1067
  const start = await this.safePath(relativePath);
1556
1068
  const isDirectory = (await lstat3(start.path)).isDirectory();
1557
- const requestPath = wirePath(path6.relative(this.root, start.path)) || ".";
1069
+ const requestPath = wirePath(path3.relative(this.root, start.path)) || ".";
1558
1070
  const limit = options.limit ?? options.maxMatches ?? 100;
1559
1071
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 500)
1560
1072
  throw new HarnessWorkspaceError("limit must be between 1 and 500.");
@@ -1679,7 +1191,7 @@ class Workspace {
1679
1191
  });
1680
1192
  const start = await this.safePath(relativePath);
1681
1193
  const isDirectory = (await lstat3(start.path)).isDirectory();
1682
- const requestPath = wirePath(path6.relative(this.root, start.path)) || ".";
1194
+ const requestPath = wirePath(path3.relative(this.root, start.path)) || ".";
1683
1195
  const prefix = requestPath === "." ? "" : `${requestPath}/`;
1684
1196
  const index = isDirectory ? await this.getWorkspaceIndex() : undefined;
1685
1197
  const candidateIndex = requestPath === "." ? 0 : firstPathAtLeast(index?.files ?? [], prefix);
@@ -1773,7 +1285,7 @@ class Workspace {
1773
1285
  this.auditEntries.push(record);
1774
1286
  if (this.auditPath) {
1775
1287
  const temporary = `${this.auditPath}.${randomUUID()}.tmp`;
1776
- const handle = await open3(temporary, "wx", 384);
1288
+ const handle = await open2(temporary, "wx", 384);
1777
1289
  try {
1778
1290
  await handle.writeFile(JSON.stringify(this.auditEntries));
1779
1291
  await handle.sync();
@@ -1792,14 +1304,14 @@ class Workspace {
1792
1304
  return this.auditEntries.map((entry) => ({ ...entry }));
1793
1305
  }
1794
1306
  async secureWorkspaceDirectory(directory, mode = 493) {
1795
- const resolvedInput = path6.resolve(directory);
1307
+ const resolvedInput = path3.resolve(directory);
1796
1308
  if (!isInside(this.root, resolvedInput)) {
1797
1309
  throw new HarnessWorkspaceError("A mutation directory escapes the workspace.");
1798
1310
  }
1799
- const segments = path6.relative(this.root, resolvedInput).split(path6.sep).filter(Boolean);
1311
+ const segments = path3.relative(this.root, resolvedInput).split(path3.sep).filter(Boolean);
1800
1312
  let current = this.root;
1801
1313
  for (const segment of segments) {
1802
- current = path6.join(current, segment);
1314
+ current = path3.join(current, segment);
1803
1315
  try {
1804
1316
  const entry = await lstat3(current);
1805
1317
  if (entry.isSymbolicLink())
@@ -1827,9 +1339,9 @@ class Workspace {
1827
1339
  return canonical;
1828
1340
  }
1829
1341
  async stageFile(target, contents, mode) {
1830
- const directory = await this.secureWorkspaceDirectory(path6.dirname(target));
1831
- const temporary = path6.join(directory, `.${path6.basename(target)}.zhivex-${randomUUID()}.tmp`);
1832
- const handle = await open3(temporary, "wx", mode);
1342
+ const directory = await this.secureWorkspaceDirectory(path3.dirname(target));
1343
+ const temporary = path3.join(directory, `.${path3.basename(target)}.zhivex-${randomUUID()}.tmp`);
1344
+ const handle = await open2(temporary, "wx", mode);
1833
1345
  try {
1834
1346
  await handle.writeFile(contents);
1835
1347
  await handle.chmod(mode);
@@ -2052,7 +1564,7 @@ class Workspace {
2052
1564
  const destination = await this.safePath(parsed.destination, { allowMissing: true });
2053
1565
  if (destination.exists)
2054
1566
  throw new HarnessWorkspaceError(`Move destination already exists: ${parsed.destination}.`);
2055
- await this.secureWorkspaceDirectory(path6.dirname(destination.path));
1567
+ await this.secureWorkspaceDirectory(path3.dirname(destination.path));
2056
1568
  const destinationRecheck = await this.safePath(parsed.destination, { allowMissing: true });
2057
1569
  if (destinationRecheck.exists)
2058
1570
  throw new HarnessWorkspaceError(`Move destination already exists: ${parsed.destination}.`);
@@ -2080,7 +1592,7 @@ class Workspace {
2080
1592
  const segments = [".zhivex-harness", "quarantine"];
2081
1593
  let current = this.root;
2082
1594
  for (const segment of segments) {
2083
- current = path6.join(current, segment);
1595
+ current = path3.join(current, segment);
2084
1596
  try {
2085
1597
  const entry = await lstat3(current);
2086
1598
  if (entry.isSymbolicLink()) {
@@ -2111,7 +1623,7 @@ class Workspace {
2111
1623
  }
2112
1624
  async writeManifest(manifest) {
2113
1625
  const directory = await this.secureQuarantineDirectory(true);
2114
- const target = path6.join(directory, `${manifest.quarantineId}.json`);
1626
+ const target = path3.join(directory, `${manifest.quarantineId}.json`);
2115
1627
  const temporary = await this.stageFile(target, `${JSON.stringify(manifest, null, 2)}
2116
1628
  `, 384);
2117
1629
  await rename(temporary, target);
@@ -2130,7 +1642,7 @@ class Workspace {
2130
1642
  throw new HarnessWorkspaceError(`Stale quarantine rejected for ${parsed.path}.`);
2131
1643
  const quarantineId = `${Date.now()}-${randomUUID()}`;
2132
1644
  const directory = await this.secureQuarantineDirectory(true);
2133
- const dataPath = path6.join(directory, `${quarantineId}.data`);
1645
+ const dataPath = path3.join(directory, `${quarantineId}.data`);
2134
1646
  if ((await this.readStableFile(parsed.path)).digest !== parsed.expectedDigest)
2135
1647
  throw new HarnessWorkspaceError(`Stale quarantine rejected for ${parsed.path}.`);
2136
1648
  await link(source.absolutePath, dataPath);
@@ -2153,7 +1665,7 @@ class Workspace {
2153
1665
  await unlink(source.absolutePath);
2154
1666
  } catch (error) {
2155
1667
  await unlink(dataPath).catch(() => {});
2156
- await unlink(path6.join(directory, `${quarantineId}.json`)).catch(() => {});
1668
+ await unlink(path3.join(directory, `${quarantineId}.json`)).catch(() => {});
2157
1669
  throw error;
2158
1670
  }
2159
1671
  this.invalidateWorkspaceIndex();
@@ -2169,7 +1681,7 @@ class Workspace {
2169
1681
  const directory = await this.secureQuarantineDirectory(false);
2170
1682
  let manifest;
2171
1683
  try {
2172
- const manifestFile = await this.readInternalRegularFile(path6.join(directory, `${parsed.quarantineId}.json`), "Quarantine manifest", 64 * 1024);
1684
+ const manifestFile = await this.readInternalRegularFile(path3.join(directory, `${parsed.quarantineId}.json`), "Quarantine manifest", 64 * 1024);
2173
1685
  manifest = JSON.parse(manifestFile.contents.toString("utf8"));
2174
1686
  } catch {
2175
1687
  throw new HarnessWorkspaceError(`Quarantine entry was not found: ${parsed.quarantineId}.`);
@@ -2177,17 +1689,17 @@ class Workspace {
2177
1689
  if (manifest.schemaVersion !== 1 || manifest.quarantineId !== parsed.quarantineId || manifest.status !== "quarantined") {
2178
1690
  throw new HarnessWorkspaceError(`Quarantine entry is not restorable: ${parsed.quarantineId}.`);
2179
1691
  }
2180
- const dataPath = path6.join(directory, `${parsed.quarantineId}.data`);
1692
+ const dataPath = path3.join(directory, `${parsed.quarantineId}.data`);
2181
1693
  const dataFile = await this.readInternalRegularFile(dataPath, "Quarantine payload", MAX_FILE_BYTES);
2182
- const digest2 = digestBytes(dataFile.contents);
2183
- if (digest2 !== manifest.digest || parsed.expectedDigest && parsed.expectedDigest !== digest2) {
1694
+ const digest = digestBytes(dataFile.contents);
1695
+ if (digest !== manifest.digest || parsed.expectedDigest && parsed.expectedDigest !== digest) {
2184
1696
  throw new HarnessWorkspaceError(`Quarantine digest mismatch: ${parsed.quarantineId}.`);
2185
1697
  }
2186
1698
  const destinationPath = parsed.destination ?? manifest.originalPath;
2187
1699
  const destination = await this.safePath(destinationPath, { allowMissing: true });
2188
1700
  if (destination.exists)
2189
1701
  throw new HarnessWorkspaceError(`Restore destination already exists: ${destinationPath}.`);
2190
- await this.secureWorkspaceDirectory(path6.dirname(destination.path));
1702
+ await this.secureWorkspaceDirectory(path3.dirname(destination.path));
2191
1703
  const destinationRecheck = await this.safePath(destinationPath, { allowMissing: true });
2192
1704
  if (destinationRecheck.exists)
2193
1705
  throw new HarnessWorkspaceError(`Restore destination already exists: ${destinationPath}.`);
@@ -2197,7 +1709,7 @@ class Workspace {
2197
1709
  }
2198
1710
  await link(dataPath, destination.path);
2199
1711
  const linkedDestination = await this.readInternalRegularFile(destination.path, "Restore destination", MAX_FILE_BYTES);
2200
- if (linkedDestination.stat.dev !== dataFile.stat.dev || linkedDestination.stat.ino !== dataFile.stat.ino || digestBytes(linkedDestination.contents) !== digest2) {
1712
+ if (linkedDestination.stat.dev !== dataFile.stat.dev || linkedDestination.stat.ino !== dataFile.stat.ino || digestBytes(linkedDestination.contents) !== digest) {
2201
1713
  await unlink(destination.path).catch(() => {});
2202
1714
  throw new HarnessWorkspaceError("Restore destination did not match the quarantined payload.");
2203
1715
  }
@@ -2230,8 +1742,8 @@ class Workspace {
2230
1742
  throw rollbackErrors.length ? new AggregateError([error, ...rollbackErrors], "Restore failed and rollback was incomplete.") : error;
2231
1743
  }
2232
1744
  this.invalidateWorkspaceIndex();
2233
- const audit = await this.audit({ operation: "restore", path: destinationPath, afterDigest: digest2, quarantineId: parsed.quarantineId });
2234
- return { quarantineId: parsed.quarantineId, path: destinationPath, digest: digest2, audit };
1745
+ const audit = await this.audit({ operation: "restore", path: destinationPath, afterDigest: digest, quarantineId: parsed.quarantineId });
1746
+ return { quarantineId: parsed.quarantineId, path: destinationPath, digest, audit };
2235
1747
  }
2236
1748
  async runCheck(check, expectedScript, allowedChecks = DEFAULT_CHECKS) {
2237
1749
  let manifest;
@@ -2273,214 +1785,21 @@ class EnvironmentPatchDriftError extends Error {
2273
1785
  }
2274
1786
  }
2275
1787
 
2276
- // src/runtime/task-acceptance-delivery.ts
2277
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
2278
- import { z as z4 } from "zod";
2279
-
2280
- // src/runtime/task-acceptance-checks.ts
2281
- import { createHash as createHash4 } from "node:crypto";
2282
- import { z as z3 } from "zod";
2283
- var sha = z3.string().regex(/^sha256:[a-f0-9]{64}$/);
2284
- var taskCheckReceiptSchema = z3.strictObject({
2285
- schemaVersion: z3.literal(1),
2286
- checkId: z3.string().max(128),
2287
- contractDigest: sha,
2288
- contractRevision: z3.number().int().positive(),
2289
- runId: z3.string().max(512),
2290
- executionIdentity: z3.string().max(512),
2291
- patchId: sha,
2292
- snapshotDigest: sha,
2293
- argvDigest: sha,
2294
- exitCode: z3.number().int(),
2295
- timedOut: z3.boolean(),
2296
- unchanged: z3.boolean(),
2297
- source: z3.strictObject({ id: z3.string().min(1).max(512), name: z3.string().min(1).max(128), startedAt: z3.number().finite().nonnegative().optional() }).optional()
2298
- });
2299
- var argvDigest = (command, args) => "sha256:" + createHash4("sha256").update(JSON.stringify([command, ...args])).digest("hex");
2300
- function createTaskAcceptanceChecks(ledger, previous = [], journal = []) {
2301
- const current = ledger.revisions.at(-1);
2302
- const receipts = new Map;
2303
- const parsed = z3.array(taskCheckReceiptSchema).max(32).safeParse(previous);
2304
- if (parsed.success)
2305
- for (const receipt of parsed.data) {
2306
- const check = current.contract.requiredChecks.find((c) => c.id === receipt.checkId);
2307
- if (check && receipt.contractDigest === current.digest && receipt.contractRevision === current.revision && receipt.argvDigest === argvDigest(check.command, check.args) && reconciledReceipt(receipt, journal))
2308
- receipts.set(check.id, receipt);
2309
- }
2310
- return {
2311
- matching(command, args) {
2312
- return current.contract.requiredChecks.filter((check) => argvDigest(check.command, check.args) === argvDigest(command, args));
2313
- },
2314
- begin(checkIds) {
2315
- for (const id of checkIds)
2316
- receipts.delete(id);
2317
- },
2318
- record(checkId, before, after, result, source) {
2319
- const check = current.contract.requiredChecks.find((c) => c.id === checkId);
2320
- if (!check)
2321
- throw new Error("TASK_ACCEPTANCE_UNKNOWN_CHECK");
2322
- const receipt = taskCheckReceiptSchema.parse({
2323
- schemaVersion: 1,
2324
- checkId,
2325
- contractDigest: current.digest,
2326
- contractRevision: current.revision,
2327
- ...before,
2328
- ...source ? { source: { id: source.id, name: source.name, ...source.startedAt !== undefined ? { startedAt: source.startedAt } : {} } } : {},
2329
- argvDigest: argvDigest(check.command, check.args),
2330
- exitCode: result.exitCode,
2331
- timedOut: result.timedOut,
2332
- unchanged: before.runId === after.runId && before.executionIdentity === after.executionIdentity && before.patchId === after.patchId && before.snapshotDigest === after.snapshotDigest
2333
- });
2334
- receipts.set(checkId, receipt);
2335
- return structuredClone(receipt);
2336
- },
2337
- missing(binding) {
2338
- return current.contract.requiredChecks.filter((check) => {
2339
- const receipt = receipts.get(check.id);
2340
- return !receipt || receipt.exitCode !== 0 || receipt.timedOut || !receipt.unchanged || receipt.runId !== binding.runId || receipt.executionIdentity !== binding.executionIdentity || receipt.patchId !== binding.patchId || receipt.snapshotDigest !== binding.snapshotDigest;
2341
- }).map((check) => check.id);
2342
- },
2343
- snapshot() {
2344
- return [...receipts.values()].map((receipt) => structuredClone(receipt));
2345
- }
2346
- };
2347
- }
2348
- var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
2349
- var commandDigest = (value) => {
2350
- const input = object(value);
2351
- return typeof input?.command === "string" && Array.isArray(input.args) && input.args.every((arg) => typeof arg === "string") ? argvDigest(input.command, input.args) : undefined;
2352
- };
2353
- function reconciledReceipt(receipt, journal) {
2354
- if (!receipt.source)
2355
- return false;
2356
- const matches = journal.filter((row2) => row2.runId === receipt.runId && row2.providerToolCallId === receipt.source.id && row2.toolName === receipt.source.name);
2357
- if (matches.length !== 1)
2358
- return false;
2359
- const row = matches[0];
2360
- const startedAt = receipt.source.startedAt ?? row.startedAt;
2361
- if (row.status !== "completed" || !Number.isFinite(startedAt) || !Number.isFinite(row.completedAt) || row.completedAt < startedAt)
2362
- return false;
2363
- if (!["run_environment_command", "run_check", "verify_and_apply_environment_patch", "verify_and_apply_reviewed_edits"].includes(row.toolName))
2364
- return false;
2365
- const output = object(row.output), result = object(output?.verification) ?? output;
2366
- if (!result || result.exitCode !== receipt.exitCode || result.timedOut !== receipt.timedOut || !Array.isArray(result.command) || !result.command.every((arg) => typeof arg === "string") || typeof result.command[0] !== "string" || argvDigest(result.command[0], result.command.slice(1)) !== receipt.argvDigest)
2367
- return false;
2368
- if (row.toolName !== "run_check" && commandDigest(row.input) !== receipt.argvDigest)
2369
- return false;
2370
- for (const attempt of journal) {
2371
- if (attempt === row || attempt.runId !== receipt.runId)
2372
- continue;
2373
- if (attempt.status === "pending" || attempt.status === "running")
2374
- return false;
2375
- const input = object(attempt.input);
2376
- const sameCheck = commandDigest(input) === receipt.argvDigest || attempt.toolName === "run_check" && row.toolName === "run_check" && input?.check === object(row.input)?.check || attempt.toolName === "run_environment_batch" && Array.isArray(input?.commands) && input.commands.some((command) => commandDigest(command) === receipt.argvDigest);
2377
- if (sameCheck && (!Number.isFinite(attempt.completedAt) || attempt.completedAt >= startedAt))
2378
- return false;
2379
- }
2380
- return true;
2381
- }
2382
-
2383
- // src/runtime/task-acceptance-delivery.ts
2384
- var scopes = new AsyncLocalStorage2;
2385
- function withTaskAcceptanceDelivery(workspace, ledger, work, previousEvidence, journal = []) {
2386
- const latest = ledger.revisions.at(-1);
2387
- const previous = z4.object({ contractDigest: z4.literal(latest.digest), contractRevision: z4.literal(latest.revision), diagnostic: z4.strictObject({
2388
- code: z4.literal("TASK_ACCEPTANCE_SCOPE_VIOLATION"),
2389
- runId: z4.string().max(512),
2390
- patchId: z4.string().regex(/^sha256:[a-f0-9]{64}$/),
2391
- paths: z4.array(z4.string().max(1024)).max(256)
2392
- }) }).safeParse(previousEvidence);
2393
- const previousDelivery = z4.object({ contractDigest: z4.literal(latest.digest), contractRevision: z4.literal(latest.revision), delivery: z4.strictObject({
2394
- runId: z4.string().min(1).max(512),
2395
- executionIdentity: z4.string().min(1).max(512),
2396
- patchId: z4.string().regex(/^sha256:[a-f0-9]{64}$/),
2397
- snapshotDigest: z4.string().regex(/^sha256:[a-f0-9]{64}$/)
2398
- }) }).safeParse(previousEvidence);
2399
- return scopes.run({
2400
- ...previousDelivery.success ? { previousDelivery: previousDelivery.data.delivery } : {},
2401
- workspace,
2402
- revision: latest.revision,
2403
- digest: latest.digest,
2404
- checks: createTaskAcceptanceChecks(ledger, previousEvidence && typeof previousEvidence === "object" && "checks" in previousEvidence ? previousEvidence.checks : [], journal),
2405
- allowed: new Set(latest.contract.allowedWritePaths),
2406
- protected: new Set(latest.contract.protectedFiles.map((file) => file.toLowerCase())),
2407
- ...previous.success ? { violation: previous.data.diagnostic } : {}
2408
- }, work);
2409
- }
2410
- function assertTaskAcceptanceImport(input) {
2411
- const scope = scopes.getStore();
2412
- if (!scope)
2413
- return;
2414
- const blocked = input.entries.filter((entry) => {
2415
- const candidate = entry.path.toLowerCase();
2416
- return input.workspace !== scope.workspace || !scope.allowed.has(entry.path) || [...scope.protected].some((file) => candidate === file || candidate.startsWith(file + "/") || file.startsWith(candidate + "/"));
2417
- });
2418
- if (blocked.length) {
2419
- scope.violation = { code: "TASK_ACCEPTANCE_SCOPE_VIOLATION", runId: input.runId, patchId: input.patchId, paths: blocked.map((entry) => entry.path).slice(0, 256) };
2420
- throw new Error("TASK_ACCEPTANCE_SCOPE_VIOLATION: the OCI patch touches files outside the task contract; no host import was performed.");
2421
- }
2422
- if (!input.executionIdentity || !input.snapshotDigest || scope.checks.missing({ runId: input.runId, patchId: input.patchId, executionIdentity: input.executionIdentity, snapshotDigest: input.snapshotDigest }).length) {
2423
- throw new Error("TASK_ACCEPTANCE_CHECKS_MISSING: every required check must succeed on the exact final snapshot and patch before import.");
2424
- }
2425
- }
2426
- var taskAcceptanceChecks = () => scopes.getStore()?.checks;
2427
- function taskAcceptanceDeliveryDiagnostic(digest2, revision) {
2428
- const scope = scopes.getStore();
2429
- return scope?.digest === digest2 && scope.revision === revision && scope.violation ? structuredClone(scope.violation) : undefined;
2430
- }
2431
- function confirmTaskAcceptanceImport(binding, validate) {
2432
- const scope = scopes.getStore();
2433
- if (scope)
2434
- scope.imported = { binding: structuredClone(binding), validate };
2435
- }
2436
- async function evaluateTaskAcceptanceOutcome(state, ledger) {
2437
- const current = ledger.revisions.at(-1), scope = scopes.getStore();
2438
- const terminal = ["completed", "failed", "cancelled", "timed_out"].includes(state.status);
2439
- if (!scope || scope.digest !== current.digest || scope.revision !== current.revision) {
2440
- return { status: terminal ? "incomplete" : "pending", reason: "TASK_ACCEPTANCE_NO_DELIVERY_EVIDENCE" };
2441
- }
2442
- if (scope.violation)
2443
- return { status: "failed", reason: scope.violation.code };
2444
- if (state.status !== "completed")
2445
- return { status: state.status === "failed" ? "failed" : terminal ? "incomplete" : "pending", reason: "TASK_ACCEPTANCE_RUN_NOT_COMPLETED" };
2446
- if (state.finishReason !== "stop")
2447
- return { status: "incomplete", reason: "TASK_ACCEPTANCE_RUN_NOT_FINISHED" };
2448
- const imported = scope.imported;
2449
- if (!imported || imported.binding.runId !== state.runId)
2450
- return { status: "incomplete", reason: "TASK_ACCEPTANCE_IMPORT_UNCONFIRMED" };
2451
- const delivery = { ...imported.binding };
2452
- if (scope.checks.missing(delivery).length)
2453
- return { status: "incomplete", reason: "TASK_ACCEPTANCE_CHECKS_MISSING", delivery };
2454
- try {
2455
- if (!await imported.validate())
2456
- return { status: "incomplete", reason: "TASK_ACCEPTANCE_DELIVERY_DRIFT", delivery };
2457
- } catch {
2458
- return { status: "incomplete", reason: "TASK_ACCEPTANCE_DELIVERY_INSPECTION_FAILED", delivery };
2459
- }
2460
- return { status: current.contract.humanReview.length ? "pending_review" : "verified", reason: current.contract.humanReview.length ? "TASK_ACCEPTANCE_HUMAN_REVIEW_REQUIRED" : "TASK_ACCEPTANCE_VERIFIED", delivery };
2461
- }
2462
- async function taskAcceptanceOutcome(state, ledger) {
2463
- const outcome = await evaluateTaskAcceptanceOutcome(state, ledger);
2464
- const scope = scopes.getStore(), latest = ledger.revisions.at(-1);
2465
- const delivery = scope?.digest === latest.digest && scope.revision === latest.revision ? scope.imported?.binding ?? scope.previousDelivery : undefined;
2466
- return { ...outcome, ...delivery && delivery.runId === state.runId ? { delivery: structuredClone(delivery) } : {} };
2467
- }
2468
-
2469
1788
  // src/execution/acceptance-snapshot.ts
2470
- import { createHash as createHash5 } from "node:crypto";
1789
+ import { createHash as createHash3 } from "node:crypto";
2471
1790
  import { lstat as lstat4, readdir as readdir2 } from "node:fs/promises";
2472
- import path7 from "node:path";
1791
+ import path4 from "node:path";
2473
1792
  async function acceptanceSnapshotDigest(root, maxBytes) {
2474
1793
  const rows = [];
2475
1794
  let bytes = 0;
2476
1795
  async function visit(relative) {
2477
- const names = await readdir2(path7.join(root, relative));
1796
+ const names = await readdir2(path4.join(root, relative));
2478
1797
  names.sort();
2479
1798
  for (const name of names) {
2480
1799
  const item = relative ? relative + "/" + name : name;
2481
1800
  if (rows.length >= 20000)
2482
1801
  throw new Error("TASK_ACCEPTANCE_SNAPSHOT_CAPACITY");
2483
- const absolute = path7.join(root, item), entry = await lstat4(absolute);
1802
+ const absolute = path4.join(root, item), entry = await lstat4(absolute);
2484
1803
  if (entry.isSymbolicLink())
2485
1804
  throw new Error("TASK_ACCEPTANCE_SNAPSHOT_UNSAFE");
2486
1805
  if (entry.isDirectory()) {
@@ -2489,13 +1808,13 @@ async function acceptanceSnapshotDigest(root, maxBytes) {
2489
1808
  } else if (entry.isFile() && entry.nlink === 1) {
2490
1809
  const file = await readRegularFileNoFollow(absolute, { label: "Acceptance snapshot file", maxBytes: maxBytes - bytes, requireSingleLink: true });
2491
1810
  bytes += file.contents.byteLength;
2492
- rows.push([item, "file", file.stat.mode & 511, createHash5("sha256").update(file.contents).digest("hex")]);
1811
+ rows.push([item, "file", file.stat.mode & 511, createHash3("sha256").update(file.contents).digest("hex")]);
2493
1812
  } else
2494
1813
  throw new Error("TASK_ACCEPTANCE_SNAPSHOT_UNSAFE");
2495
1814
  }
2496
1815
  }
2497
1816
  await visit("");
2498
- return "sha256:" + createHash5("sha256").update(JSON.stringify(rows)).digest("hex");
1817
+ return "sha256:" + createHash3("sha256").update(JSON.stringify(rows)).digest("hex");
2499
1818
  }
2500
1819
 
2501
1820
  // src/execution/oci-observability.ts
@@ -2519,9 +1838,9 @@ async function observeOciPhase(operation, action) {
2519
1838
  }
2520
1839
 
2521
1840
  // src/execution/execution-environment.ts
2522
- import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
1841
+ import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
2523
1842
  import { spawn as spawn2 } from "node:child_process";
2524
- import { constants as fsConstants2 } from "node:fs";
1843
+ import { constants as fsConstants } from "node:fs";
2525
1844
  import {
2526
1845
  chmod,
2527
1846
  copyFile,
@@ -2533,7 +1852,7 @@ import {
2533
1852
  rm,
2534
1853
  writeFile
2535
1854
  } from "node:fs/promises";
2536
- import path8 from "node:path";
1855
+ import path5 from "node:path";
2537
1856
  import { createAgentExecutionEnvironmentBinding } from "@zhivex-ai/agents/beta";
2538
1857
  var HARNESS_EXECUTION_ARTIFACT_SCHEMA_VERSION = 1;
2539
1858
  var HARNESS_OCI_LABEL = "com.zhivex.harness.execution";
@@ -2577,7 +1896,7 @@ var BUILT_IN_TOOL_NAMES = new Set([
2577
1896
  "verify_and_apply_reviewed_edits",
2578
1897
  "environment_status"
2579
1898
  ]);
2580
- var digest2 = (value) => `sha256:${createHash6("sha256").update(value).digest("hex")}`;
1899
+ var digest = (value) => `sha256:${createHash4("sha256").update(value).digest("hex")}`;
2581
1900
  var executionScopeKey = (scope) => {
2582
1901
  if (scope) {
2583
1902
  for (const value of [scope.tenantId, scope.userId, scope.namespace]) {
@@ -2590,11 +1909,11 @@ var executionScopeKey = (scope) => {
2590
1909
  }
2591
1910
  return JSON.stringify([scope?.tenantId ?? null, scope?.userId ?? null, scope?.namespace ?? null]);
2592
1911
  };
2593
- var executionIdentity = (workspace, stateDirectory, runId, scopeKey) => digest2(JSON.stringify(["scoped-oci-v2", workspace, stateDirectory, scopeKey, runId]));
2594
- var runHash = (runId) => createHash6("sha256").update(runId).digest("hex").slice(0, 24);
1912
+ var executionIdentity = (workspace, stateDirectory, runId, scopeKey) => digest(JSON.stringify(["scoped-oci-v2", workspace, stateDirectory, scopeKey, runId]));
1913
+ var runHash = (runId) => createHash4("sha256").update(runId).digest("hex").slice(0, 24);
2595
1914
  var isInside2 = (root, candidate) => {
2596
- const relative = path8.relative(root, candidate);
2597
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path8.sep}`) && !path8.isAbsolute(relative);
1915
+ const relative = path5.relative(root, candidate);
1916
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path5.sep}`) && !path5.isAbsolute(relative);
2598
1917
  };
2599
1918
  var privateDirectory = async (directory) => {
2600
1919
  await mkdir3(directory, { recursive: true, mode: 448 });
@@ -2733,14 +2052,14 @@ var updateSnapshotMetadata = (target, kind, relative, entry) => {
2733
2052
  var validateSynchronizedSnapshot = async (stagedRoot, previousRoot, maxWorkspaceBytes, maxFileWriteBytes) => {
2734
2053
  let entries = 0;
2735
2054
  let totalBytes = 0;
2736
- const seal = createHash6("sha256");
2737
- const metadata = createHash6("sha256");
2055
+ const seal = createHash4("sha256");
2056
+ const metadata = createHash4("sha256");
2738
2057
  const visit = async (directory, relativeDirectory = "") => {
2739
2058
  const children = (await readdir3(directory, { withFileTypes: true })).sort((left, right) => left.name.localeCompare(right.name));
2740
2059
  for (const child of children) {
2741
2060
  const name = child.name;
2742
2061
  const relative = relativeDirectory ? `${relativeDirectory}/${name}` : name;
2743
- const absolute = path8.join(directory, name);
2062
+ const absolute = path5.join(directory, name);
2744
2063
  if (!isInside2(stagedRoot, absolute) || relative.length > 1024) {
2745
2064
  throw new Error(`OCI workspace export contains an invalid path: ${relative}.`);
2746
2065
  }
@@ -2787,18 +2106,18 @@ var validateSynchronizedSnapshot = async (stagedRoot, previousRoot, maxWorkspace
2787
2106
  if (totalBytes > maxWorkspaceBytes) {
2788
2107
  throw new Error(`OCI workspace export exceeds the ${maxWorkspaceBytes}-byte workspace limit.`);
2789
2108
  }
2790
- const contentDigest = digest2(contents);
2109
+ const contentDigest = digest(contents);
2791
2110
  updateSnapshotMetadata(metadata, "file", relative, entry);
2792
2111
  seal.update(`file\x00${relative}\x00${entry.mode & 511}\x00${entry.size}\x00${contentDigest}\x00`);
2793
2112
  if (entry.size > maxFileWriteBytes) {
2794
- const previous = path8.join(previousRoot, ...relative.split("/"));
2113
+ const previous = path5.join(previousRoot, ...relative.split("/"));
2795
2114
  let unchanged = false;
2796
2115
  try {
2797
2116
  const previousFile = await readRegularFileNoFollow(previous, {
2798
2117
  label: `Previous OCI workspace file ${relative}`,
2799
2118
  maxBytes: entry.size
2800
2119
  });
2801
- unchanged = previousFile.stat.size === entry.size && digest2(previousFile.contents) === contentDigest;
2120
+ unchanged = previousFile.stat.size === entry.size && digest(previousFile.contents) === contentDigest;
2802
2121
  } catch (error) {
2803
2122
  if (error.code !== "ENOENT")
2804
2123
  throw error;
@@ -2820,13 +2139,13 @@ var validateSynchronizedSnapshot = async (stagedRoot, previousRoot, maxWorkspace
2820
2139
  var snapshotMetadataFingerprint = async (root, maxWorkspaceBytes) => {
2821
2140
  let entries = 0;
2822
2141
  let totalBytes = 0;
2823
- const metadata = createHash6("sha256");
2142
+ const metadata = createHash4("sha256");
2824
2143
  const visit = async (directory, relativeDirectory = "") => {
2825
2144
  for (const name of (await readdir3(directory)).sort()) {
2826
2145
  const relative = relativeDirectory ? `${relativeDirectory}/${name}` : name;
2827
2146
  if (relative === "node_modules")
2828
2147
  continue;
2829
- const absolute = path8.join(directory, name);
2148
+ const absolute = path5.join(directory, name);
2830
2149
  if (!isInside2(root, absolute) || relative.length > 1024) {
2831
2150
  throw new Error(`OCI workspace snapshot contains an invalid path: ${relative}.`);
2832
2151
  }
@@ -2986,7 +2305,7 @@ ${result.stdout}`)) {
2986
2305
  }
2987
2306
  }
2988
2307
  requestFingerprint(request) {
2989
- return digest2(JSON.stringify({
2308
+ return digest(JSON.stringify({
2990
2309
  runId: request.runId,
2991
2310
  snapshotRoot: request.snapshotRoot,
2992
2311
  dependencyRoot: request.dependencyRoot ?? null,
@@ -3105,7 +2424,7 @@ ${result.stdout}`)) {
3105
2424
  await this.cli([
3106
2425
  "cp",
3107
2426
  "-a",
3108
- `${request.snapshotRoot}${path8.sep}.`,
2427
+ `${request.snapshotRoot}${path5.sep}.`,
3109
2428
  `${name}:/workspace`
3110
2429
  ], 60000);
3111
2430
  if (request.dependencyRoot) {
@@ -3237,7 +2556,7 @@ ${result.stdout}`)) {
3237
2556
  };
3238
2557
  }
3239
2558
  const workspaceExportStartedAt = process.hrtime.bigint();
3240
- const stagedRoot = path8.join(path8.dirname(request.snapshotRoot), `.workspace-sync-${randomUUID2()}`);
2559
+ const stagedRoot = path5.join(path5.dirname(request.snapshotRoot), `.workspace-sync-${randomUUID2()}`);
3241
2560
  try {
3242
2561
  await privateDirectory(stagedRoot);
3243
2562
  await observeOciPhase("oci_export", () => this.cli(["cp", `${session.name}:/workspace/.`, stagedRoot], 60000));
@@ -3451,7 +2770,7 @@ var collectSnapshotInventory = async (workspace, maxWorkspaceBytes, metrics, max
3451
2770
  if (metrics)
3452
2771
  metrics.inventoryPages += 1;
3453
2772
  for await (const candidates of boundedBatches(page.files, async (file) => {
3454
- const absolute = path8.join(workspace.root, ...file.path.split("/"));
2773
+ const absolute = path5.join(workspace.root, ...file.path.split("/"));
3455
2774
  if (!isInside2(workspace.root, absolute))
3456
2775
  throw new Error(`Snapshot file escaped its workspace: ${file.path}.`);
3457
2776
  if (await realpath3(absolute) !== absolute)
@@ -3472,7 +2791,7 @@ var collectSnapshotInventory = async (workspace, maxWorkspaceBytes, metrics, max
3472
2791
  if (stable.stat.dev !== entry.dev || stable.stat.ino !== entry.ino || stable.stat.size !== entry.size || stable.stat.mtimeMs !== entry.mtimeMs || stable.stat.ctimeMs !== entry.ctimeMs) {
3473
2792
  throw new Error(`Snapshot inventory file changed while being read: ${file.path}.`);
3474
2793
  }
3475
- return { path: file.path, digest: digest2(stable.contents), mode: stable.stat.mode & 511, bytes: stable.contents.byteLength };
2794
+ return { path: file.path, digest: digest(stable.contents), mode: stable.stat.mode & 511, bytes: stable.contents.byteLength };
3476
2795
  }, 4))
3477
2796
  for (const file of batch) {
3478
2797
  if (files.size >= maxEntries)
@@ -3485,7 +2804,7 @@ var collectSnapshotInventory = async (workspace, maxWorkspaceBytes, metrics, max
3485
2804
  return files;
3486
2805
  };
3487
2806
  var readSnapshotFile = async (workspace, expected, metrics, requireSingleLink = false) => {
3488
- const absolute = path8.join(workspace.root, ...expected.path.split("/"));
2807
+ const absolute = path5.join(workspace.root, ...expected.path.split("/"));
3489
2808
  if (!isInside2(workspace.root, absolute)) {
3490
2809
  throw new Error(`Snapshot file escaped its workspace: ${expected.path}.`);
3491
2810
  }
@@ -3498,7 +2817,7 @@ var readSnapshotFile = async (workspace, expected, metrics, requireSingleLink =
3498
2817
  });
3499
2818
  const { contents } = file;
3500
2819
  const entry = file.stat;
3501
- const actualDigest = digest2(contents);
2820
+ const actualDigest = digest(contents);
3502
2821
  if (actualDigest !== expected.digest || contents.byteLength !== expected.bytes || (entry.mode & 511) !== expected.mode) {
3503
2822
  throw new Error(`Snapshot source changed after inventory: ${expected.path}.`);
3504
2823
  }
@@ -3510,7 +2829,7 @@ var readSnapshotFile = async (workspace, expected, metrics, requireSingleLink =
3510
2829
  };
3511
2830
  var copySnapshotFile = async (source, target, metrics) => {
3512
2831
  try {
3513
- await copyFile(source, target, fsConstants2.COPYFILE_FICLONE_FORCE);
2832
+ await copyFile(source, target, fsConstants.COPYFILE_FICLONE_FORCE);
3514
2833
  } catch (error) {
3515
2834
  const code = error.code;
3516
2835
  if (!code || !COPY_ON_WRITE_UNSUPPORTED_CODES.has(code))
@@ -3532,11 +2851,11 @@ var copyWorkspaceSnapshot = async (source, baseRoot, snapshotRoot, maxWorkspaceB
3532
2851
  }
3533
2852
  for await (const _batch of boundedBatches([...files.values()], async (expected) => {
3534
2853
  const file = await readSnapshotFile(source, expected, metrics);
3535
- const baseTarget = path8.join(baseRoot, ...file.path.split("/"));
3536
- const snapshotTarget = path8.join(snapshotRoot, ...file.path.split("/"));
2854
+ const baseTarget = path5.join(baseRoot, ...file.path.split("/"));
2855
+ const snapshotTarget = path5.join(snapshotRoot, ...file.path.split("/"));
3537
2856
  await Promise.all([
3538
- mkdir3(path8.dirname(baseTarget), { recursive: true, mode: 448 }),
3539
- mkdir3(path8.dirname(snapshotTarget), { recursive: true, mode: 448 })
2857
+ mkdir3(path5.dirname(baseTarget), { recursive: true, mode: 448 }),
2858
+ mkdir3(path5.dirname(snapshotTarget), { recursive: true, mode: 448 })
3540
2859
  ]);
3541
2860
  await writeFile(baseTarget, file.contents, { mode: file.mode });
3542
2861
  await chmod(baseTarget, file.mode);
@@ -3552,7 +2871,7 @@ var copyWorkspaceSnapshot = async (source, baseRoot, snapshotRoot, maxWorkspaceB
3552
2871
  var deliveryPaths = (value) => {
3553
2872
  if (value === undefined)
3554
2873
  return [];
3555
- if (!Array.isArray(value) || value.length > MAX_SYNC_ENTRIES || value.some((item) => typeof item !== "string" || !item || item.length > 8192 || item.includes("\\") || item.includes("\x00") || path8.posix.isAbsolute(item) || item.split("/").some((segment) => !segment || segment === "." || segment === "..")) || Buffer.byteLength(JSON.stringify(value)) > 512 * 1024) {
2874
+ if (!Array.isArray(value) || value.length > MAX_SYNC_ENTRIES || value.some((item) => typeof item !== "string" || !item || item.length > 8192 || item.includes("\\") || item.includes("\x00") || path5.posix.isAbsolute(item) || item.split("/").some((segment) => !segment || segment === "." || segment === "..")) || Buffer.byteLength(JSON.stringify(value)) > 512 * 1024) {
3556
2875
  throw new Error("Invalid or oversized OCI delivery path history.");
3557
2876
  }
3558
2877
  return [...new Set(value)];
@@ -3613,7 +2932,7 @@ var createEnvironmentPatch = async (runId, base, current, maxFileWriteBytes, max
3613
2932
  throw new Error(`Environment patch exceeds the ${MAX_EDIT_PROPOSAL_BYTES}-byte import limit.`);
3614
2933
  }
3615
2934
  const payload = patchPayload(runId, entries);
3616
- return { entries, totalBytes, patchId: digest2(JSON.stringify({ ...payload, executionIdentity: identity ?? null })) };
2935
+ return { entries, totalBytes, patchId: digest(JSON.stringify({ ...payload, executionIdentity: identity ?? null })) };
3617
2936
  };
3618
2937
  var inspectHostPrecondition = async (workspace, filePath, expectedDigest, expectedMode) => {
3619
2938
  try {
@@ -3745,7 +3064,7 @@ var harnessExecutionSession = (context) => {
3745
3064
  var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3746
3065
  const runtime = options.runtime ?? new CliOciRuntimeAdapter(options.config.runtime);
3747
3066
  const image = await runtime.inspectImage(options.config.image);
3748
- const workspaceIdentity = digest2(options.workspace.root);
3067
+ const workspaceIdentity = digest(options.workspace.root);
3749
3068
  const manifest = {
3750
3069
  schemaVersion: 1,
3751
3070
  id: `zhivex-harness-${options.config.runtime}-oci`,
@@ -3800,7 +3119,7 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3800
3119
  }
3801
3120
  };
3802
3121
  const binding = createAgentExecutionEnvironmentBinding(manifest);
3803
- const environmentRoot = path8.join(options.stateDirectory, "environments");
3122
+ const environmentRoot = path5.join(options.stateDirectory, "environments");
3804
3123
  const reviewSnapshot = async (request, allowAbsent = false) => {
3805
3124
  let stateDirectory;
3806
3125
  try {
@@ -3812,9 +3131,9 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3812
3131
  }
3813
3132
  const scopeKey = executionScopeKey(request.scope);
3814
3133
  const identity = executionIdentity(options.workspace.root, stateDirectory, request.runId, scopeKey);
3815
- const root = path8.join(stateDirectory, "environments");
3816
- const directory = path8.join(root, runHash(identity));
3817
- for (const candidate of [root, directory, path8.join(directory, "base"), path8.join(directory, "workspace")]) {
3134
+ const root = path5.join(stateDirectory, "environments");
3135
+ const directory = path5.join(root, runHash(identity));
3136
+ for (const candidate of [root, directory, path5.join(directory, "base"), path5.join(directory, "workspace")]) {
3818
3137
  let entry;
3819
3138
  try {
3820
3139
  entry = await lstat5(candidate);
@@ -3827,7 +3146,7 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3827
3146
  throw new Error("Unsafe execution review directory.");
3828
3147
  }
3829
3148
  }
3830
- const file = await readRegularFileNoFollow(path8.join(directory, "environment.json"), {
3149
+ const file = await readRegularFileNoFollow(path5.join(directory, "environment.json"), {
3831
3150
  label: "Execution metadata",
3832
3151
  maxBytes: 1024 * 1024
3833
3152
  });
@@ -3835,8 +3154,8 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3835
3154
  if (metadata.schemaVersion !== HARNESS_EXECUTION_ARTIFACT_SCHEMA_VERSION || metadata.runId !== request.runId || metadata.scopeKey !== scopeKey || metadata.stateDirectory !== stateDirectory || metadata.executionIdentity !== identity || metadata.hostWorkspace !== options.workspace.root || metadata.binding.fingerprint !== binding.fingerprint || metadata.binding.workspaceId !== binding.workspaceId) {
3836
3155
  throw Object.assign(new Error("Execution review binding changed."), { diagnosticCode: "OCI_EXECUTION_BINDING_CHANGED" });
3837
3156
  }
3838
- const base = await Workspace.open(path8.join(directory, "base"));
3839
- const current = await Workspace.open(path8.join(directory, "workspace"));
3157
+ const base = await Workspace.open(path5.join(directory, "base"));
3158
+ const current = await Workspace.open(path5.join(directory, "workspace"));
3840
3159
  const patch = await createEnvironmentPatch(request.runId, base, current, options.config.maxFileWriteBytes, options.config.maxWorkspaceBytes, undefined, identity);
3841
3160
  deliveryPaths(metadata.deliveryPaths);
3842
3161
  return { metadata, patch, current };
@@ -3895,11 +3214,11 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3895
3214
  const stateDirectory = await realpath3(options.stateDirectory);
3896
3215
  const scopeKey = executionScopeKey(request.scope);
3897
3216
  const identity = executionIdentity(options.workspace.root, stateDirectory, request.runId, scopeKey);
3898
- const directory = path8.join(environmentRoot, runHash(identity));
3217
+ const directory = path5.join(environmentRoot, runHash(identity));
3899
3218
  await privateDirectory(directory);
3900
- const metadataPath = path8.join(directory, "environment.json");
3901
- const baseRoot = path8.join(directory, "base");
3902
- const snapshotRoot = path8.join(directory, "workspace");
3219
+ const metadataPath = path5.join(directory, "environment.json");
3220
+ const baseRoot = path5.join(directory, "base");
3221
+ const snapshotRoot = path5.join(directory, "workspace");
3903
3222
  let metadata;
3904
3223
  try {
3905
3224
  const metadataFile = await readRegularFileNoFollow(metadataPath, {
@@ -3914,7 +3233,7 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3914
3233
  if (error.code !== "ENOENT")
3915
3234
  throw error;
3916
3235
  try {
3917
- await lstat5(path8.join(environmentRoot, runHash(request.runId)));
3236
+ await lstat5(path5.join(environmentRoot, runHash(request.runId)));
3918
3237
  throw new Error("Unscoped legacy OCI artifact requires its original runtime; start a new run.");
3919
3238
  } catch (legacyError) {
3920
3239
  if (legacyError.code !== "ENOENT")
@@ -3941,9 +3260,9 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
3941
3260
  delete metadata.releasedAt;
3942
3261
  delete metadata.status;
3943
3262
  await atomicJson(metadataPath, metadata);
3944
- const workspace = await Workspace.open(snapshotRoot, { auditPath: path8.join(directory, "mutation-audit.json") });
3263
+ const workspace = await Workspace.open(snapshotRoot, { auditPath: path5.join(directory, "mutation-audit.json") });
3945
3264
  const base = await Workspace.open(baseRoot);
3946
- const dependencyPath = path8.join(options.workspace.root, "node_modules");
3265
+ const dependencyPath = path5.join(options.workspace.root, "node_modules");
3947
3266
  let dependencyRoot;
3948
3267
  try {
3949
3268
  const entry = await lstat5(dependencyPath);
@@ -4022,7 +3341,7 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
4022
3341
  });
4023
3342
  for (const check of matching)
4024
3343
  if (check.kind === "package-script") {
4025
- const file = await readRegularFileNoFollow(path8.join(workspace.root, "package.json"), { label: "Acceptance package manifest", maxBytes: 256 * 1024, requireSingleLink: true });
3344
+ const file = await readRegularFileNoFollow(path5.join(workspace.root, "package.json"), { label: "Acceptance package manifest", maxBytes: 256 * 1024, requireSingleLink: true });
4026
3345
  const manifestDocument = JSON.parse(file.contents.toString("utf8"));
4027
3346
  const resolved = await resolvePackageCheckCommand(workspace.root, manifestDocument, check.script, check.expectedScript, [check.script]);
4028
3347
  if (JSON.stringify(resolved.command) !== JSON.stringify(argv))
@@ -4157,7 +3476,7 @@ var createHarnessOciExecutionEnvironmentUnsafe = async (options) => {
4157
3476
  async runCheck(check, expectedScript, allowedChecks, context) {
4158
3477
  let manifestDocument;
4159
3478
  try {
4160
- const manifestFile = await readRegularFileNoFollow(path8.join(snapshotRoot, "package.json"), {
3479
+ const manifestFile = await readRegularFileNoFollow(path5.join(snapshotRoot, "package.json"), {
4161
3480
  label: "Snapshot package.json",
4162
3481
  maxBytes: 1024 * 1024
4163
3482
  });
@@ -4261,7 +3580,7 @@ var createHarnessOciExecutionEnvironment = async (options) => {
4261
3580
  }
4262
3581
  };
4263
3582
  var cleanupHarnessExecutionArtifacts = async (stateDirectory, before, selection) => {
4264
- const root = path8.join(stateDirectory, "environments");
3583
+ const root = path5.join(stateDirectory, "environments");
4265
3584
  const result = { scanned: 0, deleted: 0, skipped: 0 };
4266
3585
  let entries;
4267
3586
  try {
@@ -4279,7 +3598,7 @@ var cleanupHarnessExecutionArtifacts = async (stateDirectory, before, selection)
4279
3598
  continue;
4280
3599
  }
4281
3600
  result.scanned += 1;
4282
- const directory = path8.join(root, entry.name);
3601
+ const directory = path5.join(root, entry.name);
4283
3602
  try {
4284
3603
  const resolved = await realpath3(directory);
4285
3604
  if (!isInside2(root, resolved))
@@ -4288,7 +3607,7 @@ var cleanupHarnessExecutionArtifacts = async (stateDirectory, before, selection)
4288
3607
  if (directoryEntry.isSymbolicLink() || !directoryEntry.isDirectory()) {
4289
3608
  throw new Error("unsafe execution artifact directory");
4290
3609
  }
4291
- const metadataPath = path8.join(directory, "environment.json");
3610
+ const metadataPath = path5.join(directory, "environment.json");
4292
3611
  const metadataFile = await readRegularFileNoFollow(metadataPath, {
4293
3612
  label: "Execution cleanup metadata",
4294
3613
  maxBytes: 1024 * 1024
@@ -4307,7 +3626,7 @@ var cleanupHarnessExecutionArtifacts = async (stateDirectory, before, selection)
4307
3626
  result.skipped += 1;
4308
3627
  continue;
4309
3628
  }
4310
- const stagedDirectory = path8.join(root, `.cleanup-${artifactName}-${randomUUID2()}`);
3629
+ const stagedDirectory = path5.join(root, `.cleanup-${artifactName}-${randomUUID2()}`);
4311
3630
  let staged = false;
4312
3631
  try {
4313
3632
  await rename2(directory, stagedDirectory);
@@ -4316,7 +3635,7 @@ var cleanupHarnessExecutionArtifacts = async (stateDirectory, before, selection)
4316
3635
  if (movedEntry.isSymbolicLink() || !movedEntry.isDirectory() || movedEntry.dev !== directoryEntry.dev || movedEntry.ino !== directoryEntry.ino) {
4317
3636
  throw new Error("execution artifact directory changed before cleanup");
4318
3637
  }
4319
- const recheckedMetadata = await readRegularFileNoFollow(path8.join(stagedDirectory, "environment.json"), { label: "Execution cleanup metadata", maxBytes: 1024 * 1024 });
3638
+ const recheckedMetadata = await readRegularFileNoFollow(path5.join(stagedDirectory, "environment.json"), { label: "Execution cleanup metadata", maxBytes: 1024 * 1024 });
4320
3639
  if (!recheckedMetadata.contents.equals(metadataFile.contents)) {
4321
3640
  throw new Error("execution artifact metadata changed before cleanup");
4322
3641
  }
@@ -4343,4 +3662,4 @@ var executionFingerprintInput = (execution, environment) => execution.backend ==
4343
3662
  };
4344
3663
  var describeOciCommand = (command, args) => commandDisplay([command, ...args]);
4345
3664
 
4346
- export { EDIT_CONTRACT_SCHEMA_VERSION, EDIT_DIGEST_ALGORITHM, MAX_EDIT_CHANGES, MAX_EDIT_FILE_BYTES, MAX_EDIT_PROPOSAL_BYTES, fileDigestSchema, workspaceFilePathSchema, editChangeSchema, editChangesSchema, editProposalInputSchema, editProposalChangeSchema, editProposalSchema, applyEditProposalInputSchema, moveFileInputSchema, quarantineFileInputSchema, restoreFileInputSchema, mutationOperationSchema, mutationAuditEntrySchema, createEditProposal, validateEditProposal, editContractDocument, protectPersistenceSecret, acquireSqliteAccess, exclusiveSqliteAccessDescriptor, adoptExclusiveSqliteAccess, SqliteDatabase, UnsafeFileTypeError, FileSizeLimitError, FileChangedWhileReadingError, statRegularFileNoFollow, readRegularFileNoFollow, readRegularFileChunksNoFollow, withWorkspaceMutation, EnvironmentPatchDriftError, taskCheckReceiptSchema, createTaskAcceptanceChecks, withTaskAcceptanceDelivery, taskAcceptanceChecks, taskAcceptanceDeliveryDiagnostic, confirmTaskAcceptanceImport, taskAcceptanceOutcome, boundedBatches, resolvePackageManager, resolvePackageCheckCommand, replacementEditSchema, runPortableProcess, isHardIgnored, Workspace, HARNESS_EXECUTION_ARTIFACT_SCHEMA_VERSION, HARNESS_OCI_LABEL, HARNESS_OCI_LABEL_VALUE, CliOciRuntimeAdapter, collectSnapshotInventory, readSnapshotFile, harnessExecutionSession, createHarnessOciExecutionEnvironment, cleanupHarnessExecutionArtifacts, executionFingerprintInput, describeOciCommand };
3665
+ export { withWorkspaceMutation, EnvironmentPatchDriftError, boundedBatches, resolvePackageManager, resolvePackageCheckCommand, replacementEditSchema, runPortableProcess, isHardIgnored, Workspace, HARNESS_EXECUTION_ARTIFACT_SCHEMA_VERSION, HARNESS_OCI_LABEL, HARNESS_OCI_LABEL_VALUE, CliOciRuntimeAdapter, collectSnapshotInventory, readSnapshotFile, harnessExecutionSession, createHarnessOciExecutionEnvironment, cleanupHarnessExecutionArtifacts, executionFingerprintInput, describeOciCommand };