harnery 0.45.0 → 0.45.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.
- package/dist/commander.js +0 -1
- package/dist/commands/files.d.ts +2 -2
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +4 -7
- package/dist/commands/servers.d.ts.map +1 -1
- package/dist/commands/servers.js +17 -11
- package/dist/commands/tunnel.d.ts +0 -15
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +153 -453
- package/dist/core/agents/live-authority-v3.d.ts +0 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +0 -11
- package/dist/core/agents/live-lifecycle-v3.d.ts +2 -4
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/live-lifecycle-v3.js +7 -28
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +14 -25
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-writer.js +0 -5
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +0 -5
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +70 -180
- package/dist/core/artifacts/activity.d.ts +4 -1
- package/dist/core/artifacts/activity.d.ts.map +1 -1
- package/dist/core/artifacts/activity.js +8 -2
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
- package/dist/core/artifacts/delivery-card.js +1 -2
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +38 -12
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +0 -29
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +0 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +0 -7
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +64 -77
- package/dist/core/hooks/cli.js +78 -48
- package/dist/core/servers/index.d.ts +13 -10
- package/dist/core/servers/index.d.ts.map +1 -1
- package/dist/core/servers/index.js +97 -192
- package/dist/core/servers/tunnels.d.ts +3 -5
- package/dist/core/servers/tunnels.d.ts.map +1 -1
- package/dist/core/servers/tunnels.js +2 -45
- package/dist/core/storage/durable-history.js +56 -22
- package/dist/core/storage/segments.d.ts.map +1 -1
- package/dist/core/storage/segments.js +73 -17
- package/dist/core/work/state.js +7 -7
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +21 -65
- package/dist/core/workflow/live-session-v3.d.ts +0 -6
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +5 -126
- package/dist/core/workflow/proof.d.ts +4 -4
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +4 -12
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +0 -19
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +0 -13
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +0 -19
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
- package/dist/core/workflow/spawn-opencode.js +0 -14
- package/dist/core/workflow/types.d.ts +11 -54
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +0 -4
- package/dist/lib/tunnel/state.d.ts +6 -13
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +12 -58
- package/package.json +1 -6
- package/src/commander.ts +0 -10
- package/src/commands/files.ts +5 -13
- package/src/commands/servers.ts +23 -12
- package/src/commands/tunnel.ts +166 -533
- package/src/core/agents/live-authority-v3.ts +0 -17
- package/src/core/agents/live-lifecycle-v3.ts +14 -52
- package/src/core/agents/state/heartbeat-writer.ts +12 -29
- package/src/core/agents/state/live-coordination-writer.ts +0 -29
- package/src/core/agents/state/pidmap.ts +0 -13
- package/src/core/agents/state/stale-sweep.ts +82 -247
- package/src/core/artifacts/activity.ts +9 -2
- package/src/core/artifacts/delivery-card.ts +1 -7
- package/src/core/artifacts/index.ts +45 -12
- package/src/core/events/v3/authority-outbox.ts +0 -56
- package/src/core/events/v3/producers/coordination-recorder.ts +0 -15
- package/src/core/events/v3/producers/recorder.ts +68 -94
- package/src/core/hooks/cli.ts +85 -47
- package/src/core/servers/index.ts +106 -228
- package/src/core/servers/tunnels.ts +3 -55
- package/src/core/storage/durable-history.ts +52 -20
- package/src/core/storage/segments.ts +79 -17
- package/src/core/work/state.ts +7 -7
- package/src/core/workflow/engine.ts +21 -73
- package/src/core/workflow/live-session-v3.ts +5 -146
- package/src/core/workflow/proof.ts +5 -21
- package/src/core/workflow/spawn-claude.ts +0 -18
- package/src/core/workflow/spawn-codex.ts +0 -13
- package/src/core/workflow/spawn-cursor.ts +0 -18
- package/src/core/workflow/spawn-opencode.ts +0 -14
- package/src/core/workflow/types.ts +11 -41
- package/src/lib/identities/assume.ts +0 -4
- package/src/lib/tunnel/state.ts +15 -70
- package/dist/commands/turn-rollback.d.ts +0 -5
- package/dist/commands/turn-rollback.d.ts.map +0 -1
- package/dist/commands/turn-rollback.js +0 -76
- package/dist/core/agents/state/unchanged-file.d.ts +0 -44
- package/dist/core/agents/state/unchanged-file.d.ts.map +0 -1
- package/dist/core/agents/state/unchanged-file.js +0 -390
- package/dist/core/events/v3/generation-custody.d.ts +0 -5
- package/dist/core/events/v3/generation-custody.d.ts.map +0 -1
- package/dist/core/events/v3/generation-custody.js +0 -50
- package/dist/core/turn-rollback/content.d.ts +0 -53
- package/dist/core/turn-rollback/content.d.ts.map +0 -1
- package/dist/core/turn-rollback/content.js +0 -396
- package/dist/core/turn-rollback/index.d.ts +0 -72
- package/dist/core/turn-rollback/index.d.ts.map +0 -1
- package/dist/core/turn-rollback/index.js +0 -443
- package/dist/core/workflow/failure-evidence.d.ts +0 -16
- package/dist/core/workflow/failure-evidence.d.ts.map +0 -1
- package/dist/core/workflow/failure-evidence.js +0 -114
- package/src/commands/turn-rollback.ts +0 -111
- package/src/core/agents/state/unchanged-file.ts +0 -456
- package/src/core/events/v3/generation-custody.ts +0 -59
- package/src/core/turn-rollback/content.ts +0 -499
- package/src/core/turn-rollback/index.ts +0 -580
- package/src/core/workflow/failure-evidence.ts +0 -141
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnels.d.ts","sourceRoot":"","sources":["../../../src/core/servers/tunnels.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"tunnels.d.ts","sourceRoot":"","sources":["../../../src/core/servers/tunnels.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,CAc5F"}
|
|
@@ -2,57 +2,15 @@
|
|
|
2
2
|
* Tunnels as registry services.
|
|
3
3
|
*
|
|
4
4
|
* `tunnel up` and `tunnel reload` register the new gate; `tunnel down` removes
|
|
5
|
-
* its record.
|
|
5
|
+
* its record. Older tunnels need an explicit adoption of an observed listener.
|
|
6
6
|
*/
|
|
7
|
-
import { hostname } from "node:os";
|
|
8
7
|
import { resolve } from "node:path";
|
|
9
|
-
import { gateLogFile
|
|
10
|
-
import { readServer, verifyProcessGeneration, withServerRegistrationCustody, } from "./index.js";
|
|
11
|
-
/** Verify only witnesses saved by the original tunnel registration. */
|
|
12
|
-
export function createTunnelReadinessVerifier(options) {
|
|
13
|
-
return {
|
|
14
|
-
observeProcess(pid, originalToken) {
|
|
15
|
-
try {
|
|
16
|
-
process.kill(pid, 0);
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
const code = error.code;
|
|
20
|
-
if (code === "ESRCH")
|
|
21
|
-
return "absent";
|
|
22
|
-
return "unknown";
|
|
23
|
-
}
|
|
24
|
-
return verifyProcessGeneration(pid, originalToken);
|
|
25
|
-
},
|
|
26
|
-
withRegistration(state, inspect) {
|
|
27
|
-
try {
|
|
28
|
-
const original = readServer(tunnelServerId(state.name), options);
|
|
29
|
-
if (!original ||
|
|
30
|
-
original.host !== hostname() ||
|
|
31
|
-
original.kind !== "service" ||
|
|
32
|
-
original.type !== "tunnel" ||
|
|
33
|
-
original.registration_id !== state.registration_id ||
|
|
34
|
-
original.pid !== state.gate_pid ||
|
|
35
|
-
original.start_token !== state.gate_start_token ||
|
|
36
|
-
original.port !== state.gate_port ||
|
|
37
|
-
original.url !== state.url)
|
|
38
|
-
return "unknown";
|
|
39
|
-
return withServerRegistrationCustody(original, options, inspect);
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return "unknown";
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
8
|
+
import { gateLogFile } from "../../lib/tunnel/state.js";
|
|
47
9
|
export function tunnelServerId(name) {
|
|
48
10
|
return `tunnel-${name.toLowerCase().replace(/[^a-z0-9._-]+/g, "-")}`;
|
|
49
11
|
}
|
|
50
12
|
/** Register the new gate; saved helper PIDs have no generation witnesses. */
|
|
51
13
|
export function tunnelServerInput(state, coordRoot) {
|
|
52
|
-
if (Object.hasOwn(state, "provider_pid") || Object.hasOwn(state, "provider_start_token"))
|
|
53
|
-
throw new Error("obsolete tunnel provider authority is unknown; state retained");
|
|
54
|
-
if (!state.gate_start_token)
|
|
55
|
-
throw new Error("tunnel gate generation witness is unavailable; state retained");
|
|
56
14
|
return {
|
|
57
15
|
id: tunnelServerId(state.name),
|
|
58
16
|
kind: "service",
|
|
@@ -61,7 +19,6 @@ export function tunnelServerInput(state, coordRoot) {
|
|
|
61
19
|
url: state.url,
|
|
62
20
|
port: state.gate_port,
|
|
63
21
|
pid: state.gate_pid,
|
|
64
|
-
start_token: state.gate_start_token,
|
|
65
22
|
log: resolve(coordRoot, ".cache", "tunnel", gateLogFile(state.name)),
|
|
66
23
|
cwd: coordRoot,
|
|
67
24
|
started_at: state.started_at,
|
|
@@ -394,31 +394,55 @@ function acquireLease(lease) {
|
|
|
394
394
|
pid: process.pid,
|
|
395
395
|
acquired_at: new Date().toISOString(),
|
|
396
396
|
};
|
|
397
|
-
|
|
398
|
-
try {
|
|
399
|
-
mkdirSync(lease, { mode: stateDirMode() });
|
|
400
|
-
assertDirectoryWithinParent(lease, parent);
|
|
401
|
-
claimed = captureDirectoryIdentity(lease);
|
|
402
|
-
writeOwner(join(lease, "owner.json"), owner);
|
|
403
|
-
syncDirectory(claimed);
|
|
397
|
+
if (claimLease(lease, parent, owner))
|
|
404
398
|
return owner;
|
|
399
|
+
if (recoverStaleLease(lease, DURABLE_HISTORY_LEASE_STALE_MS))
|
|
400
|
+
continue;
|
|
401
|
+
throw new Error(`durable history lease busy: ${lease}`);
|
|
402
|
+
}
|
|
403
|
+
throw new Error(`durable history lease busy: ${lease}`);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Publish a complete lease in one rename. The owner record is written and synced
|
|
407
|
+
* in a private claim directory first, so a writer stopped at any point leaves
|
|
408
|
+
* either no lease or one with an owner. A held lease always has an owner record,
|
|
409
|
+
* here and in the earlier create-then-write protocol, so a rename that replaces
|
|
410
|
+
* an empty lease directory never takes a held lease. A lease with any entry makes
|
|
411
|
+
* the rename fail and the caller reports it busy.
|
|
412
|
+
*/
|
|
413
|
+
function claimLease(lease, parent, owner) {
|
|
414
|
+
const claim = `${lease}.claim-${process.pid}-${owner.owner_id}`;
|
|
415
|
+
try {
|
|
416
|
+
mkdirSync(claim, { mode: stateDirMode() });
|
|
417
|
+
assertDirectoryWithinParent(claim, parent);
|
|
418
|
+
const claimed = captureDirectoryIdentity(claim);
|
|
419
|
+
writeOwner(join(claim, "owner.json"), owner);
|
|
420
|
+
syncDirectory(claimed);
|
|
421
|
+
renameSync(claim, lease);
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
finally {
|
|
427
|
+
try {
|
|
428
|
+
rmSync(claim, { recursive: true, force: true });
|
|
405
429
|
}
|
|
406
430
|
catch {
|
|
407
|
-
|
|
408
|
-
try {
|
|
409
|
-
assertDirectoryIdentity(claimed);
|
|
410
|
-
rmSync(lease, { recursive: true, force: false });
|
|
411
|
-
}
|
|
412
|
-
catch {
|
|
413
|
-
// Never remove a lease after its directory identity changes.
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (recoverStaleLease(lease, DURABLE_HISTORY_LEASE_STALE_MS))
|
|
417
|
-
continue;
|
|
418
|
-
throw new Error(`durable history lease busy: ${lease}`);
|
|
431
|
+
// A leftover claim directory never blocks a lease.
|
|
419
432
|
}
|
|
420
433
|
}
|
|
421
|
-
|
|
434
|
+
try {
|
|
435
|
+
assertDirectoryWithinParent(lease, parent);
|
|
436
|
+
const current = JSON.parse(completeJsonl(join(lease, "owner.json")));
|
|
437
|
+
if (current.owner_id !== owner.owner_id)
|
|
438
|
+
return false;
|
|
439
|
+
syncDirectory(parent);
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
releaseOwnedLease(lease, owner);
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
422
446
|
}
|
|
423
447
|
function writeOwner(path, owner) {
|
|
424
448
|
const parent = captureDirectoryIdentity(dirname(path));
|
|
@@ -468,7 +492,7 @@ function recoverStaleLease(lease, staleMs) {
|
|
|
468
492
|
assertDirectoryIdentity(leaseIdentity);
|
|
469
493
|
if (completeJsonl(ownerPath) !== raw)
|
|
470
494
|
return false;
|
|
471
|
-
|
|
495
|
+
retireLease(lease, randomUUID());
|
|
472
496
|
return true;
|
|
473
497
|
}
|
|
474
498
|
catch {
|
|
@@ -480,12 +504,22 @@ function releaseOwnedLease(lease, owner) {
|
|
|
480
504
|
const current = JSON.parse(completeJsonl(join(lease, "owner.json")));
|
|
481
505
|
if (current.owner_id !== owner.owner_id)
|
|
482
506
|
return;
|
|
483
|
-
|
|
507
|
+
retireLease(lease, owner.owner_id);
|
|
484
508
|
}
|
|
485
509
|
catch {
|
|
486
510
|
// A missing or replaced lease does not belong to this operation.
|
|
487
511
|
}
|
|
488
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Move a lease aside before deleting it. Its path goes from held to absent in
|
|
515
|
+
* one rename and is never an empty directory that a concurrent claim could
|
|
516
|
+
* replace while a recursive removal is still running.
|
|
517
|
+
*/
|
|
518
|
+
function retireLease(lease, tag) {
|
|
519
|
+
const retired = `${lease}.retired-${process.pid}-${tag}`;
|
|
520
|
+
renameSync(lease, retired);
|
|
521
|
+
rmSync(retired, { recursive: true, force: true });
|
|
522
|
+
}
|
|
489
523
|
function processIsAlive(pid) {
|
|
490
524
|
try {
|
|
491
525
|
process.kill(pid, 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../../src/core/storage/segments.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../../src/core/storage/segments.ts"],"names":[],"mappings":"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"}
|
|
@@ -191,25 +191,19 @@ export async function withFamilyLease(directory, policy, operation) {
|
|
|
191
191
|
let owner;
|
|
192
192
|
while (true) {
|
|
193
193
|
try {
|
|
194
|
-
|
|
195
|
-
const leaseIdentity = captureDirectoryIdentity(lease);
|
|
196
|
-
owner = {
|
|
197
|
-
owner_id: randomUUID(),
|
|
198
|
-
pid: process.pid,
|
|
199
|
-
acquired_at: new Date().toISOString(),
|
|
200
|
-
};
|
|
201
|
-
writeNewFile(join(lease, "owner.json"), Buffer.from(`${JSON.stringify(owner)}\n`));
|
|
202
|
-
assertDirectoryIdentity(leaseIdentity);
|
|
194
|
+
owner = claimLease(lease);
|
|
203
195
|
break;
|
|
204
196
|
}
|
|
205
197
|
catch (error) {
|
|
206
|
-
if (
|
|
198
|
+
if (leaseHasWrongType(lease)) {
|
|
207
199
|
throw new HarneryLogLeaseError("wrong_type", `log lease is not a directory: ${lease}`);
|
|
208
200
|
}
|
|
209
201
|
if (recoverStaleLease(lease, policy.lease_stale_ms))
|
|
210
202
|
continue;
|
|
211
203
|
if (Date.now() - started >= policy.lease_timeout_ms) {
|
|
212
|
-
throw new HarneryLogLeaseError("timeout",
|
|
204
|
+
throw new HarneryLogLeaseError("timeout", leaseHasValidOwner(lease)
|
|
205
|
+
? `timed out acquiring log lease: ${lease}`
|
|
206
|
+
: `timed out acquiring log lease with no valid owner; an interrupted writer left it, and it is never recovered automatically: ${lease}`);
|
|
213
207
|
}
|
|
214
208
|
await new Promise((resolve) => setTimeout(resolve, policy.lease_retry_ms));
|
|
215
209
|
void error;
|
|
@@ -223,6 +217,42 @@ export async function withFamilyLease(directory, policy, operation) {
|
|
|
223
217
|
releaseOwnedLease(lease, owner);
|
|
224
218
|
}
|
|
225
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Publish a complete lease in one rename. The owner record is written and synced
|
|
222
|
+
* in a private claim directory first, so a writer stopped at any point leaves
|
|
223
|
+
* either no lease or one with an owner. A held lease always has an owner record,
|
|
224
|
+
* here and in the earlier create-then-write protocol, so a rename that replaces
|
|
225
|
+
* an empty lease directory never takes a held lease. A lease with any entry makes
|
|
226
|
+
* the rename fail, and the caller waits or recovers as before.
|
|
227
|
+
*/
|
|
228
|
+
function claimLease(lease) {
|
|
229
|
+
const owner = {
|
|
230
|
+
owner_id: randomUUID(),
|
|
231
|
+
pid: process.pid,
|
|
232
|
+
acquired_at: new Date().toISOString(),
|
|
233
|
+
};
|
|
234
|
+
const content = `${JSON.stringify(owner)}\n`;
|
|
235
|
+
const claim = `${lease}.claim-${process.pid}-${owner.owner_id}`;
|
|
236
|
+
try {
|
|
237
|
+
mkdirSync(claim, { mode: stateDirMode() });
|
|
238
|
+
writeNewFile(join(claim, "owner.json"), Buffer.from(content));
|
|
239
|
+
renameSync(claim, lease);
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
rmSync(claim, { recursive: true, force: true });
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
captureDirectoryIdentity(lease);
|
|
246
|
+
if (readRegularFile(join(lease, "owner.json"), 4_096).toString("utf8") !== content) {
|
|
247
|
+
throw new Error(`log lease owner changed during claim: ${lease}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
releaseOwnedLease(lease, owner);
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
return owner;
|
|
255
|
+
}
|
|
226
256
|
function shouldRotate(active, incoming, options, now) {
|
|
227
257
|
const stat = regularFileStat(active);
|
|
228
258
|
const incomingBytes = incoming.reduce((sum, record) => sum + record.byteLength, 0);
|
|
@@ -315,6 +345,18 @@ function atomicJson(path, value) {
|
|
|
315
345
|
renameSync(temporary, path);
|
|
316
346
|
assertRegularPath(path, captureDirectoryIdentity(dirname(path)));
|
|
317
347
|
}
|
|
348
|
+
function leaseHasValidOwner(lease) {
|
|
349
|
+
try {
|
|
350
|
+
const owner = JSON.parse(readRegularFile(join(lease, "owner.json"), 4_096).toString("utf8"));
|
|
351
|
+
return (typeof owner?.owner_id === "string" &&
|
|
352
|
+
owner.owner_id.length > 0 &&
|
|
353
|
+
Number.isSafeInteger(owner.pid) &&
|
|
354
|
+
Number.isFinite(Date.parse(owner.acquired_at)));
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
318
360
|
function recoverStaleLease(lease, maximumAgeMs) {
|
|
319
361
|
let identity;
|
|
320
362
|
let raw;
|
|
@@ -344,7 +386,7 @@ function recoverStaleLease(lease, maximumAgeMs) {
|
|
|
344
386
|
assertDirectoryIdentity(identity);
|
|
345
387
|
if (readRegularFile(join(lease, "owner.json"), 4_096).toString("utf8") !== raw)
|
|
346
388
|
return false;
|
|
347
|
-
|
|
389
|
+
retireLease(lease, randomUUID());
|
|
348
390
|
return true;
|
|
349
391
|
}
|
|
350
392
|
catch {
|
|
@@ -356,12 +398,22 @@ function releaseOwnedLease(lease, owner) {
|
|
|
356
398
|
const current = JSON.parse(readRegularFile(join(lease, "owner.json"), 4_096).toString("utf8"));
|
|
357
399
|
if (current.owner_id !== owner.owner_id)
|
|
358
400
|
return;
|
|
359
|
-
|
|
401
|
+
retireLease(lease, owner.owner_id);
|
|
360
402
|
}
|
|
361
403
|
catch {
|
|
362
404
|
// A missing or replaced lease does not belong to this operation.
|
|
363
405
|
}
|
|
364
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Move a lease aside before deleting it. Its path goes from held to absent in
|
|
409
|
+
* one rename and is never an empty directory that a concurrent claim could
|
|
410
|
+
* replace while a recursive removal is still running.
|
|
411
|
+
*/
|
|
412
|
+
function retireLease(lease, tag) {
|
|
413
|
+
const retired = `${lease}.retired-${process.pid}-${tag}`;
|
|
414
|
+
renameSync(lease, retired);
|
|
415
|
+
rmSync(retired, { recursive: true, force: true });
|
|
416
|
+
}
|
|
365
417
|
function processIsAlive(pid) {
|
|
366
418
|
try {
|
|
367
419
|
process.kill(pid, 0);
|
|
@@ -519,12 +571,16 @@ function writeAllSync(fd, buffer, writer) {
|
|
|
519
571
|
function nativeWriteSync(fd, buffer, offset, length) {
|
|
520
572
|
return writeSync(fd, buffer, offset, length);
|
|
521
573
|
}
|
|
522
|
-
|
|
574
|
+
/** One lstat, so a lease released between checks reads as absent, not as a wrong type. */
|
|
575
|
+
function leaseHasWrongType(path) {
|
|
523
576
|
try {
|
|
524
|
-
|
|
577
|
+
const stat = lstatSync(path);
|
|
578
|
+
return stat.isSymbolicLink() || !stat.isDirectory();
|
|
525
579
|
}
|
|
526
|
-
catch {
|
|
527
|
-
|
|
580
|
+
catch (error) {
|
|
581
|
+
if (error.code === "ENOENT")
|
|
582
|
+
return false;
|
|
583
|
+
throw error;
|
|
528
584
|
}
|
|
529
585
|
}
|
|
530
586
|
function pathExists(path) {
|
package/dist/core/work/state.js
CHANGED
|
@@ -6,7 +6,7 @@ import { appendSegmentedJsonlFile, readSegmentedJsonlFileSync, } from "../storag
|
|
|
6
6
|
import { stateDirMode, stateFileMode } from "../storage/modes.js";
|
|
7
7
|
import { readWorkflowApproval } from "../workflow/approvals.js";
|
|
8
8
|
import { stableDigest } from "../workflow/durable-record.js";
|
|
9
|
-
import {
|
|
9
|
+
import { readWorkflowProof } from "../workflow/proof.js";
|
|
10
10
|
import { readWorkflowRunManifest, workflowScriptDigest } from "../workflow/run-state.js";
|
|
11
11
|
import { WORKFLOW_TRANSCRIPT_EVENT_BYTES, workflowTranscriptPath } from "../workflow/transcript.js";
|
|
12
12
|
import { isWorkspaceBoundExecutionEvidence } from "../workflow/workspaces/validate.js";
|
|
@@ -464,13 +464,13 @@ function inspectAttempt(coordRoot, event, intent, priorRunId) {
|
|
|
464
464
|
proof.acceptance.summary.unknown === 0
|
|
465
465
|
? "succeeded"
|
|
466
466
|
: "failed";
|
|
467
|
-
//
|
|
468
|
-
//
|
|
469
|
-
//
|
|
467
|
+
// A failed attempt the run classified as uninformative about the work is
|
|
468
|
+
// uncharged (ADR 0046). Absent class ⇒ charged, as before. Read only for a
|
|
469
|
+
// failed attempt: a succeeded run never carries a class.
|
|
470
470
|
if (attempt.status === "failed" &&
|
|
471
|
-
(proof.run.class === "
|
|
472
|
-
|
|
473
|
-
|
|
471
|
+
(proof.run.class === "environment" ||
|
|
472
|
+
proof.run.class === "upstream" ||
|
|
473
|
+
proof.run.class === "decision")) {
|
|
474
474
|
attempt.uncharged = proof.run.class;
|
|
475
475
|
if (proof.run.class === "decision" && typeof proof.run.decision_id === "string") {
|
|
476
476
|
attempt.blocked_on = proof.run.decision_id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAiDH,OAAO,KAAK,EAIV,UAAU,EAGV,SAAS,EAeV,MAAM,YAAY,CAAC;AAuDpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAOvF;AAED;;;;6EAI6E;AAC7E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEjB,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAUhD;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6E1F"}
|
|
@@ -37,8 +37,7 @@ import { freezeWorkflowAttemptContext } from "./attempt-context.js";
|
|
|
37
37
|
import { probeBilling } from "./billing.js";
|
|
38
38
|
import { stableDigest } from "./durable-record.js";
|
|
39
39
|
import { evidencePreflightError } from "./evidence-preflight.js";
|
|
40
|
-
import {
|
|
41
|
-
import { endWorkflowChildSessionV3, recordWorkflowChildTerminalFailureV3, startWorkflowChildSessionV3, } from "./live-session-v3.js";
|
|
40
|
+
import { endWorkflowChildSessionV3, startWorkflowChildSessionV3 } from "./live-session-v3.js";
|
|
42
41
|
import { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, writeWorkflowProof, } from "./proof.js";
|
|
43
42
|
import { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
|
|
44
43
|
import { assertProjectionWithinWorkspace, resolveGitGrantRoots } from "./sandbox-projection.js";
|
|
@@ -865,40 +864,23 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
865
864
|
},
|
|
866
865
|
});
|
|
867
866
|
agentProof.access = access;
|
|
868
|
-
let childGenerationId;
|
|
869
867
|
let recordAgentEnd;
|
|
870
868
|
const finalizeChild = () => {
|
|
871
869
|
try {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
// Result publication is the resume-cache boundary, after canonical custody.
|
|
870
|
+
// Record the canonical terminal first. agent.end is the resume-cache
|
|
871
|
+
// boundary, so a child whose end was not recorded never reports success.
|
|
872
|
+
endWorkflowChildSessionV3({
|
|
873
|
+
coordRoot: opts.coordRoot,
|
|
874
|
+
instanceId: childInstanceId(runId, id),
|
|
875
|
+
runId,
|
|
876
|
+
agentId: id,
|
|
877
|
+
adapter,
|
|
878
|
+
cleanExit: agentProof.status === "succeeded",
|
|
879
|
+
});
|
|
883
880
|
recordAgentEnd?.();
|
|
884
881
|
}
|
|
885
882
|
catch (error) {
|
|
886
|
-
|
|
887
|
-
try {
|
|
888
|
-
if (childGenerationId)
|
|
889
|
-
recordWorkflowChildTerminalFailureV3({
|
|
890
|
-
coordRoot: opts.coordRoot,
|
|
891
|
-
instanceId: childInstanceId(runId, id),
|
|
892
|
-
runId,
|
|
893
|
-
agentId: id,
|
|
894
|
-
adapter,
|
|
895
|
-
expectedGenerationId: childGenerationId,
|
|
896
|
-
reason,
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
catch (visibilityError) {
|
|
900
|
-
reason += `; blocked lifecycle recording failed: ${visibilityError.message}`;
|
|
901
|
-
}
|
|
883
|
+
const reason = `V3 terminal recording failed: ${error.message}`;
|
|
902
884
|
const failure = new Error(agentProof.error ? `${agentProof.error}; ${reason}` : reason, {
|
|
903
885
|
cause: error,
|
|
904
886
|
});
|
|
@@ -930,7 +912,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
930
912
|
// Headless children do not reliably fire adapter hooks. The engine owns
|
|
931
913
|
// their canonical V3 start so every dispatched child has an auditable
|
|
932
914
|
// generation before it begins work.
|
|
933
|
-
|
|
915
|
+
startWorkflowChildSessionV3({
|
|
934
916
|
coordRoot: opts.coordRoot,
|
|
935
917
|
instanceId: childInstanceId(runId, id),
|
|
936
918
|
runId,
|
|
@@ -939,13 +921,9 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
939
921
|
label,
|
|
940
922
|
model: agentOpts.model,
|
|
941
923
|
});
|
|
942
|
-
if (!child.v3_generation_id)
|
|
943
|
-
throw new Error("workflow_child_v3_generation_missing");
|
|
944
|
-
childGenerationId = child.v3_generation_id;
|
|
945
924
|
let attemptPrompt = dispatchPrompt;
|
|
946
925
|
let last = null;
|
|
947
926
|
let agentCostUsd = 0;
|
|
948
|
-
let informativeAttempt;
|
|
949
927
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
950
928
|
last = await spawner({
|
|
951
929
|
prompt: attemptPrompt,
|
|
@@ -967,29 +945,15 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
967
945
|
agentCostUsd += last.costUsd ?? 0;
|
|
968
946
|
costUsd += last.costUsd ?? 0;
|
|
969
947
|
if (!last.ok) {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
effect: { state: "unknown" },
|
|
977
|
-
partial_output: informativeAttempt.partial_output,
|
|
978
|
-
}
|
|
979
|
-
: observed;
|
|
980
|
-
transcript("agent.attempt_failed", {
|
|
981
|
-
id,
|
|
982
|
-
attempt,
|
|
983
|
-
error: last.error,
|
|
984
|
-
failure_evidence: observed,
|
|
985
|
-
result_digest: digestResult(last.text, "text"),
|
|
986
|
-
text: last.text,
|
|
987
|
-
});
|
|
988
|
-
if (!canRetryFailedSpawn({ ...last, failureEvidence: agentProof.failure_evidence }))
|
|
948
|
+
transcript("agent.attempt_failed", { id, attempt, error: last.error });
|
|
949
|
+
// ADR 0046: an environment failure (the binary was absent) cannot be
|
|
950
|
+
// helped by retrying an unchanged environment, so stop the in-agent
|
|
951
|
+
// retry too — not just the outer attempt/replan budget. An upstream
|
|
952
|
+
// refusal keeps retrying here: the vendor may recover mid-loop.
|
|
953
|
+
if (last.class === "environment")
|
|
989
954
|
break;
|
|
990
|
-
continue;
|
|
955
|
+
continue; // spawn-level failure: retry with the original prompt
|
|
991
956
|
}
|
|
992
|
-
informativeAttempt = observeSpawnFailure({}, last.text, "final_message");
|
|
993
957
|
if (!agentOpts.schema) {
|
|
994
958
|
agentProof.status = "succeeded";
|
|
995
959
|
agentProof.cost_usd =
|
|
@@ -1030,14 +994,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
1030
994
|
}, "json", parsed.value);
|
|
1031
995
|
return parsed.value;
|
|
1032
996
|
}
|
|
1033
|
-
|
|
1034
|
-
transcript("agent.schema_retry", {
|
|
1035
|
-
id,
|
|
1036
|
-
attempt,
|
|
1037
|
-
problems,
|
|
1038
|
-
rejected_text: last.text,
|
|
1039
|
-
result_digest: digestResult(last.text, "text"),
|
|
1040
|
-
});
|
|
997
|
+
transcript("agent.schema_retry", { id, attempt, problems });
|
|
1041
998
|
// Keep the original cache identity while making the actual output
|
|
1042
999
|
// contract explicit. A full bounded copy of the rejected value lets the
|
|
1043
1000
|
// child repair omissions instead of reconstructing an unseen object.
|
|
@@ -1076,7 +1033,6 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
1076
1033
|
finalizeChild();
|
|
1077
1034
|
}
|
|
1078
1035
|
finally {
|
|
1079
|
-
// A slot is disposable; unresolved custody remains visible and failed.
|
|
1080
1036
|
release();
|
|
1081
1037
|
}
|
|
1082
1038
|
}
|
|
@@ -14,12 +14,6 @@ export declare function startWorkflowChildSessionV3(input: WorkflowChildSessionV
|
|
|
14
14
|
/** Record the authoritative terminal before removing the disposable coordination cache. */
|
|
15
15
|
export declare function endWorkflowChildSessionV3(input: WorkflowChildSessionV3Input & {
|
|
16
16
|
cleanExit: boolean;
|
|
17
|
-
expectedGenerationId: string;
|
|
18
|
-
}): void;
|
|
19
|
-
/** Persist unresolved terminal custody only for the generation this dispatch owns. */
|
|
20
|
-
export declare function recordWorkflowChildTerminalFailureV3(input: WorkflowChildSessionV3Input & {
|
|
21
|
-
expectedGenerationId: string;
|
|
22
|
-
reason: string;
|
|
23
17
|
}): void;
|
|
24
18
|
export { stableScopeId } from "./scope-id.js";
|
|
25
19
|
//# sourceMappingURL=live-session-v3.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-session-v3.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/live-session-v3.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"live-session-v3.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/live-session-v3.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,qCAAqC,CAAC;AAY7C,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8FAA8F;AAC9F,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,2BAA2B,GAAG,SAAS,CAiDzF;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,2BAA2B,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAC1D,IAAI,CAmBN;AAgBD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|