agent-dealer 0.2.0 → 1.0.0

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 (276) hide show
  1. package/bundle/server/dist/adapters/agent-deck-bind.js +443 -0
  2. package/bundle/server/dist/adapters/agent-deck-bind.test.js +454 -0
  3. package/bundle/server/dist/adapters/agent-deck.js +38 -50
  4. package/bundle/server/dist/adapters/agent-deck.test.js +63 -0
  5. package/bundle/server/dist/adapters/agent-health.js +230 -33
  6. package/bundle/server/dist/adapters/agent-health.test.js +237 -0
  7. package/bundle/server/dist/adapters/authority-lifecycle.js +289 -0
  8. package/bundle/server/dist/adapters/codex-scoped-config.js +103 -0
  9. package/bundle/server/dist/adapters/execution-authority.js +103 -0
  10. package/bundle/server/dist/adapters/execution-authority.test.js +166 -0
  11. package/bundle/server/dist/adapters/external.js +0 -1
  12. package/bundle/server/dist/adapters/git-worktree.js +514 -0
  13. package/bundle/server/dist/adapters/git-worktree.test.js +502 -0
  14. package/bundle/server/dist/adapters/github.js +170 -0
  15. package/bundle/server/dist/adapters/github.test.js +205 -0
  16. package/bundle/server/dist/adapters/linear-inbox.js +199 -30
  17. package/bundle/server/dist/adapters/linear-inbox.test.js +35 -0
  18. package/bundle/server/dist/adapters/linear-sync.js +3 -101
  19. package/bundle/server/dist/adapters/managed-repo.js +168 -0
  20. package/bundle/server/dist/adapters/managed-repo.test.js +63 -0
  21. package/bundle/server/dist/adapters/outbound-delivery.js +83 -0
  22. package/bundle/server/dist/adapters/outbound-delivery.test.js +53 -0
  23. package/bundle/server/dist/adapters/reflect-authority.js +43 -0
  24. package/bundle/server/dist/cli-env.js +26 -0
  25. package/bundle/server/dist/cli-env.test.js +14 -1
  26. package/bundle/server/dist/coordinator/abort.integration.test.js +74 -0
  27. package/bundle/server/dist/coordinator/admission.js +330 -0
  28. package/bundle/server/dist/coordinator/admission.test.js +338 -0
  29. package/bundle/server/dist/coordinator/args.js +128 -0
  30. package/bundle/server/dist/coordinator/args.test.js +132 -0
  31. package/bundle/server/dist/coordinator/authority-recovery.integration.test.js +661 -0
  32. package/bundle/server/dist/coordinator/auto-merge.integration.test.js +363 -0
  33. package/bundle/server/dist/coordinator/auto-merge.js +286 -0
  34. package/bundle/server/dist/coordinator/auto-merge.timeout.test.js +14 -0
  35. package/bundle/server/dist/coordinator/branch-progress.js +81 -0
  36. package/bundle/server/dist/coordinator/clock-jump.js +98 -0
  37. package/bundle/server/dist/coordinator/commands.js +1088 -0
  38. package/bundle/server/dist/coordinator/commands.test.js +554 -0
  39. package/bundle/server/dist/coordinator/deck-outage-config.js +32 -0
  40. package/bundle/server/dist/coordinator/deck-outage.integration.test.js +200 -0
  41. package/bundle/server/dist/coordinator/dependencies.js +242 -0
  42. package/bundle/server/dist/coordinator/dependency-readiness.integration.test.js +535 -0
  43. package/bundle/server/dist/coordinator/developer-effect.js +959 -0
  44. package/bundle/server/dist/coordinator/developer-effect.test.js +1143 -0
  45. package/bundle/server/dist/coordinator/dispatcher.js +58 -0
  46. package/bundle/server/dist/coordinator/dispatcher.test.js +81 -0
  47. package/bundle/server/dist/coordinator/effect-registry.js +17 -0
  48. package/bundle/server/dist/coordinator/execution-env.integration.test.js +122 -0
  49. package/bundle/server/dist/coordinator/failure-reason.js +273 -0
  50. package/bundle/server/dist/coordinator/failure-reason.test.js +234 -0
  51. package/bundle/server/dist/coordinator/guidance.js +33 -0
  52. package/bundle/server/dist/coordinator/guidance.test.js +110 -0
  53. package/bundle/server/dist/coordinator/human-resolution.js +88 -0
  54. package/bundle/server/dist/coordinator/human-resolution.test.js +72 -0
  55. package/bundle/server/dist/coordinator/intent-forecast.js +13 -0
  56. package/bundle/server/dist/coordinator/intent-forecast.test.js +34 -0
  57. package/bundle/server/dist/coordinator/latest-failure.js +100 -0
  58. package/bundle/server/dist/coordinator/latest-failure.test.js +125 -0
  59. package/bundle/server/dist/coordinator/metrics.js +35 -0
  60. package/bundle/server/dist/coordinator/metrics.test.js +52 -0
  61. package/bundle/server/dist/coordinator/permissions.js +127 -0
  62. package/bundle/server/dist/coordinator/permissions.test.js +184 -0
  63. package/bundle/server/dist/coordinator/presumed-dead-budget.integration.test.js +146 -0
  64. package/bundle/server/dist/coordinator/process-liveness.js +191 -0
  65. package/bundle/server/dist/coordinator/profile-snapshot.js +20 -0
  66. package/bundle/server/dist/coordinator/profile-snapshot.test.js +118 -0
  67. package/bundle/server/dist/coordinator/projection.js +147 -0
  68. package/bundle/server/dist/coordinator/projection.test.js +121 -0
  69. package/bundle/server/dist/coordinator/prompts.js +164 -0
  70. package/bundle/server/dist/coordinator/prompts.test.js +177 -0
  71. package/bundle/server/dist/coordinator/queue-by-default.integration.test.js +271 -0
  72. package/bundle/server/dist/coordinator/reclaim-republish.integration.test.js +372 -0
  73. package/bundle/server/dist/coordinator/recovery.js +466 -0
  74. package/bundle/server/dist/coordinator/recovery.test.js +164 -0
  75. package/bundle/server/dist/coordinator/reflect-trigger.js +218 -0
  76. package/bundle/server/dist/coordinator/reflect-trigger.test.js +324 -0
  77. package/bundle/server/dist/coordinator/repair-cycle.integration.test.js +234 -0
  78. package/bundle/server/dist/coordinator/restart-recovery.integration.test.js +363 -0
  79. package/bundle/server/dist/coordinator/reviewer-effect.js +507 -0
  80. package/bundle/server/dist/coordinator/reviewer-effect.test.js +612 -0
  81. package/bundle/server/dist/coordinator/reviewer-result.js +38 -0
  82. package/bundle/server/dist/coordinator/reviewer-result.test.js +45 -0
  83. package/bundle/server/dist/coordinator/routing.js +160 -0
  84. package/bundle/server/dist/coordinator/routing.test.js +336 -0
  85. package/bundle/server/dist/coordinator/session-lifecycle.integration.test.js +127 -0
  86. package/bundle/server/dist/coordinator/session-lifecycle.js +280 -0
  87. package/bundle/server/dist/coordinator/session-lifecycle.test.js +121 -0
  88. package/bundle/server/dist/coordinator/session-progress.js +351 -0
  89. package/bundle/server/dist/coordinator/session-progress.test.js +190 -0
  90. package/bundle/server/dist/coordinator/session-timeouts.js +33 -0
  91. package/bundle/server/dist/coordinator/sleep-recovery.integration.test.js +233 -0
  92. package/bundle/server/dist/coordinator/spawn.js +49 -0
  93. package/bundle/server/dist/coordinator/sync-issue-base-branch.js +18 -0
  94. package/bundle/server/dist/coordinator/usage-cap-config.js +10 -0
  95. package/bundle/server/dist/coordinator/usage-cap-defer.js +189 -0
  96. package/bundle/server/dist/coordinator/usage-cap.integration.test.js +193 -0
  97. package/bundle/server/dist/coordinator/usage.js +40 -0
  98. package/bundle/server/dist/coordinator/usage.test.js +69 -0
  99. package/bundle/server/dist/coordinator/verification-receipt.js +333 -0
  100. package/bundle/server/dist/coordinator/verification-receipt.test.js +382 -0
  101. package/bundle/server/dist/coordinator/worker-loop.js +363 -0
  102. package/bundle/server/dist/coordinator/worker-loop.test.js +327 -0
  103. package/bundle/server/dist/coordinator/workflow-instances.test.js +45 -0
  104. package/bundle/server/dist/coordinator/worktree-owner-liveness.js +82 -0
  105. package/bundle/server/dist/coordinator/worktree-owner-liveness.test.js +199 -0
  106. package/bundle/server/dist/db/artifacts-issue-columns.test.js +18 -0
  107. package/bundle/server/dist/db/authority-attempts-stale-at-migration.test.js +65 -0
  108. package/bundle/server/dist/db/idempotency-index-migration.test.js +57 -0
  109. package/bundle/server/dist/db/index.js +359 -7
  110. package/bundle/server/dist/db/linear-inbox-unlock.test.js +67 -0
  111. package/bundle/server/dist/db/migrate-to-issues.js +824 -0
  112. package/bundle/server/dist/db/migrate-to-issues.test.js +842 -0
  113. package/bundle/server/dist/db/schema.sql +311 -1
  114. package/bundle/server/dist/db/schema.test.js +66 -0
  115. package/bundle/server/dist/db/worker-session-pid-migration.test.js +112 -0
  116. package/bundle/server/dist/dev-review-cli-happy-path.integration.test.js +338 -0
  117. package/bundle/server/dist/direct-start-liveness.integration.test.js +350 -0
  118. package/bundle/server/dist/index.js +58 -5
  119. package/bundle/server/dist/paths.js +40 -4
  120. package/bundle/server/dist/paths.test.js +42 -0
  121. package/bundle/server/dist/pid-marker-claim-child.js +18 -0
  122. package/bundle/server/dist/pid-marker-hold-arbiter-child.js +24 -0
  123. package/bundle/server/dist/pid-marker.js +141 -0
  124. package/bundle/server/dist/pid-marker.test.js +208 -0
  125. package/bundle/server/dist/queue/approve-deliver.js +128 -28
  126. package/bundle/server/dist/queue/reflect-schedule.js +25 -0
  127. package/bundle/server/dist/queue/result-qa.js +1 -1
  128. package/bundle/server/dist/queue/send-gate.test.js +172 -36
  129. package/bundle/server/dist/repository/agents.js +55 -18
  130. package/bundle/server/dist/repository/artifacts-for-issue.js +42 -0
  131. package/bundle/server/dist/repository/artifacts-for-issue.test.js +48 -0
  132. package/bundle/server/dist/repository/artifacts.js +47 -0
  133. package/bundle/server/dist/repository/artifacts.test.js +48 -0
  134. package/bundle/server/dist/repository/authority-attempts.js +189 -0
  135. package/bundle/server/dist/repository/findings.js +70 -0
  136. package/bundle/server/dist/repository/findings.test.js +68 -0
  137. package/bundle/server/dist/repository/human-actions.js +142 -0
  138. package/bundle/server/dist/repository/human-actions.test.js +123 -0
  139. package/bundle/server/dist/repository/intake-settings.js +5 -59
  140. package/bundle/server/dist/repository/issues.js +305 -0
  141. package/bundle/server/dist/repository/issues.test.js +69 -0
  142. package/bundle/server/dist/repository/outbound-drafts.js +28 -0
  143. package/bundle/server/dist/repository/queue-entries.js +162 -0
  144. package/bundle/server/dist/repository/review-publications.js +153 -0
  145. package/bundle/server/dist/repository/review-publications.test.js +78 -0
  146. package/bundle/server/dist/repository/runs-external-id.test.js +5 -3
  147. package/bundle/server/dist/repository/runs.js +4 -211
  148. package/bundle/server/dist/repository/runtime-availability.js +54 -0
  149. package/bundle/server/dist/repository/usage-events.js +60 -0
  150. package/bundle/server/dist/repository/usage-events.test.js +56 -0
  151. package/bundle/server/dist/repository/work-items.js +305 -0
  152. package/bundle/server/dist/repository/work-items.test.js +142 -0
  153. package/bundle/server/dist/repository/worker-sessions.js +219 -0
  154. package/bundle/server/dist/repository/worker-sessions.test.js +60 -0
  155. package/bundle/server/dist/repository/workflow-events.js +193 -0
  156. package/bundle/server/dist/repository/workflow-events.test.js +89 -0
  157. package/bundle/server/dist/resolve-tsx-bin.js +19 -0
  158. package/bundle/server/dist/routes/human-actions.js +68 -0
  159. package/bundle/server/dist/routes/human-actions.test.js +284 -0
  160. package/bundle/server/dist/routes/index.js +29 -496
  161. package/bundle/server/dist/routes/issues.js +240 -0
  162. package/bundle/server/dist/routes/issues.test.js +451 -0
  163. package/bundle/server/dist/routes/queue.js +41 -0
  164. package/bundle/server/dist/routes/queue.test.js +78 -0
  165. package/bundle/server/dist/runners/claude-args.js +18 -30
  166. package/bundle/server/dist/runners/claude.js +19 -163
  167. package/bundle/server/dist/runners/claude.test.js +15 -70
  168. package/bundle/server/dist/runners/codex-args.js +59 -0
  169. package/bundle/server/dist/runners/codex-args.test.js +72 -0
  170. package/bundle/server/dist/runners/codex-jsonl.js +150 -0
  171. package/bundle/server/dist/runners/codex-jsonl.test.js +36 -0
  172. package/bundle/server/dist/runners/codex-resume.test.js +19 -0
  173. package/bundle/server/dist/runners/codex.js +46 -0
  174. package/bundle/server/dist/runners/models-codex.test.js +14 -0
  175. package/bundle/server/dist/runners/models.js +53 -1
  176. package/bundle/server/dist/runners/persist.js +4 -1
  177. package/bundle/server/dist/runners/process-registry.js +11 -0
  178. package/bundle/server/dist/runners/prompts.js +13 -280
  179. package/bundle/server/dist/runners/prompts.test.js +22 -153
  180. package/bundle/server/dist/runners/qa.js +17 -1
  181. package/bundle/server/dist/runners/reflect.js +4 -16
  182. package/bundle/server/dist/runners/spawn-cli.js +197 -0
  183. package/bundle/server/dist/runners/spawn-cli.test.js +130 -0
  184. package/bundle/server/dist/runners/stream-json.js +0 -141
  185. package/bundle/server/dist/runners/usage-cap.js +242 -0
  186. package/bundle/server/dist/runners/usage-cap.test.js +97 -0
  187. package/bundle/server/dist/server-liveness.js +37 -0
  188. package/bundle/server/dist/server-liveness.test.js +82 -0
  189. package/bundle/server/dist/static-ui.test.js +44 -0
  190. package/bundle/server/package.json +4 -2
  191. package/bundle/server/static-ui/assets/index-BTtPGYpY.js +60 -0
  192. package/bundle/server/static-ui/assets/index-BxTx4b1d.css +1 -0
  193. package/bundle/server/static-ui/index.html +2 -2
  194. package/bundle/shared/dist/agents.d.ts +262 -133
  195. package/bundle/shared/dist/agents.js +85 -19
  196. package/bundle/shared/dist/cursor-auth-health.d.ts +12 -0
  197. package/bundle/shared/dist/cursor-auth-health.js +36 -0
  198. package/bundle/shared/dist/cursor-auth-health.test.d.ts +1 -0
  199. package/bundle/shared/dist/cursor-auth-health.test.js +40 -0
  200. package/bundle/shared/dist/findings.d.ts +46 -0
  201. package/bundle/shared/dist/findings.js +17 -0
  202. package/bundle/shared/dist/findings.test.d.ts +1 -0
  203. package/bundle/shared/dist/findings.test.js +20 -0
  204. package/bundle/shared/dist/github-repo.d.ts +28 -0
  205. package/bundle/shared/dist/github-repo.js +98 -0
  206. package/bundle/shared/dist/github-repo.test.d.ts +1 -0
  207. package/bundle/shared/dist/github-repo.test.js +32 -0
  208. package/bundle/shared/dist/human-actions.d.ts +66 -0
  209. package/bundle/shared/dist/human-actions.js +51 -0
  210. package/bundle/shared/dist/human-actions.test.d.ts +1 -0
  211. package/bundle/shared/dist/human-actions.test.js +57 -0
  212. package/bundle/shared/dist/index.d.ts +567 -757
  213. package/bundle/shared/dist/index.js +22 -36
  214. package/bundle/shared/dist/issues.d.ts +385 -0
  215. package/bundle/shared/dist/issues.js +169 -0
  216. package/bundle/shared/dist/issues.test.d.ts +1 -0
  217. package/bundle/shared/dist/issues.test.js +72 -0
  218. package/bundle/shared/dist/outbound-draft.d.ts +6 -0
  219. package/bundle/shared/dist/outbound-draft.js +4 -0
  220. package/bundle/shared/dist/plan-triage.d.ts +6 -6
  221. package/bundle/shared/dist/profile-snapshot.d.ts +154 -0
  222. package/bundle/shared/dist/profile-snapshot.js +145 -0
  223. package/bundle/shared/dist/profile-snapshot.test.d.ts +1 -0
  224. package/bundle/shared/dist/profile-snapshot.test.js +67 -0
  225. package/bundle/shared/dist/queue-entries.d.ts +89 -0
  226. package/bundle/shared/dist/queue-entries.js +19 -0
  227. package/bundle/shared/dist/result-qa.d.ts +2 -2
  228. package/bundle/shared/dist/runtime-auth-health.d.ts +66 -0
  229. package/bundle/shared/dist/runtime-auth-health.js +186 -0
  230. package/bundle/shared/dist/runtime-auth-health.test.d.ts +1 -0
  231. package/bundle/shared/dist/runtime-auth-health.test.js +200 -0
  232. package/bundle/shared/dist/runtime-availability.d.ts +51 -0
  233. package/bundle/shared/dist/runtime-availability.js +13 -0
  234. package/bundle/shared/dist/runtime.d.ts +1 -1
  235. package/bundle/shared/dist/runtime.js +1 -1
  236. package/bundle/shared/dist/usage-events.d.ts +36 -0
  237. package/bundle/shared/dist/usage-events.js +13 -0
  238. package/bundle/shared/dist/worker-sessions.d.ts +140 -0
  239. package/bundle/shared/dist/worker-sessions.js +70 -0
  240. package/bundle/shared/dist/worker-sessions.test.d.ts +1 -0
  241. package/bundle/shared/dist/worker-sessions.test.js +39 -0
  242. package/bundle/shared/dist/workflow.d.ts +78 -0
  243. package/bundle/shared/dist/workflow.js +59 -0
  244. package/bundle/shared/dist/workflow.test.d.ts +1 -0
  245. package/bundle/shared/dist/workflow.test.js +61 -0
  246. package/bundle/shared/package.json +1 -1
  247. package/dist/action.d.ts +1 -0
  248. package/dist/action.js +50 -0
  249. package/dist/action.test.d.ts +1 -0
  250. package/dist/action.test.js +70 -0
  251. package/dist/agent.d.ts +1 -0
  252. package/dist/agent.js +17 -0
  253. package/dist/agent.test.d.ts +1 -0
  254. package/dist/agent.test.js +19 -0
  255. package/dist/cli-check.d.ts +7 -0
  256. package/dist/cli-check.js +40 -0
  257. package/dist/doctor.js +59 -1
  258. package/dist/http.d.ts +5 -0
  259. package/dist/http.js +19 -0
  260. package/dist/index.js +28 -0
  261. package/dist/issue.d.ts +35 -0
  262. package/dist/issue.js +143 -0
  263. package/dist/issue.test.d.ts +1 -0
  264. package/dist/issue.test.js +240 -0
  265. package/dist/lifecycle.contract.test.d.ts +1 -0
  266. package/dist/lifecycle.contract.test.js +135 -0
  267. package/dist/queue.d.ts +11 -0
  268. package/dist/queue.js +60 -0
  269. package/dist/queue.test.d.ts +1 -0
  270. package/dist/queue.test.js +46 -0
  271. package/dist/test-fetch-stub.d.ts +6 -0
  272. package/dist/test-fetch-stub.js +31 -0
  273. package/package.json +2 -1
  274. package/templates/prod.env.example +1 -1
  275. package/bundle/server/static-ui/assets/index-B_7S7xJb.js +0 -79
  276. package/bundle/server/static-ui/assets/index-QYv3zmE6.css +0 -1
@@ -0,0 +1,72 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { canTransitionIssue, CreateIssueInput, Issue } from "./issues.js";
4
+ test("issue transitions: ready to developing is allowed", () => {
5
+ assert.equal(canTransitionIssue("ready", "developing"), true);
6
+ });
7
+ test("issue transitions: done is terminal", () => {
8
+ assert.equal(canTransitionIssue("done", "developing"), false);
9
+ assert.equal(canTransitionIssue("done", "closed"), false);
10
+ });
11
+ test("issue transitions: cannot skip straight from ready to final_review", () => {
12
+ assert.equal(canTransitionIssue("ready", "final_review"), false);
13
+ });
14
+ test("issue transitions: final_review can send back to repairing", () => {
15
+ assert.equal(canTransitionIssue("final_review", "repairing"), true);
16
+ });
17
+ test("issue transitions: reviewing can self-loop (stale-review retry at a fresh head)", () => {
18
+ assert.equal(canTransitionIssue("reviewing", "reviewing"), true);
19
+ });
20
+ test("Issue schema parses a well-formed issue", () => {
21
+ const issue = {
22
+ id: "11111111-1111-1111-1111-111111111111",
23
+ source: "manual",
24
+ externalId: null,
25
+ externalLabel: null,
26
+ externalUrl: null,
27
+ title: "Fix login bug",
28
+ description: null,
29
+ acceptanceCriteria: null,
30
+ repo: "acme/app",
31
+ baseBranch: "main",
32
+ status: "ready",
33
+ currentOwner: "system",
34
+ currentIntent: null,
35
+ developerAgentId: "22222222-2222-2222-2222-222222222222",
36
+ reviewerAgentId: "33333333-3333-3333-3333-333333333333",
37
+ maxReviewRounds: 3,
38
+ currentRound: 1,
39
+ maxInfraAttempts: 3,
40
+ infraAttempts: 0,
41
+ branch: null,
42
+ baseSha: null,
43
+ headSha: null,
44
+ prNumber: null,
45
+ prUrl: null,
46
+ autoMerge: false,
47
+ createdAt: new Date().toISOString(),
48
+ updatedAt: new Date().toISOString()
49
+ };
50
+ assert.deepStrictEqual(Issue.parse(issue), issue);
51
+ });
52
+ test("CreateIssueInput defaults baseBranch to main and maxReviewRounds to 3", () => {
53
+ const parsed = CreateIssueInput.parse({
54
+ title: "Fix login bug",
55
+ repo: "acme/app",
56
+ developerAgentId: "22222222-2222-2222-2222-222222222222",
57
+ reviewerAgentId: "33333333-3333-3333-3333-333333333333"
58
+ });
59
+ assert.equal(parsed.baseBranch, "main");
60
+ assert.equal(parsed.maxReviewRounds, 3);
61
+ assert.equal(parsed.source, "manual");
62
+ assert.equal(parsed.autoMerge, false);
63
+ assert.equal(parsed.repo, "github.com/acme/app");
64
+ });
65
+ test("CreateIssueInput rejects local filesystem paths (NOT-149)", () => {
66
+ assert.throws(() => CreateIssueInput.parse({
67
+ title: "Local",
68
+ repo: "/repo",
69
+ developerAgentId: "22222222-2222-2222-2222-222222222222",
70
+ reviewerAgentId: "33333333-3333-3333-3333-333333333333",
71
+ }), /Local filesystem|Invalid/);
72
+ });
@@ -132,6 +132,10 @@ export declare const OutboundDraftContent: z.ZodObject<{
132
132
  sentAt: z.ZodOptional<z.ZodString>;
133
133
  rejectedAt: z.ZodOptional<z.ZodString>;
134
134
  bodyMismatch: z.ZodOptional<z.ZodBoolean>;
135
+ /** Count of real delivery attempts made for this draft (NOT-95) — feeds the execution
136
+ * authority idempotency key (`${draftArtifactId}:${deliveryAttempts}`) so a retry after
137
+ * INTERACTION_REQUIRED mints a genuinely distinct authority rather than reusing one. */
138
+ deliveryAttempts: z.ZodDefault<z.ZodNumber>;
135
139
  }, "strip", z.ZodTypeAny, {
136
140
  status: "pending" | "sent" | "rejected";
137
141
  draft: {
@@ -146,6 +150,7 @@ export declare const OutboundDraftContent: z.ZodObject<{
146
150
  arguments: Record<string, unknown>;
147
151
  };
148
152
  };
153
+ deliveryAttempts: number;
149
154
  sentAt?: string | undefined;
150
155
  rejectedAt?: string | undefined;
151
156
  bodyMismatch?: boolean | undefined;
@@ -166,6 +171,7 @@ export declare const OutboundDraftContent: z.ZodObject<{
166
171
  sentAt?: string | undefined;
167
172
  rejectedAt?: string | undefined;
168
173
  bodyMismatch?: boolean | undefined;
174
+ deliveryAttempts?: number | undefined;
169
175
  }>;
170
176
  export type OutboundDraftContent = z.infer<typeof OutboundDraftContent>;
171
177
  /** send_receipt artifact contentJson (PRD §7.3). */
@@ -23,6 +23,10 @@ export const OutboundDraftContent = z.object({
23
23
  sentAt: z.string().optional(),
24
24
  rejectedAt: z.string().optional(),
25
25
  bodyMismatch: z.boolean().optional(),
26
+ /** Count of real delivery attempts made for this draft (NOT-95) — feeds the execution
27
+ * authority idempotency key (`${draftArtifactId}:${deliveryAttempts}`) so a retry after
28
+ * INTERACTION_REQUIRED mints a genuinely distinct authority rather than reusing one. */
29
+ deliveryAttempts: z.number().int().min(0).default(0),
26
30
  });
27
31
  /** send_receipt artifact contentJson (PRD §7.3). */
28
32
  export const SendReceiptContent = z.object({
@@ -74,8 +74,8 @@ export declare const PlanTriageBlock: z.ZodEffects<z.ZodObject<{
74
74
  question: string;
75
75
  }>, "many">>;
76
76
  }, "strip", z.ZodTypeAny, {
77
- verdict: "trivial" | "needs_review";
78
77
  rationale: string;
78
+ verdict: "trivial" | "needs_review";
79
79
  questions: {
80
80
  options: {
81
81
  label: string;
@@ -85,8 +85,8 @@ export declare const PlanTriageBlock: z.ZodEffects<z.ZodObject<{
85
85
  question: string;
86
86
  }[];
87
87
  }, {
88
- verdict: "trivial" | "needs_review";
89
88
  rationale: string;
89
+ verdict: "trivial" | "needs_review";
90
90
  questions?: {
91
91
  options: {
92
92
  label: string;
@@ -96,8 +96,8 @@ export declare const PlanTriageBlock: z.ZodEffects<z.ZodObject<{
96
96
  question: string;
97
97
  }[] | undefined;
98
98
  }>, {
99
- verdict: "trivial" | "needs_review";
100
99
  rationale: string;
100
+ verdict: "trivial" | "needs_review";
101
101
  questions: {
102
102
  options: {
103
103
  label: string;
@@ -107,8 +107,8 @@ export declare const PlanTriageBlock: z.ZodEffects<z.ZodObject<{
107
107
  question: string;
108
108
  }[];
109
109
  }, {
110
- verdict: "trivial" | "needs_review";
111
110
  rationale: string;
111
+ verdict: "trivial" | "needs_review";
112
112
  questions?: {
113
113
  options: {
114
114
  label: string;
@@ -155,8 +155,8 @@ export declare const PlanTriageContent: z.ZodObject<{
155
155
  parseFallback: z.ZodBoolean;
156
156
  consumed: z.ZodDefault<z.ZodBoolean>;
157
157
  }, "strip", z.ZodTypeAny, {
158
- verdict: "trivial" | "needs_review";
159
158
  rationale: string;
159
+ verdict: "trivial" | "needs_review";
160
160
  questions: {
161
161
  options: {
162
162
  label: string;
@@ -169,8 +169,8 @@ export declare const PlanTriageContent: z.ZodObject<{
169
169
  consumed: boolean;
170
170
  sessionId?: string | undefined;
171
171
  }, {
172
- verdict: "trivial" | "needs_review";
173
172
  rationale: string;
173
+ verdict: "trivial" | "needs_review";
174
174
  questions: {
175
175
  options: {
176
176
  label: string;
@@ -0,0 +1,154 @@
1
+ import { z } from "zod";
2
+ import { WorkerSessionRole } from "./worker-sessions.js";
3
+ /**
4
+ * The effective capabilities a worker session may exercise at the runtime boundary
5
+ * (ADR 0003 §Role permissions). Resolved once when the session is created and frozen
6
+ * into `worker_sessions.profile_snapshot_json` — a later profile edit never changes a
7
+ * queued or running session.
8
+ *
9
+ * Every field here is backed by a control this codebase can actually enforce from
10
+ * outside the worker process — a CLI tool-permission grant (`--allowedTools` /
11
+ * `-s read-only`) or a config-loading boundary (`--ignore-user-config`) — never a
12
+ * denylist over arguments to a capability (e.g. Bash) the worker already holds
13
+ * unrestricted, which a review round proved bypassable (absolute paths, `-C`, wrapper
14
+ * commands, or — for `push` — simply editing the very git config meant to restrict it,
15
+ * since that config lives inside the worktree the same process can already write).
16
+ * `push` / `openPr` are NOT modeled here for that reason: real enforcement needs those
17
+ * credentialed effects to move to a call the worker never makes itself (the coordinator,
18
+ * which already owns "the only component that publishes" for reviews) — developer→PR
19
+ * handoff scope (NOT-61+), not a profile toggle this ticket can honestly ship.
20
+ *
21
+ * Role defaults are the ceiling: a profile's `permissionPolicy` override may only
22
+ * *tighten* a capability (turn it off), never grant one the role does not have.
23
+ */
24
+ export declare const PermissionPolicy: z.ZodObject<{
25
+ /** developer only: read/write files in its own worktree — CLI tool-grant enforced. */
26
+ worktreeWrite: z.ZodBoolean;
27
+ /** never true in v1 — the coordinator, not the reviewer, publishes the review. */
28
+ publishReview: z.ZodBoolean;
29
+ /** call outbound-mutation deck tools (`call_service_tool`). Off for both roles in v1. */
30
+ outboundMutation: z.ZodBoolean;
31
+ /** resolve human actions / edit workflow topology. Always off for workers. */
32
+ resolveHumanAction: z.ZodBoolean;
33
+ }, "strip", z.ZodTypeAny, {
34
+ worktreeWrite: boolean;
35
+ publishReview: boolean;
36
+ outboundMutation: boolean;
37
+ resolveHumanAction: boolean;
38
+ }, {
39
+ worktreeWrite: boolean;
40
+ publishReview: boolean;
41
+ outboundMutation: boolean;
42
+ resolveHumanAction: boolean;
43
+ }>;
44
+ export type PermissionPolicy = z.infer<typeof PermissionPolicy>;
45
+ /** The subset of a policy a profile may pin off. Absent field = use the role default. */
46
+ export declare const PermissionPolicyOverride: z.ZodObject<{
47
+ worktreeWrite: z.ZodOptional<z.ZodBoolean>;
48
+ outboundMutation: z.ZodOptional<z.ZodBoolean>;
49
+ }, "strict", z.ZodTypeAny, {
50
+ worktreeWrite?: boolean | undefined;
51
+ outboundMutation?: boolean | undefined;
52
+ }, {
53
+ worktreeWrite?: boolean | undefined;
54
+ outboundMutation?: boolean | undefined;
55
+ }>;
56
+ export type PermissionPolicyOverride = z.infer<typeof PermissionPolicyOverride>;
57
+ export declare const DEVELOPER_ROLE_CEILING: PermissionPolicy;
58
+ export declare const REVIEWER_ROLE_CEILING: PermissionPolicy;
59
+ export declare function roleCeiling(role: z.infer<typeof WorkerSessionRole>): PermissionPolicy;
60
+ /**
61
+ * Tiered reasoning / thinking effort for CLIs that expose it (Codex
62
+ * `model_reasoning_effort`, Claude Code `--effort`). Cursor has no separate flag —
63
+ * effort is only expressible inside a parameterized model id.
64
+ */
65
+ export declare const ReasoningEffort: z.ZodEnum<["low", "medium", "high"]>;
66
+ export type ReasoningEffort = z.infer<typeof ReasoningEffort>;
67
+ /**
68
+ * The immutable execution contract snapshotted onto every `worker_session` at creation
69
+ * (design §`agents` / §"Immutable execution-profile snapshot"). Transcripts, findings,
70
+ * and usage stay owned by the issue/session — completing work never writes anything back
71
+ * into the profile.
72
+ */
73
+ export declare const ProfileSnapshot: z.ZodObject<{
74
+ /** Schema version so an in-flight session stays reconstructable across format changes. */
75
+ version: z.ZodLiteral<1>;
76
+ agentId: z.ZodNullable<z.ZodString>;
77
+ role: z.ZodEnum<["developer", "reviewer", "legacy"]>;
78
+ runtime: z.ZodNullable<z.ZodEnum<["claude_code", "cursor_local", "codex_local"]>>;
79
+ model: z.ZodNullable<z.ZodString>;
80
+ /**
81
+ * Reasoning effort frozen with the session (NOT-81). `.default(null)` so snapshots
82
+ * written before this field still parse instead of invalidating the whole contract.
83
+ */
84
+ effort: z.ZodDefault<z.ZodNullable<z.ZodEnum<["low", "medium", "high"]>>>;
85
+ /** Serialized PhaseBudget; null = runtime default (no CLI caps). */
86
+ budgetJson: z.ZodNullable<z.ZodString>;
87
+ permissionPolicy: z.ZodObject<{
88
+ /** developer only: read/write files in its own worktree — CLI tool-grant enforced. */
89
+ worktreeWrite: z.ZodBoolean;
90
+ /** never true in v1 — the coordinator, not the reviewer, publishes the review. */
91
+ publishReview: z.ZodBoolean;
92
+ /** call outbound-mutation deck tools (`call_service_tool`). Off for both roles in v1. */
93
+ outboundMutation: z.ZodBoolean;
94
+ /** resolve human actions / edit workflow topology. Always off for workers. */
95
+ resolveHumanAction: z.ZodBoolean;
96
+ }, "strip", z.ZodTypeAny, {
97
+ worktreeWrite: boolean;
98
+ publishReview: boolean;
99
+ outboundMutation: boolean;
100
+ resolveHumanAction: boolean;
101
+ }, {
102
+ worktreeWrite: boolean;
103
+ publishReview: boolean;
104
+ outboundMutation: boolean;
105
+ resolveHumanAction: boolean;
106
+ }>;
107
+ /** Launch-selected Deck — required for new sessions; null only on legacy in-flight rows. */
108
+ deckId: z.ZodNullable<z.ZodString>;
109
+ purpose: z.ZodNullable<z.ZodString>;
110
+ capturedAt: z.ZodString;
111
+ }, "strip", z.ZodTypeAny, {
112
+ role: "developer" | "reviewer" | "legacy";
113
+ agentId: string | null;
114
+ runtime: "claude_code" | "cursor_local" | "codex_local" | null;
115
+ model: string | null;
116
+ budgetJson: string | null;
117
+ version: 1;
118
+ effort: "low" | "medium" | "high" | null;
119
+ permissionPolicy: {
120
+ worktreeWrite: boolean;
121
+ publishReview: boolean;
122
+ outboundMutation: boolean;
123
+ resolveHumanAction: boolean;
124
+ };
125
+ deckId: string | null;
126
+ purpose: string | null;
127
+ capturedAt: string;
128
+ }, {
129
+ role: "developer" | "reviewer" | "legacy";
130
+ agentId: string | null;
131
+ runtime: "claude_code" | "cursor_local" | "codex_local" | null;
132
+ model: string | null;
133
+ budgetJson: string | null;
134
+ version: 1;
135
+ permissionPolicy: {
136
+ worktreeWrite: boolean;
137
+ publishReview: boolean;
138
+ outboundMutation: boolean;
139
+ resolveHumanAction: boolean;
140
+ };
141
+ deckId: string | null;
142
+ purpose: string | null;
143
+ capturedAt: string;
144
+ effort?: "low" | "medium" | "high" | null | undefined;
145
+ }>;
146
+ export type ProfileSnapshot = z.infer<typeof ProfileSnapshot>;
147
+ export declare function parseProfileSnapshot(json: string | null | undefined): ProfileSnapshot | null;
148
+ /** Serialized `string[]` helpers for the profile list columns. */
149
+ export declare function serializeStringList(list: readonly string[] | null | undefined): string | null;
150
+ export declare function parseStringList(json: string | null | undefined): string[];
151
+ export declare function serializePermissionPolicyOverride(override: PermissionPolicyOverride | null | undefined): string | null;
152
+ export declare function parsePermissionPolicyOverride(json: string | null | undefined): PermissionPolicyOverride | null;
153
+ /** Apply a profile override to a role ceiling. Override can only turn capabilities off. */
154
+ export declare function resolvePermissionPolicy(role: z.infer<typeof WorkerSessionRole>, override: PermissionPolicyOverride | null | undefined): PermissionPolicy;
@@ -0,0 +1,145 @@
1
+ import { z } from "zod";
2
+ import { Runtime } from "./runtime.js";
3
+ import { WorkerSessionRole } from "./worker-sessions.js";
4
+ /**
5
+ * The effective capabilities a worker session may exercise at the runtime boundary
6
+ * (ADR 0003 §Role permissions). Resolved once when the session is created and frozen
7
+ * into `worker_sessions.profile_snapshot_json` — a later profile edit never changes a
8
+ * queued or running session.
9
+ *
10
+ * Every field here is backed by a control this codebase can actually enforce from
11
+ * outside the worker process — a CLI tool-permission grant (`--allowedTools` /
12
+ * `-s read-only`) or a config-loading boundary (`--ignore-user-config`) — never a
13
+ * denylist over arguments to a capability (e.g. Bash) the worker already holds
14
+ * unrestricted, which a review round proved bypassable (absolute paths, `-C`, wrapper
15
+ * commands, or — for `push` — simply editing the very git config meant to restrict it,
16
+ * since that config lives inside the worktree the same process can already write).
17
+ * `push` / `openPr` are NOT modeled here for that reason: real enforcement needs those
18
+ * credentialed effects to move to a call the worker never makes itself (the coordinator,
19
+ * which already owns "the only component that publishes" for reviews) — developer→PR
20
+ * handoff scope (NOT-61+), not a profile toggle this ticket can honestly ship.
21
+ *
22
+ * Role defaults are the ceiling: a profile's `permissionPolicy` override may only
23
+ * *tighten* a capability (turn it off), never grant one the role does not have.
24
+ */
25
+ export const PermissionPolicy = z.object({
26
+ /** developer only: read/write files in its own worktree — CLI tool-grant enforced. */
27
+ worktreeWrite: z.boolean(),
28
+ /** never true in v1 — the coordinator, not the reviewer, publishes the review. */
29
+ publishReview: z.boolean(),
30
+ /** call outbound-mutation deck tools (`call_service_tool`). Off for both roles in v1. */
31
+ outboundMutation: z.boolean(),
32
+ /** resolve human actions / edit workflow topology. Always off for workers. */
33
+ resolveHumanAction: z.boolean(),
34
+ });
35
+ /** The subset of a policy a profile may pin off. Absent field = use the role default. */
36
+ export const PermissionPolicyOverride = z
37
+ .object({
38
+ worktreeWrite: z.boolean().optional(),
39
+ outboundMutation: z.boolean().optional(),
40
+ })
41
+ .strict();
42
+ export const DEVELOPER_ROLE_CEILING = {
43
+ worktreeWrite: true,
44
+ publishReview: false,
45
+ outboundMutation: false,
46
+ resolveHumanAction: false,
47
+ };
48
+ export const REVIEWER_ROLE_CEILING = {
49
+ worktreeWrite: false,
50
+ publishReview: false,
51
+ outboundMutation: false,
52
+ resolveHumanAction: false,
53
+ };
54
+ export function roleCeiling(role) {
55
+ return role === "developer" ? DEVELOPER_ROLE_CEILING : REVIEWER_ROLE_CEILING;
56
+ }
57
+ /**
58
+ * Tiered reasoning / thinking effort for CLIs that expose it (Codex
59
+ * `model_reasoning_effort`, Claude Code `--effort`). Cursor has no separate flag —
60
+ * effort is only expressible inside a parameterized model id.
61
+ */
62
+ export const ReasoningEffort = z.enum(["low", "medium", "high"]);
63
+ /**
64
+ * The immutable execution contract snapshotted onto every `worker_session` at creation
65
+ * (design §`agents` / §"Immutable execution-profile snapshot"). Transcripts, findings,
66
+ * and usage stay owned by the issue/session — completing work never writes anything back
67
+ * into the profile.
68
+ */
69
+ export const ProfileSnapshot = z.object({
70
+ /** Schema version so an in-flight session stays reconstructable across format changes. */
71
+ version: z.literal(1),
72
+ agentId: z.string().nullable(),
73
+ role: WorkerSessionRole,
74
+ runtime: Runtime.nullable(),
75
+ model: z.string().nullable(),
76
+ /**
77
+ * Reasoning effort frozen with the session (NOT-81). `.default(null)` so snapshots
78
+ * written before this field still parse instead of invalidating the whole contract.
79
+ */
80
+ effort: ReasoningEffort.nullable().default(null),
81
+ /** Serialized PhaseBudget; null = runtime default (no CLI caps). */
82
+ budgetJson: z.string().nullable(),
83
+ permissionPolicy: PermissionPolicy,
84
+ /** Launch-selected Deck — required for new sessions; null only on legacy in-flight rows. */
85
+ deckId: z.string().nullable(),
86
+ purpose: z.string().nullable(),
87
+ capturedAt: z.string(),
88
+ });
89
+ export function parseProfileSnapshot(json) {
90
+ if (!json?.trim())
91
+ return null;
92
+ try {
93
+ return ProfileSnapshot.parse(JSON.parse(json));
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ /** Serialized `string[]` helpers for the profile list columns. */
100
+ export function serializeStringList(list) {
101
+ if (!list)
102
+ return null;
103
+ const cleaned = list.map((s) => s.trim()).filter(Boolean);
104
+ return cleaned.length ? JSON.stringify(cleaned) : null;
105
+ }
106
+ export function parseStringList(json) {
107
+ if (!json?.trim())
108
+ return [];
109
+ try {
110
+ const parsed = JSON.parse(json);
111
+ return z.array(z.string()).parse(parsed);
112
+ }
113
+ catch {
114
+ return [];
115
+ }
116
+ }
117
+ export function serializePermissionPolicyOverride(override) {
118
+ if (!override)
119
+ return null;
120
+ const entries = Object.entries(override).filter(([, v]) => v !== undefined);
121
+ return entries.length ? JSON.stringify(Object.fromEntries(entries)) : null;
122
+ }
123
+ export function parsePermissionPolicyOverride(json) {
124
+ if (!json?.trim())
125
+ return null;
126
+ try {
127
+ return PermissionPolicyOverride.parse(JSON.parse(json));
128
+ }
129
+ catch {
130
+ return null;
131
+ }
132
+ }
133
+ /** Apply a profile override to a role ceiling. Override can only turn capabilities off. */
134
+ export function resolvePermissionPolicy(role, override) {
135
+ const ceiling = roleCeiling(role);
136
+ if (!override)
137
+ return { ...ceiling };
138
+ const resolved = { ...ceiling };
139
+ for (const key of ["worktreeWrite", "outboundMutation"]) {
140
+ if (override[key] === false)
141
+ resolved[key] = false;
142
+ // override[key] === true can never raise the ceiling — ignored.
143
+ }
144
+ return resolved;
145
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { parsePermissionPolicyOverride, parseProfileSnapshot, parseStringList, resolvePermissionPolicy, serializePermissionPolicyOverride, serializeStringList, } from "./profile-snapshot.js";
4
+ test("serializeStringList trims, drops blanks, and returns null when empty", () => {
5
+ assert.equal(serializeStringList([" a ", "", "b"]), JSON.stringify(["a", "b"]));
6
+ assert.equal(serializeStringList([]), null);
7
+ assert.equal(serializeStringList(null), null);
8
+ assert.deepEqual(parseStringList(serializeStringList(["x", "y"])), ["x", "y"]);
9
+ assert.deepEqual(parseStringList("not json"), []);
10
+ });
11
+ test("resolvePermissionPolicy: override only tightens, never loosens", () => {
12
+ assert.equal(resolvePermissionPolicy("developer", { outboundMutation: false }).outboundMutation, false);
13
+ assert.equal(resolvePermissionPolicy("developer", { outboundMutation: false }).worktreeWrite, true);
14
+ assert.equal(resolvePermissionPolicy("reviewer", { worktreeWrite: true }).worktreeWrite, false);
15
+ });
16
+ test("permission-policy override serialization round-trips; parse rejects unknown keys", () => {
17
+ assert.equal(serializePermissionPolicyOverride({ worktreeWrite: false }), JSON.stringify({ worktreeWrite: false }));
18
+ assert.equal(serializePermissionPolicyOverride(null), null);
19
+ assert.deepEqual(parsePermissionPolicyOverride(JSON.stringify({ worktreeWrite: false })), {
20
+ worktreeWrite: false,
21
+ });
22
+ // push/openPr are not a recognized override key (never modeled — see PermissionPolicy
23
+ // doc comment) and resolveHumanAction is not overridable either; both are rejected.
24
+ assert.equal(parsePermissionPolicyOverride(JSON.stringify({ push: false })), null);
25
+ assert.equal(parsePermissionPolicyOverride(JSON.stringify({ resolveHumanAction: true })), null);
26
+ });
27
+ test("parseProfileSnapshot round-trips a valid snapshot and rejects junk", () => {
28
+ const snap = {
29
+ version: 1,
30
+ agentId: "a1",
31
+ role: "reviewer",
32
+ runtime: "claude_code",
33
+ model: null,
34
+ effort: "medium",
35
+ budgetJson: null,
36
+ permissionPolicy: resolvePermissionPolicy("reviewer", null),
37
+ deckId: "00000000-0000-4000-a000-000000000099",
38
+ purpose: null,
39
+ capturedAt: new Date().toISOString(),
40
+ };
41
+ assert.deepEqual(parseProfileSnapshot(JSON.stringify(snap)), snap);
42
+ assert.equal(parseProfileSnapshot("{}"), null);
43
+ assert.equal(parseProfileSnapshot(null), null);
44
+ });
45
+ test("parseProfileSnapshot strips legacy workspace/playbook/memory fields (NOT-149)", () => {
46
+ const legacy = {
47
+ version: 1,
48
+ agentId: "a1",
49
+ role: "developer",
50
+ runtime: "codex_local",
51
+ model: "gpt-5",
52
+ budgetJson: null,
53
+ permissionPolicy: resolvePermissionPolicy("developer", null),
54
+ deckId: null,
55
+ workspaceRoot: "/repo",
56
+ playbookIds: ["pb_x"],
57
+ externalMemoryRefs: ["vault://x"],
58
+ purpose: null,
59
+ capturedAt: new Date().toISOString(),
60
+ };
61
+ const parsed = parseProfileSnapshot(JSON.stringify(legacy));
62
+ assert.ok(parsed);
63
+ assert.equal(parsed.effort, null);
64
+ assert.equal("workspaceRoot" in parsed, false);
65
+ assert.equal("playbookIds" in parsed, false);
66
+ assert.equal("externalMemoryRefs" in parsed, false);
67
+ });
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import type { WorkflowInstance } from "./workflow.js";
3
+ export declare const QueueEntryState: z.ZodEnum<["queued", "admitted", "removed"]>;
4
+ export type QueueEntryState = z.infer<typeof QueueEntryState>;
5
+ export declare const QueueEntry: z.ZodObject<{
6
+ id: z.ZodString;
7
+ issueId: z.ZodString;
8
+ position: z.ZodNumber;
9
+ enqueuedAt: z.ZodString;
10
+ state: z.ZodEnum<["queued", "admitted", "removed"]>;
11
+ waitReason: z.ZodNullable<z.ZodString>;
12
+ waitReasonAt: z.ZodNullable<z.ZodString>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ id: string;
15
+ issueId: string;
16
+ position: number;
17
+ enqueuedAt: string;
18
+ state: "queued" | "admitted" | "removed";
19
+ waitReason: string | null;
20
+ waitReasonAt: string | null;
21
+ }, {
22
+ id: string;
23
+ issueId: string;
24
+ position: number;
25
+ enqueuedAt: string;
26
+ state: "queued" | "admitted" | "removed";
27
+ waitReason: string | null;
28
+ waitReasonAt: string | null;
29
+ }>;
30
+ export type QueueEntry = z.infer<typeof QueueEntry>;
31
+ /** Enriched row for GET /api/queue — includes issue title for UI/CLI. */
32
+ export declare const QueueEntryView: z.ZodObject<{
33
+ id: z.ZodString;
34
+ issueId: z.ZodString;
35
+ position: z.ZodNumber;
36
+ enqueuedAt: z.ZodString;
37
+ state: z.ZodEnum<["queued", "admitted", "removed"]>;
38
+ waitReason: z.ZodNullable<z.ZodString>;
39
+ waitReasonAt: z.ZodNullable<z.ZodString>;
40
+ } & {
41
+ title: z.ZodOptional<z.ZodString>;
42
+ issueStatus: z.ZodOptional<z.ZodString>;
43
+ }, "strip", z.ZodTypeAny, {
44
+ id: string;
45
+ issueId: string;
46
+ position: number;
47
+ enqueuedAt: string;
48
+ state: "queued" | "admitted" | "removed";
49
+ waitReason: string | null;
50
+ waitReasonAt: string | null;
51
+ title?: string | undefined;
52
+ issueStatus?: string | undefined;
53
+ }, {
54
+ id: string;
55
+ issueId: string;
56
+ position: number;
57
+ enqueuedAt: string;
58
+ state: "queued" | "admitted" | "removed";
59
+ waitReason: string | null;
60
+ waitReasonAt: string | null;
61
+ title?: string | undefined;
62
+ issueStatus?: string | undefined;
63
+ }>;
64
+ export type QueueEntryView = z.infer<typeof QueueEntryView>;
65
+ export declare const EnqueueIssueInput: z.ZodObject<{
66
+ issueId: z.ZodString;
67
+ }, "strip", z.ZodTypeAny, {
68
+ issueId: string;
69
+ }, {
70
+ issueId: string;
71
+ }>;
72
+ export type EnqueueIssueInput = z.infer<typeof EnqueueIssueInput>;
73
+ /**
74
+ * NOT-118 `POST /api/issues/:id/start` response. Start has no queue bypass: it moves the
75
+ * issue to the front and admits it when a slot is free, otherwise it waits at the top with
76
+ * a reason. `workItem` is the round-1 developer item the admitted start enqueued.
77
+ */
78
+ export type StartIssueResponse = {
79
+ state: "admitted";
80
+ instance: WorkflowInstance;
81
+ workItem: {
82
+ id: string;
83
+ kind: string;
84
+ };
85
+ } | {
86
+ state: "queued";
87
+ position: number;
88
+ waitReason: string | null;
89
+ };
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ export const QueueEntryState = z.enum(["queued", "admitted", "removed"]);
3
+ export const QueueEntry = z.object({
4
+ id: z.string().uuid(),
5
+ issueId: z.string().uuid(),
6
+ position: z.number().int(),
7
+ enqueuedAt: z.string(),
8
+ state: QueueEntryState,
9
+ waitReason: z.string().nullable(),
10
+ waitReasonAt: z.string().nullable(),
11
+ });
12
+ /** Enriched row for GET /api/queue — includes issue title for UI/CLI. */
13
+ export const QueueEntryView = QueueEntry.extend({
14
+ title: z.string().optional(),
15
+ issueStatus: z.string().optional(),
16
+ });
17
+ export const EnqueueIssueInput = z.object({
18
+ issueId: z.string().uuid(),
19
+ });
@@ -13,7 +13,7 @@ export declare const ResultQaContent: z.ZodObject<{
13
13
  answeredAt: z.ZodOptional<z.ZodString>;
14
14
  error: z.ZodOptional<z.ZodString>;
15
15
  }, "strip", z.ZodTypeAny, {
16
- status: "pending" | "answered" | "failed";
16
+ status: "failed" | "pending" | "answered";
17
17
  question: string;
18
18
  exchangeId: string;
19
19
  sessionResumed: boolean;
@@ -22,7 +22,7 @@ export declare const ResultQaContent: z.ZodObject<{
22
22
  answer?: string | undefined;
23
23
  error?: string | undefined;
24
24
  }, {
25
- status: "pending" | "answered" | "failed";
25
+ status: "failed" | "pending" | "answered";
26
26
  question: string;
27
27
  exchangeId: string;
28
28
  sessionResumed: boolean;