@cat-factory/contracts 0.284.0 → 0.285.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 (60) hide show
  1. package/dist/agent-presentation.d.ts +2 -2
  2. package/dist/binary-candidates.d.ts +261 -0
  3. package/dist/binary-candidates.d.ts.map +1 -0
  4. package/dist/binary-candidates.js +202 -0
  5. package/dist/binary-candidates.js.map +1 -0
  6. package/dist/binary-capabilities.d.ts +328 -0
  7. package/dist/binary-capabilities.d.ts.map +1 -0
  8. package/dist/binary-capabilities.js +361 -0
  9. package/dist/binary-capabilities.js.map +1 -0
  10. package/dist/binary-generators.d.ts +27 -0
  11. package/dist/binary-generators.d.ts.map +1 -1
  12. package/dist/binary-generators.js +28 -0
  13. package/dist/binary-generators.js.map +1 -1
  14. package/dist/binary-outputs.d.ts +31 -0
  15. package/dist/binary-outputs.d.ts.map +1 -1
  16. package/dist/binary-outputs.js +30 -0
  17. package/dist/binary-outputs.js.map +1 -1
  18. package/dist/entities.d.ts +10 -0
  19. package/dist/entities.d.ts.map +1 -1
  20. package/dist/execution.d.ts +90 -0
  21. package/dist/execution.d.ts.map +1 -1
  22. package/dist/execution.js +13 -0
  23. package/dist/execution.js.map +1 -1
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/requests.d.ts +10 -0
  29. package/dist/requests.d.ts.map +1 -1
  30. package/dist/result-views.d.ts +1 -1
  31. package/dist/result-views.d.ts.map +1 -1
  32. package/dist/result-views.js +1 -0
  33. package/dist/result-views.js.map +1 -1
  34. package/dist/routes/agent-runs.d.ts +68 -0
  35. package/dist/routes/agent-runs.d.ts.map +1 -1
  36. package/dist/routes/binaryCandidates.d.ts +139 -0
  37. package/dist/routes/binaryCandidates.d.ts.map +1 -0
  38. package/dist/routes/binaryCandidates.js +31 -0
  39. package/dist/routes/binaryCandidates.js.map +1 -0
  40. package/dist/routes/bug-hunt.d.ts +68 -0
  41. package/dist/routes/bug-hunt.d.ts.map +1 -1
  42. package/dist/routes/execution.d.ts +272 -0
  43. package/dist/routes/execution.d.ts.map +1 -1
  44. package/dist/routes/human-review.d.ts +34 -0
  45. package/dist/routes/human-review.d.ts.map +1 -1
  46. package/dist/routes/human-test.d.ts +170 -0
  47. package/dist/routes/human-test.d.ts.map +1 -1
  48. package/dist/routes/index.d.ts +1 -0
  49. package/dist/routes/index.d.ts.map +1 -1
  50. package/dist/routes/index.js +1 -0
  51. package/dist/routes/index.js.map +1 -1
  52. package/dist/routes/pipelines.d.ts +40 -0
  53. package/dist/routes/pipelines.d.ts.map +1 -1
  54. package/dist/routes/visual-confirm.d.ts +102 -0
  55. package/dist/routes/visual-confirm.d.ts.map +1 -1
  56. package/dist/routes/workspaces.d.ts +82 -2
  57. package/dist/routes/workspaces.d.ts.map +1 -1
  58. package/dist/snapshot.d.ts +41 -1
  59. package/dist/snapshot.d.ts.map +1 -1
  60. package/package.json +1 -1
@@ -93,7 +93,7 @@ export declare const agentPresentationSchema: v.ObjectSchema<{
93
93
  * to the deployment and paired on the frontend (an unpaired one degrades to the generic
94
94
  * panel — the `pairById` `missing` bucket). Omitted ⇒ the generic step-detail panel.
95
95
  */
96
- readonly resultView: v.OptionalSchema<v.UnionSchema<[v.PicklistSchema<readonly ["outcome", "requirements-review", "clarity-review", "brainstorm", "tester", "human-test", "visual-confirm", "gate", "consensus-session", "generic-structured", "service-spec", "follow-ups", "merger", "initiative-tracker", "initiative-planning", "doc-interview", "fork-decision", "judge", "pr-review", "ralph-loop"], undefined>, v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Consumer id must be <namespace>:<name> (lowercase a-z0-9, dash-separated)">]>], undefined>, undefined>;
96
+ readonly resultView: v.OptionalSchema<v.UnionSchema<[v.PicklistSchema<readonly ["outcome", "requirements-review", "clarity-review", "brainstorm", "tester", "human-test", "visual-confirm", "gate", "consensus-session", "generic-structured", "service-spec", "follow-ups", "merger", "initiative-tracker", "initiative-planning", "doc-interview", "fork-decision", "binary-candidates", "judge", "pr-review", "ralph-loop"], undefined>, v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Consumer id must be <namespace>:<name> (lowercase a-z0-9, dash-separated)">]>], undefined>, undefined>;
97
97
  }, undefined>;
98
98
  export type AgentPresentation = v.InferOutput<typeof agentPresentationSchema>;
99
99
  /** A registered agent kind's id + presentation + whether it runs in a container — the
@@ -152,7 +152,7 @@ export declare const customAgentKindSchema: v.ObjectSchema<{
152
152
  * to the deployment and paired on the frontend (an unpaired one degrades to the generic
153
153
  * panel — the `pairById` `missing` bucket). Omitted ⇒ the generic step-detail panel.
154
154
  */
155
- readonly resultView: v.OptionalSchema<v.UnionSchema<[v.PicklistSchema<readonly ["outcome", "requirements-review", "clarity-review", "brainstorm", "tester", "human-test", "visual-confirm", "gate", "consensus-session", "generic-structured", "service-spec", "follow-ups", "merger", "initiative-tracker", "initiative-planning", "doc-interview", "fork-decision", "judge", "pr-review", "ralph-loop"], undefined>, v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Consumer id must be <namespace>:<name> (lowercase a-z0-9, dash-separated)">]>], undefined>, undefined>;
155
+ readonly resultView: v.OptionalSchema<v.UnionSchema<[v.PicklistSchema<readonly ["outcome", "requirements-review", "clarity-review", "brainstorm", "tester", "human-test", "visual-confirm", "gate", "consensus-session", "generic-structured", "service-spec", "follow-ups", "merger", "initiative-tracker", "initiative-planning", "doc-interview", "fork-decision", "binary-candidates", "judge", "pr-review", "ralph-loop"], undefined>, v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Consumer id must be <namespace>:<name> (lowercase a-z0-9, dash-separated)">]>], undefined>, undefined>;
156
156
  }, undefined>;
157
157
  /** Whether the kind runs in a container (vs an inline LLM call). */
158
158
  readonly container: v.BooleanSchema<undefined>;
@@ -0,0 +1,261 @@
1
+ import * as v from 'valibot';
2
+ /**
3
+ * The per-step comparison declaration: this step generates candidates and PARKS for a human.
4
+ *
5
+ * Its presence is the switch. There is no `enabled: false`, because a step that is not comparing
6
+ * carries nothing, and a disabled bag would be a saved configuration that describes a behaviour
7
+ * the run does not have.
8
+ */
9
+ export declare const binaryCandidateComparisonSchema: v.ObjectSchema<{
10
+ /**
11
+ * How many candidates EACH selected integration should produce per subject. Defaults to one,
12
+ * which is the case the whole feature is named for: one render from each of the integrations
13
+ * that overlap.
14
+ *
15
+ * Above one it also covers the single-integration case, where the comparison is between seeds
16
+ * rather than between vendors. That is not a lesser use: a step holding one pixel-art API and
17
+ * asking for four candidates is exactly how a sprite gets picked, and refusing it would make
18
+ * the feature depend on a deployment happening to have bought two vendors.
19
+ */
20
+ readonly perGenerator: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 4, undefined>]>, undefined>;
21
+ /**
22
+ * Whether MORE THAN ONE candidate may be kept. Off by default: the ordinary case is a choice,
23
+ * and a picker that silently allowed two would leave a step delivering an artifact count nobody
24
+ * asked for.
25
+ *
26
+ * On, every kept candidate is stored under its own id (`storeAs`), which is what makes keeping
27
+ * two a real outcome rather than a collision: two files at one location is one file.
28
+ */
29
+ readonly multiSelect: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
30
+ }, undefined>;
31
+ export type BinaryCandidateComparison = v.InferOutput<typeof binaryCandidateComparisonSchema>;
32
+ /**
33
+ * One generated candidate, as the agent declared it in its fenced ```binary-candidates block.
34
+ *
35
+ * `id` is engine-minted (`cand_*`) rather than taken from the reply: the id is what a human's
36
+ * choice names, so a model that repeats one, omits one, or writes a 4 KB one would break the
37
+ * decision rather than its own bookkeeping. What the agent DOES supply is `label`, which is how
38
+ * it refers to the candidate in its own prose, kept so the two records can be lined up.
39
+ */
40
+ export declare const binaryCandidateSchema: v.ObjectSchema<{
41
+ /** Engine-minted stable id (`cand_*`), assigned when the declaration is recorded. */
42
+ readonly id: v.StringSchema<undefined>;
43
+ /** The agent's own name for this candidate, retained so its prose can be matched to the row. */
44
+ readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
45
+ /**
46
+ * The integration that produced it. Optional for the same reason the deliverable's own
47
+ * `generator` is (a model with native image output produces without a registered integration),
48
+ * and far more load-bearing here: with several producers in play it is the axis the human is
49
+ * comparing along, so a candidate that omits it is rendered as unattributed rather than
50
+ * silently attributed to the step's first integration.
51
+ */
52
+ readonly generator: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
53
+ /**
54
+ * What this candidate DEPICTS, in the agent's words (`product:tea-kettle`, `sprite:anvil`).
55
+ * Candidates are grouped by it, so a step that generated forty subjects renders forty
56
+ * comparisons rather than one wall of eighty images.
57
+ */
58
+ readonly subject: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
59
+ /** The service the candidate was staged through, lowercased on read-back like a deliverable's. */
60
+ readonly service: v.StringSchema<undefined>;
61
+ /** Where it lives in that service's addressing, verbatim. */
62
+ readonly location: v.StringSchema<undefined>;
63
+ /** The media type the agent reports for it. */
64
+ readonly contentType: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
65
+ /**
66
+ * A URL the SPA can render the candidate from, when the storage service issued one.
67
+ *
68
+ * ABSENT is a real and common state, not a failure: an org's asset store may be private, and
69
+ * the platform will not invent a link into it. The surface then renders the candidate's
70
+ * metadata and says the preview is unavailable, which is what lets a private estate use this
71
+ * feature at all. Constrained to `https` (or loopback) at parse time, because it is rendered
72
+ * in a browser from text a model wrote.
73
+ */
74
+ readonly previewUrl: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
75
+ /** One line on what makes this candidate different, from the agent that made it. */
76
+ readonly note: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
77
+ }, undefined>;
78
+ export type BinaryCandidate = v.InferOutput<typeof binaryCandidateSchema>;
79
+ /**
80
+ * Why a comparison step did NOT park, when it did not.
81
+ *
82
+ * Its own vocabulary rather than an absent state, because every member is a different fault with
83
+ * a different fix and all three end with the run advancing. A comparison that wedged a run on a
84
+ * model that forgot a fenced block would be a worse outcome than the one it exists to improve.
85
+ */
86
+ export declare const binaryCandidateNoChoiceReasonSchema: v.PicklistSchema<["undeclared", "parse_failed", "no_candidates"], undefined>;
87
+ export type BinaryCandidateNoChoiceReason = v.InferOutput<typeof binaryCandidateNoChoiceReasonSchema>;
88
+ /**
89
+ * The candidate lifecycle on a comparison step:
90
+ * - `awaiting_choice`: parked; the human is comparing.
91
+ * - `chosen`: the human decided; the step re-runs and stores what survived.
92
+ * - `no_choice`: nothing to choose between, for one of the reasons above. No park.
93
+ */
94
+ export declare const binaryCandidateStatusSchema: v.PicklistSchema<["awaiting_choice", "chosen", "no_choice"], undefined>;
95
+ export type BinaryCandidateStatus = v.InferOutput<typeof binaryCandidateStatusSchema>;
96
+ /** One candidate the human kept, and the id it is to be stored under. */
97
+ export declare const binaryCandidateKeepSchema: v.ObjectSchema<{
98
+ readonly candidateId: v.StringSchema<undefined>;
99
+ /**
100
+ * The ALTERNATE ID this candidate is stored under, which is the whole mechanism behind keeping
101
+ * more than one: two survivors of one subject are two deliverables, and two deliverables need
102
+ * two addresses. Absent ⇒ the step's ordinary naming applies, which is correct for the single
103
+ * survivor and is why it is optional rather than defaulted to something invented.
104
+ */
105
+ readonly storeAs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>, v.RegexAction<string, "must be a plain id (letters, digits, . _ -)">]>, undefined>;
106
+ }, undefined>;
107
+ export type BinaryCandidateKeep = v.InferOutput<typeof binaryCandidateKeepSchema>;
108
+ /** The human's resolution, recorded on the step. */
109
+ export declare const binaryCandidateChoiceSchema: v.ObjectSchema<{
110
+ readonly kept: v.ArraySchema<v.ObjectSchema<{
111
+ readonly candidateId: v.StringSchema<undefined>;
112
+ /**
113
+ * The ALTERNATE ID this candidate is stored under, which is the whole mechanism behind keeping
114
+ * more than one: two survivors of one subject are two deliverables, and two deliverables need
115
+ * two addresses. Absent ⇒ the step's ordinary naming applies, which is correct for the single
116
+ * survivor and is why it is optional rather than defaulted to something invented.
117
+ */
118
+ readonly storeAs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>, v.RegexAction<string, "must be a plain id (letters, digits, . _ -)">]>, undefined>;
119
+ }, undefined>, undefined>;
120
+ /**
121
+ * The candidate ids that were NOT kept, recorded explicitly rather than derived by subtraction
122
+ * at read time. The surviving record must still say what was rejected once the step re-runs and
123
+ * the candidate list is the only thing left describing a generation nobody kept.
124
+ */
125
+ readonly discarded: v.ArraySchema<v.StringSchema<undefined>, undefined>;
126
+ /** Why, in the human's words. Folded into the re-run's brief so the agent knows what was wrong. */
127
+ readonly note: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
128
+ /**
129
+ * Set when the engine kept the only candidate rather than parking, so NOBODY reviewed it.
130
+ *
131
+ * Its own flag rather than an absent decider, because the two are the same record and opposite
132
+ * facts: a surface that renders an auto-kept artifact as "chosen" is telling a reader that a
133
+ * person looked at this and approved it, which is exactly the claim this feature exists to make
134
+ * true. An auto-keep is a legitimate outcome and a quieter one, and it says so.
135
+ */
136
+ readonly automatic: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
137
+ readonly at: v.NumberSchema<undefined>;
138
+ }, undefined>;
139
+ export type BinaryCandidateChoice = v.InferOutput<typeof binaryCandidateChoiceSchema>;
140
+ /**
141
+ * Live candidate-comparison state carried on the run's step. All of it rides `PipelineStep`, no
142
+ * side table, so D1 and Drizzle parity is free exactly as it is for `forkDecision` / `followUps`.
143
+ *
144
+ * The bookkeeping fields mirror `binaryOutputReportSchema`'s, and for the same reason: every way
145
+ * a candidate was lost is COUNTED rather than absorbed, so a comparison over three images that
146
+ * was meant to be over five does not read as a complete one.
147
+ */
148
+ export declare const binaryCandidateStepStateSchema: v.ObjectSchema<{
149
+ readonly status: v.PicklistSchema<["awaiting_choice", "chosen", "no_choice"], undefined>;
150
+ readonly candidates: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
151
+ /** Engine-minted stable id (`cand_*`), assigned when the declaration is recorded. */
152
+ readonly id: v.StringSchema<undefined>;
153
+ /** The agent's own name for this candidate, retained so its prose can be matched to the row. */
154
+ readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
155
+ /**
156
+ * The integration that produced it. Optional for the same reason the deliverable's own
157
+ * `generator` is (a model with native image output produces without a registered integration),
158
+ * and far more load-bearing here: with several producers in play it is the axis the human is
159
+ * comparing along, so a candidate that omits it is rendered as unattributed rather than
160
+ * silently attributed to the step's first integration.
161
+ */
162
+ readonly generator: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
163
+ /**
164
+ * What this candidate DEPICTS, in the agent's words (`product:tea-kettle`, `sprite:anvil`).
165
+ * Candidates are grouped by it, so a step that generated forty subjects renders forty
166
+ * comparisons rather than one wall of eighty images.
167
+ */
168
+ readonly subject: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
169
+ /** The service the candidate was staged through, lowercased on read-back like a deliverable's. */
170
+ readonly service: v.StringSchema<undefined>;
171
+ /** Where it lives in that service's addressing, verbatim. */
172
+ readonly location: v.StringSchema<undefined>;
173
+ /** The media type the agent reports for it. */
174
+ readonly contentType: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
175
+ /**
176
+ * A URL the SPA can render the candidate from, when the storage service issued one.
177
+ *
178
+ * ABSENT is a real and common state, not a failure: an org's asset store may be private, and
179
+ * the platform will not invent a link into it. The surface then renders the candidate's
180
+ * metadata and says the preview is unavailable, which is what lets a private estate use this
181
+ * feature at all. Constrained to `https` (or loopback) at parse time, because it is rendered
182
+ * in a browser from text a model wrote.
183
+ */
184
+ readonly previewUrl: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
185
+ /** One line on what makes this candidate different, from the agent that made it. */
186
+ readonly note: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
187
+ }, undefined>, undefined>, readonly []>;
188
+ /** Set only when `status` is `no_choice`. */
189
+ readonly noChoiceReason: v.OptionalSchema<v.NullableSchema<v.PicklistSchema<["undeclared", "parse_failed", "no_candidates"], undefined>, undefined>, undefined>;
190
+ /** Set once the human decides. */
191
+ readonly choice: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
192
+ readonly kept: v.ArraySchema<v.ObjectSchema<{
193
+ readonly candidateId: v.StringSchema<undefined>;
194
+ /**
195
+ * The ALTERNATE ID this candidate is stored under, which is the whole mechanism behind keeping
196
+ * more than one: two survivors of one subject are two deliverables, and two deliverables need
197
+ * two addresses. Absent ⇒ the step's ordinary naming applies, which is correct for the single
198
+ * survivor and is why it is optional rather than defaulted to something invented.
199
+ */
200
+ readonly storeAs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>, v.RegexAction<string, "must be a plain id (letters, digits, . _ -)">]>, undefined>;
201
+ }, undefined>, undefined>;
202
+ /**
203
+ * The candidate ids that were NOT kept, recorded explicitly rather than derived by subtraction
204
+ * at read time. The surviving record must still say what was rejected once the step re-runs and
205
+ * the candidate list is the only thing left describing a generation nobody kept.
206
+ */
207
+ readonly discarded: v.ArraySchema<v.StringSchema<undefined>, undefined>;
208
+ /** Why, in the human's words. Folded into the re-run's brief so the agent knows what was wrong. */
209
+ readonly note: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
210
+ /**
211
+ * Set when the engine kept the only candidate rather than parking, so NOBODY reviewed it.
212
+ *
213
+ * Its own flag rather than an absent decider, because the two are the same record and opposite
214
+ * facts: a surface that renders an auto-kept artifact as "chosen" is telling a reader that a
215
+ * person looked at this and approved it, which is exactly the claim this feature exists to make
216
+ * true. An auto-keep is a legitimate outcome and a quieter one, and it says so.
217
+ */
218
+ readonly automatic: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
219
+ readonly at: v.NumberSchema<undefined>;
220
+ }, undefined>, undefined>, undefined>;
221
+ /** Whether more than one candidate may be kept, frozen from the step's config at record time
222
+ * so the resolver judges the request against the rule the human was actually shown. */
223
+ readonly multiSelect: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
224
+ /** Declared entries dropped because they were not `{ service, location }` objects. */
225
+ readonly invalidEntries: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
226
+ /** Valid entries dropped past the per-step cap, so `candidates` is a PREFIX. */
227
+ readonly omitted: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
228
+ /** Preview URLs dropped because they were not an `https`/loopback URL. The candidate is kept
229
+ * and rendered without a preview: a refused link is not a refused candidate. */
230
+ readonly unusablePreviews: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
231
+ }, undefined>;
232
+ export type BinaryCandidateStepState = v.InferOutput<typeof binaryCandidateStepStateSchema>;
233
+ /**
234
+ * Keep one or more candidates and discard the rest.
235
+ *
236
+ * At least one must be kept: "discard everything" is a different act (it means the generation was
237
+ * a failure), and answering it through this verb would re-run the step to store nothing while
238
+ * reporting a completed choice. A step whose candidates are all bad is retried or reworked
239
+ * through the surfaces that already exist for that.
240
+ */
241
+ export declare const keepBinaryCandidatesSchema: v.ObjectSchema<{
242
+ readonly keep: v.SchemaWithPipe<readonly [v.ArraySchema<v.ObjectSchema<{
243
+ readonly candidateId: v.StringSchema<undefined>;
244
+ /**
245
+ * The ALTERNATE ID this candidate is stored under, which is the whole mechanism behind keeping
246
+ * more than one: two survivors of one subject are two deliverables, and two deliverables need
247
+ * two addresses. Absent ⇒ the step's ordinary naming applies, which is correct for the single
248
+ * survivor and is why it is optional rather than defaulted to something invented.
249
+ */
250
+ readonly storeAs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>, v.RegexAction<string, "must be a plain id (letters, digits, . _ -)">]>, undefined>;
251
+ }, undefined>, undefined>, v.MinLengthAction<{
252
+ candidateId: string;
253
+ storeAs?: string | undefined;
254
+ }[], 1, undefined>, v.MaxLengthAction<{
255
+ candidateId: string;
256
+ storeAs?: string | undefined;
257
+ }[], 16, undefined>]>;
258
+ readonly note: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 4000, undefined>]>, undefined>;
259
+ }, undefined>;
260
+ export type KeepBinaryCandidatesInput = v.InferOutput<typeof keepBinaryCandidatesSchema>;
261
+ //# sourceMappingURL=binary-candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-candidates.d.ts","sourceRoot":"","sources":["../src/binary-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAmC5B;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B;IAC1C;;;;;;;;;OASG;;IAEH;;;;;;;OAOG;;aAEH,CAAA;AACF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE7F;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB;IAChC,qFAAqF;;IAErF,gGAAgG;;IAEhG;;;;;;OAMG;;IAEH;;;;OAIG;;IAEH,kGAAkG;;IAElG,6DAA6D;;IAE7D,+CAA+C;;IAE/C;;;;;;;;OAQG;;IAEH,oFAAoF;;aAEpF,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,8EAa9C,CAAA;AACF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,WAAW,CACvD,OAAO,mCAAmC,CAC3C,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,yEAAyD,CAAA;AACjG,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAErF,yEAAyE;AACzE,eAAO,MAAM,yBAAyB;;IAEpC;;;;;OAKG;;aAEH,CAAA;AACF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEjF,oDAAoD;AACpD,eAAO,MAAM,2BAA2B;;;QAXtC;;;;;WAKG;;;IAQH;;;;OAIG;;IAEH,mGAAmG;;IAEnG;;;;;;;OAOG;;;aAGH,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAErF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B;;;QAtHzC,qFAAqF;;QAErF,gGAAgG;;QAEhG;;;;;;WAMG;;QAEH;;;;WAIG;;QAEH,kGAAkG;;QAElG,6DAA6D;;QAE7D,+CAA+C;;QAE/C;;;;;;;;WAQG;;QAEH,oFAAoF;;;IAuFpF,6CAA6C;;IAE7C,kCAAkC;;;;YA/ClC;;;;;eAKG;;;QAQH;;;;WAIG;;QAEH,mGAAmG;;QAEnG;;;;;;;WAOG;;;;IAqBH;4FACwF;;IAExF,sFAAsF;;IAEtF,gFAAgF;;IAEhF;qFACiF;;aAEjF,CAAA;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAI3F;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B;;;QAxErC;;;;;WAKG;;;;;;;;;;aAsEH,CAAA;AACF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
@@ -0,0 +1,202 @@
1
+ import * as v from 'valibot';
2
+ // ---------------------------------------------------------------------------
3
+ // SIDE-BY-SIDE CANDIDATE COMPARISON for a binary-output step.
4
+ //
5
+ // A step may select several generative integrations that produce the same content type. The
6
+ // design record states the overlap to both the agent and the step's author and deliberately ranks
7
+ // nothing, because the platform has no cost model, no quality model and no view of what the step
8
+ // is for. That is the right answer while the choice has to be made BEFORE the pictures exist.
9
+ //
10
+ // It is the wrong answer when it does not. Two image APIs asked for the same sprite return two
11
+ // sprites, and a person looking at them decides in a second what no description could have
12
+ // decided in advance. So a step may instead declare a COMPARISON: generate a candidate from every
13
+ // selected integration, park, and let a human keep one, or keep several under DISTINCT ids.
14
+ //
15
+ // Two properties are load-bearing and both follow from the rest of the feature:
16
+ //
17
+ // - **The platform never holds the bytes.** Candidates are staged through the step's own storage
18
+ // service exactly as deliverables are, and what the SPA renders is whatever preview URL that
19
+ // service reported. A service that reports none leaves the candidate legible as metadata and
20
+ // says the preview is unavailable, which is a different fact from a candidate that failed.
21
+ // - **The decision is DATA, and the agent executes it.** Keeping a candidate does not move a file:
22
+ // it records which candidates survive and under which id, and the step re-runs with that
23
+ // folded into its brief. The platform's own artifact store is for run evidence, and a product
24
+ // asset it never touched is not something it should start touching to implement a picker.
25
+ // ---------------------------------------------------------------------------
26
+ const candidateSlug = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(64), v.regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, 'must be a plain id (letters, digits, . _ -)'));
27
+ /**
28
+ * The per-step comparison declaration: this step generates candidates and PARKS for a human.
29
+ *
30
+ * Its presence is the switch. There is no `enabled: false`, because a step that is not comparing
31
+ * carries nothing, and a disabled bag would be a saved configuration that describes a behaviour
32
+ * the run does not have.
33
+ */
34
+ export const binaryCandidateComparisonSchema = v.object({
35
+ /**
36
+ * How many candidates EACH selected integration should produce per subject. Defaults to one,
37
+ * which is the case the whole feature is named for: one render from each of the integrations
38
+ * that overlap.
39
+ *
40
+ * Above one it also covers the single-integration case, where the comparison is between seeds
41
+ * rather than between vendors. That is not a lesser use: a step holding one pixel-art API and
42
+ * asking for four candidates is exactly how a sprite gets picked, and refusing it would make
43
+ * the feature depend on a deployment happening to have bought two vendors.
44
+ */
45
+ perGenerator: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(4))),
46
+ /**
47
+ * Whether MORE THAN ONE candidate may be kept. Off by default: the ordinary case is a choice,
48
+ * and a picker that silently allowed two would leave a step delivering an artifact count nobody
49
+ * asked for.
50
+ *
51
+ * On, every kept candidate is stored under its own id (`storeAs`), which is what makes keeping
52
+ * two a real outcome rather than a collision: two files at one location is one file.
53
+ */
54
+ multiSelect: v.optional(v.literal(true)),
55
+ });
56
+ /**
57
+ * One generated candidate, as the agent declared it in its fenced ```binary-candidates block.
58
+ *
59
+ * `id` is engine-minted (`cand_*`) rather than taken from the reply: the id is what a human's
60
+ * choice names, so a model that repeats one, omits one, or writes a 4 KB one would break the
61
+ * decision rather than its own bookkeeping. What the agent DOES supply is `label`, which is how
62
+ * it refers to the candidate in its own prose, kept so the two records can be lined up.
63
+ */
64
+ export const binaryCandidateSchema = v.object({
65
+ /** Engine-minted stable id (`cand_*`), assigned when the declaration is recorded. */
66
+ id: v.string(),
67
+ /** The agent's own name for this candidate, retained so its prose can be matched to the row. */
68
+ label: v.optional(v.string()),
69
+ /**
70
+ * The integration that produced it. Optional for the same reason the deliverable's own
71
+ * `generator` is (a model with native image output produces without a registered integration),
72
+ * and far more load-bearing here: with several producers in play it is the axis the human is
73
+ * comparing along, so a candidate that omits it is rendered as unattributed rather than
74
+ * silently attributed to the step's first integration.
75
+ */
76
+ generator: v.optional(v.string()),
77
+ /**
78
+ * What this candidate DEPICTS, in the agent's words (`product:tea-kettle`, `sprite:anvil`).
79
+ * Candidates are grouped by it, so a step that generated forty subjects renders forty
80
+ * comparisons rather than one wall of eighty images.
81
+ */
82
+ subject: v.optional(v.string()),
83
+ /** The service the candidate was staged through, lowercased on read-back like a deliverable's. */
84
+ service: v.string(),
85
+ /** Where it lives in that service's addressing, verbatim. */
86
+ location: v.string(),
87
+ /** The media type the agent reports for it. */
88
+ contentType: v.optional(v.string()),
89
+ /**
90
+ * A URL the SPA can render the candidate from, when the storage service issued one.
91
+ *
92
+ * ABSENT is a real and common state, not a failure: an org's asset store may be private, and
93
+ * the platform will not invent a link into it. The surface then renders the candidate's
94
+ * metadata and says the preview is unavailable, which is what lets a private estate use this
95
+ * feature at all. Constrained to `https` (or loopback) at parse time, because it is rendered
96
+ * in a browser from text a model wrote.
97
+ */
98
+ previewUrl: v.optional(v.string()),
99
+ /** One line on what makes this candidate different, from the agent that made it. */
100
+ note: v.optional(v.string()),
101
+ });
102
+ /**
103
+ * Why a comparison step did NOT park, when it did not.
104
+ *
105
+ * Its own vocabulary rather than an absent state, because every member is a different fault with
106
+ * a different fix and all three end with the run advancing. A comparison that wedged a run on a
107
+ * model that forgot a fenced block would be a worse outcome than the one it exists to improve.
108
+ */
109
+ export const binaryCandidateNoChoiceReasonSchema = v.picklist([
110
+ /** The reply carried no ```binary-candidates block at all. A prompt/model problem. */
111
+ 'undeclared',
112
+ /** A block was present and its body was not parseable. */
113
+ 'parse_failed',
114
+ /**
115
+ * The block was read and NO candidate survived it: the agent staged nothing, or every entry it
116
+ * declared was malformed. Deliberately not "fewer than two": a single candidate is auto-kept
117
+ * (see {@link BinaryCandidateChoice.automatic}) rather than treated as a failed comparison,
118
+ * mirroring the fork decision's single-path escape hatch. Nobody is asked to choose between one
119
+ * thing, and discarding a real generation because it had no rival would be the worse outcome.
120
+ */
121
+ 'no_candidates',
122
+ ]);
123
+ /**
124
+ * The candidate lifecycle on a comparison step:
125
+ * - `awaiting_choice`: parked; the human is comparing.
126
+ * - `chosen`: the human decided; the step re-runs and stores what survived.
127
+ * - `no_choice`: nothing to choose between, for one of the reasons above. No park.
128
+ */
129
+ export const binaryCandidateStatusSchema = v.picklist(['awaiting_choice', 'chosen', 'no_choice']);
130
+ /** One candidate the human kept, and the id it is to be stored under. */
131
+ export const binaryCandidateKeepSchema = v.object({
132
+ candidateId: v.string(),
133
+ /**
134
+ * The ALTERNATE ID this candidate is stored under, which is the whole mechanism behind keeping
135
+ * more than one: two survivors of one subject are two deliverables, and two deliverables need
136
+ * two addresses. Absent ⇒ the step's ordinary naming applies, which is correct for the single
137
+ * survivor and is why it is optional rather than defaulted to something invented.
138
+ */
139
+ storeAs: v.optional(candidateSlug),
140
+ });
141
+ /** The human's resolution, recorded on the step. */
142
+ export const binaryCandidateChoiceSchema = v.object({
143
+ kept: v.array(binaryCandidateKeepSchema),
144
+ /**
145
+ * The candidate ids that were NOT kept, recorded explicitly rather than derived by subtraction
146
+ * at read time. The surviving record must still say what was rejected once the step re-runs and
147
+ * the candidate list is the only thing left describing a generation nobody kept.
148
+ */
149
+ discarded: v.array(v.string()),
150
+ /** Why, in the human's words. Folded into the re-run's brief so the agent knows what was wrong. */
151
+ note: v.optional(v.nullable(v.string())),
152
+ /**
153
+ * Set when the engine kept the only candidate rather than parking, so NOBODY reviewed it.
154
+ *
155
+ * Its own flag rather than an absent decider, because the two are the same record and opposite
156
+ * facts: a surface that renders an auto-kept artifact as "chosen" is telling a reader that a
157
+ * person looked at this and approved it, which is exactly the claim this feature exists to make
158
+ * true. An auto-keep is a legitimate outcome and a quieter one, and it says so.
159
+ */
160
+ automatic: v.optional(v.literal(true)),
161
+ at: v.number(),
162
+ });
163
+ /**
164
+ * Live candidate-comparison state carried on the run's step. All of it rides `PipelineStep`, no
165
+ * side table, so D1 and Drizzle parity is free exactly as it is for `forkDecision` / `followUps`.
166
+ *
167
+ * The bookkeeping fields mirror `binaryOutputReportSchema`'s, and for the same reason: every way
168
+ * a candidate was lost is COUNTED rather than absorbed, so a comparison over three images that
169
+ * was meant to be over five does not read as a complete one.
170
+ */
171
+ export const binaryCandidateStepStateSchema = v.object({
172
+ status: binaryCandidateStatusSchema,
173
+ candidates: v.optional(v.array(binaryCandidateSchema), []),
174
+ /** Set only when `status` is `no_choice`. */
175
+ noChoiceReason: v.optional(v.nullable(binaryCandidateNoChoiceReasonSchema)),
176
+ /** Set once the human decides. */
177
+ choice: v.optional(v.nullable(binaryCandidateChoiceSchema)),
178
+ /** Whether more than one candidate may be kept, frozen from the step's config at record time
179
+ * so the resolver judges the request against the rule the human was actually shown. */
180
+ multiSelect: v.optional(v.boolean()),
181
+ /** Declared entries dropped because they were not `{ service, location }` objects. */
182
+ invalidEntries: v.optional(v.number(), 0),
183
+ /** Valid entries dropped past the per-step cap, so `candidates` is a PREFIX. */
184
+ omitted: v.optional(v.number(), 0),
185
+ /** Preview URLs dropped because they were not an `https`/loopback URL. The candidate is kept
186
+ * and rendered without a preview: a refused link is not a refused candidate. */
187
+ unusablePreviews: v.optional(v.number(), 0),
188
+ });
189
+ // ---- Request bodies -------------------------------------------------------
190
+ /**
191
+ * Keep one or more candidates and discard the rest.
192
+ *
193
+ * At least one must be kept: "discard everything" is a different act (it means the generation was
194
+ * a failure), and answering it through this verb would re-run the step to store nothing while
195
+ * reporting a completed choice. A step whose candidates are all bad is retried or reworked
196
+ * through the surfaces that already exist for that.
197
+ */
198
+ export const keepBinaryCandidatesSchema = v.object({
199
+ keep: v.pipe(v.array(binaryCandidateKeepSchema), v.minLength(1), v.maxLength(16)),
200
+ note: v.optional(v.pipe(v.string(), v.trim(), v.maxLength(4000))),
201
+ });
202
+ //# sourceMappingURL=binary-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-candidates.js","sourceRoot":"","sources":["../src/binary-candidates.ts"],"names":[],"mappings":"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"}