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,234 @@
1
+ import { BROKER_RESULT_VERSION } from '../contract/types.js';
2
+ import { ValidationError } from '../contract/errors.js';
3
+ import { readJsonIfExists, writeJsonAtomic } from '../contract/paths.js';
4
+ import { normalizeEvent, tailSummary } from '../events/normalize.js';
5
+ import { lastResult } from '../events/parse.js';
6
+ import { blockerFromDenial, blockerFromEnvironmentBlock, blockerFromGateMissing, blockerFromMissingArtifact, countActionable, renderBlocker, } from './blockers.js';
7
+ import { decideOutcome } from './outcome.js';
8
+ import { verifyJob } from './verify.js';
9
+ const DEFAULT_LOG_TAIL_LINES = 40;
10
+ export function buildBrokerResult(store, input) {
11
+ const verification = verifyJob(store, {
12
+ job: input.job,
13
+ events: input.events,
14
+ expectedArtifacts: input.expectedArtifacts,
15
+ cwd: input.job.cwd,
16
+ // Where a captured --json-schema payload actually lands on the wire is
17
+ // unmeasured (see verify.ts checkContract) — nothing to pass through yet.
18
+ structuredOutput: undefined,
19
+ jsonSchemaPath: input.jsonSchemaPath,
20
+ });
21
+ if (input.idleClosedAfterMs !== null) {
22
+ verification.warnings.push(`session closed by idle_timeout_ms (${input.idleClosedAfterMs} ms) with no agy_send after the last turn — resume with agy_start({ session_id })`);
23
+ }
24
+ // I4: fold the gate watchdog's own verdict into the same `blockers` list
25
+ // everything else uses, so `agy_result`'s verification section carries this
26
+ // exactly like any other blocker instead of a special-cased field.
27
+ if (input.gateConfirmed === false) {
28
+ const gateBlocker = blockerFromGateMissing();
29
+ verification.blockers.push(gateBlocker);
30
+ verification.warnings.push(renderBlocker(gateBlocker));
31
+ }
32
+ const agentReport = buildAgentReport(input.events);
33
+ const hadExpectations = input.expectedArtifacts.length > 0 || input.jsonSchemaPath !== null;
34
+ const decision = decideOutcome({
35
+ lifecycle: input.job.lifecycle,
36
+ exitCode: input.exitCode,
37
+ agentStatus: agentReport.status,
38
+ verification,
39
+ timedOut: input.timedOut,
40
+ canceled: input.canceled,
41
+ gateMissing: input.gateConfirmed === false,
42
+ runnerLost: input.runnerLost,
43
+ pidReused: input.pidReused,
44
+ hadExpectations,
45
+ });
46
+ const counts = countEvents(input.events, input.malformedLines);
47
+ const normalized = input.events
48
+ .map((e) => normalizeEvent(e))
49
+ .filter((n) => n !== null);
50
+ const logTail = tailSummary(normalized, DEFAULT_LOG_TAIL_LINES);
51
+ const finishedAt = input.finishedAt ?? input.now;
52
+ const durationMs = input.job.started_at !== null ? Math.max(0, finishedAt - input.job.started_at) : null;
53
+ const brokerSummary = {
54
+ headline: decision.headline,
55
+ outcome: decision.outcome,
56
+ exit_code: input.exitCode,
57
+ duration_ms: durationMs,
58
+ counts,
59
+ log_tail: logTail,
60
+ };
61
+ return {
62
+ schema_version: BROKER_RESULT_VERSION,
63
+ job_id: input.job.job_id,
64
+ session_id: input.job.session_id,
65
+ conversation_id: agentReport.conversation_id,
66
+ lifecycle: 'finished',
67
+ cwd: input.job.cwd,
68
+ profile: input.job.profile,
69
+ session_mode: input.job.session_mode,
70
+ created_at: input.job.created_at,
71
+ started_at: input.job.started_at,
72
+ finished_at: finishedAt,
73
+ agent_report: agentReport,
74
+ broker_summary: brokerSummary,
75
+ verification,
76
+ agent_status: agentReport.status,
77
+ contract_status: decision.contract_status,
78
+ structured_output: null,
79
+ finalized_at: input.now,
80
+ };
81
+ }
82
+ function countEvents(events, malformedLines) {
83
+ let steps = 0;
84
+ let toolCalls = 0;
85
+ let toolErrors = 0;
86
+ let turns = 0;
87
+ for (const e of events) {
88
+ if (e.event === 'result') {
89
+ turns++;
90
+ continue;
91
+ }
92
+ if (e.event !== 'step_update')
93
+ continue;
94
+ steps++;
95
+ const su = e.step_update;
96
+ if (su.step_type !== 'tool')
97
+ continue;
98
+ if (su.state === 'DONE')
99
+ toolCalls++;
100
+ if (su.state === 'ERROR')
101
+ toolErrors++;
102
+ }
103
+ return {
104
+ events: events.length,
105
+ steps,
106
+ tool_calls: toolCalls,
107
+ tool_errors: toolErrors,
108
+ turns,
109
+ malformed_lines: malformedLines,
110
+ };
111
+ }
112
+ /** Extract agy's unverified self-report. Quarantined from `broker_summary` on purpose. */
113
+ export function buildAgentReport(events) {
114
+ const r = lastResult(events);
115
+ if (!r) {
116
+ return { status: 'unknown', response: null, error: null, num_turns: null, usage: null, conversation_id: null };
117
+ }
118
+ const status = r.result.status === 'SUCCESS' || r.result.status === 'ERROR' ? r.result.status : 'unknown';
119
+ return {
120
+ status,
121
+ response: r.result.response ?? null,
122
+ error: r.result.error ?? null,
123
+ num_turns: r.result.num_turns ?? null,
124
+ usage: r.result.usage ?? null,
125
+ conversation_id: r.result.conversation_id ?? null,
126
+ };
127
+ }
128
+ /** Atomic write, so a concurrent reader never sees a half-written result. */
129
+ export function writeBrokerResult(paths, result) {
130
+ writeJsonAtomic(paths.brokerResult, result);
131
+ }
132
+ /**
133
+ * Null when the job has not been finalized yet.
134
+ *
135
+ * A `broker-result.json` written by an older server is migrated in memory
136
+ * (see {@link migrateBrokerResult}) rather than crashing a tool call — job
137
+ * directories outlive an upgrade, and `agy_result` on yesterday's job must keep
138
+ * working. A version we do not know how to read is refused loudly instead of
139
+ * being handed on half-typed.
140
+ *
141
+ * @throws {import('../contract/errors.js').ValidationError} on an unknown version.
142
+ */
143
+ export function loadBrokerResult(paths) {
144
+ const raw = readJsonIfExists(paths.brokerResult);
145
+ if (raw === null)
146
+ return null;
147
+ return migrateBrokerResult(raw, paths.brokerResult);
148
+ }
149
+ /**
150
+ * Bring a stored result up to {@link BROKER_RESULT_VERSION}.
151
+ *
152
+ * Version 1 kept `verification.permission_denials` and
153
+ * `verification.environment_blocks`; version 2 collapsed those into the single
154
+ * `verification.blockers`; version 3 adds `verification.verify` (PR6,
155
+ * `verify_command`) — always `null` on a migrated file, since no job written
156
+ * before 0.2.0 ever ran a verify command. The version-1 migration runs the
157
+ * same constructors the live path uses, so an old job is judged by exactly
158
+ * today's rules — and nothing in the old records is dropped, since each one is
159
+ * carried in `Blocker.detail`.
160
+ */
161
+ export function migrateBrokerResult(raw, path) {
162
+ const version = raw.schema_version;
163
+ if (version === BROKER_RESULT_VERSION)
164
+ return raw;
165
+ if (version !== 1 && version !== 2) {
166
+ throw new ValidationError({
167
+ field: `schema_version of ${path}`,
168
+ value: version,
169
+ expected: `a broker-result.json version this server can read (1, 2 or ${BROKER_RESULT_VERSION}) — this file was written by a newer server`,
170
+ });
171
+ }
172
+ let verification;
173
+ if (version === 1) {
174
+ const legacy = raw.verification;
175
+ const artifacts = legacy.expected_artifacts ?? [];
176
+ const blockers = [
177
+ ...(legacy.permission_denials ?? []).map(blockerFromDenial),
178
+ ...(legacy.environment_blocks ?? []).map((b) => blockerFromEnvironmentBlock(b)),
179
+ ...artifacts.filter((a) => !a.exists).map(blockerFromMissingArtifact),
180
+ ];
181
+ verification = {
182
+ blockers,
183
+ expected_artifacts: artifacts,
184
+ changed_files: legacy.changed_files ?? [],
185
+ warnings: legacy.warnings ?? [],
186
+ contract_status: legacy.contract_status,
187
+ checked_at: legacy.checked_at,
188
+ verify: null,
189
+ };
190
+ }
191
+ else {
192
+ // version === 2: everything but `verify` is already in today's shape.
193
+ verification = { ...raw.verification, verify: null };
194
+ }
195
+ return {
196
+ ...raw,
197
+ schema_version: BROKER_RESULT_VERSION,
198
+ verification,
199
+ };
200
+ }
201
+ /**
202
+ * Project the judgement packet `agy_wait` returns: counts, warnings, headline,
203
+ * and a short log tail. No lists, no raw response text — those live in
204
+ * `agy_result`.
205
+ */
206
+ export function projectJudgementPacket(result, opts) {
207
+ const maxLines = opts?.maxLogTailLines;
208
+ const logTail = maxLines !== undefined && maxLines < result.broker_summary.log_tail.length
209
+ ? result.broker_summary.log_tail.slice(-maxLines)
210
+ : result.broker_summary.log_tail;
211
+ return {
212
+ job_id: result.job_id,
213
+ lifecycle: result.lifecycle,
214
+ outcome: result.broker_summary.outcome,
215
+ headline: result.broker_summary.headline,
216
+ exit_code: result.broker_summary.exit_code,
217
+ duration_ms: result.broker_summary.duration_ms,
218
+ agent_status: result.agent_status,
219
+ contract_status: result.contract_status,
220
+ counts: {
221
+ // Two numbers instead of four differently-defined ones: how much stood in
222
+ // the way, and how much of it the caller can act on. `headline` names the
223
+ // sources; `agy_result`'s `verification.blockers` has each one in full.
224
+ blockers: result.verification.blockers.length,
225
+ actionable: countActionable(result.verification.blockers),
226
+ tool_errors: result.broker_summary.counts.tool_errors,
227
+ turns: result.broker_summary.counts.turns,
228
+ },
229
+ warnings: result.verification.warnings,
230
+ log_tail: logTail,
231
+ cursor: opts?.cursor ?? 0,
232
+ };
233
+ }
234
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/broker/result.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { AgyEvent, ArtifactCheck, ContractStatus, EffectivePolicy, JobRow, Verification } from '../contract/types.js';
2
+ import type { Store } from '../store/db.js';
3
+ /**
4
+ * Independent checks the broker runs on its own, without asking agy anything.
5
+ *
6
+ * Verification scope: expected-artifact existence, `git status` changed files,
7
+ * and Class 1 / Class 2 denial aggregation. Running arbitrary commands here in
8
+ * the broker is deliberately out — that needs its own allowlist design; PR6's
9
+ * `verify_command` instead runs once, in the *runner*, before this ever sees
10
+ * the job. This module's only job re: that
11
+ * is `readVerifyResult` below, which reads back what the runner already wrote.
12
+ */
13
+ export interface VerifyInput {
14
+ job: JobRow;
15
+ events: AgyEvent[];
16
+ expectedArtifacts: string[];
17
+ /** Canonical workspace. */
18
+ cwd: string;
19
+ /** Raw structured output, when `--json-schema` was requested. */
20
+ structuredOutput?: unknown;
21
+ jsonSchemaPath?: string | null;
22
+ policy?: EffectivePolicy | null;
23
+ }
24
+ export declare function verifyJob(store: Store, input: VerifyInput): Verification;
25
+ /**
26
+ * Existence and size of each expected artifact.
27
+ *
28
+ * Paths are workspace-relative and containment-checked before use, so a job
29
+ * cannot claim success by writing outside its workspace. A path that escapes the
30
+ * workspace is treated as missing, not as an error — the caller asked for a
31
+ * verifiable fact, and "escaped the sandbox" is not a fact in its favour.
32
+ */
33
+ export declare function checkExpectedArtifacts(cwd: string, expected: string[]): ArtifactCheck[];
34
+ /**
35
+ * `git status --porcelain` inside the workspace, via an argv array (never a shell
36
+ * string). Empty when the workspace is not a git repo — that is not an error.
37
+ */
38
+ export declare function changedFiles(cwd: string): string[];
39
+ /**
40
+ * Whether the structured output honoured the requested schema. `not_required`
41
+ * when no schema was asked for; `violated` keeps the raw payload regardless, since
42
+ * a schema miss must never destroy the response.
43
+ *
44
+ * ⚠ agy's actual `--json-schema` failure signalling is unmeasured.
45
+ * This is a conservative, documented placeholder:
46
+ * presence of a non-null payload is treated as satisfying the schema; its
47
+ * absence when one was requested is `unknown` rather than a confident
48
+ * `violated`, since we have no measured evidence of what an actual schema
49
+ * failure looks like on the wire.
50
+ */
51
+ export declare function checkContract(structuredOutput: unknown, jsonSchemaPath: string | null): ContractStatus;
52
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/broker/verify.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EAEb,cAAc,EAEd,eAAe,EACf,MAAM,EACN,YAAY,EAGb,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAW3C;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;CAChC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,CAmExE;AAgCD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAevF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBlD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,gBAAgB,EAAE,OAAO,EACzB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,cAAc,CAIhB"}
@@ -0,0 +1,174 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync, readFileSync, statSync } from 'node:fs';
3
+ import { isAbsolute, join } from 'node:path';
4
+ import { canonicalize, containedOrNull, jobPaths, readJsonIfExists } from '../contract/paths.js';
5
+ import { scanDenials } from '../events/detect.js';
6
+ import { now } from '../store/db.js';
7
+ import { blockerFromDenial, blockerFromEnvironmentBlock, blockerFromMissingArtifact, blockersFromGateLog, ceilingAbsenceWarning, renderBlockers, } from './blockers.js';
8
+ export function verifyJob(store, input) {
9
+ const paths = jobPaths(store.paths, input.job.job_id);
10
+ const policy = input.policy ??
11
+ readJsonIfExists(paths.policy) ??
12
+ readJsonIfExists(paths.effectiveConfig)?.policy ??
13
+ null;
14
+ const denials = scanDenials(input.events);
15
+ const artifacts = checkExpectedArtifacts(input.cwd, input.expectedArtifacts);
16
+ const changed = changedFiles(input.cwd);
17
+ const contractStatus = checkContract(input.structuredOutput, input.jsonSchemaPath ?? null);
18
+ const verify = readVerifyResult(store, input.job.job_id);
19
+ // One list, one vocabulary. Which of these force `outcome: 'blocked'` and
20
+ // which are only reported is decided in `blockers.ts` and nowhere else.
21
+ // A Class 2 signature only means "the sandbox refused" when the job actually
22
+ // ran sandboxed. With `bypass_sandbox: true` there is no sandbox to refuse
23
+ // anything, so the same text is an ordinary command failure (a real EACCES,
24
+ // a network that is really down) — reported as a warning, never a blocker,
25
+ // and never a reason to call the job `blocked`.
26
+ let gateLogBlockers = [];
27
+ if (existsSync(paths.gateLog)) {
28
+ try {
29
+ gateLogBlockers = blockersFromGateLog(readFileSync(paths.gateLog, 'utf8'));
30
+ }
31
+ catch {
32
+ // tolerate missing or unreadable gate log
33
+ }
34
+ }
35
+ // `sandbox` is the 0.3.0 field; a pre-0.3.0 policy file only has bypass_sandbox.
36
+ const ranUnsandboxed = policy ? (policy.sandbox ?? (policy.bypass_sandbox ? 'none' : 'agy')) === 'none' : false;
37
+ const blockers = [
38
+ ...denials.permission_denials.map(blockerFromDenial),
39
+ ...(ranUnsandboxed ? [] : denials.environment_blocks.map((b) => blockerFromEnvironmentBlock(b, policy))),
40
+ ...artifacts.filter((a) => !a.exists).map(blockerFromMissingArtifact),
41
+ ...gateLogBlockers,
42
+ ];
43
+ const warnings = renderBlockers(blockers);
44
+ // A gate refusal whose remedy is a rule string is exactly what a ceiling
45
+ // would open. Without a ceiling file the agent has no `agy_capabilities`
46
+ // entry to point at, so say it here, once, next to the blocker.
47
+ const ceilingHint = ceilingAbsenceWarning(policy, blockers);
48
+ if (ceilingHint)
49
+ warnings.push(ceilingHint);
50
+ if (ranUnsandboxed) {
51
+ for (const b of denials.environment_blocks) {
52
+ warnings.push(`${b.tool}${b.command ? ` (${b.command})` : ''} printed sandbox signature "${b.signature}", but this job ran with no OS sandbox (sandbox: none), so it is the command's own failure, not a sandbox block: ${b.excerpt}`);
53
+ }
54
+ }
55
+ if (contractStatus === 'violated') {
56
+ // Not a blocker: `checkContract` never returns 'violated' on measured
57
+ // evidence (see below), so there is nothing here we could claim to confirm.
58
+ warnings.push('structured output did not honour the requested --json-schema');
59
+ }
60
+ return {
61
+ blockers,
62
+ expected_artifacts: artifacts,
63
+ changed_files: changed,
64
+ warnings,
65
+ contract_status: contractStatus,
66
+ checked_at: now(),
67
+ verify,
68
+ };
69
+ }
70
+ /**
71
+ * `Verification.verify` (PR6 §6.3): `null` when `jobs/<id>/verify.json` was
72
+ * never written — no `verify_command` was requested, or the job's own
73
+ * deadline killed agy before the runner could get to it (`runner.ts` skips
74
+ * verify entirely when `timedOut === true`). Deliberately re-read from disk
75
+ * rather than threaded through as an extra `VerifyInput` field: `jobPaths` is
76
+ * already the one place that knows where the runner wrote it, and every
77
+ * caller of `verifyJob` already has a `Store` (and so a `ProjectPaths`) in
78
+ * hand.
79
+ */
80
+ function readVerifyResult(store, jobId) {
81
+ const paths = jobPaths(store.paths, jobId);
82
+ const record = readJsonIfExists(paths.verifyJson);
83
+ if (!record)
84
+ return null;
85
+ return { ...record, output_tail: readOutputTail(paths.verifyLog) };
86
+ }
87
+ /** Last 2 KiB of `verify.log`, byte-accurate; `''` when the file is empty or missing. */
88
+ const OUTPUT_TAIL_BYTES = 2048;
89
+ function readOutputTail(logPath) {
90
+ try {
91
+ const buf = readFileSync(logPath);
92
+ if (buf.length <= OUTPUT_TAIL_BYTES)
93
+ return buf.toString('utf8');
94
+ return buf.subarray(buf.length - OUTPUT_TAIL_BYTES).toString('utf8');
95
+ }
96
+ catch {
97
+ return '';
98
+ }
99
+ }
100
+ /**
101
+ * Existence and size of each expected artifact.
102
+ *
103
+ * Paths are workspace-relative and containment-checked before use, so a job
104
+ * cannot claim success by writing outside its workspace. A path that escapes the
105
+ * workspace is treated as missing, not as an error — the caller asked for a
106
+ * verifiable fact, and "escaped the sandbox" is not a fact in its favour.
107
+ */
108
+ export function checkExpectedArtifacts(cwd, expected) {
109
+ const canonicalCwd = canonicalize(cwd);
110
+ return expected.map((rel) => {
111
+ const attempted = isAbsolute(rel) ? rel : join(canonicalCwd, rel);
112
+ const contained = containedOrNull(attempted, [canonicalCwd]);
113
+ if (contained === null) {
114
+ return { path: rel, absolute: canonicalize(attempted), exists: false, size: null };
115
+ }
116
+ try {
117
+ const st = statSync(contained);
118
+ return { path: rel, absolute: contained, exists: true, size: st.size };
119
+ }
120
+ catch {
121
+ return { path: rel, absolute: contained, exists: false, size: null };
122
+ }
123
+ });
124
+ }
125
+ /**
126
+ * `git status --porcelain` inside the workspace, via an argv array (never a shell
127
+ * string). Empty when the workspace is not a git repo — that is not an error.
128
+ */
129
+ export function changedFiles(cwd) {
130
+ try {
131
+ // This call runs inside `finalizeCore`'s `BEGIN IMMEDIATE` transaction,
132
+ // so an unbounded `git status` — blocked on a network
133
+ // FS or an `index.lock` — would hold the SQLite write lock for as long as
134
+ // git hangs. Bounding it here is a minimal mitigation for finding 7;
135
+ // moving this work outside the transaction entirely is the fuller fix and
136
+ // is not done here.
137
+ const out = execFileSync('git', ['status', '--porcelain'], {
138
+ cwd: canonicalize(cwd),
139
+ encoding: 'utf8',
140
+ stdio: ['ignore', 'pipe', 'ignore'],
141
+ timeout: 5000,
142
+ killSignal: 'SIGKILL',
143
+ });
144
+ return out
145
+ .split('\n')
146
+ .map((l) => l.trimEnd())
147
+ .filter((l) => l.length > 0);
148
+ }
149
+ catch {
150
+ // Not a git repo, git not installed, or the command failed. None of these
151
+ // are fatal to the job — they just mean nothing to report here.
152
+ return [];
153
+ }
154
+ }
155
+ /**
156
+ * Whether the structured output honoured the requested schema. `not_required`
157
+ * when no schema was asked for; `violated` keeps the raw payload regardless, since
158
+ * a schema miss must never destroy the response.
159
+ *
160
+ * ⚠ agy's actual `--json-schema` failure signalling is unmeasured.
161
+ * This is a conservative, documented placeholder:
162
+ * presence of a non-null payload is treated as satisfying the schema; its
163
+ * absence when one was requested is `unknown` rather than a confident
164
+ * `violated`, since we have no measured evidence of what an actual schema
165
+ * failure looks like on the wire.
166
+ */
167
+ export function checkContract(structuredOutput, jsonSchemaPath) {
168
+ if (!jsonSchemaPath)
169
+ return 'not_required';
170
+ if (structuredOutput === undefined || structuredOutput === null)
171
+ return 'unknown';
172
+ return 'satisfied';
173
+ }
174
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/broker/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Structured errors. READ-ONLY after Stage 1.
3
+ *
4
+ * Every error carries a machine-readable `detail` so the *calling agent* can
5
+ * repair itself without another round trip: which job holds the lock, which rule
6
+ * string to add, which enum values exist.
7
+ */
8
+ import type { LockRequestScope, OnDenial, RuleVerb } from './types.js';
9
+ export type ErrorCode = 'LOCK_CONFLICT' | 'POLICY_DENIED' | 'PATH_ESCAPE' | 'JOB_NOT_FOUND' | 'VALIDATION';
10
+ /** Wire shape of any error surfaced through MCP. */
11
+ export interface ErrorEnvelope<D = unknown> {
12
+ error: ErrorCode;
13
+ message: string;
14
+ detail: D;
15
+ /** Concrete next action for the caller. Always present. */
16
+ remedy: string;
17
+ }
18
+ /** Base for everything in this module. `instanceof` works across all subclasses. */
19
+ export declare abstract class AgyWorkerError<D = unknown> extends Error {
20
+ abstract readonly code: ErrorCode;
21
+ readonly detail: D;
22
+ readonly remedy: string;
23
+ protected constructor(message: string, detail: D, remedy: string);
24
+ toJSON(): ErrorEnvelope<D>;
25
+ }
26
+ export declare function isAgyWorkerError(e: unknown): e is AgyWorkerError;
27
+ /** Normalizes anything thrown into an envelope so a tool handler never leaks a stack. */
28
+ export declare function toErrorEnvelope(e: unknown): ErrorEnvelope;
29
+ export interface LockConflictDetail {
30
+ /** `running_limit` means the project-wide concurrency ceiling, not a row. */
31
+ scope: LockRequestScope;
32
+ /** Canonical cwd, session id, or `'*'` for the running limit. */
33
+ key: string;
34
+ /** Whether an existing holder blocked it, or the ceiling did. */
35
+ reason: 'held' | 'limit';
36
+ /** Job currently holding the lock. Null for `reason: 'limit'`. */
37
+ holder_job_id: string | null;
38
+ holder_pid: number | null;
39
+ holder_started_at: number | null;
40
+ acquired_at: number | null;
41
+ /** Every job counted against the ceiling, for `reason: 'limit'`. */
42
+ running_job_ids: string[];
43
+ limit: number | null;
44
+ }
45
+ /**
46
+ * Losing a lock race is an error, never a silent serialization.
47
+ * The caller decides whether to wait on the holder or pick a different cwd.
48
+ */
49
+ export declare class LockConflictError extends AgyWorkerError<LockConflictDetail> {
50
+ readonly code: "LOCK_CONFLICT";
51
+ constructor(detail: LockConflictDetail, message?: string);
52
+ }
53
+ export interface PolicyDeniedDetail {
54
+ job_id: string | null;
55
+ profile: string;
56
+ tool: string;
57
+ command: string | null;
58
+ /**
59
+ * Rule string that would have permitted this, e.g. `command(python -m pytest)`.
60
+ * Paste it into the next `agy_start`'s `permissions.allow`.
61
+ */
62
+ required_rule: string | null;
63
+ /** The deny entry that matched, when the refusal came from a deny list. */
64
+ matched_rule: string | null;
65
+ /** Which stage of the decision order refused. */
66
+ policy: 'unsupported' | 'control' | 'containment' | 'deny_list' | 'profile_allowlist' | 'default';
67
+ /** True when no client request can lift it (hard deny / profile ceiling). */
68
+ immutable: boolean;
69
+ on_denial: OnDenial;
70
+ }
71
+ /** A policy refusal, whether reported by the gate or replayed by the broker. */
72
+ export declare class PolicyDeniedError extends AgyWorkerError<PolicyDeniedDetail> {
73
+ readonly code: "POLICY_DENIED";
74
+ constructor(detail: PolicyDeniedDetail, message?: string);
75
+ }
76
+ export interface PathEscapeDetail {
77
+ /** What the caller supplied. */
78
+ input_path: string;
79
+ /** After realpath + `..` resolution. This is what actually escaped. */
80
+ resolved_path: string;
81
+ /** Whether read or write containment was violated. */
82
+ kind: 'read' | 'write';
83
+ /** Canonical roots that were allowed. */
84
+ roots: string[];
85
+ /** True when a symlink was what carried the path outside. */
86
+ via_symlink: boolean;
87
+ }
88
+ /** Containment failure. Checked *after* realpath, never before (see docs/permissions.md). */
89
+ export declare class PathEscapeError extends AgyWorkerError<PathEscapeDetail> {
90
+ readonly code: "PATH_ESCAPE";
91
+ constructor(detail: PathEscapeDetail, message?: string);
92
+ }
93
+ export interface JobNotFoundDetail {
94
+ job_id: string;
95
+ /** A few recent job ids so the caller can spot a typo without another call. */
96
+ known_recent: string[];
97
+ project_root: string;
98
+ }
99
+ export declare class JobNotFoundError extends AgyWorkerError<JobNotFoundDetail> {
100
+ readonly code: "JOB_NOT_FOUND";
101
+ constructor(detail: JobNotFoundDetail, message?: string);
102
+ }
103
+ export interface ValidationDetail {
104
+ /** Dotted path of the offending input, e.g. `permissions.allow[0]`. */
105
+ field: string;
106
+ /** What arrived. Truncated by the thrower if large. */
107
+ value: unknown;
108
+ /** Human description of what was required. */
109
+ expected: string;
110
+ /** Complete enum when the field is an enum. Lets the caller self-correct. */
111
+ allowed?: string[];
112
+ /** Rule verbs, when the failure was an unparsable permission rule. */
113
+ allowed_verbs?: RuleVerb[];
114
+ }
115
+ export declare class ValidationError extends AgyWorkerError<ValidationDetail> {
116
+ readonly code: "VALIDATION";
117
+ constructor(detail: ValidationDetail, message?: string);
118
+ }
119
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/contract/errors.ts"],"names":[],"mappings":"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"}