harnery 0.44.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.
Files changed (138) hide show
  1. package/dist/commands/workflow.d.ts.map +1 -1
  2. package/dist/commands/workflow.js +44 -0
  3. package/dist/core/agents/coord-client.d.ts.map +1 -1
  4. package/dist/core/agents/coord-client.js +18 -0
  5. package/dist/core/agents/live-authority-v3.d.ts +0 -1
  6. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  7. package/dist/core/agents/live-authority-v3.js +0 -11
  8. package/dist/core/agents/live-lifecycle-v3.d.ts +2 -4
  9. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  10. package/dist/core/agents/live-lifecycle-v3.js +7 -28
  11. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  12. package/dist/core/agents/state/heartbeat-writer.js +14 -25
  13. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
  14. package/dist/core/agents/state/live-coordination-writer.js +0 -5
  15. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  16. package/dist/core/agents/state/pidmap.js +0 -5
  17. package/dist/core/agents/state/proc-start.d.ts +5 -6
  18. package/dist/core/agents/state/proc-start.d.ts.map +1 -1
  19. package/dist/core/agents/state/proc-start.js +13 -9
  20. package/dist/core/agents/state/process-handle.d.ts +26 -0
  21. package/dist/core/agents/state/process-handle.d.ts.map +1 -0
  22. package/dist/core/agents/state/process-handle.js +121 -0
  23. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  24. package/dist/core/agents/state/stale-sweep.js +70 -180
  25. package/dist/core/artifacts/activity.d.ts +4 -1
  26. package/dist/core/artifacts/activity.d.ts.map +1 -1
  27. package/dist/core/artifacts/activity.js +8 -2
  28. package/dist/core/artifacts/index.d.ts.map +1 -1
  29. package/dist/core/artifacts/index.js +38 -12
  30. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  31. package/dist/core/events/v3/authority-outbox.js +0 -29
  32. package/dist/core/events/v3/producers/coordination-recorder.d.ts +0 -1
  33. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  34. package/dist/core/events/v3/producers/coordination-recorder.js +0 -7
  35. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  36. package/dist/core/events/v3/producers/recorder.js +64 -77
  37. package/dist/core/hooks/cli.js +78 -48
  38. package/dist/core/resources/service.d.ts +2 -16
  39. package/dist/core/resources/service.d.ts.map +1 -1
  40. package/dist/core/resources/service.js +1 -78
  41. package/dist/core/semantic/service.d.ts.map +1 -1
  42. package/dist/core/semantic/service.js +2 -9
  43. package/dist/core/servers/index.d.ts +4 -0
  44. package/dist/core/servers/index.d.ts.map +1 -1
  45. package/dist/core/servers/index.js +21 -3
  46. package/dist/core/storage/durable-history.js +56 -22
  47. package/dist/core/storage/segments.d.ts.map +1 -1
  48. package/dist/core/storage/segments.js +73 -17
  49. package/dist/core/supervisor/service.d.ts +2 -4
  50. package/dist/core/supervisor/service.d.ts.map +1 -1
  51. package/dist/core/work/state.js +7 -7
  52. package/dist/core/workflow/engine.d.ts.map +1 -1
  53. package/dist/core/workflow/engine.js +21 -65
  54. package/dist/core/workflow/index.d.ts +4 -2
  55. package/dist/core/workflow/index.d.ts.map +1 -1
  56. package/dist/core/workflow/index.js +2 -1
  57. package/dist/core/workflow/live-session-v3.d.ts +0 -6
  58. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  59. package/dist/core/workflow/live-session-v3.js +5 -126
  60. package/dist/core/workflow/proof.d.ts +4 -4
  61. package/dist/core/workflow/proof.d.ts.map +1 -1
  62. package/dist/core/workflow/proof.js +4 -12
  63. package/dist/core/workflow/recovery-audit.d.ts +30 -0
  64. package/dist/core/workflow/recovery-audit.d.ts.map +1 -0
  65. package/dist/core/workflow/recovery-audit.js +116 -0
  66. package/dist/core/workflow/run-state.d.ts +19 -2
  67. package/dist/core/workflow/run-state.d.ts.map +1 -1
  68. package/dist/core/workflow/run-state.js +113 -8
  69. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  70. package/dist/core/workflow/spawn-claude.js +0 -19
  71. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  72. package/dist/core/workflow/spawn-codex.js +0 -13
  73. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  74. package/dist/core/workflow/spawn-cursor.js +0 -19
  75. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
  76. package/dist/core/workflow/spawn-opencode.js +0 -14
  77. package/dist/core/workflow/types.d.ts +11 -54
  78. package/dist/core/workflow/types.d.ts.map +1 -1
  79. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  80. package/dist/core/workflow/workspaces/local-git.js +70 -14
  81. package/dist/core/workflow/workspaces/reclaim.d.ts +6 -1
  82. package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
  83. package/dist/core/workflow/workspaces/recovery.d.ts +2 -0
  84. package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
  85. package/dist/core/workflow/workspaces/recovery.js +24 -0
  86. package/dist/lib/identities/assume.d.ts.map +1 -1
  87. package/dist/lib/identities/assume.js +0 -4
  88. package/package.json +1 -1
  89. package/src/commands/workflow.ts +59 -0
  90. package/src/core/agents/coord-client.ts +20 -0
  91. package/src/core/agents/live-authority-v3.ts +0 -17
  92. package/src/core/agents/live-lifecycle-v3.ts +14 -52
  93. package/src/core/agents/state/heartbeat-writer.ts +12 -29
  94. package/src/core/agents/state/live-coordination-writer.ts +0 -29
  95. package/src/core/agents/state/pidmap.ts +0 -13
  96. package/src/core/agents/state/proc-start.ts +14 -11
  97. package/src/core/agents/state/process-handle.ts +165 -0
  98. package/src/core/agents/state/stale-sweep.ts +82 -247
  99. package/src/core/artifacts/activity.ts +9 -2
  100. package/src/core/artifacts/index.ts +45 -12
  101. package/src/core/events/v3/authority-outbox.ts +0 -56
  102. package/src/core/events/v3/producers/coordination-recorder.ts +0 -15
  103. package/src/core/events/v3/producers/recorder.ts +68 -94
  104. package/src/core/hooks/cli.ts +85 -47
  105. package/src/core/resources/service.ts +3 -88
  106. package/src/core/semantic/service.ts +2 -8
  107. package/src/core/servers/index.ts +30 -3
  108. package/src/core/storage/durable-history.ts +52 -20
  109. package/src/core/storage/segments.ts +79 -17
  110. package/src/core/supervisor/service.ts +2 -3
  111. package/src/core/work/state.ts +7 -7
  112. package/src/core/workflow/engine.ts +21 -73
  113. package/src/core/workflow/index.ts +12 -1
  114. package/src/core/workflow/live-session-v3.ts +5 -146
  115. package/src/core/workflow/proof.ts +5 -21
  116. package/src/core/workflow/recovery-audit.ts +181 -0
  117. package/src/core/workflow/run-state.ts +137 -8
  118. package/src/core/workflow/spawn-claude.ts +0 -18
  119. package/src/core/workflow/spawn-codex.ts +0 -13
  120. package/src/core/workflow/spawn-cursor.ts +0 -18
  121. package/src/core/workflow/spawn-opencode.ts +0 -14
  122. package/src/core/workflow/types.ts +11 -41
  123. package/src/core/workflow/workspaces/local-git.ts +86 -15
  124. package/src/core/workflow/workspaces/reclaim.ts +4 -0
  125. package/src/core/workflow/workspaces/recovery.ts +23 -0
  126. package/src/lib/identities/assume.ts +0 -4
  127. package/dist/core/agents/state/unchanged-file.d.ts +0 -44
  128. package/dist/core/agents/state/unchanged-file.d.ts.map +0 -1
  129. package/dist/core/agents/state/unchanged-file.js +0 -390
  130. package/dist/core/events/v3/generation-custody.d.ts +0 -5
  131. package/dist/core/events/v3/generation-custody.d.ts.map +0 -1
  132. package/dist/core/events/v3/generation-custody.js +0 -50
  133. package/dist/core/workflow/failure-evidence.d.ts +0 -16
  134. package/dist/core/workflow/failure-evidence.d.ts.map +0 -1
  135. package/dist/core/workflow/failure-evidence.js +0 -114
  136. package/src/core/agents/state/unchanged-file.ts +0 -456
  137. package/src/core/events/v3/generation-custody.ts +0 -59
  138. package/src/core/workflow/failure-evidence.ts +0 -141
@@ -0,0 +1,121 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { constants } from "node:os";
3
+ // The helper owns the descriptor throughout observation and effect. The second
4
+ // input line authorizes the effect; EOF releases the handle without signaling.
5
+ export const LINUX_PROCESS_HANDLE_SCRIPT = `
6
+ import json, os, pathlib, signal, sys
7
+ result = {"sent": False, "verdict": "unknown"}
8
+ fd = None
9
+ try:
10
+ request = json.loads(sys.stdin.readline())
11
+ if not hasattr(os, "pidfd_open") or not hasattr(signal, "pidfd_send_signal"):
12
+ raise RuntimeError("pidfd support unavailable")
13
+ fd = os.pidfd_open(request["pid"])
14
+ stat = pathlib.Path("/proc/%d/stat" % request["pid"]).read_text()
15
+ ticks = stat[stat.rfind(") ") + 2:].split()[19]
16
+ boot = pathlib.Path("/proc/sys/kernel/random/boot_id").read_text().strip().replace("-", "")[:8]
17
+ token = "l%s.%s" % (boot, ticks)
18
+ result["token"] = token
19
+ recorded = request.get("token")
20
+ result["verdict"] = "same" if token == recorded else "different"
21
+ if request["mode"] == "signal" and result["verdict"] == "same":
22
+ print(json.dumps({"phase": "verified"}), flush=True)
23
+ if sys.stdin.readline().strip() == "signal":
24
+ signal.pidfd_send_signal(fd, request["signal"])
25
+ result["sent"] = True
26
+ except Exception:
27
+ pass
28
+ finally:
29
+ if fd is not None:
30
+ os.close(fd)
31
+ print(json.dumps(result), flush=True)
32
+ `;
33
+ export const WINDOWS_PROCESS_HANDLE_SCRIPT = `
34
+ $ErrorActionPreference = 'Stop'
35
+ $result = @{ sent = $false; verdict = 'unknown' }
36
+ $handle = [IntPtr]::Zero
37
+ try {
38
+ Add-Type -TypeDefinition @'
39
+ using System;
40
+ using System.Runtime.InteropServices;
41
+ public static class HarneryProcessHandle {
42
+ [DllImport("kernel32.dll", SetLastError=true)] public static extern IntPtr OpenProcess(uint access, bool inherit, uint processId);
43
+ [DllImport("kernel32.dll", SetLastError=true)] public static extern bool GetProcessTimes(IntPtr handle, out long creation, out long exit, out long kernel, out long user);
44
+ [DllImport("kernel32.dll", SetLastError=true)] public static extern bool TerminateProcess(IntPtr handle, uint exitCode);
45
+ [DllImport("kernel32.dll")] public static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);
46
+ [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr handle);
47
+ }
48
+ '@
49
+ $request = [Console]::In.ReadLine() | ConvertFrom-Json
50
+ $access = [uint32]0x101000
51
+ if ($request.mode -eq 'signal') { $access = $access -bor 1 }
52
+ $handle = [HarneryProcessHandle]::OpenProcess($access, $false, [uint32]$request.pid)
53
+ if ($handle -eq [IntPtr]::Zero) { throw 'process handle unavailable' }
54
+ [long]$creation = 0; [long]$exitTime = 0; [long]$kernel = 0; [long]$userTime = 0
55
+ if (-not [HarneryProcessHandle]::GetProcessTimes($handle, [ref]$creation, [ref]$exitTime, [ref]$kernel, [ref]$userTime)) { throw 'process time unavailable' }
56
+ $token = 'w' + $creation.ToString([Globalization.CultureInfo]::InvariantCulture)
57
+ $result.token = $token
58
+ $result.verdict = if ($token -ceq $request.token) { 'same' } else { 'different' }
59
+ if ($request.mode -eq 'signal' -and $result.verdict -eq 'same') {
60
+ [Console]::Out.WriteLine('{"phase":"verified"}')
61
+ [Console]::Out.Flush()
62
+ if ([Console]::In.ReadLine() -eq 'signal' -and [HarneryProcessHandle]::WaitForSingleObject($handle, 0) -eq 258) {
63
+ $result.sent = [HarneryProcessHandle]::TerminateProcess($handle, 1)
64
+ }
65
+ }
66
+ } catch {} finally {
67
+ if ($handle -ne [IntPtr]::Zero) { [void][HarneryProcessHandle]::CloseHandle($handle) }
68
+ }
69
+ $result | ConvertTo-Json -Compress
70
+ `;
71
+ function runHelper(request, platform, run) {
72
+ const unknown = { sent: false, verdict: "unknown" };
73
+ if (!Number.isInteger(request.pid) || request.pid <= 0)
74
+ return unknown;
75
+ if (platform !== "linux" && platform !== "win32")
76
+ return unknown;
77
+ try {
78
+ const command = platform === "linux" ? "python3" : "powershell.exe";
79
+ const args = platform === "linux"
80
+ ? ["-I", "-c", LINUX_PROCESS_HANDLE_SCRIPT]
81
+ : ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", WINDOWS_PROCESS_HANDLE_SCRIPT];
82
+ const output = run(command, args, {
83
+ input: `${JSON.stringify(request)}\nsignal\n`,
84
+ encoding: "utf8",
85
+ timeout: 10_000,
86
+ maxBuffer: 64 * 1024,
87
+ windowsHide: true,
88
+ });
89
+ if (output.error || output.status !== 0)
90
+ return unknown;
91
+ const lines = String(output.stdout ?? "")
92
+ .trim()
93
+ .split(/\r?\n/);
94
+ const parsed = JSON.parse(lines.at(-1) ?? "");
95
+ if (typeof parsed.sent !== "boolean" ||
96
+ !["same", "different", "unknown"].includes(parsed.verdict) ||
97
+ (parsed.sent && parsed.verdict !== "same"))
98
+ return unknown;
99
+ return parsed;
100
+ }
101
+ catch {
102
+ return unknown;
103
+ }
104
+ }
105
+ /** Windows creation FILETIME, read from an OpenProcess handle. */
106
+ export function windowsProcessStartToken(pid, run = spawnSync) {
107
+ const result = runHelper({ mode: "probe", pid }, "win32", run);
108
+ return typeof result.token === "string" && /^w\d+$/.test(result.token) ? result.token : null;
109
+ }
110
+ /** No numeric-PID signaling fallback is permitted when an exact handle fails. */
111
+ export function signalProcessWithHandle(pid, recordedToken, signal, options = {}) {
112
+ const platform = options.platform ?? process.platform;
113
+ const number = typeof signal === "number" ? signal : constants.signals[signal];
114
+ if (!Number.isInteger(number) ||
115
+ number <= 0 ||
116
+ (platform === "linux" && !/^l[0-9a-f]{8}\.\d+$/.test(recordedToken)) ||
117
+ (platform === "win32" && (!/^w\d+$/.test(recordedToken) || ![9, 15].includes(number))))
118
+ return { sent: false, verdict: "unknown" };
119
+ const result = runHelper({ mode: "signal", pid, token: recordedToken, signal: number }, platform, options.run ?? spawnSync);
120
+ return { sent: result.sent, verdict: result.verdict };
121
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"stale-sweep.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/state/stale-sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAyIH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;IAC7C,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAuPA"}
1
+ {"version":3,"file":"stale-sweep.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/state/stale-sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkEH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;IAC7C,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAyJA"}
@@ -9,15 +9,12 @@
9
9
  * HARNERY_AGENT_COORD_FRESHNESS env var or `.harnery/config.jsonc`
10
10
  * `coord.freshness_seconds` (see `coordFreshnessSeconds`).
11
11
  */
12
- import { existsSync, lstatSync, readdirSync } from "node:fs";
13
- import { basename, dirname, join, resolve } from "node:path";
12
+ import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from "node:fs";
13
+ import { join } from "node:path";
14
14
  import { coordFreshnessSeconds } from "../../config.js";
15
15
  import { eventAdapterIdV3FromPlatform } from "../../events/v3/adapter-id.js";
16
- import { withGenerationCustodyV3 } from "../../events/v3/generation-custody.js";
17
- import { liveInstanceIdV3 } from "../../events/v3/live-routing.js";
18
16
  import { writeProducerDiagnosticV3 } from "../../events/v3/producers/intake.js";
19
17
  import { recordLiveSweepObservationV3 } from "../live-lifecycle-v3.js";
20
- import { captureFileRevision, deleteFileIfUnchanged, recoverInterruptedFileDeletions, } from "./unchanged-file.js";
21
18
  /** platform → adapter, for the swept-event envelope (mirrors heartbeat-writer's adapterOf). */
22
19
  /**
23
20
  * Record the sweep before deleting disposable cache state.
@@ -28,14 +25,13 @@ import { captureFileRevision, deleteFileIfUnchanged, recoverInterruptedFileDelet
28
25
  * diagnostics spool instead. If neither durable record can be written, fail
29
26
  * closed and keep the file.
30
27
  */
31
- function emitSwept(coordRoot, instanceId, adapter, sessionId, expectedGenerationId, reason, ageSecs) {
28
+ function emitSwept(coordRoot, instanceId, adapter, sessionId, reason, ageSecs) {
32
29
  try {
33
30
  recordLiveSweepObservationV3({
34
31
  coordRoot,
35
32
  owner: instanceId,
36
33
  nativeSessionId: sessionId,
37
34
  adapter,
38
- expectedGenerationId,
39
35
  observation: reason === "stale"
40
36
  ? "stale_heartbeat"
41
37
  : reason === "unparseable"
@@ -57,58 +53,14 @@ function emitSwept(coordRoot, instanceId, adapter, sessionId, expectedGeneration
57
53
  }));
58
54
  }
59
55
  }
60
- /** Any retained or unreadable owner row prevents dependent cache deletion. */
61
- function retainsHeartbeat(coordRoot, activeDir, owner, uncertainOwners) {
62
- if (uncertainOwners.has("*") || uncertainOwners.has(owner))
63
- return true;
64
- if (!/^[A-Za-z0-9_-]{1,128}$/.test(owner))
65
- return true;
66
- const heartbeat = join(activeDir, `${owner}.json`);
56
+ /** File mtime in epoch-seconds, or +Infinity if it can't be read (treat as fresh → don't reap). */
57
+ function mtimeSecs(path) {
67
58
  try {
68
- lstatSync(heartbeat);
69
- return true;
70
- }
71
- catch (error) {
72
- if (error.code !== "ENOENT")
73
- return true;
74
- }
75
- try {
76
- if (!lstatSync(activeDir).isDirectory())
77
- return true;
78
- }
79
- catch (error) {
80
- return error.code !== "ENOENT";
81
- }
82
- // Callers hold this owner's custody. A sweeper that died after the initial
83
- // directory scan may have left its heartbeat hidden under a private pin.
84
- for (const recovery of recoverInterruptedFileDeletions(activeDir, (source) => source === heartbeat)) {
85
- if (recovery.sourcePath && recovery.sourcePath !== heartbeat)
86
- continue;
87
- if (recovery.state !== "restored") {
88
- uncertainOwners.add(recovery.sourcePath ? owner : "*");
89
- recordCleanupFailure(coordRoot, recovery.sourcePath ?? activeDir, recovery);
90
- }
91
- return true;
92
- }
93
- return false;
94
- }
95
- function recordCleanupFailure(coordRoot, sourcePath, result) {
96
- if (result.state !== "error" &&
97
- result.state !== "recovery-required" &&
98
- result.state !== "retained") {
99
- return;
59
+ return Math.floor(statSync(path).mtimeMs / 1000);
100
60
  }
101
- writeProducerDiagnosticV3(coordRoot, "heartbeat_sweep_unrecorded", {
102
- signal: "cache.cleanup",
103
- state: "cache_cleanup_pending",
104
- reason: `${result.state}:${result.error ?? "file_cleanup_pending"}; source=${sourcePath}; recovery=${result.recoveryPath ?? "unavailable"}`,
105
- });
106
- }
107
- function recordHeartbeatCleanupResult(coordRoot, sourcePath, owner, result, uncertainOwners) {
108
- if (result.state === "recovery-required" || result.state === "error") {
109
- uncertainOwners.add(owner);
61
+ catch {
62
+ return Number.POSITIVE_INFINITY;
110
63
  }
111
- recordCleanupFailure(coordRoot, sourcePath, result);
112
64
  }
113
65
  export function staleSweep(coordRoot) {
114
66
  const heartbeatsRemoved = [];
@@ -134,129 +86,81 @@ export function staleSweep(coordRoot) {
134
86
  // lifecycle.sweep_observed; a terminal or unavailable generation gets a
135
87
  // heartbeat_sweep_unrecorded producer diagnostic without being resurrected.
136
88
  const liveInstanceIds = new Set();
137
- const uncertainOwners = new Set();
138
- const d = resolve(coordRoot, ".harnery", "active");
139
- for (const recovery of existsSync(d)
140
- ? recoverInterruptedFileDeletions(d, (source) => dirname(source) === d && /^[A-Za-z0-9_-]{1,128}\.json$/.test(basename(source)))
141
- : []) {
142
- if (recovery.state !== "restored") {
143
- uncertainOwners.add(recovery.sourcePath ? basename(recovery.sourcePath, ".json") : "*");
144
- recordCleanupFailure(coordRoot, recovery.sourcePath ?? d, recovery);
145
- }
146
- }
89
+ const d = join(coordRoot, ".harnery", "active");
147
90
  if (existsSync(d)) {
148
91
  for (const f of readdirSync(d)) {
149
92
  if (!f.endsWith(".json"))
150
93
  continue;
151
94
  const path = join(d, f);
152
95
  const idFromFile = f.replace(/\.json$/, "");
153
- if (!/^[A-Za-z0-9_-]{1,128}$/.test(idFromFile))
154
- continue;
96
+ let parsed = null;
155
97
  try {
156
- withGenerationCustodyV3(coordRoot, [liveInstanceIdV3(idFromFile)], () => {
157
- const revision = captureFileRevision(path);
158
- if (!revision)
159
- return;
160
- const mtimeSecs = Number(revision.mtimeNs / 1000000000n);
161
- let parsed = null;
98
+ parsed = JSON.parse(readFileSync(path, "utf8"));
99
+ }
100
+ catch {
101
+ parsed = null;
102
+ }
103
+ if (parsed === null) {
104
+ // Unparseable: only reap if the file itself is mtime-old.
105
+ if (mtimeSecs(path) < cutoff) {
162
106
  try {
163
- const value = JSON.parse(revision.bytes.toString("utf8"));
164
- if (value && typeof value === "object" && !Array.isArray(value))
165
- parsed = value;
166
- }
167
- catch {
168
- parsed = null;
169
- }
170
- if (parsed === null) {
171
- // Unparseable: only reap if the file itself is mtime-old.
172
- if (mtimeSecs < cutoff) {
173
- const result = deleteFileIfUnchanged(path, revision, () => emitSwept(coordRoot, idFromFile, "claude-code", idFromFile, null, "unparseable", nowSec - mtimeSecs));
174
- recordHeartbeatCleanupResult(coordRoot, path, idFromFile, result, uncertainOwners);
175
- if (result.state === "deleted") {
176
- heartbeatsRemoved.push(f);
177
- }
107
+ const ageSecs = nowSec - mtimeSecs(path);
108
+ if (!emitSwept(coordRoot, idFromFile, "claude-code", idFromFile, "unparseable", ageSecs)) {
109
+ continue;
178
110
  }
179
- return;
111
+ unlinkSync(path);
112
+ heartbeatsRemoved.push(f);
180
113
  }
181
- // The filename selects the writer's custody scope. A conflicting content
182
- // identity cannot authorize an audit or deletion for a different owner.
183
- if (parsed.instance_id !== undefined && parsed.instance_id !== idFromFile)
184
- return;
185
- const instanceId = parsed.instance_id ?? idFromFile;
186
- const adapter = eventAdapterIdV3FromPlatform(parsed.platform, { context: "stale-sweep" });
187
- const sessionId = parsed.session_id ?? instanceId;
188
- const generationId = typeof parsed.v3_generation_id === "string" &&
189
- /^gen_[A-Za-z0-9._-]+$/.test(parsed.v3_generation_id)
190
- ? parsed.v3_generation_id
191
- : null;
192
- const ts = parsed.last_heartbeat
193
- ? Math.floor(Date.parse(parsed.last_heartbeat) / 1000)
194
- : Number.NaN;
195
- if (!parsed.last_heartbeat || !Number.isFinite(ts)) {
196
- // No / NaN last_heartbeat: can't trust content; gate on mtime.
197
- if (mtimeSecs < cutoff) {
198
- const result = deleteFileIfUnchanged(path, revision, () => emitSwept(coordRoot, instanceId, adapter, sessionId, generationId, "missing_ts", nowSec - mtimeSecs));
199
- recordHeartbeatCleanupResult(coordRoot, path, idFromFile, result, uncertainOwners);
200
- if (result.state === "deleted") {
201
- heartbeatsRemoved.push(f);
202
- }
203
- }
204
- else if (parsed.instance_id) {
205
- liveInstanceIds.add(parsed.instance_id);
206
- }
207
- return;
114
+ catch {
115
+ /* swallow */
208
116
  }
209
- if (ts < cutoff) {
210
- // Legitimate stale prune (valid timestamp, past the freshness cutoff).
211
- const result = deleteFileIfUnchanged(path, revision, () => emitSwept(coordRoot, instanceId, adapter, sessionId, generationId, "stale", nowSec - ts));
212
- recordHeartbeatCleanupResult(coordRoot, path, idFromFile, result, uncertainOwners);
213
- if (result.state === "deleted") {
214
- heartbeatsRemoved.push(f);
215
- }
216
- return;
117
+ }
118
+ continue;
119
+ }
120
+ const instanceId = parsed.instance_id ?? idFromFile;
121
+ const adapter = eventAdapterIdV3FromPlatform(parsed.platform, { context: "stale-sweep" });
122
+ const sessionId = parsed.session_id ?? instanceId;
123
+ const ts = parsed.last_heartbeat
124
+ ? Math.floor(Date.parse(parsed.last_heartbeat) / 1000)
125
+ : Number.NaN;
126
+ if (!parsed.last_heartbeat || !Number.isFinite(ts)) {
127
+ // No / NaN last_heartbeat: can't trust content; gate on mtime.
128
+ if (mtimeSecs(path) < cutoff) {
129
+ if (!emitSwept(coordRoot, instanceId, adapter, sessionId, "missing_ts", nowSec - mtimeSecs(path))) {
130
+ continue;
217
131
  }
218
- if (parsed.instance_id)
219
- liveInstanceIds.add(parsed.instance_id);
220
- });
132
+ unlinkSync(path);
133
+ heartbeatsRemoved.push(f);
134
+ }
135
+ else if (parsed.instance_id) {
136
+ liveInstanceIds.add(parsed.instance_id);
137
+ }
138
+ continue;
221
139
  }
222
- catch {
223
- // Busy or unknown custody retains the cache and its dependent files.
224
- uncertainOwners.add(idFromFile);
140
+ if (ts < cutoff) {
141
+ // Legitimate stale prune (valid timestamp, past the freshness cutoff).
142
+ if (!emitSwept(coordRoot, instanceId, adapter, sessionId, "stale", nowSec - ts)) {
143
+ continue;
144
+ }
145
+ unlinkSync(path);
146
+ heartbeatsRemoved.push(f);
147
+ continue;
225
148
  }
149
+ if (parsed.instance_id)
150
+ liveInstanceIds.add(parsed.instance_id);
226
151
  }
227
152
  }
228
153
  // 2. Prune pid-map entries whose instance has no live heartbeat.
229
- const pidmapDir = resolve(coordRoot, ".harnery", "pid-map");
230
- for (const recovery of existsSync(pidmapDir)
231
- ? recoverInterruptedFileDeletions(pidmapDir, (source) => dirname(source) === pidmapDir && /^\d+$/.test(basename(source)))
232
- : [])
233
- recordCleanupFailure(coordRoot, recovery.sourcePath ?? pidmapDir, recovery);
154
+ const pidmapDir = join(coordRoot, ".harnery", "pid-map");
234
155
  if (existsSync(pidmapDir)) {
235
156
  for (const f of readdirSync(pidmapDir)) {
236
- if (f.startsWith(".harnery-delete-"))
237
- continue;
238
157
  const path = join(pidmapDir, f);
239
158
  try {
240
- const revision = captureFileRevision(path);
241
- if (!revision)
242
- continue;
243
- const row = revision.bytes.toString("utf8").trim();
159
+ const row = readFileSync(path, "utf8").trim();
244
160
  const ownerId = row.split("\t")[0]?.trim() ?? "";
245
- const prune = () => {
246
- if (!ownerId ||
247
- (!liveInstanceIds.has(ownerId) &&
248
- !retainsHeartbeat(coordRoot, d, ownerId, uncertainOwners))) {
249
- const result = deleteFileIfUnchanged(path, revision, () => !ownerId || !retainsHeartbeat(coordRoot, d, ownerId, uncertainOwners));
250
- recordCleanupFailure(coordRoot, path, result);
251
- if (result.state === "deleted")
252
- pidmapsRemoved += 1;
253
- }
254
- };
255
- if (/^[A-Za-z0-9_-]{1,128}$/.test(ownerId)) {
256
- withGenerationCustodyV3(coordRoot, [liveInstanceIdV3(ownerId)], prune);
257
- }
258
- else if (!ownerId) {
259
- prune();
161
+ if (!ownerId || !liveInstanceIds.has(ownerId)) {
162
+ unlinkSync(path);
163
+ pidmapsRemoved += 1;
260
164
  }
261
165
  }
262
166
  catch {
@@ -266,12 +170,7 @@ export function staleSweep(coordRoot) {
266
170
  }
267
171
  // 3. Prune prompt hashes for dead owners. Resource hashes retain their own
268
172
  // count so existing peer-hash telemetry keeps its original meaning.
269
- const agentsDir = resolve(coordRoot, ".harnery");
270
- for (const recovery of existsSync(agentsDir)
271
- ? recoverInterruptedFileDeletions(agentsDir, (source) => dirname(source) === agentsDir &&
272
- /^\.last-(?:resource|peer)-hash\.[A-Za-z0-9_-]{1,128}$/.test(basename(source)))
273
- : [])
274
- recordCleanupFailure(coordRoot, recovery.sourcePath ?? agentsDir, recovery);
173
+ const agentsDir = join(coordRoot, ".harnery");
275
174
  if (existsSync(agentsDir)) {
276
175
  for (const f of readdirSync(agentsDir)) {
277
176
  const resourceHash = f.startsWith(".last-resource-hash.");
@@ -284,25 +183,16 @@ export function staleSweep(coordRoot) {
284
183
  // retained heartbeat's liveness could not be determined safely.
285
184
  if (!/^[A-Za-z0-9_-]{1,128}$/.test(owner))
286
185
  continue;
186
+ if (existsSync(join(d, `${owner}.json`)))
187
+ continue;
287
188
  }
288
- if (!liveInstanceIds.has(owner) && /^[A-Za-z0-9_-]{1,128}$/.test(owner)) {
189
+ if (!liveInstanceIds.has(owner)) {
289
190
  try {
290
- withGenerationCustodyV3(coordRoot, [liveInstanceIdV3(owner)], () => {
291
- if (retainsHeartbeat(coordRoot, d, owner, uncertainOwners))
292
- return;
293
- const path = join(agentsDir, f);
294
- const revision = captureFileRevision(path);
295
- if (!revision)
296
- return;
297
- const result = deleteFileIfUnchanged(path, revision, () => !retainsHeartbeat(coordRoot, d, owner, uncertainOwners));
298
- recordCleanupFailure(coordRoot, path, result);
299
- if (result.state === "deleted") {
300
- if (resourceHash)
301
- resourceHashesRemoved += 1;
302
- else
303
- peerHashesRemoved += 1;
304
- }
305
- });
191
+ unlinkSync(join(agentsDir, f));
192
+ if (resourceHash)
193
+ resourceHashesRemoved += 1;
194
+ else
195
+ peerHashesRemoved += 1;
306
196
  }
307
197
  catch {
308
198
  /* swallow */
@@ -1,3 +1,4 @@
1
+ import { type Stats } from "node:fs";
1
2
  /** A checkpoint taken before an internal manifest write, never an expiry override. */
2
3
  export interface ArtifactActivity {
3
4
  last_changed_at: string;
@@ -9,6 +10,8 @@ export declare function artifactRootEntries(path: string): string;
9
10
  * Keep the prior root activity while its payload entries match the checkpoint.
10
11
  * A root deletion or rename changes that fingerprint; nested changes retain
11
12
  * their ordinary filesystem timestamps. Symlinks are inspected, never followed.
13
+ * `visit` sees every entry's lstat exactly once, including a root manifest the
14
+ * activity rules skip, so a caller can size the tree in the same walk.
12
15
  */
13
- export declare function readArtifactActivity(path: string, now: Date, previous?: ArtifactActivity): ArtifactActivity;
16
+ export declare function readArtifactActivity(path: string, now: Date, previous?: ArtifactActivity, visit?: (entry: string, stat: Stats) => void): ArtifactActivity;
14
17
  //# sourceMappingURL=activity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/core/artifacts/activity.ts"],"names":[],"mappings":"AAKA,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAS/E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,IAAI,EACT,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,gBAAgB,CA2BlB"}
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/core/artifacts/activity.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAI7D,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAS/E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,IAAI,EACT,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,GAC3C,gBAAgB,CA+BlB"}
@@ -22,8 +22,10 @@ export function artifactRootEntries(path) {
22
22
  * Keep the prior root activity while its payload entries match the checkpoint.
23
23
  * A root deletion or rename changes that fingerprint; nested changes retain
24
24
  * their ordinary filesystem timestamps. Symlinks are inspected, never followed.
25
+ * `visit` sees every entry's lstat exactly once, including a root manifest the
26
+ * activity rules skip, so a caller can size the tree in the same walk.
25
27
  */
26
- export function readArtifactActivity(path, now, previous) {
28
+ export function readArtifactActivity(path, now, previous, visit) {
27
29
  const entries = artifactRootEntries(path);
28
30
  const nowMs = now.getTime();
29
31
  const accept = (timestamp) => Number.isFinite(timestamp) && timestamp <= nowMs + 5 * 60 * 1000
@@ -31,6 +33,7 @@ export function readArtifactActivity(path, now, previous) {
31
33
  : 0;
32
34
  const walk = (entry, root = false) => {
33
35
  const stat = lstatSync(entry);
36
+ visit?.(entry, stat);
34
37
  let latest = root && previous?.root_entries_sha256 === entries
35
38
  ? accept(Date.parse(previous.last_changed_at))
36
39
  : Math.max(accept(stat.mtimeMs), accept(stat.ctimeMs));
@@ -38,8 +41,11 @@ export function readArtifactActivity(path, now, previous) {
38
41
  for (const name of readdirSync(entry)) {
39
42
  // Only this unit's own control manifest is metadata. Nested artifact
40
43
  // manifests are payload from the containing workspace's point of view.
41
- if (root && previous && name === ARTIFACT_MANIFEST)
44
+ if (root && previous && name === ARTIFACT_MANIFEST) {
45
+ if (visit)
46
+ visit(join(entry, name), lstatSync(join(entry, name)));
42
47
  continue;
48
+ }
43
49
  latest = Math.max(latest, walk(join(entry, name)));
44
50
  }
45
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/artifacts/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/artifacts/index.ts"],"names":[],"mappings":"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"}
@@ -497,12 +497,14 @@ export function cleanArtifacts(repoRoot, opts = {}) {
497
497
  }
498
498
  }
499
499
  function cleanArtifactsUnlocked(repoRoot, opts) {
500
- const started = performance.now();
501
500
  const now = opts.now ?? new Date();
502
501
  const freshnessSeconds = opts.freshnessSeconds ?? 600;
503
502
  const rows = inventoryArtifacts(repoRoot, { now, freshnessSeconds });
504
503
  if (!opts.yes)
505
504
  return rows;
505
+ // The budget bounds deletion work. Inventory cost scales with the store, so
506
+ // counting it here would leave room for only the one guaranteed deletion.
507
+ const started = performance.now();
506
508
  let attempted = 0;
507
509
  return rows.map((entry) => {
508
510
  if (entry.action !== "would-delete")
@@ -851,7 +853,11 @@ function autoCleanArtifactsUnlocked(repoRoot, opts) {
851
853
  failures,
852
854
  ...(status === "completed"
853
855
  ? { last_completed_at: now.toISOString() }
854
- : { retry_after: new Date(now.getTime() + 60_000).toISOString() }),
856
+ : {
857
+ // A slice that deleted something continues soon. One that made no
858
+ // progress would only repeat the same walk, so it waits a full interval.
859
+ retry_after: new Date(now.getTime() + (deleted > 0 ? 60_000 : intervalMs)).toISOString(),
860
+ }),
855
861
  });
856
862
  return { ran: true, reason: status === "completed" ? "swept" : status, deleted, bytes };
857
863
  }
@@ -911,8 +917,7 @@ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
911
917
  return rowFor(path, name, repoRoot, classification, parsed.reason);
912
918
  }
913
919
  const manifest = parsed.manifest;
914
- const usage = safeTreeUsage(path);
915
- const lastModifiedMs = safeTreeLastModified(path, now, manifest.activity);
920
+ const { usage, lastModifiedMs } = scanManagedTree(path, now, manifest.activity);
916
921
  const retentionAnchorMs = Date.parse(manifest.retention.renewed_at ?? manifest.created_at);
917
922
  const retentionWindowMs = Date.parse(manifest.retention.expires_at) - retentionAnchorMs;
918
923
  const effectiveLastModifiedMs = Math.max(retentionAnchorMs, lastModifiedMs ?? 0);
@@ -1497,22 +1502,43 @@ function safeTreeUsage(path, seen = new Set()) {
1497
1502
  return null;
1498
1503
  }
1499
1504
  }
1500
- function safeTreeSize(path) {
1501
- return safeTreeUsage(path)?.disk ?? null;
1505
+ function addEntryUsage(total, st, seen) {
1506
+ if (st.isDirectory()) {
1507
+ total.disk += allocatedBytes(st);
1508
+ total.apparent += st.size;
1509
+ return;
1510
+ }
1511
+ if (!st.isFile() && !st.isSymbolicLink())
1512
+ return;
1513
+ const key = `${st.dev}:${st.ino}`;
1514
+ if (st.nlink > 1 && seen.has(key)) {
1515
+ total.apparent += st.size;
1516
+ return;
1517
+ }
1518
+ if (st.nlink > 1)
1519
+ seen.add(key);
1520
+ total.disk += allocatedBytes(st);
1521
+ total.apparent += st.size;
1502
1522
  }
1503
1523
  /**
1504
- * Return the newest filesystem change in a managed tree without following
1505
- * symlinks. A small future tolerance protects a write racing the inventory
1506
- * scan; timestamps farther ahead are ignored as clock-skewed metadata.
1524
+ * Size a managed tree and find its newest change in one walk, so inventory
1525
+ * reads each entry's metadata once instead of once per question. If the
1526
+ * activity scan fails, usage is measured on its own, as before.
1507
1527
  */
1508
- function safeTreeLastModified(path, now, activity) {
1528
+ function scanManagedTree(path, now, activity) {
1529
+ const usage = { disk: 0, apparent: 0 };
1530
+ const seen = new Set();
1509
1531
  try {
1510
- return Date.parse(readArtifactActivity(path, now, activity).last_changed_at);
1532
+ const result = readArtifactActivity(path, now, activity, (_entry, st) => addEntryUsage(usage, st, seen));
1533
+ return { usage, lastModifiedMs: Date.parse(result.last_changed_at) };
1511
1534
  }
1512
1535
  catch {
1513
- return null;
1536
+ return { usage: safeTreeUsage(path), lastModifiedMs: null };
1514
1537
  }
1515
1538
  }
1539
+ function safeTreeSize(path) {
1540
+ return safeTreeUsage(path)?.disk ?? null;
1541
+ }
1516
1542
  function rowFor(path, name, repoRoot, classification, reason, usage = safeTreeUsage(path)) {
1517
1543
  return {
1518
1544
  name,