agent-dealer 0.1.2 → 0.1.4

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 (40) hide show
  1. package/bundle/server/dist/adapters/agent-deck-deliver.test.js +52 -0
  2. package/bundle/server/dist/adapters/agent-deck.js +140 -0
  3. package/bundle/server/dist/queue/answers.test.js +117 -0
  4. package/bundle/server/dist/queue/approve-deliver.js +62 -0
  5. package/bundle/server/dist/queue/dispatcher.js +176 -2
  6. package/bundle/server/dist/queue/plan-gate.test.js +55 -0
  7. package/bundle/server/dist/queue/send-gate.test.js +108 -0
  8. package/bundle/server/dist/repository/outbound-drafts.js +62 -0
  9. package/bundle/server/dist/repository/runs.js +17 -1
  10. package/bundle/server/dist/routes/index.js +41 -17
  11. package/bundle/server/dist/runners/claude-args.js +24 -0
  12. package/bundle/server/dist/runners/claude.js +9 -18
  13. package/bundle/server/dist/runners/claude.test.js +58 -0
  14. package/bundle/server/dist/runners/persist.js +46 -7
  15. package/bundle/server/dist/runners/prompts.js +87 -1
  16. package/bundle/server/dist/runners/prompts.test.js +92 -0
  17. package/bundle/server/dist/runners/reflect.js +1 -1
  18. package/bundle/server/dist/runners/stream-json.js +51 -0
  19. package/bundle/server/dist/runners/stream-json.test.js +95 -0
  20. package/bundle/server/dist/usage-summary.js +9 -4
  21. package/bundle/server/package.json +3 -2
  22. package/bundle/server/static-ui/assets/index-Cc-h06U6.js +78 -0
  23. package/bundle/server/static-ui/assets/index-DKnME33I.css +1 -0
  24. package/bundle/server/static-ui/index.html +2 -2
  25. package/bundle/shared/dist/budget.d.ts +1 -1
  26. package/bundle/shared/dist/budget.js +3 -3
  27. package/bundle/shared/dist/index.d.ts +351 -129
  28. package/bundle/shared/dist/index.js +19 -0
  29. package/bundle/shared/dist/outbound-draft.d.ts +192 -0
  30. package/bundle/shared/dist/outbound-draft.js +46 -0
  31. package/bundle/shared/dist/outbound-draft.test.d.ts +1 -0
  32. package/bundle/shared/dist/outbound-draft.test.js +34 -0
  33. package/bundle/shared/dist/plan-triage.d.ts +317 -0
  34. package/bundle/shared/dist/plan-triage.js +65 -0
  35. package/bundle/shared/dist/plan-triage.test.d.ts +1 -0
  36. package/bundle/shared/dist/plan-triage.test.js +66 -0
  37. package/bundle/shared/package.json +1 -1
  38. package/package.json +3 -2
  39. package/bundle/server/static-ui/assets/index-ChdPKYDd.css +0 -1
  40. package/bundle/server/static-ui/assets/index-hIzZ8TM8.js +0 -77
@@ -6,6 +6,8 @@ export * from "./runtime.js";
6
6
  export * from "./agents.js";
7
7
  export * from "./budget.js";
8
8
  export * from "./execution.js";
9
+ export * from "./plan-triage.js";
10
+ export * from "./outbound-draft.js";
9
11
  export const RunStatus = z.enum([
10
12
  "queued",
11
13
  "plan_pending",
@@ -28,6 +30,8 @@ export const ArtifactKind = z.enum([
28
30
  "task_snapshot",
29
31
  "draft_plan",
30
32
  "approved_plan",
33
+ "plan_triage",
34
+ "plan_answers",
31
35
  "acceptance_criteria",
32
36
  "transcript",
33
37
  "stream_trace",
@@ -45,6 +49,7 @@ export const ArtifactKind = z.enum([
45
49
  "playbook_patch",
46
50
  "reflect_status",
47
51
  "linear_sync",
52
+ "send_receipt",
48
53
  ]);
49
54
  export const RunPhase = z.enum(["plan", "execute", "reflect"]);
50
55
  export const PlaybookPatchStatus = z.enum(["proposed", "applied", "dismissed"]);
@@ -86,10 +91,17 @@ export const UsageContent = z.object({
86
91
  durationMs: z.number().optional(),
87
92
  model: z.string().optional(),
88
93
  numTurns: z.number().optional(),
94
+ /** Resolved --max-turns cap enforced when this phase ran (snapshot at persist time). */
95
+ maxTurns: z.number().optional(),
96
+ /** Resolved --max-budget-usd cap enforced when this phase ran (snapshot at persist time). */
97
+ maxBudgetUsd: z.number().optional(),
89
98
  });
90
99
  export const UsageLineItem = z.object({
91
100
  label: z.string(),
92
101
  usage: UsageContent,
102
+ /** From usage artifact snapshot; falls back to current resolve for legacy rows. */
103
+ maxTurns: z.number().optional(),
104
+ maxBudgetUsd: z.number().optional(),
93
105
  });
94
106
  export const UsageSummary = z.object({
95
107
  lines: z.array(UsageLineItem),
@@ -98,6 +110,7 @@ export const UsageSummary = z.object({
98
110
  inputTokens: z.number(),
99
111
  outputTokens: z.number(),
100
112
  durationMs: z.number(),
113
+ numTurns: z.number(),
101
114
  }),
102
115
  });
103
116
  export const AgentSessionContent = z.object({
@@ -216,6 +229,7 @@ export const RetryRunInput = z.object({
216
229
  /** @deprecated execution retry uses executeModel */
217
230
  planModel: z.string().nullable().optional(),
218
231
  executeModel: z.string().nullable().optional(),
232
+ executeBudget: PhaseBudget.nullable().optional(),
219
233
  });
220
234
  export const LinearCandidate = z.object({
221
235
  id: z.string(),
@@ -313,6 +327,11 @@ export const QueueSnapshot = z.object({
313
327
  resultReviewRuns: z.array(Run),
314
328
  recentDone: z.array(Run),
315
329
  awaitingPlanReview: z.array(Run),
330
+ awaitingAnswerRuns: z.array(Run),
331
+ openQuestionCounts: z.record(z.string(), z.number()),
332
+ pendingSendCounts: z.record(z.string(), z.number()),
333
+ sentRunIds: z.array(z.string()).optional(),
334
+ autoApprovedRunIds: z.array(z.string()),
316
335
  runs: z.array(Run),
317
336
  agentDeckOnline: z.boolean(),
318
337
  agents: z.array(AgentWithHealth),
@@ -0,0 +1,192 @@
1
+ import { z } from "zod";
2
+ export declare const OutboundActionType: z.ZodEnum<["slack_message", "email"]>;
3
+ export type OutboundActionType = z.infer<typeof OutboundActionType>;
4
+ export declare const OutboundDraftSummary: z.ZodObject<{
5
+ target: z.ZodString;
6
+ body: z.ZodString;
7
+ }, "strip", z.ZodTypeAny, {
8
+ target: string;
9
+ body: string;
10
+ }, {
11
+ target: string;
12
+ body: string;
13
+ }>;
14
+ export type OutboundDraftSummary = z.infer<typeof OutboundDraftSummary>;
15
+ export declare const OutboundToolCall: z.ZodObject<{
16
+ serviceName: z.ZodString;
17
+ toolName: z.ZodString;
18
+ arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ serviceName: string;
21
+ toolName: string;
22
+ arguments: Record<string, unknown>;
23
+ }, {
24
+ serviceName: string;
25
+ toolName: string;
26
+ arguments: Record<string, unknown>;
27
+ }>;
28
+ export type OutboundToolCall = z.infer<typeof OutboundToolCall>;
29
+ /** Agent output contract — final fenced json block of an execute reply (PRD §7.1). */
30
+ export declare const OutboundDraftBlock: z.ZodObject<{
31
+ actionType: z.ZodEnum<["slack_message", "email"]>;
32
+ summary: z.ZodObject<{
33
+ target: z.ZodString;
34
+ body: z.ZodString;
35
+ }, "strip", z.ZodTypeAny, {
36
+ target: string;
37
+ body: string;
38
+ }, {
39
+ target: string;
40
+ body: string;
41
+ }>;
42
+ toolCall: z.ZodObject<{
43
+ serviceName: z.ZodString;
44
+ toolName: z.ZodString;
45
+ arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ serviceName: string;
48
+ toolName: string;
49
+ arguments: Record<string, unknown>;
50
+ }, {
51
+ serviceName: string;
52
+ toolName: string;
53
+ arguments: Record<string, unknown>;
54
+ }>;
55
+ }, "strip", z.ZodTypeAny, {
56
+ summary: {
57
+ target: string;
58
+ body: string;
59
+ };
60
+ actionType: "slack_message" | "email";
61
+ toolCall: {
62
+ serviceName: string;
63
+ toolName: string;
64
+ arguments: Record<string, unknown>;
65
+ };
66
+ }, {
67
+ summary: {
68
+ target: string;
69
+ body: string;
70
+ };
71
+ actionType: "slack_message" | "email";
72
+ toolCall: {
73
+ serviceName: string;
74
+ toolName: string;
75
+ arguments: Record<string, unknown>;
76
+ };
77
+ }>;
78
+ export type OutboundDraftBlock = z.infer<typeof OutboundDraftBlock>;
79
+ export declare const OutboundDraftStatus: z.ZodEnum<["pending", "sent", "rejected"]>;
80
+ export type OutboundDraftStatus = z.infer<typeof OutboundDraftStatus>;
81
+ /** slack_draft / email_draft artifact contentJson (PRD §7.2). */
82
+ export declare const OutboundDraftContent: z.ZodObject<{
83
+ draft: z.ZodObject<{
84
+ actionType: z.ZodEnum<["slack_message", "email"]>;
85
+ summary: z.ZodObject<{
86
+ target: z.ZodString;
87
+ body: z.ZodString;
88
+ }, "strip", z.ZodTypeAny, {
89
+ target: string;
90
+ body: string;
91
+ }, {
92
+ target: string;
93
+ body: string;
94
+ }>;
95
+ toolCall: z.ZodObject<{
96
+ serviceName: z.ZodString;
97
+ toolName: z.ZodString;
98
+ arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ serviceName: string;
101
+ toolName: string;
102
+ arguments: Record<string, unknown>;
103
+ }, {
104
+ serviceName: string;
105
+ toolName: string;
106
+ arguments: Record<string, unknown>;
107
+ }>;
108
+ }, "strip", z.ZodTypeAny, {
109
+ summary: {
110
+ target: string;
111
+ body: string;
112
+ };
113
+ actionType: "slack_message" | "email";
114
+ toolCall: {
115
+ serviceName: string;
116
+ toolName: string;
117
+ arguments: Record<string, unknown>;
118
+ };
119
+ }, {
120
+ summary: {
121
+ target: string;
122
+ body: string;
123
+ };
124
+ actionType: "slack_message" | "email";
125
+ toolCall: {
126
+ serviceName: string;
127
+ toolName: string;
128
+ arguments: Record<string, unknown>;
129
+ };
130
+ }>;
131
+ status: z.ZodEnum<["pending", "sent", "rejected"]>;
132
+ sentAt: z.ZodOptional<z.ZodString>;
133
+ rejectedAt: z.ZodOptional<z.ZodString>;
134
+ bodyMismatch: z.ZodOptional<z.ZodBoolean>;
135
+ }, "strip", z.ZodTypeAny, {
136
+ status: "pending" | "sent" | "rejected";
137
+ draft: {
138
+ summary: {
139
+ target: string;
140
+ body: string;
141
+ };
142
+ actionType: "slack_message" | "email";
143
+ toolCall: {
144
+ serviceName: string;
145
+ toolName: string;
146
+ arguments: Record<string, unknown>;
147
+ };
148
+ };
149
+ sentAt?: string | undefined;
150
+ rejectedAt?: string | undefined;
151
+ bodyMismatch?: boolean | undefined;
152
+ }, {
153
+ status: "pending" | "sent" | "rejected";
154
+ draft: {
155
+ summary: {
156
+ target: string;
157
+ body: string;
158
+ };
159
+ actionType: "slack_message" | "email";
160
+ toolCall: {
161
+ serviceName: string;
162
+ toolName: string;
163
+ arguments: Record<string, unknown>;
164
+ };
165
+ };
166
+ sentAt?: string | undefined;
167
+ rejectedAt?: string | undefined;
168
+ bodyMismatch?: boolean | undefined;
169
+ }>;
170
+ export type OutboundDraftContent = z.infer<typeof OutboundDraftContent>;
171
+ /** send_receipt artifact contentJson (PRD §7.3). */
172
+ export declare const SendReceiptContent: z.ZodObject<{
173
+ draftArtifactId: z.ZodString;
174
+ sentAt: z.ZodString;
175
+ toolResult: z.ZodRecord<z.ZodString, z.ZodUnknown>;
176
+ permalink: z.ZodOptional<z.ZodString>;
177
+ }, "strip", z.ZodTypeAny, {
178
+ sentAt: string;
179
+ draftArtifactId: string;
180
+ toolResult: Record<string, unknown>;
181
+ permalink?: string | undefined;
182
+ }, {
183
+ sentAt: string;
184
+ draftArtifactId: string;
185
+ toolResult: Record<string, unknown>;
186
+ permalink?: string | undefined;
187
+ }>;
188
+ export type SendReceiptContent = z.infer<typeof SendReceiptContent>;
189
+ export declare function outboundDraftKind(actionType: OutboundActionType): "slack_draft" | "email_draft";
190
+ export declare function isOutboundDraftKind(kind: string): kind is "slack_draft" | "email_draft";
191
+ /** Compare summary.body to the message field in toolCall.arguments (Slack: text, email: body). */
192
+ export declare function outboundMessageMatchesSummary(toolCall: OutboundToolCall, body: string): boolean;
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ export const OutboundActionType = z.enum(["slack_message", "email"]);
3
+ export const OutboundDraftSummary = z.object({
4
+ target: z.string().min(1).max(120),
5
+ body: z.string().min(1).max(4000),
6
+ });
7
+ export const OutboundToolCall = z.object({
8
+ serviceName: z.string().min(1).max(120),
9
+ toolName: z.string().min(1).max(120),
10
+ arguments: z.record(z.unknown()),
11
+ });
12
+ /** Agent output contract — final fenced json block of an execute reply (PRD §7.1). */
13
+ export const OutboundDraftBlock = z.object({
14
+ actionType: OutboundActionType,
15
+ summary: OutboundDraftSummary,
16
+ toolCall: OutboundToolCall,
17
+ });
18
+ export const OutboundDraftStatus = z.enum(["pending", "sent", "rejected"]);
19
+ /** slack_draft / email_draft artifact contentJson (PRD §7.2). */
20
+ export const OutboundDraftContent = z.object({
21
+ draft: OutboundDraftBlock,
22
+ status: OutboundDraftStatus,
23
+ sentAt: z.string().optional(),
24
+ rejectedAt: z.string().optional(),
25
+ bodyMismatch: z.boolean().optional(),
26
+ });
27
+ /** send_receipt artifact contentJson (PRD §7.3). */
28
+ export const SendReceiptContent = z.object({
29
+ draftArtifactId: z.string().uuid(),
30
+ sentAt: z.string(),
31
+ toolResult: z.record(z.unknown()),
32
+ permalink: z.string().url().optional(),
33
+ });
34
+ export function outboundDraftKind(actionType) {
35
+ return actionType === "slack_message" ? "slack_draft" : "email_draft";
36
+ }
37
+ const OUTBOUND_DRAFT_KINDS = new Set(["slack_draft", "email_draft"]);
38
+ export function isOutboundDraftKind(kind) {
39
+ return OUTBOUND_DRAFT_KINDS.has(kind);
40
+ }
41
+ /** Compare summary.body to the message field in toolCall.arguments (Slack: text, email: body). */
42
+ export function outboundMessageMatchesSummary(toolCall, body) {
43
+ const args = toolCall.arguments;
44
+ const candidates = [args.text, args.body, args.message].filter((v) => typeof v === "string");
45
+ return candidates.some((v) => v === body);
46
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { OutboundDraftBlock, outboundDraftKind, outboundMessageMatchesSummary, SendReceiptContent, } from "./outbound-draft.js";
4
+ const VALID_DRAFT = {
5
+ actionType: "slack_message",
6
+ summary: { target: "#test-channel", body: "Hello from agent-dealer" },
7
+ toolCall: {
8
+ serviceName: "34eb6c24-f151-4da2-8db8-d6996aa296be",
9
+ toolName: "chat_postMessage",
10
+ arguments: { channel: "C123", text: "Hello from agent-dealer" },
11
+ },
12
+ };
13
+ test("OutboundDraftBlock parses valid slack draft", () => {
14
+ const parsed = OutboundDraftBlock.parse(VALID_DRAFT);
15
+ assert.equal(parsed.actionType, "slack_message");
16
+ });
17
+ test("outboundDraftKind maps action types", () => {
18
+ assert.equal(outboundDraftKind("slack_message"), "slack_draft");
19
+ assert.equal(outboundDraftKind("email"), "email_draft");
20
+ });
21
+ test("outboundMessageMatchesSummary matches text field", () => {
22
+ assert.equal(outboundMessageMatchesSummary(VALID_DRAFT.toolCall, VALID_DRAFT.summary.body), true);
23
+ });
24
+ test("outboundMessageMatchesSummary detects mismatch", () => {
25
+ assert.equal(outboundMessageMatchesSummary(VALID_DRAFT.toolCall, "different body"), false);
26
+ });
27
+ test("SendReceiptContent requires draftArtifactId and toolResult", () => {
28
+ const receipt = SendReceiptContent.parse({
29
+ draftArtifactId: "00000000-0000-4000-a000-000000000001",
30
+ sentAt: new Date().toISOString(),
31
+ toolResult: { ok: true },
32
+ });
33
+ assert.equal(receipt.toolResult.ok, true);
34
+ });
@@ -0,0 +1,317 @@
1
+ import { z } from "zod";
2
+ export declare const PlanQuestionOption: z.ZodObject<{
3
+ label: z.ZodString;
4
+ description: z.ZodOptional<z.ZodString>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ label: string;
7
+ description?: string | undefined;
8
+ }, {
9
+ label: string;
10
+ description?: string | undefined;
11
+ }>;
12
+ export type PlanQuestionOption = z.infer<typeof PlanQuestionOption>;
13
+ export declare const PlanQuestion: z.ZodObject<{
14
+ id: z.ZodString;
15
+ question: z.ZodString;
16
+ options: z.ZodArray<z.ZodObject<{
17
+ label: z.ZodString;
18
+ description: z.ZodOptional<z.ZodString>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ label: string;
21
+ description?: string | undefined;
22
+ }, {
23
+ label: string;
24
+ description?: string | undefined;
25
+ }>, "many">;
26
+ }, "strip", z.ZodTypeAny, {
27
+ options: {
28
+ label: string;
29
+ description?: string | undefined;
30
+ }[];
31
+ id: string;
32
+ question: string;
33
+ }, {
34
+ options: {
35
+ label: string;
36
+ description?: string | undefined;
37
+ }[];
38
+ id: string;
39
+ question: string;
40
+ }>;
41
+ export type PlanQuestion = z.infer<typeof PlanQuestion>;
42
+ export declare const PlanTriageVerdict: z.ZodEnum<["trivial", "needs_review"]>;
43
+ export type PlanTriageVerdict = z.infer<typeof PlanTriageVerdict>;
44
+ /** Agent output contract — final fenced json block of a plan reply (PRD §7.1). */
45
+ export declare const PlanTriageBlock: z.ZodEffects<z.ZodObject<{
46
+ verdict: z.ZodEnum<["trivial", "needs_review"]>;
47
+ rationale: z.ZodString;
48
+ questions: z.ZodDefault<z.ZodArray<z.ZodObject<{
49
+ id: z.ZodString;
50
+ question: z.ZodString;
51
+ options: z.ZodArray<z.ZodObject<{
52
+ label: z.ZodString;
53
+ description: z.ZodOptional<z.ZodString>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ label: string;
56
+ description?: string | undefined;
57
+ }, {
58
+ label: string;
59
+ description?: string | undefined;
60
+ }>, "many">;
61
+ }, "strip", z.ZodTypeAny, {
62
+ options: {
63
+ label: string;
64
+ description?: string | undefined;
65
+ }[];
66
+ id: string;
67
+ question: string;
68
+ }, {
69
+ options: {
70
+ label: string;
71
+ description?: string | undefined;
72
+ }[];
73
+ id: string;
74
+ question: string;
75
+ }>, "many">>;
76
+ }, "strip", z.ZodTypeAny, {
77
+ verdict: "trivial" | "needs_review";
78
+ rationale: string;
79
+ questions: {
80
+ options: {
81
+ label: string;
82
+ description?: string | undefined;
83
+ }[];
84
+ id: string;
85
+ question: string;
86
+ }[];
87
+ }, {
88
+ verdict: "trivial" | "needs_review";
89
+ rationale: string;
90
+ questions?: {
91
+ options: {
92
+ label: string;
93
+ description?: string | undefined;
94
+ }[];
95
+ id: string;
96
+ question: string;
97
+ }[] | undefined;
98
+ }>, {
99
+ verdict: "trivial" | "needs_review";
100
+ rationale: string;
101
+ questions: {
102
+ options: {
103
+ label: string;
104
+ description?: string | undefined;
105
+ }[];
106
+ id: string;
107
+ question: string;
108
+ }[];
109
+ }, {
110
+ verdict: "trivial" | "needs_review";
111
+ rationale: string;
112
+ questions?: {
113
+ options: {
114
+ label: string;
115
+ description?: string | undefined;
116
+ }[];
117
+ id: string;
118
+ question: string;
119
+ }[] | undefined;
120
+ }>;
121
+ export type PlanTriageBlock = z.infer<typeof PlanTriageBlock>;
122
+ /** plan_triage artifact contentJson (PRD §7.3). */
123
+ export declare const PlanTriageContent: z.ZodObject<{
124
+ verdict: z.ZodEnum<["trivial", "needs_review"]>;
125
+ rationale: z.ZodString;
126
+ questions: z.ZodArray<z.ZodObject<{
127
+ id: z.ZodString;
128
+ question: z.ZodString;
129
+ options: z.ZodArray<z.ZodObject<{
130
+ label: z.ZodString;
131
+ description: z.ZodOptional<z.ZodString>;
132
+ }, "strip", z.ZodTypeAny, {
133
+ label: string;
134
+ description?: string | undefined;
135
+ }, {
136
+ label: string;
137
+ description?: string | undefined;
138
+ }>, "many">;
139
+ }, "strip", z.ZodTypeAny, {
140
+ options: {
141
+ label: string;
142
+ description?: string | undefined;
143
+ }[];
144
+ id: string;
145
+ question: string;
146
+ }, {
147
+ options: {
148
+ label: string;
149
+ description?: string | undefined;
150
+ }[];
151
+ id: string;
152
+ question: string;
153
+ }>, "many">;
154
+ sessionId: z.ZodOptional<z.ZodString>;
155
+ parseFallback: z.ZodBoolean;
156
+ consumed: z.ZodDefault<z.ZodBoolean>;
157
+ }, "strip", z.ZodTypeAny, {
158
+ verdict: "trivial" | "needs_review";
159
+ rationale: string;
160
+ questions: {
161
+ options: {
162
+ label: string;
163
+ description?: string | undefined;
164
+ }[];
165
+ id: string;
166
+ question: string;
167
+ }[];
168
+ parseFallback: boolean;
169
+ consumed: boolean;
170
+ sessionId?: string | undefined;
171
+ }, {
172
+ verdict: "trivial" | "needs_review";
173
+ rationale: string;
174
+ questions: {
175
+ options: {
176
+ label: string;
177
+ description?: string | undefined;
178
+ }[];
179
+ id: string;
180
+ question: string;
181
+ }[];
182
+ parseFallback: boolean;
183
+ sessionId?: string | undefined;
184
+ consumed?: boolean | undefined;
185
+ }>;
186
+ export type PlanTriageContent = z.infer<typeof PlanTriageContent>;
187
+ export declare const PlanAnswer: z.ZodEffects<z.ZodObject<{
188
+ questionId: z.ZodString;
189
+ selectedLabel: z.ZodOptional<z.ZodString>;
190
+ freeText: z.ZodOptional<z.ZodString>;
191
+ }, "strip", z.ZodTypeAny, {
192
+ questionId: string;
193
+ selectedLabel?: string | undefined;
194
+ freeText?: string | undefined;
195
+ }, {
196
+ questionId: string;
197
+ selectedLabel?: string | undefined;
198
+ freeText?: string | undefined;
199
+ }>, {
200
+ questionId: string;
201
+ selectedLabel?: string | undefined;
202
+ freeText?: string | undefined;
203
+ }, {
204
+ questionId: string;
205
+ selectedLabel?: string | undefined;
206
+ freeText?: string | undefined;
207
+ }>;
208
+ export type PlanAnswer = z.infer<typeof PlanAnswer>;
209
+ /** POST /api/runs/:id/plan/answers body (PRD §7.2). */
210
+ export declare const PlanAnswersInput: z.ZodObject<{
211
+ answers: z.ZodArray<z.ZodEffects<z.ZodObject<{
212
+ questionId: z.ZodString;
213
+ selectedLabel: z.ZodOptional<z.ZodString>;
214
+ freeText: z.ZodOptional<z.ZodString>;
215
+ }, "strip", z.ZodTypeAny, {
216
+ questionId: string;
217
+ selectedLabel?: string | undefined;
218
+ freeText?: string | undefined;
219
+ }, {
220
+ questionId: string;
221
+ selectedLabel?: string | undefined;
222
+ freeText?: string | undefined;
223
+ }>, {
224
+ questionId: string;
225
+ selectedLabel?: string | undefined;
226
+ freeText?: string | undefined;
227
+ }, {
228
+ questionId: string;
229
+ selectedLabel?: string | undefined;
230
+ freeText?: string | undefined;
231
+ }>, "many">;
232
+ executeModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
233
+ executeBudget: z.ZodOptional<z.ZodNullable<z.ZodObject<{
234
+ maxTurns: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
235
+ maxBudgetUsd: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
236
+ }, "strip", z.ZodTypeAny, {
237
+ maxTurns?: number | null | undefined;
238
+ maxBudgetUsd?: number | null | undefined;
239
+ }, {
240
+ maxTurns?: number | null | undefined;
241
+ maxBudgetUsd?: number | null | undefined;
242
+ }>>>;
243
+ }, "strip", z.ZodTypeAny, {
244
+ answers: {
245
+ questionId: string;
246
+ selectedLabel?: string | undefined;
247
+ freeText?: string | undefined;
248
+ }[];
249
+ executeModel?: string | null | undefined;
250
+ executeBudget?: {
251
+ maxTurns?: number | null | undefined;
252
+ maxBudgetUsd?: number | null | undefined;
253
+ } | null | undefined;
254
+ }, {
255
+ answers: {
256
+ questionId: string;
257
+ selectedLabel?: string | undefined;
258
+ freeText?: string | undefined;
259
+ }[];
260
+ executeModel?: string | null | undefined;
261
+ executeBudget?: {
262
+ maxTurns?: number | null | undefined;
263
+ maxBudgetUsd?: number | null | undefined;
264
+ } | null | undefined;
265
+ }>;
266
+ export type PlanAnswersInput = z.infer<typeof PlanAnswersInput>;
267
+ /** plan_answers artifact contentJson (PRD §7.4). */
268
+ export declare const PlanAnswersContent: z.ZodObject<{
269
+ answers: z.ZodArray<z.ZodEffects<z.ZodObject<{
270
+ questionId: z.ZodString;
271
+ selectedLabel: z.ZodOptional<z.ZodString>;
272
+ freeText: z.ZodOptional<z.ZodString>;
273
+ }, "strip", z.ZodTypeAny, {
274
+ questionId: string;
275
+ selectedLabel?: string | undefined;
276
+ freeText?: string | undefined;
277
+ }, {
278
+ questionId: string;
279
+ selectedLabel?: string | undefined;
280
+ freeText?: string | undefined;
281
+ }>, {
282
+ questionId: string;
283
+ selectedLabel?: string | undefined;
284
+ freeText?: string | undefined;
285
+ }, {
286
+ questionId: string;
287
+ selectedLabel?: string | undefined;
288
+ freeText?: string | undefined;
289
+ }>, "many">;
290
+ outcome: z.ZodEnum<["approved", "redraft"]>;
291
+ answeredAt: z.ZodString;
292
+ }, "strip", z.ZodTypeAny, {
293
+ answers: {
294
+ questionId: string;
295
+ selectedLabel?: string | undefined;
296
+ freeText?: string | undefined;
297
+ }[];
298
+ outcome: "approved" | "redraft";
299
+ answeredAt: string;
300
+ }, {
301
+ answers: {
302
+ questionId: string;
303
+ selectedLabel?: string | undefined;
304
+ freeText?: string | undefined;
305
+ }[];
306
+ outcome: "approved" | "redraft";
307
+ answeredAt: string;
308
+ }>;
309
+ export type PlanAnswersContent = z.infer<typeof PlanAnswersContent>;
310
+ export type PlanGateDecision = "auto_approve" | "await_answers" | "await_review";
311
+ /** After this many question rounds, drafts always go to manual review (PRD F3.5). */
312
+ export declare const MAX_QUESTION_ROUNDS = 2;
313
+ export declare function planGateDecision(input: {
314
+ triage: Pick<PlanTriageContent, "verdict" | "questions" | "consumed" | "parseFallback">;
315
+ /** Count of PRIOR plan_triage artifacts on this run that carried questions. */
316
+ priorQuestionRounds: number;
317
+ }): PlanGateDecision;