agy-worker-mcp 0.3.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 (227) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/LICENSE +21 -0
  3. package/README.md +309 -0
  4. package/commands/agy-ceiling.md +31 -0
  5. package/dist/broker/blockers.d.ts +86 -0
  6. package/dist/broker/blockers.d.ts.map +1 -0
  7. package/dist/broker/blockers.js +390 -0
  8. package/dist/broker/blockers.js.map +1 -0
  9. package/dist/broker/outcome.d.ts +85 -0
  10. package/dist/broker/outcome.d.ts.map +1 -0
  11. package/dist/broker/outcome.js +147 -0
  12. package/dist/broker/outcome.js.map +1 -0
  13. package/dist/broker/reconcile.d.ts +74 -0
  14. package/dist/broker/reconcile.d.ts.map +1 -0
  15. package/dist/broker/reconcile.js +415 -0
  16. package/dist/broker/reconcile.js.map +1 -0
  17. package/dist/broker/result.d.ts +88 -0
  18. package/dist/broker/result.d.ts.map +1 -0
  19. package/dist/broker/result.js +234 -0
  20. package/dist/broker/result.js.map +1 -0
  21. package/dist/broker/verify.d.ts +52 -0
  22. package/dist/broker/verify.d.ts.map +1 -0
  23. package/dist/broker/verify.js +174 -0
  24. package/dist/broker/verify.js.map +1 -0
  25. package/dist/contract/errors.d.ts +119 -0
  26. package/dist/contract/errors.d.ts.map +1 -0
  27. package/dist/contract/errors.js +99 -0
  28. package/dist/contract/errors.js.map +1 -0
  29. package/dist/contract/index.d.ts +10 -0
  30. package/dist/contract/index.d.ts.map +1 -0
  31. package/dist/contract/index.js +10 -0
  32. package/dist/contract/index.js.map +1 -0
  33. package/dist/contract/paths.d.ts +139 -0
  34. package/dist/contract/paths.d.ts.map +1 -0
  35. package/dist/contract/paths.js +359 -0
  36. package/dist/contract/paths.js.map +1 -0
  37. package/dist/contract/schema.sql +64 -0
  38. package/dist/contract/types.d.ts +1113 -0
  39. package/dist/contract/types.d.ts.map +1 -0
  40. package/dist/contract/types.js +114 -0
  41. package/dist/contract/types.js.map +1 -0
  42. package/dist/events/cursor.d.ts +65 -0
  43. package/dist/events/cursor.d.ts.map +1 -0
  44. package/dist/events/cursor.js +286 -0
  45. package/dist/events/cursor.js.map +1 -0
  46. package/dist/events/detect.d.ts +58 -0
  47. package/dist/events/detect.d.ts.map +1 -0
  48. package/dist/events/detect.js +183 -0
  49. package/dist/events/detect.js.map +1 -0
  50. package/dist/events/normalize.d.ts +30 -0
  51. package/dist/events/normalize.d.ts.map +1 -0
  52. package/dist/events/normalize.js +158 -0
  53. package/dist/events/normalize.js.map +1 -0
  54. package/dist/events/parse.d.ts +41 -0
  55. package/dist/events/parse.d.ts.map +1 -0
  56. package/dist/events/parse.js +89 -0
  57. package/dist/events/parse.js.map +1 -0
  58. package/dist/gate/bind.d.ts +28 -0
  59. package/dist/gate/bind.d.ts.map +1 -0
  60. package/dist/gate/bind.js +154 -0
  61. package/dist/gate/bind.js.map +1 -0
  62. package/dist/gate/gate.d.ts +139 -0
  63. package/dist/gate/gate.d.ts.map +1 -0
  64. package/dist/gate/gate.js +488 -0
  65. package/dist/gate/gate.js.map +1 -0
  66. package/dist/gate/hooks-file.d.ts +55 -0
  67. package/dist/gate/hooks-file.d.ts.map +1 -0
  68. package/dist/gate/hooks-file.js +104 -0
  69. package/dist/gate/hooks-file.js.map +1 -0
  70. package/dist/gate.d.ts +3 -0
  71. package/dist/gate.d.ts.map +1 -0
  72. package/dist/gate.js +20 -0
  73. package/dist/gate.js.map +1 -0
  74. package/dist/policy/ceiling-review.d.ts +22 -0
  75. package/dist/policy/ceiling-review.d.ts.map +1 -0
  76. package/dist/policy/ceiling-review.js +170 -0
  77. package/dist/policy/ceiling-review.js.map +1 -0
  78. package/dist/policy/ceiling.d.ts +128 -0
  79. package/dist/policy/ceiling.d.ts.map +1 -0
  80. package/dist/policy/ceiling.js +273 -0
  81. package/dist/policy/ceiling.js.map +1 -0
  82. package/dist/policy/containment.d.ts +100 -0
  83. package/dist/policy/containment.d.ts.map +1 -0
  84. package/dist/policy/containment.js +1071 -0
  85. package/dist/policy/containment.js.map +1 -0
  86. package/dist/policy/hard-deny.d.ts +28 -0
  87. package/dist/policy/hard-deny.d.ts.map +1 -0
  88. package/dist/policy/hard-deny.js +78 -0
  89. package/dist/policy/hard-deny.js.map +1 -0
  90. package/dist/policy/profiles.d.ts +82 -0
  91. package/dist/policy/profiles.d.ts.map +1 -0
  92. package/dist/policy/profiles.js +317 -0
  93. package/dist/policy/profiles.js.map +1 -0
  94. package/dist/policy/rules.d.ts +138 -0
  95. package/dist/policy/rules.d.ts.map +1 -0
  96. package/dist/policy/rules.js +1180 -0
  97. package/dist/policy/rules.js.map +1 -0
  98. package/dist/policy/seatbelt.d.ts +32 -0
  99. package/dist/policy/seatbelt.d.ts.map +1 -0
  100. package/dist/policy/seatbelt.js +59 -0
  101. package/dist/policy/seatbelt.js.map +1 -0
  102. package/dist/policy/tools.d.ts +36 -0
  103. package/dist/policy/tools.d.ts.map +1 -0
  104. package/dist/policy/tools.js +94 -0
  105. package/dist/policy/tools.js.map +1 -0
  106. package/dist/runner/gate-watchdog.d.ts +93 -0
  107. package/dist/runner/gate-watchdog.d.ts.map +1 -0
  108. package/dist/runner/gate-watchdog.js +153 -0
  109. package/dist/runner/gate-watchdog.js.map +1 -0
  110. package/dist/runner/idle.d.ts +51 -0
  111. package/dist/runner/idle.d.ts.map +1 -0
  112. package/dist/runner/idle.js +81 -0
  113. package/dist/runner/idle.js.map +1 -0
  114. package/dist/runner/inbox.d.ts +56 -0
  115. package/dist/runner/inbox.d.ts.map +1 -0
  116. package/dist/runner/inbox.js +134 -0
  117. package/dist/runner/inbox.js.map +1 -0
  118. package/dist/runner/reap.d.ts +65 -0
  119. package/dist/runner/reap.d.ts.map +1 -0
  120. package/dist/runner/reap.js +168 -0
  121. package/dist/runner/reap.js.map +1 -0
  122. package/dist/runner/runner.d.ts +51 -0
  123. package/dist/runner/runner.d.ts.map +1 -0
  124. package/dist/runner/runner.js +289 -0
  125. package/dist/runner/runner.js.map +1 -0
  126. package/dist/runner/spawn.d.ts +98 -0
  127. package/dist/runner/spawn.d.ts.map +1 -0
  128. package/dist/runner/spawn.js +230 -0
  129. package/dist/runner/spawn.js.map +1 -0
  130. package/dist/runner/verify.d.ts +24 -0
  131. package/dist/runner/verify.d.ts.map +1 -0
  132. package/dist/runner/verify.js +108 -0
  133. package/dist/runner/verify.js.map +1 -0
  134. package/dist/runner.d.ts +3 -0
  135. package/dist/runner.d.ts.map +1 -0
  136. package/dist/runner.js +15 -0
  137. package/dist/runner.js.map +1 -0
  138. package/dist/server/context.d.ts +41 -0
  139. package/dist/server/context.d.ts.map +1 -0
  140. package/dist/server/context.js +59 -0
  141. package/dist/server/context.js.map +1 -0
  142. package/dist/server/instructions.d.ts +13 -0
  143. package/dist/server/instructions.d.ts.map +1 -0
  144. package/dist/server/instructions.js +121 -0
  145. package/dist/server/instructions.js.map +1 -0
  146. package/dist/server/server.d.ts +20 -0
  147. package/dist/server/server.d.ts.map +1 -0
  148. package/dist/server/server.js +55 -0
  149. package/dist/server/server.js.map +1 -0
  150. package/dist/server/tools/cancel.d.ts +24 -0
  151. package/dist/server/tools/cancel.d.ts.map +1 -0
  152. package/dist/server/tools/cancel.js +59 -0
  153. package/dist/server/tools/cancel.js.map +1 -0
  154. package/dist/server/tools/capabilities.d.ts +36 -0
  155. package/dist/server/tools/capabilities.d.ts.map +1 -0
  156. package/dist/server/tools/capabilities.js +116 -0
  157. package/dist/server/tools/capabilities.js.map +1 -0
  158. package/dist/server/tools/ceiling.d.ts +31 -0
  159. package/dist/server/tools/ceiling.d.ts.map +1 -0
  160. package/dist/server/tools/ceiling.js +121 -0
  161. package/dist/server/tools/ceiling.js.map +1 -0
  162. package/dist/server/tools/index.d.ts +38 -0
  163. package/dist/server/tools/index.d.ts.map +1 -0
  164. package/dist/server/tools/index.js +115 -0
  165. package/dist/server/tools/index.js.map +1 -0
  166. package/dist/server/tools/listJobs.d.ts +30 -0
  167. package/dist/server/tools/listJobs.d.ts.map +1 -0
  168. package/dist/server/tools/listJobs.js +37 -0
  169. package/dist/server/tools/listJobs.js.map +1 -0
  170. package/dist/server/tools/logs.d.ts +31 -0
  171. package/dist/server/tools/logs.d.ts.map +1 -0
  172. package/dist/server/tools/logs.js +96 -0
  173. package/dist/server/tools/logs.js.map +1 -0
  174. package/dist/server/tools/result.d.ts +32 -0
  175. package/dist/server/tools/result.d.ts.map +1 -0
  176. package/dist/server/tools/result.js +95 -0
  177. package/dist/server/tools/result.js.map +1 -0
  178. package/dist/server/tools/send.d.ts +37 -0
  179. package/dist/server/tools/send.d.ts.map +1 -0
  180. package/dist/server/tools/send.js +71 -0
  181. package/dist/server/tools/send.js.map +1 -0
  182. package/dist/server/tools/sessions.d.ts +28 -0
  183. package/dist/server/tools/sessions.d.ts.map +1 -0
  184. package/dist/server/tools/sessions.js +54 -0
  185. package/dist/server/tools/sessions.js.map +1 -0
  186. package/dist/server/tools/start.d.ts +107 -0
  187. package/dist/server/tools/start.d.ts.map +1 -0
  188. package/dist/server/tools/start.js +482 -0
  189. package/dist/server/tools/start.js.map +1 -0
  190. package/dist/server/tools/wait.d.ts +29 -0
  191. package/dist/server/tools/wait.d.ts.map +1 -0
  192. package/dist/server/tools/wait.js +120 -0
  193. package/dist/server/tools/wait.js.map +1 -0
  194. package/dist/server.d.ts +3 -0
  195. package/dist/server.d.ts.map +1 -0
  196. package/dist/server.js +17 -0
  197. package/dist/server.js.map +1 -0
  198. package/dist/setup/install.d.ts +52 -0
  199. package/dist/setup/install.d.ts.map +1 -0
  200. package/dist/setup/install.js +108 -0
  201. package/dist/setup/install.js.map +1 -0
  202. package/dist/setup.d.ts +3 -0
  203. package/dist/setup.d.ts.map +1 -0
  204. package/dist/setup.js +24 -0
  205. package/dist/setup.js.map +1 -0
  206. package/dist/store/db.d.ts +49 -0
  207. package/dist/store/db.d.ts.map +1 -0
  208. package/dist/store/db.js +101 -0
  209. package/dist/store/db.js.map +1 -0
  210. package/dist/store/jobs.d.ts +45 -0
  211. package/dist/store/jobs.d.ts.map +1 -0
  212. package/dist/store/jobs.js +150 -0
  213. package/dist/store/jobs.js.map +1 -0
  214. package/dist/store/locks.d.ts +60 -0
  215. package/dist/store/locks.d.ts.map +1 -0
  216. package/dist/store/locks.js +172 -0
  217. package/dist/store/locks.js.map +1 -0
  218. package/dist/store/sessions.d.ts +37 -0
  219. package/dist/store/sessions.d.ts.map +1 -0
  220. package/dist/store/sessions.js +117 -0
  221. package/dist/store/sessions.js.map +1 -0
  222. package/dist/trace/digest.d.ts +77 -0
  223. package/dist/trace/digest.d.ts.map +1 -0
  224. package/dist/trace/digest.js +481 -0
  225. package/dist/trace/digest.js.map +1 -0
  226. package/package.json +68 -0
  227. package/skills/agy-ceiling/SKILL.md +72 -0
@@ -0,0 +1,74 @@
1
+ import type { JobRow } from '../contract/types.js';
2
+ import type { Store } from '../store/db.js';
3
+ /**
4
+ * The daemon replacement.
5
+ *
6
+ * Every MCP tool handler calls this first. It has to be cheap, idempotent, and
7
+ * guarded by `BEGIN IMMEDIATE` so two servers racing to finalize the same job
8
+ * write the result exactly once.
9
+ *
10
+ * | observation | action |
11
+ * | ---------------------------------------- | --------------------------------------------- |
12
+ * | `exit_code` exists, lifecycle = running | finalize → verify → outcome/headline → unlock |
13
+ * | pid gone, runner alive (`runner_pid`) | still running — the runner is in `verifying` |
14
+ * | | or its writeback window; leave it alone |
15
+ * | pid gone, runner gone, no `exit_code` | `process_error` (the runner was killed) |
16
+ * | `deadline_at` elapsed, pid alive | `timed_out` after killpg |
17
+ * | `deadline_at` elapsed, runner `verifying`| wait: verify has its own clock (backstop below)|
18
+ * | pid alive but start_time mismatch | pid reused → `orphaned` |
19
+ *
20
+ * `pid` is agy's, not the runner's (`spawn.ts`). Between agy's exit and the
21
+ * runner's final write the runner may be running `verify_command` for
22
+ * minutes (0.2.2 PR1): `state.json.phase === 'verifying'`
23
+ * with a live `state.json.runner_pid` is the only way to tell that apart from
24
+ * a lost runner, and every row above that would otherwise conclude "gone"
25
+ * checks it first.
26
+ *
27
+ * The order above is the order these are checked in, and it matters: `exit_code`
28
+ * existing always wins (even over a passed deadline — the runner beat us to it),
29
+ * and a passed deadline is checked before a pid-reuse mismatch. Among the last
30
+ * two, pid reuse is checked first: it is the only *positive* observation of the
31
+ * three, while "pid gone" covers both an ordinary exit and a lost runner.
32
+ */
33
+ export interface ReconcileOptions {
34
+ /** Freeze the clock in tests. */
35
+ now?: number;
36
+ /** Skip the (more expensive) verification pass; used by hot read-only paths. */
37
+ skipVerify?: boolean;
38
+ }
39
+ export interface ReconcileReport {
40
+ checked: number;
41
+ finalized: string[];
42
+ timedOut: string[];
43
+ orphaned: string[];
44
+ processErrors: string[];
45
+ locksReleased: number;
46
+ durationMs: number;
47
+ }
48
+ /** Sweep every live job. Safe to call on every tool invocation. */
49
+ export declare function reconcile(store: Store, opts?: ReconcileOptions): Promise<ReconcileReport>;
50
+ /**
51
+ * Reconcile one job and return its current row.
52
+ *
53
+ * A no-op when the job is already `finished`: a second caller arriving after
54
+ * finalization reads the existing `broker-result.json`, not rebuilds it.
55
+ */
56
+ export declare function reconcileJob(store: Store, job: JobRow, opts?: ReconcileOptions): Promise<JobRow>;
57
+ /**
58
+ * Finalize a job whose `exit_code` file has appeared: run verification, decide
59
+ * the outcome, write `broker-result.json`, set `lifecycle = 'finished'`, release
60
+ * locks. All inside one transaction.
61
+ *
62
+ * The job's *incoming* lifecycle carries one more fact: `'canceling'` means
63
+ * `agy_cancel` had already asked for this exit, so the outcome is `canceled`
64
+ * even though a normal exit code came back. `timedOut` carries the other one,
65
+ * from `state.json`: the runner's watchdog killed the group at the deadline,
66
+ * which is not an ordinary failure however the exit code reads.
67
+ */
68
+ export declare function finalizeJob(store: Store, job: JobRow, exitCode: number, nowMs: number, timedOut?: boolean): JobRow;
69
+ export type AbnormalKind = 'process_error' | 'orphaned' | 'timed_out';
70
+ /** Opportunistic cleanup of old job directories, triggered from `agy_start`. */
71
+ export declare function cleanupOldJobs(store: Store, maxAgeMs: number): number;
72
+ /** Convenience: reconcile one job by id, fetching its current row first. */
73
+ export declare function reconcileJobById(store: Store, jobId: string, opts?: ReconcileOptions): Promise<JobRow>;
74
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/broker/reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,MAAM,EAAgB,MAAM,sBAAsB,CAAA;AAMjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAO3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AA0BD,mEAAmE;AACnE,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA0C/F;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0GtG;AA0CD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,UAAQ,GACf,MAAM,CAiBR;AAED,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,UAAU,GAAG,WAAW,CAAA;AAmIrE,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoBrE;AA8BD,4EAA4E;AAC5E,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5G"}
@@ -0,0 +1,415 @@
1
+ import { readFileSync, rmSync } from 'node:fs';
2
+ import { jobPaths, readJsonIfExists } from '../contract/paths.js';
3
+ import { readLinesFrom } from '../events/cursor.js';
4
+ import { okEvents, parseEventLines } from '../events/parse.js';
5
+ import { removeGateHook } from '../gate/hooks-file.js';
6
+ import { checkProcessIdentity, isPidAlive, isSameProcess, killProcessGroup } from '../runner/reap.js';
7
+ import { now, transaction } from '../store/db.js';
8
+ import { getJob, listJobs, LIVE_LIFECYCLES, tryGetJob, updateJob } from '../store/jobs.js';
9
+ import { listLocks, releaseJobLocks } from '../store/locks.js';
10
+ import { bindConversationId, getSession } from '../store/sessions.js';
11
+ import { buildBrokerResult, writeBrokerResult } from './result.js';
12
+ /**
13
+ * How long the runner is given to write `exit_code` after its agy child is
14
+ * already gone. The runner only has to `writeFileAtomic` a couple of bytes from
15
+ * an `exit` handler, so this is generous; it only ever costs latency on a run
16
+ * that really did lose its runner.
17
+ */
18
+ const RUNNER_WRITEBACK_GRACE_MS = 1500;
19
+ /**
20
+ * How long past `deadline_at + verify.timeout_ms` a `verifying` runner is
21
+ * still trusted to finish on its own before reconcile stops deferring to it.
22
+ * The runner enforces `verify_timeout_ms` itself; this only bounds the case
23
+ * where that enforcement somehow never returns.
24
+ */
25
+ const VERIFY_BACKSTOP_MS = 60_000;
26
+ /** Lifecycles that can have a live process and so are worth reconciling. */
27
+ const RECONCILABLE_LIFECYCLES = [
28
+ 'queued',
29
+ 'starting',
30
+ 'running',
31
+ 'canceling',
32
+ ];
33
+ /** Sweep every live job. Safe to call on every tool invocation. */
34
+ export async function reconcile(store, opts) {
35
+ const start = Date.now();
36
+ const nowMs = opts?.now ?? now();
37
+ const candidates = listJobs(store, { lifecycle: [...RECONCILABLE_LIFECYCLES], limit: 10000 });
38
+ const locksBefore = listLocks(store).length;
39
+ const report = {
40
+ checked: 0,
41
+ finalized: [],
42
+ timedOut: [],
43
+ orphaned: [],
44
+ processErrors: [],
45
+ locksReleased: 0,
46
+ durationMs: 0,
47
+ };
48
+ for (const job of candidates) {
49
+ report.checked++;
50
+ const before = job.lifecycle;
51
+ const after = await reconcileJob(store, job, { ...opts, now: nowMs, skipVerify: opts?.skipVerify });
52
+ if (before === 'finished' || after.lifecycle !== 'finished')
53
+ continue;
54
+ switch (after.outcome) {
55
+ case 'timed_out':
56
+ report.timedOut.push(after.job_id);
57
+ break;
58
+ case 'orphaned':
59
+ report.orphaned.push(after.job_id);
60
+ break;
61
+ case 'process_error':
62
+ report.processErrors.push(after.job_id);
63
+ break;
64
+ default:
65
+ report.finalized.push(after.job_id);
66
+ }
67
+ }
68
+ const locksAfter = listLocks(store).length;
69
+ report.locksReleased = Math.max(0, locksBefore - locksAfter);
70
+ report.durationMs = Date.now() - start;
71
+ return report;
72
+ }
73
+ /**
74
+ * Reconcile one job and return its current row.
75
+ *
76
+ * A no-op when the job is already `finished`: a second caller arriving after
77
+ * finalization reads the existing `broker-result.json`, not rebuilds it.
78
+ */
79
+ export async function reconcileJob(store, job, opts) {
80
+ if (job.lifecycle === 'finished')
81
+ return job;
82
+ const nowMs = opts?.now ?? now();
83
+ const paths = jobPaths(store.paths, job.job_id);
84
+ // The runner (which must never import `src/server/**`) records pid/pgid/
85
+ // proc_start_time/lifecycle only in `state.json`; reconcile is the sole place
86
+ // that absorbs it into the jobs row, since nothing else reads it back.
87
+ job = ingestRunnerState(store, job, paths.state);
88
+ const exitCode = readExitCode(paths.exitCode);
89
+ if (exitCode !== null) {
90
+ // The runner's own watchdog may have produced this exit code by killing the
91
+ // process group at the deadline. Only `state.json` carries that fact — the
92
+ // exit code alone is indistinguishable from an ordinary failure.
93
+ const runnerTimedOut = readJsonIfExists(paths.state)?.timed_out === true;
94
+ return finalizeJob(store, job, exitCode, nowMs, runnerTimedOut);
95
+ }
96
+ // Row 3 (checked ahead of the pid-null early return): a deadline that has
97
+ // passed must finalize the job even when the runner never published a pid —
98
+ // otherwise a runner that fails to start (or dies before spawning agy) leaves
99
+ // the job, and its locks, live forever.
100
+ const state = readJsonIfExists(paths.state);
101
+ if (job.deadline_at !== null && nowMs >= job.deadline_at) {
102
+ // `verify_command` runs on its own clock, past `deadline_at` by design
103
+ // (`docs/tools.md`, `verify_timeout_ms`). A runner that is verifying is
104
+ // not late — until even the verify clock plus a backstop has run out.
105
+ if (runnerIsVerifying(state)) {
106
+ const config = readJsonIfExists(paths.effectiveConfig);
107
+ const verifyBudget = job.deadline_at + (config?.verify?.timeout_ms ?? 0) + VERIFY_BACKSTOP_MS;
108
+ if (nowMs < verifyBudget)
109
+ return job;
110
+ }
111
+ if (job.pid !== null &&
112
+ job.pgid !== null &&
113
+ isPidAlive(job.pid) &&
114
+ isSameProcess(job.pid, job.proc_start_time)) {
115
+ await killProcessGroup(job.pgid);
116
+ }
117
+ const exitAfterKill = await pollExitCode(paths.exitCode);
118
+ if (exitAfterKill !== null) {
119
+ // We killed it for the deadline, so the exit code it produced is a
120
+ // timeout's exit code, not a failure's.
121
+ return finalizeJob(store, job, exitAfterKill, now(), true);
122
+ }
123
+ return finalizeAbnormal(store, job, 'timed_out', now());
124
+ }
125
+ if (job.pid === null) {
126
+ // Not spawned yet (still `queued`/`starting`) and its deadline (if any)
127
+ // has not passed. Nothing observable to reconcile.
128
+ return job;
129
+ }
130
+ const identity = checkProcessIdentity(job.pid, job.proc_start_time);
131
+ // Row 4: pid alive, but the start-time token belongs to a *different*
132
+ // process. Checked before row 2 because it is the only positive conclusion of
133
+ // the three — `gone` covers both an ordinary exit and a lost runner, and
134
+ // telling those apart is row 2's job.
135
+ if (identity === 'different') {
136
+ return finalizeAbnormal(store, job, 'orphaned', nowMs);
137
+ }
138
+ // Row 2: pid gone, no exit_code file. The runner was killed before it could
139
+ // record a result.
140
+ //
141
+ // `agy` dying is NOT by itself evidence of that: between agy's exit and the
142
+ // runner's `writeExitCode` there is a short window in which the pid is
143
+ // already gone while a perfectly healthy run is about to record exit 0.
144
+ // Reading only `isPidAlive` here misclassifies every normally-finishing job
145
+ // caught in that window as `process_error`, which a caller polling reconcile
146
+ // in a loop hits reliably. So re-poll for the exit_code first, and only
147
+ // conclude the runner is lost once the grace elapses with nothing written.
148
+ if (identity === 'gone') {
149
+ // The runner is still there (verifying, or about to write `exit_code`):
150
+ // nothing is lost, and the next reconcile will find the exit code. Without
151
+ // this check every job whose verify outlived the grace below was judged
152
+ // `process_error` with a real exit 0 landing seconds later (audit `08`).
153
+ if (runnerIsAlive(state))
154
+ return job;
155
+ const exitAfterDeath = await pollExitCode(paths.exitCode, RUNNER_WRITEBACK_GRACE_MS);
156
+ if (exitAfterDeath !== null) {
157
+ return finalizeJob(store, job, exitAfterDeath, now());
158
+ }
159
+ return finalizeAbnormal(store, job, 'process_error', now());
160
+ }
161
+ // Row 5: the gate marked this job `canceling` (on_denial: 'abort'). The gate
162
+ // only marks it — reconcile owns the actual killpg, and does it here rather
163
+ // than waiting for the deadline.
164
+ if (job.lifecycle === 'canceling' && job.pgid !== null) {
165
+ await killProcessGroup(job.pgid);
166
+ const exitAfterKill = await pollExitCode(paths.exitCode);
167
+ if (exitAfterKill !== null) {
168
+ return finalizeJob(store, job, exitAfterKill, now());
169
+ }
170
+ return finalizeAbnormal(store, job, 'timed_out', now());
171
+ }
172
+ // Still genuinely running.
173
+ return job;
174
+ }
175
+ /**
176
+ * Absorb `state.json` (written only by the runner) into the jobs row: pid,
177
+ * pgid, proc_start_time and started_at are filled in once and never
178
+ * contradicted (the runner never rewrites them to null), and lifecycle is only
179
+ * ever moved forward (`queued` → `starting` → `running`) — never used to
180
+ * downgrade a `canceling` mark the gate made, and `finished` is decided
181
+ * exclusively by the presence of `exit_code`, never by `state.json` alone.
182
+ */
183
+ function ingestRunnerState(store, job, statePath) {
184
+ const state = readJsonIfExists(statePath);
185
+ if (!state)
186
+ return job;
187
+ const patch = {};
188
+ if (state.pid !== null && job.pid === null)
189
+ patch.pid = state.pid;
190
+ if (state.pgid !== null && job.pgid === null)
191
+ patch.pgid = state.pgid;
192
+ if (state.proc_start_time !== null && job.proc_start_time === null) {
193
+ patch.proc_start_time = state.proc_start_time;
194
+ }
195
+ if (state.started_at !== null && job.started_at === null)
196
+ patch.started_at = state.started_at;
197
+ if (state.lifecycle === 'running' && (job.lifecycle === 'queued' || job.lifecycle === 'starting')) {
198
+ patch.lifecycle = 'running';
199
+ }
200
+ else if (state.lifecycle === 'starting' && job.lifecycle === 'queued') {
201
+ patch.lifecycle = 'starting';
202
+ }
203
+ if (Object.keys(patch).length === 0)
204
+ return job;
205
+ return updateJob(store, job.job_id, patch);
206
+ }
207
+ /** `state.json` names a runner pid and that pid is alive. */
208
+ function runnerIsAlive(state) {
209
+ return state?.runner_pid != null && isPidAlive(state.runner_pid);
210
+ }
211
+ /** The runner announced `verify_command` is running, and it is still there to run it. */
212
+ function runnerIsVerifying(state) {
213
+ return state?.phase === 'verifying' && runnerIsAlive(state);
214
+ }
215
+ /**
216
+ * Finalize a job whose `exit_code` file has appeared: run verification, decide
217
+ * the outcome, write `broker-result.json`, set `lifecycle = 'finished'`, release
218
+ * locks. All inside one transaction.
219
+ *
220
+ * The job's *incoming* lifecycle carries one more fact: `'canceling'` means
221
+ * `agy_cancel` had already asked for this exit, so the outcome is `canceled`
222
+ * even though a normal exit code came back. `timedOut` carries the other one,
223
+ * from `state.json`: the runner's watchdog killed the group at the deadline,
224
+ * which is not an ordinary failure however the exit code reads.
225
+ */
226
+ export function finalizeJob(store, job, exitCode, nowMs, timedOut = false) {
227
+ return transaction(store.db, () => {
228
+ const fresh = tryGetJob(store, job.job_id);
229
+ if (fresh === null)
230
+ return job;
231
+ if (fresh.lifecycle === 'finished')
232
+ return fresh;
233
+ const canceled = fresh.lifecycle === 'canceling';
234
+ return finalizeCore(store, fresh, {
235
+ exitCode,
236
+ // An explicit cancel outranks the deadline: the user asked for this exit.
237
+ timedOut: timedOut && !canceled,
238
+ canceled,
239
+ runnerLost: false,
240
+ pidReused: false,
241
+ nowMs,
242
+ });
243
+ });
244
+ }
245
+ /**
246
+ * Finalize a job with no real `exit_code` — the runner vanished, the pid was
247
+ * reused, or our own deadline enforcement had to kill it directly.
248
+ */
249
+ function finalizeAbnormal(store, job, kind, nowMs) {
250
+ return transaction(store.db, () => {
251
+ const fresh = tryGetJob(store, job.job_id);
252
+ if (fresh === null)
253
+ return job;
254
+ if (fresh.lifecycle === 'finished')
255
+ return fresh;
256
+ const canceled = fresh.lifecycle === 'canceling';
257
+ return finalizeCore(store, fresh, {
258
+ exitCode: null,
259
+ timedOut: kind === 'timed_out' && !canceled,
260
+ canceled,
261
+ runnerLost: kind === 'process_error' && !canceled,
262
+ pidReused: kind === 'orphaned' && !canceled,
263
+ nowMs,
264
+ });
265
+ });
266
+ }
267
+ /** Shared body of {@link finalizeJob} / {@link finalizeAbnormal}. Must run inside a transaction. */
268
+ function finalizeCore(store, job, flags) {
269
+ const paths = jobPaths(store.paths, job.job_id);
270
+ const config = readJsonIfExists(paths.effectiveConfig);
271
+ const expectedArtifacts = config?.expected_artifacts ?? [];
272
+ const jsonSchemaPath = config?.json_schema_path ?? null;
273
+ // Only `state.json` records that the runner's idle watchdog closed stdin; the
274
+ // exit code it produces is an ordinary 0.
275
+ const state = readJsonIfExists(paths.state);
276
+ const idleClosed = state?.idle_closed === true;
277
+ const idleClosedAfterMs = idleClosed ? (config?.idle_timeout_ms ?? null) : null;
278
+ // I4: null on a `state.json` predating this field, or on a job that ended
279
+ // before any tool step ever ran — neither forces `outcome`.
280
+ const gateConfirmed = state?.gate_confirmed ?? null;
281
+ // The runner's own end time, when it recorded one (it writes `state.json`
282
+ // before `exit_code`, so on the normal path it is always there). Abnormal
283
+ // finalization has no runner-recorded end; the discovery time stands in.
284
+ const finishedAt = flags.exitCode !== null && state?.finished_at != null ? state.finished_at : flags.nowMs;
285
+ const read = readLinesFrom(paths.events, 0);
286
+ const parsed = parseEventLines(read.lines, 0);
287
+ const events = okEvents(parsed);
288
+ const malformedLines = parsed.filter((p) => !p.ok).length;
289
+ const result = buildBrokerResult(store, {
290
+ job,
291
+ events,
292
+ malformedLines,
293
+ exitCode: flags.exitCode,
294
+ timedOut: flags.timedOut,
295
+ canceled: flags.canceled,
296
+ runnerLost: flags.runnerLost,
297
+ pidReused: flags.pidReused,
298
+ expectedArtifacts,
299
+ jsonSchemaPath,
300
+ idleClosedAfterMs,
301
+ gateConfirmed,
302
+ finishedAt,
303
+ now: flags.nowMs,
304
+ });
305
+ writeBrokerResult(paths, result);
306
+ releaseJobLocks(store, job.job_id);
307
+ // Write the conversation id back to the session the moment the broker result
308
+ // knows it, independent of whether the gate ever bound this conversation
309
+ // (finding 14) — otherwise a later `agy_start({session_id})` reads
310
+ // `conversation_id: null` and silently starts a brand-new conversation
311
+ // instead of resuming this one.
312
+ if (result.conversation_id && job.session_id) {
313
+ const session = getSession(store, job.session_id);
314
+ if (session && session.conversation_id === null) {
315
+ try {
316
+ bindConversationId(store, job.session_id, result.conversation_id);
317
+ }
318
+ catch {
319
+ // Best effort — a concurrent bind from the gate already won.
320
+ }
321
+ }
322
+ }
323
+ const finalized = updateJob(store, job.job_id, {
324
+ lifecycle: 'finished',
325
+ outcome: result.broker_summary.outcome,
326
+ headline: result.broker_summary.headline,
327
+ exit_code: result.broker_summary.exit_code,
328
+ agent_status: result.agent_status,
329
+ contract_status: result.contract_status,
330
+ finished_at: finishedAt,
331
+ });
332
+ removeGateHookIfIdle(store, finalized);
333
+ return finalized;
334
+ }
335
+ /**
336
+ * Once a job lands in `finished`, remove only our own `hooks.json` entry
337
+ * (`GATE_HOOK_KEY`), and only when no other job
338
+ * with the same canonical `cwd` is still live — a second live job on that
339
+ * workspace still needs the hook. Runs *after* `updateJob` above so this job's
340
+ * own row already reads `finished` and does not count itself as a live holdout.
341
+ *
342
+ * The runner never opens the store (it must run even when every server process is dead),
343
+ * so reconcile is the only place that
344
+ * can know "is anything else on this cwd still live" and act on it. Best
345
+ * effort: `removeGateHook` swallows its own failures, and a stale entry left
346
+ * behind here is harmless until the next `agy_start` on the same workspace,
347
+ * which overwrites it unconditionally.
348
+ */
349
+ function removeGateHookIfIdle(store, job) {
350
+ try {
351
+ const stillLive = listJobs(store, { lifecycle: [...LIVE_LIFECYCLES], cwd: job.cwd, limit: 1 });
352
+ if (stillLive.length === 0)
353
+ removeGateHook(job.cwd);
354
+ }
355
+ catch {
356
+ // Best effort — hook-file housekeeping must never break reconcile.
357
+ }
358
+ }
359
+ /** Opportunistic cleanup of old job directories, triggered from `agy_start`. */
360
+ export function cleanupOldJobs(store, maxAgeMs) {
361
+ const cutoff = now() - maxAgeMs;
362
+ const finished = listJobs(store, { lifecycle: 'finished', limit: 10000 });
363
+ let removed = 0;
364
+ for (const job of finished) {
365
+ const ts = job.finished_at ?? job.created_at;
366
+ if (ts >= cutoff)
367
+ continue;
368
+ const paths = jobPaths(store.paths, job.job_id);
369
+ try {
370
+ rmSync(paths.dir, { recursive: true, force: true });
371
+ }
372
+ catch {
373
+ // Best effort: an already-gone directory is not a failure.
374
+ }
375
+ store.db.prepare('DELETE FROM jobs WHERE job_id = ?').run(job.job_id);
376
+ removed++;
377
+ }
378
+ return removed;
379
+ }
380
+ /** `jobs/<id>/exit_code` holds a bare integer; missing or unparsable reads as null. */
381
+ function readExitCode(path) {
382
+ try {
383
+ const raw = readFileSync(path, 'utf8').trim();
384
+ if (raw.length === 0)
385
+ return null;
386
+ const n = Number.parseInt(raw, 10);
387
+ return Number.isFinite(n) ? n : null;
388
+ }
389
+ catch {
390
+ return null;
391
+ }
392
+ }
393
+ /**
394
+ * After a forced `killpg`, give a still-alive runner a short window to observe
395
+ * the child's exit and write `exit_code` itself, so the finalize path reuses the
396
+ * real exit code instead of manufacturing one. Bounded so reconcile stays cheap
397
+ * even when the runner is not there to write anything.
398
+ */
399
+ async function pollExitCode(path, totalMs = 2000, intervalMs = 200) {
400
+ const deadline = Date.now() + totalMs;
401
+ for (;;) {
402
+ const code = readExitCode(path);
403
+ if (code !== null)
404
+ return code;
405
+ if (Date.now() >= deadline)
406
+ return null;
407
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
408
+ }
409
+ }
410
+ /** Convenience: reconcile one job by id, fetching its current row first. */
411
+ export async function reconcileJobById(store, jobId, opts) {
412
+ const job = getJob(store, jobId);
413
+ return reconcileJob(store, job, opts);
414
+ }
415
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/broker/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import type { AgentReport, AgyEvent, BrokerResult, JobRow, JudgementPacket } from '../contract/types.js';
2
+ import type { JobPaths } from '../contract/paths.js';
3
+ import type { Store } from '../store/db.js';
4
+ /**
5
+ * `broker-result.json` is the single source of truth.
6
+ *
7
+ * `agy_wait` projects a subset of it, `agy_result` pages all of it, and nothing
8
+ * else recomputes `outcome` — if a tool derives its own verdict, two callers can
9
+ * be told different things about the same job.
10
+ */
11
+ export interface BuildResultInput {
12
+ job: JobRow;
13
+ events: AgyEvent[];
14
+ malformedLines: number;
15
+ exitCode: number | null;
16
+ timedOut: boolean;
17
+ canceled: boolean;
18
+ runnerLost: boolean;
19
+ pidReused: boolean;
20
+ expectedArtifacts: string[];
21
+ jsonSchemaPath: string | null;
22
+ /**
23
+ * `idle_timeout_ms` when the runner's idle watchdog ended the session, null
24
+ * otherwise. A clean exit 0, so nothing here changes the outcome — but the
25
+ * caller cannot otherwise tell an idle close from an ordinary finish, and the
26
+ * two call for different next steps.
27
+ */
28
+ idleClosedAfterMs: number | null;
29
+ /**
30
+ * `state.json.gate_confirmed`, verbatim (I4). `false` adds a `source:'broker'`
31
+ * blocker and forces `outcome: 'process_error'`; `null` (no tool step ever
32
+ * ran, or an older `state.json`) changes nothing.
33
+ */
34
+ gateConfirmed: boolean | null;
35
+ /**
36
+ * When the runner actually finished (`state.json.finished_at`), if known.
37
+ * `finished_at` / `duration_ms` come from this; `now` is only when the
38
+ * broker got around to judging it (`finalized_at`). Absent on abnormal
39
+ * finalization (no `exit_code`, so no runner-recorded end) — `now` then.
40
+ * 0.2.2 (PR1): a job nobody polled for four days used to
41
+ * report an 86-hour duration for a 30-minute run.
42
+ */
43
+ finishedAt?: number | null;
44
+ now: number;
45
+ }
46
+ export declare function buildBrokerResult(store: Store, input: BuildResultInput): BrokerResult;
47
+ /** Extract agy's unverified self-report. Quarantined from `broker_summary` on purpose. */
48
+ export declare function buildAgentReport(events: AgyEvent[]): AgentReport;
49
+ /** Atomic write, so a concurrent reader never sees a half-written result. */
50
+ export declare function writeBrokerResult(paths: JobPaths, result: BrokerResult): void;
51
+ /**
52
+ * Null when the job has not been finalized yet.
53
+ *
54
+ * A `broker-result.json` written by an older server is migrated in memory
55
+ * (see {@link migrateBrokerResult}) rather than crashing a tool call — job
56
+ * directories outlive an upgrade, and `agy_result` on yesterday's job must keep
57
+ * working. A version we do not know how to read is refused loudly instead of
58
+ * being handed on half-typed.
59
+ *
60
+ * @throws {import('../contract/errors.js').ValidationError} on an unknown version.
61
+ */
62
+ export declare function loadBrokerResult(paths: JobPaths): BrokerResult | null;
63
+ /**
64
+ * Bring a stored result up to {@link BROKER_RESULT_VERSION}.
65
+ *
66
+ * Version 1 kept `verification.permission_denials` and
67
+ * `verification.environment_blocks`; version 2 collapsed those into the single
68
+ * `verification.blockers`; version 3 adds `verification.verify` (PR6,
69
+ * `verify_command`) — always `null` on a migrated file, since no job written
70
+ * before 0.2.0 ever ran a verify command. The version-1 migration runs the
71
+ * same constructors the live path uses, so an old job is judged by exactly
72
+ * today's rules — and nothing in the old records is dropped, since each one is
73
+ * carried in `Blocker.detail`.
74
+ */
75
+ export declare function migrateBrokerResult(raw: BrokerResult, path: string): BrokerResult;
76
+ export interface ProjectOptions {
77
+ maxLogTailLines?: number;
78
+ maxBytes?: number;
79
+ /** Cursor to report back for the caller's next `agy_logs` / `agy_wait`. */
80
+ cursor?: number;
81
+ }
82
+ /**
83
+ * Project the judgement packet `agy_wait` returns: counts, warnings, headline,
84
+ * and a short log tail. No lists, no raw response text — those live in
85
+ * `agy_result`.
86
+ */
87
+ export declare function projectJudgementPacket(result: BrokerResult, opts?: ProjectOptions): JudgementPacket;
88
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/broker/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EAIZ,MAAM,EACN,eAAe,EAEhB,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAIpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAY3C;;;;;;GAMG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC;;;;OAIG;IACH,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;CACZ;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAkFrF;AA+BD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAchE;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAE7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,GAAG,YAAY,GAAG,IAAI,CAIrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CA0CjF;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,eAAe,CA6BnG"}