harnery 0.45.0 → 0.45.2

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 (235) hide show
  1. package/dist/commander.js +0 -1
  2. package/dist/commands/files.d.ts +2 -2
  3. package/dist/commands/files.d.ts.map +1 -1
  4. package/dist/commands/files.js +4 -7
  5. package/dist/commands/servers.d.ts.map +1 -1
  6. package/dist/commands/servers.js +17 -11
  7. package/dist/commands/tunnel.d.ts +0 -15
  8. package/dist/commands/tunnel.d.ts.map +1 -1
  9. package/dist/commands/tunnel.js +153 -453
  10. package/dist/commands/workflow.d.ts.map +1 -1
  11. package/dist/commands/workflow.js +6 -45
  12. package/dist/core/agents/coord-client.d.ts.map +1 -1
  13. package/dist/core/agents/coord-client.js +0 -18
  14. package/dist/core/agents/live-authority-v3.d.ts +0 -1
  15. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  16. package/dist/core/agents/live-authority-v3.js +0 -11
  17. package/dist/core/agents/live-lifecycle-v3.d.ts +2 -4
  18. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  19. package/dist/core/agents/live-lifecycle-v3.js +7 -28
  20. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  21. package/dist/core/agents/state/heartbeat-writer.js +14 -25
  22. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
  23. package/dist/core/agents/state/live-coordination-writer.js +0 -5
  24. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  25. package/dist/core/agents/state/pidmap.js +2 -7
  26. package/dist/core/agents/state/proc-start.d.ts +20 -31
  27. package/dist/core/agents/state/proc-start.d.ts.map +1 -1
  28. package/dist/core/agents/state/proc-start.js +37 -70
  29. package/dist/core/agents/state/service-process.d.ts +61 -0
  30. package/dist/core/agents/state/service-process.d.ts.map +1 -0
  31. package/dist/core/agents/state/service-process.js +143 -0
  32. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  33. package/dist/core/agents/state/stale-sweep.js +70 -180
  34. package/dist/core/artifacts/activity.d.ts +4 -1
  35. package/dist/core/artifacts/activity.d.ts.map +1 -1
  36. package/dist/core/artifacts/activity.js +8 -2
  37. package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
  38. package/dist/core/artifacts/delivery-card.js +1 -2
  39. package/dist/core/artifacts/index.d.ts.map +1 -1
  40. package/dist/core/artifacts/index.js +38 -12
  41. package/dist/core/context/index.d.ts +6 -4
  42. package/dist/core/context/index.d.ts.map +1 -1
  43. package/dist/core/context/index.js +194 -256
  44. package/dist/core/context/observation.d.ts +9 -9
  45. package/dist/core/context/observation.d.ts.map +1 -1
  46. package/dist/core/context/observation.js +37 -6
  47. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  48. package/dist/core/events/v3/authority-outbox.js +0 -29
  49. package/dist/core/events/v3/producers/coordination-recorder.d.ts +0 -1
  50. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  51. package/dist/core/events/v3/producers/coordination-recorder.js +0 -7
  52. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  53. package/dist/core/events/v3/producers/recorder.js +64 -77
  54. package/dist/core/events/v3/runtime-build.d.ts +14 -0
  55. package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
  56. package/dist/core/events/v3/runtime-build.js +44 -0
  57. package/dist/core/governor/index.d.ts +2 -1
  58. package/dist/core/governor/index.d.ts.map +1 -1
  59. package/dist/core/governor/index.js +2 -1
  60. package/dist/core/governor/service-read.d.ts +3 -10
  61. package/dist/core/governor/service-read.d.ts.map +1 -1
  62. package/dist/core/governor/service-read.js +10 -94
  63. package/dist/core/governor/service.d.ts +3 -7
  64. package/dist/core/governor/service.d.ts.map +1 -1
  65. package/dist/core/governor/service.js +17 -182
  66. package/dist/core/hooks/cli.js +78 -48
  67. package/dist/core/hooks/resolve/owner.js +2 -2
  68. package/dist/core/resources/sampler.js +2 -2
  69. package/dist/core/resources/service-status.d.ts +2 -14
  70. package/dist/core/resources/service-status.d.ts.map +1 -1
  71. package/dist/core/resources/service-status.js +3 -23
  72. package/dist/core/resources/service.d.ts +3 -7
  73. package/dist/core/resources/service.d.ts.map +1 -1
  74. package/dist/core/resources/service.js +12 -101
  75. package/dist/core/resources/status.d.ts.map +1 -1
  76. package/dist/core/resources/status.js +3 -2
  77. package/dist/core/semantic/service.d.ts.map +1 -1
  78. package/dist/core/semantic/service.js +9 -2
  79. package/dist/core/servers/index.d.ts +11 -10
  80. package/dist/core/servers/index.d.ts.map +1 -1
  81. package/dist/core/servers/index.js +82 -192
  82. package/dist/core/servers/tunnels.d.ts +3 -5
  83. package/dist/core/servers/tunnels.d.ts.map +1 -1
  84. package/dist/core/servers/tunnels.js +2 -45
  85. package/dist/core/storage/durable-history.js +56 -22
  86. package/dist/core/storage/segments.d.ts.map +1 -1
  87. package/dist/core/storage/segments.js +73 -17
  88. package/dist/core/supervisor/service.d.ts +4 -7
  89. package/dist/core/supervisor/service.d.ts.map +1 -1
  90. package/dist/core/supervisor/service.js +23 -122
  91. package/dist/core/supervisor/services.js +2 -2
  92. package/dist/core/supervisor/status.d.ts +3 -17
  93. package/dist/core/supervisor/status.d.ts.map +1 -1
  94. package/dist/core/supervisor/status.js +7 -70
  95. package/dist/core/work/state.js +7 -7
  96. package/dist/core/workflow/engine.d.ts.map +1 -1
  97. package/dist/core/workflow/engine.js +23 -66
  98. package/dist/core/workflow/index.d.ts +3 -4
  99. package/dist/core/workflow/index.d.ts.map +1 -1
  100. package/dist/core/workflow/index.js +2 -2
  101. package/dist/core/workflow/live-session-v3.d.ts +0 -6
  102. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  103. package/dist/core/workflow/live-session-v3.js +5 -126
  104. package/dist/core/workflow/proof.d.ts +4 -4
  105. package/dist/core/workflow/proof.d.ts.map +1 -1
  106. package/dist/core/workflow/proof.js +34 -86
  107. package/dist/core/workflow/resume-lock.d.ts +17 -0
  108. package/dist/core/workflow/resume-lock.d.ts.map +1 -0
  109. package/dist/core/workflow/resume-lock.js +158 -0
  110. package/dist/core/workflow/run-state.d.ts +0 -21
  111. package/dist/core/workflow/run-state.d.ts.map +1 -1
  112. package/dist/core/workflow/run-state.js +3 -174
  113. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  114. package/dist/core/workflow/spawn-claude.js +0 -19
  115. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  116. package/dist/core/workflow/spawn-codex.js +0 -13
  117. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  118. package/dist/core/workflow/spawn-cursor.js +0 -19
  119. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
  120. package/dist/core/workflow/spawn-opencode.js +0 -14
  121. package/dist/core/workflow/types.d.ts +11 -54
  122. package/dist/core/workflow/types.d.ts.map +1 -1
  123. package/dist/core/workflow/workspaces/leases.d.ts +4 -0
  124. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  125. package/dist/core/workflow/workspaces/leases.js +1 -1
  126. package/dist/core/workflow/workspaces/local-git.js +91 -210
  127. package/dist/core/workflow/workspaces/ownership.d.ts +0 -7
  128. package/dist/core/workflow/workspaces/ownership.d.ts.map +1 -1
  129. package/dist/core/workflow/workspaces/ownership.js +3 -130
  130. package/dist/core/workflow/workspaces/reclaim.d.ts +4 -7
  131. package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
  132. package/dist/core/workflow/workspaces/reclaim.js +0 -4
  133. package/dist/core/workflow/workspaces/recovery.d.ts +1 -1
  134. package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
  135. package/dist/core/workflow/workspaces/recovery.js +1 -1
  136. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  137. package/dist/core/workflow/workspaces/state.js +1 -4
  138. package/dist/lib/identities/assume.d.ts.map +1 -1
  139. package/dist/lib/identities/assume.js +0 -4
  140. package/dist/lib/tunnel/state.d.ts +6 -13
  141. package/dist/lib/tunnel/state.d.ts.map +1 -1
  142. package/dist/lib/tunnel/state.js +12 -58
  143. package/package.json +1 -6
  144. package/src/commander.ts +0 -10
  145. package/src/commands/files.ts +5 -13
  146. package/src/commands/servers.ts +23 -12
  147. package/src/commands/tunnel.ts +166 -533
  148. package/src/commands/workflow.ts +8 -58
  149. package/src/core/agents/coord-client.ts +0 -20
  150. package/src/core/agents/live-authority-v3.ts +0 -17
  151. package/src/core/agents/live-lifecycle-v3.ts +14 -52
  152. package/src/core/agents/state/heartbeat-writer.ts +12 -29
  153. package/src/core/agents/state/live-coordination-writer.ts +0 -29
  154. package/src/core/agents/state/pidmap.ts +2 -15
  155. package/src/core/agents/state/proc-start.ts +41 -69
  156. package/src/core/agents/state/service-process.ts +217 -0
  157. package/src/core/agents/state/stale-sweep.ts +82 -247
  158. package/src/core/artifacts/activity.ts +9 -2
  159. package/src/core/artifacts/delivery-card.ts +1 -7
  160. package/src/core/artifacts/index.ts +45 -12
  161. package/src/core/context/index.ts +207 -272
  162. package/src/core/context/observation.ts +40 -9
  163. package/src/core/events/v3/authority-outbox.ts +0 -56
  164. package/src/core/events/v3/producers/coordination-recorder.ts +0 -15
  165. package/src/core/events/v3/producers/recorder.ts +68 -94
  166. package/src/core/events/v3/runtime-build.ts +62 -0
  167. package/src/core/governor/index.ts +1 -2
  168. package/src/core/governor/service-read.ts +15 -114
  169. package/src/core/governor/service.ts +36 -220
  170. package/src/core/hooks/cli.ts +85 -47
  171. package/src/core/hooks/resolve/owner.ts +2 -2
  172. package/src/core/resources/sampler.ts +3 -2
  173. package/src/core/resources/service-status.ts +6 -35
  174. package/src/core/resources/service.ts +23 -133
  175. package/src/core/resources/status.ts +3 -2
  176. package/src/core/semantic/service.ts +8 -2
  177. package/src/core/servers/index.ts +86 -228
  178. package/src/core/servers/tunnels.ts +3 -55
  179. package/src/core/storage/durable-history.ts +52 -20
  180. package/src/core/storage/segments.ts +79 -17
  181. package/src/core/supervisor/service.ts +33 -155
  182. package/src/core/supervisor/services.ts +2 -2
  183. package/src/core/supervisor/status.ts +10 -85
  184. package/src/core/work/state.ts +7 -7
  185. package/src/core/workflow/engine.ts +22 -74
  186. package/src/core/workflow/index.ts +2 -13
  187. package/src/core/workflow/live-session-v3.ts +5 -146
  188. package/src/core/workflow/proof.ts +40 -104
  189. package/src/core/workflow/resume-lock.ts +179 -0
  190. package/src/core/workflow/run-state.ts +3 -207
  191. package/src/core/workflow/spawn-claude.ts +0 -18
  192. package/src/core/workflow/spawn-codex.ts +0 -13
  193. package/src/core/workflow/spawn-cursor.ts +0 -18
  194. package/src/core/workflow/spawn-opencode.ts +0 -14
  195. package/src/core/workflow/types.ts +11 -41
  196. package/src/core/workflow/workspaces/leases.ts +1 -1
  197. package/src/core/workflow/workspaces/local-git.ts +120 -239
  198. package/src/core/workflow/workspaces/ownership.ts +3 -158
  199. package/src/core/workflow/workspaces/reclaim.ts +3 -9
  200. package/src/core/workflow/workspaces/recovery.ts +1 -1
  201. package/src/core/workflow/workspaces/state.ts +1 -5
  202. package/src/lib/identities/assume.ts +0 -4
  203. package/src/lib/tunnel/state.ts +15 -70
  204. package/dist/commands/turn-rollback.d.ts +0 -5
  205. package/dist/commands/turn-rollback.d.ts.map +0 -1
  206. package/dist/commands/turn-rollback.js +0 -76
  207. package/dist/core/agents/state/process-handle.d.ts +0 -26
  208. package/dist/core/agents/state/process-handle.d.ts.map +0 -1
  209. package/dist/core/agents/state/process-handle.js +0 -121
  210. package/dist/core/agents/state/unchanged-file.d.ts +0 -44
  211. package/dist/core/agents/state/unchanged-file.d.ts.map +0 -1
  212. package/dist/core/agents/state/unchanged-file.js +0 -390
  213. package/dist/core/events/v3/generation-custody.d.ts +0 -5
  214. package/dist/core/events/v3/generation-custody.d.ts.map +0 -1
  215. package/dist/core/events/v3/generation-custody.js +0 -50
  216. package/dist/core/turn-rollback/content.d.ts +0 -53
  217. package/dist/core/turn-rollback/content.d.ts.map +0 -1
  218. package/dist/core/turn-rollback/content.js +0 -396
  219. package/dist/core/turn-rollback/index.d.ts +0 -72
  220. package/dist/core/turn-rollback/index.d.ts.map +0 -1
  221. package/dist/core/turn-rollback/index.js +0 -443
  222. package/dist/core/workflow/failure-evidence.d.ts +0 -16
  223. package/dist/core/workflow/failure-evidence.d.ts.map +0 -1
  224. package/dist/core/workflow/failure-evidence.js +0 -114
  225. package/dist/core/workflow/recovery-audit.d.ts +0 -30
  226. package/dist/core/workflow/recovery-audit.d.ts.map +0 -1
  227. package/dist/core/workflow/recovery-audit.js +0 -116
  228. package/src/commands/turn-rollback.ts +0 -111
  229. package/src/core/agents/state/process-handle.ts +0 -165
  230. package/src/core/agents/state/unchanged-file.ts +0 -456
  231. package/src/core/events/v3/generation-custody.ts +0 -59
  232. package/src/core/turn-rollback/content.ts +0 -499
  233. package/src/core/turn-rollback/index.ts +0 -580
  234. package/src/core/workflow/failure-evidence.ts +0 -141
  235. package/src/core/workflow/recovery-audit.ts +0 -181
@@ -1,135 +1,8 @@
1
- import { lstatSync, readdirSync, readFileSync, realpathSync } from "node:fs";
2
- import { basename, dirname, isAbsolute, join, resolve } from "node:path";
3
- import { readJsonRecord, stableDigest } from "../durable-record.js";
4
- import { acquireNoClobberLease } from "./leases.js";
1
+ import { lstatSync, realpathSync } from "node:fs";
2
+ import { basename, dirname, isAbsolute, resolve } from "node:path";
3
+ import { stableDigest } from "../durable-record.js";
5
4
  import { containsPath } from "./paths.js";
6
5
  import { isWorkspaceAllocationRequest } from "./validate.js";
7
- const STALE_MS = 5 * 60 * 1_000;
8
- const RESERVATION_SCOPE = "workspace-reclaim";
9
- function leaseRoot(coordRoot, providerId) {
10
- return join(resolve(coordRoot), ".harnery", "workspaces", providerId, ".leases");
11
- }
12
- /** Serialize only publication and reservation registration, never Git work. */
13
- function withPublicationGate(coordRoot, providerId, operation) {
14
- const authority = stableDigest({ provider_id: providerId, scope: "workspace-publication" });
15
- const gate = acquireNoClobberLease({
16
- path: join(leaseRoot(coordRoot, providerId), "publication.lock"),
17
- scope: "workspace-publication",
18
- authoritySha256: authority,
19
- staleAfterMs: STALE_MS,
20
- validateStaleOwner: (owner) => owner.authority_sha256 === authority,
21
- });
22
- try {
23
- return operation();
24
- }
25
- finally {
26
- gate.release();
27
- }
28
- }
29
- function reservationPath(coordRoot, claim) {
30
- return join(leaseRoot(coordRoot, claim.provider_id), `reclaim-${claim.binding_id}.lock`);
31
- }
32
- function acquireReservation(coordRoot, claim) {
33
- const authority = stableDigest(claim);
34
- return acquireNoClobberLease({
35
- path: reservationPath(coordRoot, claim),
36
- scope: RESERVATION_SCOPE,
37
- authoritySha256: authority,
38
- staleAfterMs: STALE_MS,
39
- metadata: { binding_id: claim.binding_id, request_sha256: claim.request_sha256 },
40
- validateStaleOwner: (owner) => owner.authority_sha256 === authority &&
41
- owner.metadata?.binding_id === claim.binding_id &&
42
- owner.metadata?.request_sha256 === claim.request_sha256,
43
- });
44
- }
45
- /** The immutable claim is the authority; the lease reserves its destructive path. */
46
- export function reserveWorkspaceReclaim(coordRoot, claim) {
47
- assertClaimAuthority(claim, claim.provider_id, claim.binding_id);
48
- const lease = withPublicationGate(coordRoot, claim.provider_id, () => acquireReservation(coordRoot, claim));
49
- return {
50
- assertCurrent() {
51
- const path = reservationPath(coordRoot, claim);
52
- const current = join(path, "current");
53
- const pin = join(path, lease.owner.owner_file);
54
- const a = lstatSync(current, { bigint: true });
55
- const b = lstatSync(pin, { bigint: true });
56
- if (!a.isFile() ||
57
- !b.isFile() ||
58
- a.dev !== b.dev ||
59
- a.ino !== b.ino ||
60
- readFileSync(current, "utf8") !== readFileSync(pin, "utf8") ||
61
- stableDigest(readJsonRecord(current, "reclaim reservation")) !== stableDigest(lease.owner)) {
62
- throw new Error("workspace reclaim reservation owner changed");
63
- }
64
- const persisted = readJsonRecord(join(dirname(dirname(path)), claim.binding_id, "claim.json"), "reserved workspace claim");
65
- if (stableDigest(persisted) !== stableDigest(claim)) {
66
- throw new Error("workspace reclaim reservation claim changed");
67
- }
68
- },
69
- release: () => lease.release(),
70
- };
71
- }
72
- export function publishWorkspaceClaim(coordRoot, claim, publish) {
73
- assertClaimAuthority(claim, claim.provider_id, claim.binding_id);
74
- return withPublicationGate(coordRoot, claim.provider_id, () => {
75
- for (const entry of readdirSync(leaseRoot(coordRoot, claim.provider_id), {
76
- withFileTypes: true,
77
- })) {
78
- if (!entry.name.startsWith("reclaim-") || !entry.name.endsWith(".lock"))
79
- continue;
80
- if (!entry.isDirectory())
81
- throw new Error("workspace reclaim reservation is not a directory");
82
- const path = join(leaseRoot(coordRoot, claim.provider_id), entry.name);
83
- const current = join(path, "current");
84
- try {
85
- lstatSync(current);
86
- }
87
- catch (error) {
88
- if (error.code === "ENOENT")
89
- continue;
90
- throw error;
91
- }
92
- const id = entry.name.slice("reclaim-".length, -".lock".length);
93
- const reserved = readJsonRecord(join(dirname(leaseRoot(coordRoot, claim.provider_id)), id, "claim.json"), "reserved workspace claim");
94
- assertClaimAuthority(reserved, claim.provider_id, id);
95
- // Unknown reservation authority is never interpreted as an unrelated owner.
96
- const owner = readJsonRecord(current, "reclaim reservation");
97
- if (owner.schema_version !== 1 ||
98
- typeof owner.owner_id !== "string" ||
99
- !/^[a-f0-9-]{36}$/.test(owner.owner_id) ||
100
- owner.owner_file !== `owner-${owner.owner_id}.json` ||
101
- !Number.isSafeInteger(owner.pid) ||
102
- owner.pid <= 0 ||
103
- typeof owner.host !== "string" ||
104
- owner.host.length === 0 ||
105
- !Number.isFinite(Date.parse(owner.created_at)) ||
106
- !Number.isFinite(Date.parse(owner.expires_at)) ||
107
- Date.parse(owner.expires_at) < Date.parse(owner.created_at) ||
108
- owner.scope !== RESERVATION_SCOPE ||
109
- owner.authority_sha256 !== stableDigest(reserved) ||
110
- owner.metadata?.binding_id !== id ||
111
- owner.metadata?.request_sha256 !== reserved.request_sha256) {
112
- throw new Error("workspace reclaim reservation authority is unproven");
113
- }
114
- const a = lstatSync(current, { bigint: true });
115
- const pin = join(path, owner.owner_file);
116
- const b = lstatSync(pin, { bigint: true });
117
- if (!a.isFile() ||
118
- !b.isFile() ||
119
- a.dev !== b.dev ||
120
- a.ino !== b.ino ||
121
- readFileSync(current, "utf8") !== readFileSync(pin, "utf8"))
122
- throw new Error("workspace reclaim reservation owner is unproven");
123
- if (!claimOverlapsWorkspace(claim, reserved.workspace_root))
124
- continue;
125
- // This succeeds only for an expired, provably dead, exact prior owner.
126
- // It retires the reservation, never the immutable claim or resource.
127
- const recovered = acquireReservation(coordRoot, reserved);
128
- recovered.release();
129
- }
130
- return publish();
131
- });
132
- }
133
6
  export function assertClaimAuthority(claim, providerId, id) {
134
7
  if (claim?.schema_version !== 1 ||
135
8
  !/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(providerId) ||
@@ -14,11 +14,10 @@
14
14
  * always has. So reclaim adds no second removal path that could diverge from the
15
15
  * audited one, and a force-delete of live work exists nowhere in the codebase.
16
16
  */
17
- import type { WorkflowRecoveryAuthorization } from "../recovery-audit.js";
18
17
  import type { WorkflowLiveness } from "./recovery.js";
19
18
  import type { WorkspaceCleanupAttempt, WorkspaceCleanupReceipt } from "./types.js";
20
19
  export type ReclaimMode = "salvage" | "discard";
21
- export type WorkflowReclaimRefusalCode = "workflow_reclaim_run_live" | "workflow_reclaim_liveness_unknown" | "workflow_reclaim_recovery_mismatch" | "workflow_reclaim_ownership_unproven" | "workflow_reclaim_lease_held";
20
+ export type WorkflowReclaimRefusalCode = "workflow_reclaim_run_live" | "workflow_reclaim_liveness_unknown" | "workflow_reclaim_ownership_unproven" | "workflow_reclaim_lease_held";
22
21
  export declare class WorkflowReclaimError extends Error {
23
22
  readonly code: WorkflowReclaimRefusalCode;
24
23
  constructor(code: WorkflowReclaimRefusalCode, message: string);
@@ -26,9 +25,8 @@ export declare class WorkflowReclaimError extends Error {
26
25
  export interface WorkspaceReclaimOptions {
27
26
  mode: ReclaimMode;
28
27
  yes?: boolean;
29
- unknownLiveness?: WorkflowRecoveryAuthorization & {
30
- evidenceSha256: string;
31
- };
28
+ /** Admit missing or corrupt liveness evidence; active evidence still refuses. */
29
+ force?: boolean;
32
30
  }
33
31
  export interface ReclaimLeaseHolder {
34
32
  scope: "binding" | "repository" | "resume";
@@ -42,7 +40,6 @@ export interface WorkspaceReclaimPreview {
42
40
  run_id: string;
43
41
  mode: ReclaimMode;
44
42
  liveness: WorkflowLiveness;
45
- evidence_sha256: string;
46
43
  ownership: "ok" | "unproven";
47
44
  ownership_detail?: string;
48
45
  dirty_paths: string[] | null;
@@ -72,7 +69,7 @@ export interface PrepareReclaimInput {
72
69
  worktreePath: string;
73
70
  mode: ReclaimMode;
74
71
  runId: string;
75
- /** Revalidate the held reservation and peer authority immediately before effects. */
72
+ /** Recheck peer authority once, immediately before the first destructive step. */
76
73
  beforeEffect?: () => void;
77
74
  }
78
75
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/reclaim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEnF,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,0BAA0B,GAClC,2BAA2B,GAC3B,mCAAmC,GACnC,oCAAoC,GACpC,qCAAqC,GACrC,6BAA6B,CAAC;AAElC,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,IAAI,EAAE,0BAA0B;gBAAhC,IAAI,EAAE,0BAA0B,EACzC,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,6BAA6B,GAAG;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9E;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,UAAU,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,kBAAkB,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,CAAC,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,GAAG;IACzC,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,OAAO,EAAE,uBAAuB,GAAG,uBAAuB,CAAC;CAC5D,CAAC,CAAC;AAEP,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,kBAAkB,CAwD7E;AAYD;qEACqE;AACrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
1
+ {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/reclaim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEnF,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,0BAA0B,GAClC,2BAA2B,GAC3B,mCAAmC,GACnC,qCAAqC,GACrC,6BAA6B,CAAC;AAElC,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,IAAI,EAAE,0BAA0B;gBAAhC,IAAI,EAAE,0BAA0B,EACzC,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,IAAI,GAAG,UAAU,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,kBAAkB,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,CAAC,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,GAAG;IACzC,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,OAAO,EAAE,uBAAuB,GAAG,uBAAuB,CAAC;CAC5D,CAAC,CAAC;AAEP,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,kBAAkB,CAoD7E;AAYD;qEACqE;AACrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -51,7 +51,6 @@ export function prepareReclaim(input) {
51
51
  // cannot see. Running clean first would leave staged deletions behind.
52
52
  input.beforeEffect?.();
53
53
  git(input.worktreePath, ["reset", "--hard"]);
54
- input.beforeEffect?.();
55
54
  git(input.worktreePath, ["clean", "-fd"]);
56
55
  return { action: "discarded", detail: "uncommitted changes were discarded on request" };
57
56
  }
@@ -71,13 +70,10 @@ export function prepareReclaim(input) {
71
70
  const before = git(input.worktreePath, ["rev-parse", "HEAD"]).trim();
72
71
  input.beforeEffect?.();
73
72
  git(input.worktreePath, ["add", "-A"]);
74
- input.beforeEffect?.();
75
73
  git(input.worktreePath, ["commit", "--no-verify", "-m", salvageMessage(input.runId)]);
76
74
  const commit = git(input.worktreePath, ["rev-parse", "HEAD"]).trim();
77
75
  const branch = salvageBranch(input.runId);
78
- input.beforeEffect?.();
79
76
  git(input.worktreePath, ["branch", "--force", branch, commit]);
80
- input.beforeEffect?.();
81
77
  git(input.worktreePath, ["reset", "--hard", before]);
82
78
  return {
83
79
  action: "salvaged",
@@ -1,5 +1,5 @@
1
1
  export type WorkflowLiveness = "active" | "inactive" | "unknown";
2
- /** Corruption must not hide a readable active marker from an audited override. */
2
+ /** Corruption must not hide a readable active marker from a forced reclaim. */
3
3
  export declare function hasActiveWorkflowEvidence(coordRoot: string, runId: string): boolean;
4
4
  export declare function readWorkflowLiveness(coordRoot: string, runId: string): WorkflowLiveness;
5
5
  //# sourceMappingURL=recovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/recovery.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAoBnF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CA6DvF"}
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/recovery.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE,+EAA+E;AAC/E,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAoBnF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CA6DvF"}
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import { readWorkflowProof } from "../proof.js";
4
- /** Corruption must not hide a readable active marker from an audited override. */
4
+ /** Corruption must not hide a readable active marker from a forced reclaim. */
5
5
  export function hasActiveWorkflowEvidence(coordRoot, runId) {
6
6
  const path = join(resolve(coordRoot), ".harnery", "workflows", runId, "transcript.jsonl");
7
7
  if (!existsSync(path))
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/core/workflow/workspaces/state.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readd
2
2
  import { dirname, join, resolve } from "node:path";
3
3
  import { stateDirMode, stateFileMode } from "../../storage/modes.js";
4
4
  import { canonicalJson, fsyncParentDirectory, readJsonRecord, stableDigest, writeImmutableJson, } from "../durable-record.js";
5
- import { assertClaimAuthority, publishWorkspaceClaim } from "./ownership.js";
5
+ import { assertClaimAuthority } from "./ownership.js";
6
6
  export { appendWorkflowTranscriptEvent } from "../transcript.js";
7
7
  const JSON_LIMIT = 512 * 1024;
8
8
  const WORKSPACE_EVENT_BYTES = 32 * 1024;
@@ -40,9 +40,6 @@ export function readWorkspaceRequest(coordRoot, runId) {
40
40
  : undefined;
41
41
  }
42
42
  export function writeWorkspaceClaim(coordRoot, claim) {
43
- return publishWorkspaceClaim(coordRoot, claim, () => writeClaim(coordRoot, claim));
44
- }
45
- function writeClaim(coordRoot, claim) {
46
43
  const path = workspaceClaimPath(coordRoot, claim.provider_id, claim.binding_id);
47
44
  try {
48
45
  return writeImmutableJson(path, claim);
@@ -1 +1 @@
1
- {"version":3,"file":"assume.d.ts","sourceRoot":"","sources":["../../../src/lib/identities/assume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA0BH,MAAM,MAAM,uBAAuB,GAC/B,eAAe,GACf,iBAAiB,GACjB,sBAAsB,GACtB,oBAAoB,GACpB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,mBAAmB,CAAC;AAExB,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,IAAI,EAAE,uBAAuB;gBAA7B,IAAI,EAAE,uBAAuB,EAC7C,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAOD;+EAC+E;AAC/E,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,SAAa,EAClB,mBAAmB,GAAE,WAAW,CAAC,MAAM,CAAa,GACnD,gBAAgB,GAAG,IAAI,CA6BzB;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CA6CT;AAuED,gEAAgE;AAChE,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,oBAAoB,CAyHtB"}
1
+ {"version":3,"file":"assume.d.ts","sourceRoot":"","sources":["../../../src/lib/identities/assume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA0BH,MAAM,MAAM,uBAAuB,GAC/B,eAAe,GACf,iBAAiB,GACjB,sBAAsB,GACtB,oBAAoB,GACpB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,mBAAmB,CAAC;AAExB,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,IAAI,EAAE,uBAAuB;gBAA7B,IAAI,EAAE,uBAAuB,EAC7C,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAOD;+EAC+E;AAC/E,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,SAAa,EAClB,mBAAmB,GAAE,WAAW,CAAC,MAAM,CAAa,GACnD,gBAAgB,GAAG,IAAI,CA6BzB;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAyCT;AAuED,gEAAgE;AAChE,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,oBAAoB,CAyHtB"}
@@ -85,7 +85,6 @@ export function reclaimAbandonedLocalConflict(coordRoot, conflict) {
85
85
  let sessionId = conflict.instance_id;
86
86
  let ageSecs;
87
87
  const liveRow = readLiveCoordinationRow(coordRoot, conflict.instance_id);
88
- let expectedGenerationId = liveRow?.v3_generation_id ?? null;
89
88
  if (liveRow) {
90
89
  adapter = adapterOf(liveRow.platform);
91
90
  sessionId = liveRow.session_id || conflict.instance_id;
@@ -100,10 +99,8 @@ export function reclaimAbandonedLocalConflict(coordRoot, conflict) {
100
99
  // It is required to join the exact producer state when recording the sweep.
101
100
  adapter = adapterOf(hb.platform);
102
101
  sessionId = hb.session_id || conflict.instance_id;
103
- expectedGenerationId = hb.v3_generation_id ?? null;
104
102
  }
105
103
  catch {
106
- expectedGenerationId = null;
107
104
  /* content unreadable — still reclaim the file */
108
105
  }
109
106
  try {
@@ -119,7 +116,6 @@ export function reclaimAbandonedLocalConflict(coordRoot, conflict) {
119
116
  owner: conflict.instance_id,
120
117
  nativeSessionId: sessionId,
121
118
  adapter,
122
- expectedGenerationId,
123
119
  observation: "stale_heartbeat",
124
120
  ageMs: Math.max(0, (ageSecs ?? 0) * 1_000),
125
121
  });
@@ -32,12 +32,10 @@ export interface TunnelState {
32
32
  provider: TunnelProvider;
33
33
  url: string;
34
34
  gate_pid: number;
35
- gate_start_token?: string;
36
- cloudflared_start_token?: string;
37
- registration_id?: string;
38
- provider_state?: "pending" | "ready";
39
35
  /** Present for Cloudflare quick tunnels; absent for Tailscale Serve/Funnel. */
40
36
  cloudflared_pid?: number;
37
+ /** Optional provider-side process when a provider owns one. */
38
+ provider_pid?: number;
41
39
  started_at: string;
42
40
  target: string;
43
41
  vhost: string;
@@ -59,14 +57,9 @@ export declare function clearState(name?: string, root?: string): void;
59
57
  */
60
58
  export declare function listStates(root?: string): TunnelState[];
61
59
  export declare function isProcessAlive(pid: number): boolean;
62
- export type TunnelReadiness = "ready" | "dead" | "unknown";
63
- export type TunnelProcessObservation = "same" | "absent" | "different" | "unknown";
64
- export interface TunnelReadinessVerifier {
65
- observeProcess(pid: number, originalToken: string): TunnelProcessObservation;
66
- withRegistration(state: TunnelState, inspect: () => TunnelReadiness): TunnelReadiness;
67
- }
68
- /** Classify saved original witnesses under the verifier's registration custody. */
69
- export declare function tunnelReadiness(state: TunnelState, verifier: TunnelReadinessVerifier): TunnelReadiness;
60
+ export type ProcessAliveCheck = (pid: number) => boolean;
61
+ /** True when both the local gate and its provider-side process are live. */
62
+ export declare function isTunnelStateLive(state: TunnelState, processAlive?: ProcessAliveCheck): boolean;
70
63
  export declare function tunnelTargetPort(state: TunnelState): number | null;
71
64
  /**
72
65
  * Newest live tunnel that serves `vhost` on the requested local web port.
@@ -79,7 +72,7 @@ export declare function tunnelTargetPort(state: TunnelState): number | null;
79
72
  * link 400s. Matching the vhost too keeps the returned tunnel the one that
80
73
  * actually serves the caller's origin.
81
74
  */
82
- export declare function findLiveTunnelForOrigin(port: number, vhost: string, root: string, verifier: TunnelReadinessVerifier): TunnelState | null;
75
+ export declare function findLiveTunnelForOrigin(port: number, vhost: string, root?: string, processAlive?: ProcessAliveCheck): TunnelState | null;
83
76
  /** True when the tunnel's path scope forwards every one of `paths`. */
84
77
  export declare function tunnelServesPaths(state: TunnelState, paths: readonly string[]): boolean;
85
78
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/lib/tunnel/state.ts"],"names":[],"mappings":"AAsBA,qGAAqG;AACrG,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,yEAAyE;AACzE,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,GAAE,MAAsB,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAGR;AAUD,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAW1C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAG9E;AAgBD,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACrC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAgBD,wBAAgB,UAAU,IAAI,YAAY,CAezC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEnD;AAED,wBAAgB,SAAS,CACvB,IAAI,GAAE,MAAyB,EAC/B,IAAI,GAAE,MAAsB,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,MAAsB,GAAG,IAAI,CAUjF;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAyB,EAAE,IAAI,GAAE,MAAsB,GAAG,IAAI,CAG9F;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAsB,GAAG,WAAW,EAAE,CAWtE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAC3D,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnF,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,wBAAwB,CAAC;IAC7E,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,GAAG,eAAe,CAAC;CACvF;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,uBAAuB,GAChC,eAAe,CA0CjB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAWlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,uBAAuB,GAChC,WAAW,GAAG,IAAI,CASpB;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAEvF;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,cAAc,GAAE,MAAM,GAAG,SAAyC,GACjE,MAAM,CAoDR"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/lib/tunnel/state.ts"],"names":[],"mappings":"AAoBA,qGAAqG;AACrG,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,yEAAyE;AACzE,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,GAAE,MAAsB,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAGR;AAUD,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAW1C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAG9E;AAgBD,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAgBD,wBAAgB,UAAU,IAAI,YAAY,CAezC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEnD;AAED,wBAAgB,SAAS,CACvB,IAAI,GAAE,MAAyB,EAC/B,IAAI,GAAE,MAAsB,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,MAAsB,GAAG,IAAI,CAEjF;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAyB,EAAE,IAAI,GAAE,MAAsB,GAAG,IAAI,CAG9F;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAsB,GAAG,WAAW,EAAE,CAWtE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;AAEzD,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,YAAY,GAAE,iBAAkC,GAC/C,OAAO,CAKT;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAWlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,MAAsB,EAC5B,YAAY,GAAE,iBAAkC,GAC/C,WAAW,GAAG,IAAI,CASpB;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAEvF;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,cAAc,GAAE,MAAM,GAAG,SAAyC,GACjE,MAAM,CAoDR"}
@@ -1,8 +1,7 @@
1
1
  // Tunnel config + state persistence + provider helpers. Commands default to
2
2
  // <cwd>/.cache/tunnel/; gitignored, so the allowlist is per-machine.
3
3
  import { spawnSync } from "node:child_process";
4
- import { randomUUID } from "node:crypto";
5
- import { accessSync, chmodSync, constants, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
4
+ import { accessSync, chmodSync, constants, existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
6
5
  import { homedir } from "node:os";
7
6
  import { delimiter, join, resolve } from "node:path";
8
7
  import { isPathAllowed } from "./path-scope.js";
@@ -105,17 +104,7 @@ export function readState(name = DEFAULT_INSTANCE, root = process.cwd()) {
105
104
  }
106
105
  }
107
106
  export function writeState(state, root = process.cwd()) {
108
- const path = cachePath(stateFile(state.name), root);
109
- const temporary = `${path}.${randomUUID()}.tmp`;
110
- try {
111
- writeFileSync(temporary, JSON.stringify(state, null, 2), { flag: "wx", mode: 0o600 });
112
- renameSync(temporary, path);
113
- }
114
- catch (error) {
115
- if (existsSync(temporary))
116
- unlinkSync(temporary);
117
- throw error;
118
- }
107
+ writeFileSync(cachePath(stateFile(state.name), root), JSON.stringify(state, null, 2));
119
108
  }
120
109
  export function clearState(name = DEFAULT_INSTANCE, root = process.cwd()) {
121
110
  const p = cachePath(stateFile(name), root);
@@ -150,49 +139,14 @@ export function isProcessAlive(pid) {
150
139
  return false;
151
140
  }
152
141
  }
153
- /** Classify saved original witnesses under the verifier's registration custody. */
154
- export function tunnelReadiness(state, verifier) {
155
- if (!state ||
156
- typeof state !== "object" ||
157
- Object.hasOwn(state, "provider_pid") ||
158
- Object.hasOwn(state, "provider_start_token") ||
159
- typeof state.registration_id !== "string" ||
160
- !state.registration_id ||
161
- !Number.isSafeInteger(state.gate_pid) ||
162
- state.gate_pid < 1 ||
163
- typeof state.gate_start_token !== "string" ||
164
- !state.gate_start_token)
165
- return "unknown";
166
- const targets = [{ pid: state.gate_pid, token: state.gate_start_token }];
167
- if (state.provider === "tailscale") {
168
- if (state.provider_state !== "ready" ||
169
- state.cloudflared_pid !== undefined ||
170
- state.cloudflared_start_token !== undefined)
171
- return "unknown";
172
- }
173
- else if (state.provider === "cloudflare") {
174
- if (!Number.isSafeInteger(state.cloudflared_pid) ||
175
- state.cloudflared_pid < 1 ||
176
- typeof state.cloudflared_start_token !== "string" ||
177
- !state.cloudflared_start_token)
178
- return "unknown";
179
- targets.push({ pid: state.cloudflared_pid, token: state.cloudflared_start_token });
180
- }
181
- else
182
- return "unknown";
183
- try {
184
- return verifier.withRegistration(state, () => {
185
- const observed = targets.map(({ pid, token }) => verifier.observeProcess(pid, token));
186
- if (observed.every((value) => value === "absent"))
187
- return "dead";
188
- if (observed.every((value) => value === "same"))
189
- return "ready";
190
- return "unknown";
191
- });
192
- }
193
- catch {
194
- return "unknown";
195
- }
142
+ /** True when both the local gate and its provider-side process are live. */
143
+ export function isTunnelStateLive(state, processAlive = isProcessAlive) {
144
+ if (!processAlive(state.gate_pid))
145
+ return false;
146
+ if (state.provider === "tailscale")
147
+ return true;
148
+ const providerPid = state.cloudflared_pid ?? state.provider_pid;
149
+ return typeof providerPid === "number" && processAlive(providerPid);
196
150
  }
197
151
  export function tunnelTargetPort(state) {
198
152
  const value = /^[a-z][a-z\d+.-]*:\/\//i.test(state.target)
@@ -219,10 +173,10 @@ export function tunnelTargetPort(state) {
219
173
  * link 400s. Matching the vhost too keeps the returned tunnel the one that
220
174
  * actually serves the caller's origin.
221
175
  */
222
- export function findLiveTunnelForOrigin(port, vhost, root, verifier) {
176
+ export function findLiveTunnelForOrigin(port, vhost, root = process.cwd(), processAlive = isProcessAlive) {
223
177
  return (listStates(root).find((state) => tunnelTargetPort(state) === port &&
224
178
  state.vhost === vhost &&
225
- tunnelReadiness(state, verifier) === "ready") ?? null);
179
+ isTunnelStateLive(state, processAlive)) ?? null);
226
180
  }
227
181
  /** True when the tunnel's path scope forwards every one of `paths`. */
228
182
  export function tunnelServesPaths(state, paths) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harnery",
3
- "version": "0.45.0",
3
+ "version": "0.45.2",
4
4
  "description": "Multi-agent coordination for AI coding agents - Claude Code, Cursor, and Codex.",
5
5
  "license": "MIT",
6
6
  "author": "Ryan Kelly",
@@ -67,11 +67,6 @@
67
67
  "types": "./dist/core/context/index.d.ts",
68
68
  "import": "./dist/core/context/index.js"
69
69
  },
70
- "./core/turn-rollback": {
71
- "bun": "./src/core/turn-rollback/index.ts",
72
- "types": "./dist/core/turn-rollback/index.d.ts",
73
- "import": "./dist/core/turn-rollback/index.js"
74
- },
75
70
  "./core/workflow": {
76
71
  "bun": "./src/core/workflow/index.ts",
77
72
  "types": "./dist/core/workflow/index.d.ts",
package/src/commander.ts CHANGED
@@ -795,16 +795,6 @@ function harneryCommandBundles({
795
795
  load: async (program) =>
796
796
  (await import("./commands/workflow.ts")).registerWorkflowCommand(program, emit),
797
797
  },
798
- lazy(
799
- "turn-rollback",
800
- "Capture and review exact turn paths before restoring owned content.",
801
- async (program) =>
802
- (await import("./commands/turn-rollback.ts")).registerTurnRollbackCommand(
803
- program,
804
- emit,
805
- context,
806
- ),
807
- ),
808
798
  lazy("work", "Track durable objectives across bounded workflow attempts.", async (program) =>
809
799
  (await import("./commands/work.ts")).registerWorkCommand(program, emit),
810
800
  ),
@@ -4,7 +4,6 @@ import type { Command } from "commander";
4
4
  import type { EmitContext, HarneryProgramContext } from "../commander.ts";
5
5
  import { resolveCoordRoot } from "../core/agents/coord-client.ts";
6
6
  import { DEFAULT_WEB_PORT, resolveWebPort } from "../core/config.ts";
7
- import { createTunnelReadinessVerifier } from "../core/servers/index.ts";
8
7
  import { coordRootId, localCoordRootIdUrl } from "../lib/coord-root-id.ts";
9
8
  import {
10
9
  encodedRepoPath,
@@ -15,10 +14,10 @@ import {
15
14
  } from "../lib/local-file-url.ts";
16
15
  import { isPathAllowed } from "../lib/tunnel/path-scope.ts";
17
16
  import {
17
+ isTunnelStateLive,
18
18
  listStates,
19
- type TunnelReadinessVerifier,
19
+ type ProcessAliveCheck,
20
20
  type TunnelState,
21
- tunnelReadiness,
22
21
  tunnelTargetPort,
23
22
  } from "../lib/tunnel/state.ts";
24
23
 
@@ -209,10 +208,10 @@ export function tunnelFileUrl(
209
208
  local: LocalFileUrl,
210
209
  port: number,
211
210
  states: TunnelState[],
212
- verifier: TunnelReadinessVerifier,
211
+ processAlive?: ProcessAliveCheck,
213
212
  ): string {
214
213
  const live = states.filter(
215
- (state) => tunnelTargetPort(state) === port && tunnelReadiness(state, verifier) === "ready",
214
+ (state) => tunnelTargetPort(state) === port && isTunnelStateLive(state, processAlive),
216
215
  );
217
216
  if (local.mode === "raw") {
218
217
  const path = `/${encodedRepoPath(local.relPath)}`;
@@ -310,14 +309,7 @@ export function registerFilesCommand(
310
309
  mode: opts.raw ? "raw" : opts.viewer ? "viewer" : "auto",
311
310
  });
312
311
  if (opts.verify !== false) await verifyDashboardRoot(coordRoot, port);
313
- const url = opts.tunnel
314
- ? tunnelFileUrl(
315
- result,
316
- port,
317
- listStates(coordRoot),
318
- createTunnelReadinessVerifier({ coordRoot }),
319
- )
320
- : result.url;
312
+ const url = opts.tunnel ? tunnelFileUrl(result, port, listStates(coordRoot)) : result.url;
321
313
  emit.text(`${url}\n`);
322
314
  } catch (error) {
323
315
  if (error instanceof TunnelLinkError) {
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { hostname } from "node:os";
2
3
  import type { Command } from "commander";
3
4
  import type { EmitContext, HarneryProgramContext } from "../commander.ts";
4
5
  import { resolveCoordRoot } from "../core/agents/coord-client.ts";
@@ -110,13 +111,23 @@ export function registerServersCommand(
110
111
  const preview = Boolean(options.type) && !options.yes;
111
112
  const results: Array<StopResult | { id: string; would_stop: true }> = [];
112
113
  for (const stray of strays) {
113
- const receipt = adoptServer(stray.pid, {
114
- coordRoot,
115
- type: "unregistered",
116
- owner: "none",
117
- dependencies: { listServers: () => report },
118
- });
119
- results.push(await stopServer(receipt, { coordRoot }));
114
+ results.push(
115
+ await stopServer(
116
+ {
117
+ schema_version: 1,
118
+ id: `pid-${stray.pid}`,
119
+ kind: "session",
120
+ type: "unregistered",
121
+ label: stray.command,
122
+ pid: stray.pid,
123
+ ...(stray.start_token ? { start_token: stray.start_token } : {}),
124
+ host: hostname(),
125
+ started_at: new Date().toISOString(),
126
+ registered_at: new Date().toISOString(),
127
+ },
128
+ { coordRoot },
129
+ ),
130
+ );
120
131
  }
121
132
  for (const view of selected) {
122
133
  if (preview && !ids.includes(view.record.id))
@@ -397,14 +408,14 @@ export function registerServersCommand(
397
408
 
398
409
  cmd
399
410
  .command("unregister <id>")
400
- .description("Remove the exact observed server registration (optionally require --pid)")
411
+ .description("Remove a server's record (with --pid, only if the record still names that pid)")
401
412
  .option("--pid <pid>", "Only remove when the record names this pid")
402
413
  .action((id: string, options: { pid?: string }) => {
403
414
  try {
404
- const coordRoot = root();
405
- const record = readServer(id, { coordRoot });
406
- const matchesPid = !options.pid || record?.pid === integer(options.pid, "--pid");
407
- const removed = !!record && matchesPid && unregisterServer(record, { coordRoot });
415
+ const removed = unregisterServer(id, {
416
+ coordRoot: root(),
417
+ ...(options.pid ? { pid: integer(options.pid, "--pid") } : {}),
418
+ });
408
419
  emit.config({ format: "json" });
409
420
  emit.data({ id, removed });
410
421
  } catch (error) {