ai-foreman 1.7.26 → 1.7.28

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 (98) hide show
  1. package/dist/adapters/codex.d.ts +12 -0
  2. package/dist/adapters/codex.js +50 -1
  3. package/dist/adapters/recovering.d.ts +4 -0
  4. package/dist/adapters/recovering.js +10 -0
  5. package/dist/adapters/sessionFailure.d.ts +6 -0
  6. package/dist/adapters/sessionFailure.js +19 -0
  7. package/dist/adapters/types.d.ts +6 -0
  8. package/dist/branch/currentGuard.d.ts +8 -0
  9. package/dist/branch/currentGuard.js +5 -0
  10. package/dist/branch/runner.js +6 -2
  11. package/dist/buildApproval.js +2 -1
  12. package/dist/buildRuns.d.ts +12 -0
  13. package/dist/buildRuns.js +50 -0
  14. package/dist/buildWorkContext.js +1 -1
  15. package/dist/buildWorkMigration.d.ts +10 -0
  16. package/dist/buildWorkMigration.js +18 -2
  17. package/dist/cli/start.d.ts +10 -1
  18. package/dist/cli/start.js +186 -31
  19. package/dist/cli/state.js +39 -1
  20. package/dist/cli/tickets.d.ts +37 -0
  21. package/dist/cli/tickets.js +367 -12
  22. package/dist/config.js +14 -4
  23. package/dist/continuity.d.ts +1 -0
  24. package/dist/continuity.js +5 -0
  25. package/dist/foreman.js +89 -8
  26. package/dist/graph/preparation.js +6 -3
  27. package/dist/graph/semantic.js +2 -1
  28. package/dist/graph/turn.js +8 -1
  29. package/dist/handoffProtocol.js +2 -1
  30. package/dist/handoffs.js +7 -19
  31. package/dist/hostQaComparison.d.ts +50 -0
  32. package/dist/hostQaComparison.js +195 -0
  33. package/dist/log.d.ts +1 -1
  34. package/dist/managerPacket.js +1 -1
  35. package/dist/observability.d.ts +2 -0
  36. package/dist/observability.js +2 -1
  37. package/dist/permissions/policy.js +32 -0
  38. package/dist/planChanges.js +1 -1
  39. package/dist/projectDiagnostics.js +30 -0
  40. package/dist/providerQuestions.js +4 -24
  41. package/dist/qaBuildGate.d.ts +6 -1
  42. package/dist/qaBuildGate.js +76 -16
  43. package/dist/qaBuilderCoverage.d.ts +2 -1
  44. package/dist/qaBuilderCoverage.js +58 -7
  45. package/dist/qaBuilderEvidence.d.ts +18 -0
  46. package/dist/qaBuilderEvidence.js +60 -0
  47. package/dist/qaContractCoverage.d.ts +12 -1
  48. package/dist/qaContractCoverage.js +34 -2
  49. package/dist/qaContractDelivery.d.ts +2 -2
  50. package/dist/qaContractDelivery.js +88 -10
  51. package/dist/qaEffectiveConfig.js +2 -1
  52. package/dist/qaFailureDelivery.d.ts +23 -0
  53. package/dist/qaFailureDelivery.js +87 -6
  54. package/dist/qaHostFacts.d.ts +2 -0
  55. package/dist/qaHostFacts.js +11 -0
  56. package/dist/qaPreparation.d.ts +38 -1
  57. package/dist/qaPreparation.js +372 -31
  58. package/dist/qaPreparationInputs.js +5 -1
  59. package/dist/qaPreparationPolicy.d.ts +2 -1
  60. package/dist/qaPreparationPolicy.js +39 -9
  61. package/dist/qaPreparationStore.d.ts +4 -0
  62. package/dist/qaPreparationStore.js +8 -0
  63. package/dist/qaRecovery.d.ts +7 -0
  64. package/dist/qaRecovery.js +73 -1
  65. package/dist/qaReview.js +58 -9
  66. package/dist/qaReviewEvidence.d.ts +6 -0
  67. package/dist/qaReviewEvidence.js +37 -0
  68. package/dist/qaRollbackRehearsal.d.ts +2 -0
  69. package/dist/qaRollbackRehearsal.js +78 -0
  70. package/dist/qaSnapshot.d.ts +3 -1
  71. package/dist/qaSnapshot.js +3 -2
  72. package/dist/qaVerificationContract.d.ts +16 -0
  73. package/dist/qaVerificationContract.js +183 -17
  74. package/dist/sources/sourceRegistry.js +16 -5
  75. package/dist/stateTransfer.d.ts +14 -0
  76. package/dist/stateTransfer.js +51 -0
  77. package/dist/statusReporter.d.ts +8 -0
  78. package/dist/statusReporter.js +5 -0
  79. package/dist/supervisedStart.js +23 -0
  80. package/dist/ticketPlanning.d.ts +373 -0
  81. package/dist/ticketPlanning.js +34 -3
  82. package/dist/ticketPopulation.d.ts +28 -3
  83. package/dist/ticketPopulation.js +127 -15
  84. package/dist/tickets/details.d.ts +2 -1
  85. package/dist/tickets/details.js +7 -3
  86. package/dist/tickets/eligibility.d.ts +6 -0
  87. package/dist/tickets/eligibility.js +12 -1
  88. package/dist/tickets/riskWaivers.d.ts +3 -0
  89. package/dist/tickets/riskWaivers.js +12 -0
  90. package/dist/tickets/stateDb.d.ts +10 -0
  91. package/dist/tickets/stateDb.js +23 -0
  92. package/dist/tickets/ticketLoader.d.ts +9 -0
  93. package/dist/tickets/ticketLoader.js +15 -2
  94. package/dist/tickets/ticketSchema.d.ts +14 -1
  95. package/dist/tickets/ticketSchema.js +2 -1
  96. package/dist/tickets/validate.js +11 -1
  97. package/dist/workflowDb.js +24 -3
  98. package/package.json +9 -4
@@ -2,6 +2,7 @@ import type { TicketDef } from "./tickets/ticketSchema.js";
2
2
  import { type TicketStatus } from "./tickets/stateDb.js";
3
3
  import { type DeliveryConfig } from "./tickets/delivery.js";
4
4
  import { type TicketBuildSetupConfig } from "./tickets/setupConfig.js";
5
+ import { z } from "zod";
5
6
  export declare const PROPOSAL_START = "RAFI_PROPOSAL_START";
6
7
  export declare const PROPOSAL_END = "RAFI_PROPOSAL_END";
7
8
  export interface TicketEdit {
@@ -68,6 +69,378 @@ export interface TicketPlanningContext {
68
69
  export interface TicketPlanValidationContext {
69
70
  futureWorkIds?: Iterable<number>;
70
71
  }
72
+ export declare const ticketPlanProposalV1Schema: z.ZodObject<{
73
+ version: z.ZodLiteral<1>;
74
+ title: z.ZodString;
75
+ markdown: z.ZodString;
76
+ additions: z.ZodArray<z.ZodObject<{
77
+ qa_preparation: z.ZodOptional<z.ZodObject<{
78
+ version: z.ZodLiteral<1>;
79
+ decisionId: z.ZodString;
80
+ level: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>;
81
+ rationale: z.ZodString;
82
+ riskFactors: z.ZodArray<z.ZodObject<{
83
+ category: z.ZodEnum<{
84
+ interaction: "interaction";
85
+ compatibility: "compatibility";
86
+ "state-transition": "state-transition";
87
+ "external-dependency": "external-dependency";
88
+ authorization: "authorization";
89
+ security: "security";
90
+ "data-integrity": "data-integrity";
91
+ migration: "migration";
92
+ concurrency: "concurrency";
93
+ recovery: "recovery";
94
+ deployment: "deployment";
95
+ "architecture-uncertainty": "architecture-uncertainty";
96
+ }>;
97
+ rationale: z.ZodString;
98
+ references: z.ZodArray<z.ZodString>;
99
+ }, z.core.$strict>>;
100
+ lowRisk: z.ZodOptional<z.ZodObject<{
101
+ narrowBehavior: z.ZodString;
102
+ understoodDependencies: z.ZodString;
103
+ adequateVerification: z.ZodString;
104
+ }, z.core.$strict>>;
105
+ policyVersion: z.ZodLiteral<"qa-preparation-v1">;
106
+ plannerOperationId: z.ZodString;
107
+ plannerIdentity: z.ZodString;
108
+ timestamp: z.ZodString;
109
+ minimumLevel: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>;
110
+ minimumReasons: z.ZodArray<z.ZodString>;
111
+ predecessorDecisionId: z.ZodOptional<z.ZodString>;
112
+ }, z.core.$strict>>;
113
+ id: z.ZodString;
114
+ order: z.ZodNumber;
115
+ documentation: z.ZodOptional<z.ZodObject<{
116
+ required: z.ZodBoolean;
117
+ targets: z.ZodArray<z.ZodString>;
118
+ criteria: z.ZodArray<z.ZodString>;
119
+ }, z.core.$strict>>;
120
+ title: z.ZodString;
121
+ area: z.ZodString;
122
+ priority: z.ZodEnum<{
123
+ P0: "P0";
124
+ P1: "P1";
125
+ P2: "P2";
126
+ P3: "P3";
127
+ }>;
128
+ size: z.ZodEnum<{
129
+ XS: "XS";
130
+ S: "S";
131
+ M: "M";
132
+ L: "L";
133
+ XL: "XL";
134
+ }>;
135
+ risk: z.ZodEnum<{
136
+ Low: "Low";
137
+ Medium: "Medium";
138
+ High: "High";
139
+ }>;
140
+ depends_on: z.ZodArray<z.ZodString>;
141
+ summary: z.ZodString;
142
+ acceptance: z.ZodArray<z.ZodString>;
143
+ required_tests: z.ZodArray<z.ZodString>;
144
+ likely_files: z.ZodArray<z.ZodString>;
145
+ rollback: z.ZodOptional<z.ZodNullable<z.ZodString>>;
146
+ notes: z.ZodOptional<z.ZodNullable<z.ZodString>>;
147
+ external_refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
148
+ provider: z.ZodString;
149
+ id: z.ZodString;
150
+ key: z.ZodOptional<z.ZodNullable<z.ZodString>>;
151
+ url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
152
+ }, z.core.$strict>>>;
153
+ source_refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
154
+ source: z.ZodString;
155
+ item: z.ZodString;
156
+ source_id: z.ZodOptional<z.ZodString>;
157
+ url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
158
+ fingerprint: z.ZodOptional<z.ZodNullable<z.ZodString>>;
159
+ note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
160
+ }, z.core.$strict>>>;
161
+ superseded_by: z.ZodOptional<z.ZodArray<z.ZodString>>;
162
+ supersedes: z.ZodOptional<z.ZodArray<z.ZodString>>;
163
+ plan_ref: z.ZodOptional<z.ZodObject<{
164
+ plan_id: z.ZodString;
165
+ revision: z.ZodNumber;
166
+ slice_ref: z.ZodString;
167
+ }, z.core.$strict>>;
168
+ }, z.core.$strict>>;
169
+ edits: z.ZodArray<z.ZodObject<{
170
+ id: z.ZodString;
171
+ patch: z.ZodObject<{
172
+ qa_preparation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
173
+ version: z.ZodLiteral<1>;
174
+ decisionId: z.ZodString;
175
+ level: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>;
176
+ rationale: z.ZodString;
177
+ riskFactors: z.ZodArray<z.ZodObject<{
178
+ category: z.ZodEnum<{
179
+ interaction: "interaction";
180
+ compatibility: "compatibility";
181
+ "state-transition": "state-transition";
182
+ "external-dependency": "external-dependency";
183
+ authorization: "authorization";
184
+ security: "security";
185
+ "data-integrity": "data-integrity";
186
+ migration: "migration";
187
+ concurrency: "concurrency";
188
+ recovery: "recovery";
189
+ deployment: "deployment";
190
+ "architecture-uncertainty": "architecture-uncertainty";
191
+ }>;
192
+ rationale: z.ZodString;
193
+ references: z.ZodArray<z.ZodString>;
194
+ }, z.core.$strict>>;
195
+ lowRisk: z.ZodOptional<z.ZodObject<{
196
+ narrowBehavior: z.ZodString;
197
+ understoodDependencies: z.ZodString;
198
+ adequateVerification: z.ZodString;
199
+ }, z.core.$strict>>;
200
+ policyVersion: z.ZodLiteral<"qa-preparation-v1">;
201
+ plannerOperationId: z.ZodString;
202
+ plannerIdentity: z.ZodString;
203
+ timestamp: z.ZodString;
204
+ minimumLevel: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>;
205
+ minimumReasons: z.ZodArray<z.ZodString>;
206
+ predecessorDecisionId: z.ZodOptional<z.ZodString>;
207
+ }, z.core.$strict>>>;
208
+ id: z.ZodOptional<z.ZodString>;
209
+ order: z.ZodOptional<z.ZodNumber>;
210
+ documentation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
211
+ required: z.ZodBoolean;
212
+ targets: z.ZodArray<z.ZodString>;
213
+ criteria: z.ZodArray<z.ZodString>;
214
+ }, z.core.$strict>>>;
215
+ title: z.ZodOptional<z.ZodString>;
216
+ area: z.ZodOptional<z.ZodString>;
217
+ priority: z.ZodOptional<z.ZodEnum<{
218
+ P0: "P0";
219
+ P1: "P1";
220
+ P2: "P2";
221
+ P3: "P3";
222
+ }>>;
223
+ size: z.ZodOptional<z.ZodEnum<{
224
+ XS: "XS";
225
+ S: "S";
226
+ M: "M";
227
+ L: "L";
228
+ XL: "XL";
229
+ }>>;
230
+ risk: z.ZodOptional<z.ZodEnum<{
231
+ Low: "Low";
232
+ Medium: "Medium";
233
+ High: "High";
234
+ }>>;
235
+ depends_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
236
+ summary: z.ZodOptional<z.ZodString>;
237
+ acceptance: z.ZodOptional<z.ZodArray<z.ZodString>>;
238
+ required_tests: z.ZodOptional<z.ZodArray<z.ZodString>>;
239
+ likely_files: z.ZodOptional<z.ZodArray<z.ZodString>>;
240
+ rollback: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
241
+ notes: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
242
+ external_refs: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
243
+ provider: z.ZodString;
244
+ id: z.ZodString;
245
+ key: z.ZodOptional<z.ZodNullable<z.ZodString>>;
246
+ url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
247
+ }, z.core.$strict>>>>;
248
+ source_refs: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
249
+ source: z.ZodString;
250
+ item: z.ZodString;
251
+ source_id: z.ZodOptional<z.ZodString>;
252
+ url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
253
+ fingerprint: z.ZodOptional<z.ZodNullable<z.ZodString>>;
254
+ note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
255
+ }, z.core.$strict>>>>;
256
+ superseded_by: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
257
+ supersedes: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
258
+ plan_ref: z.ZodOptional<z.ZodOptional<z.ZodObject<{
259
+ plan_id: z.ZodString;
260
+ revision: z.ZodNumber;
261
+ slice_ref: z.ZodString;
262
+ }, z.core.$strict>>>;
263
+ }, z.core.$strict>;
264
+ }, z.core.$strict>>;
265
+ supersessions: z.ZodArray<z.ZodObject<{
266
+ replaced: z.ZodArray<z.ZodString>;
267
+ replacements: z.ZodArray<z.ZodString>;
268
+ reason: z.ZodString;
269
+ }, z.core.$strict>>;
270
+ state_changes: z.ZodArray<z.ZodObject<{
271
+ id: z.ZodString;
272
+ status: z.ZodEnum<{
273
+ blocked: "blocked";
274
+ in_progress: "in_progress";
275
+ done: "done";
276
+ planned: "planned";
277
+ next: "next";
278
+ canceled: "canceled";
279
+ obsolete: "obsolete";
280
+ }>;
281
+ reason: z.ZodString;
282
+ }, z.core.$strict>>;
283
+ source_reconciliation: z.ZodArray<z.ZodObject<{
284
+ source: z.ZodString;
285
+ item: z.ZodString;
286
+ disposition: z.ZodEnum<{
287
+ split: "split";
288
+ deferred: "deferred";
289
+ combined: "combined";
290
+ mapped: "mapped";
291
+ excluded: "excluded";
292
+ }>;
293
+ ticket_ids: z.ZodArray<z.ZodString>;
294
+ reason: z.ZodOptional<z.ZodString>;
295
+ }, z.core.$strict>>;
296
+ delivery: z.ZodOptional<z.ZodNullable<z.ZodObject<{
297
+ version: z.ZodLiteral<1>;
298
+ plan: z.ZodOptional<z.ZodObject<{
299
+ plan_id: z.ZodString;
300
+ revision: z.ZodNumber;
301
+ }, z.core.$strict>>;
302
+ units: z.ZodArray<z.ZodObject<{
303
+ id: z.ZodString;
304
+ tickets: z.ZodArray<z.ZodString>;
305
+ branch_mode: z.ZodEnum<{
306
+ current: "current";
307
+ "per-ticket": "per-ticket";
308
+ shared: "shared";
309
+ }>;
310
+ completion: z.ZodOptional<z.ZodEnum<{
311
+ none: "none";
312
+ pr: "pr";
313
+ "auto-merge": "auto-merge";
314
+ "direct-merge": "direct-merge";
315
+ }>>;
316
+ provider: z.ZodOptional<z.ZodEnum<{
317
+ auto: "auto";
318
+ local: "local";
319
+ github: "github";
320
+ gitlab: "gitlab";
321
+ }>>;
322
+ pr_ready: z.ZodOptional<z.ZodBoolean>;
323
+ merge_method: z.ZodOptional<z.ZodEnum<{
324
+ squash: "squash";
325
+ merge: "merge";
326
+ rebase: "rebase";
327
+ }>>;
328
+ cleanup: z.ZodOptional<z.ZodBoolean>;
329
+ depends_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
330
+ dependency_mode: z.ZodOptional<z.ZodEnum<{
331
+ combine: "combine";
332
+ wait: "wait";
333
+ stack: "stack";
334
+ }>>;
335
+ }, z.core.$strict>>;
336
+ stacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
337
+ id: z.ZodString;
338
+ name: z.ZodString;
339
+ units: z.ZodArray<z.ZodString>;
340
+ status: z.ZodOptional<z.ZodEnum<{
341
+ partial: "partial";
342
+ blocked: "blocked";
343
+ in_progress: "in_progress";
344
+ planned: "planned";
345
+ merged: "merged";
346
+ awaiting_review: "awaiting_review";
347
+ }>>;
348
+ completed_prefix: z.ZodOptional<z.ZodArray<z.ZodString>>;
349
+ next_ticket: z.ZodOptional<z.ZodString>;
350
+ review_links: z.ZodOptional<z.ZodArray<z.ZodString>>;
351
+ remote_checked_at: z.ZodOptional<z.ZodString>;
352
+ remote_stale: z.ZodOptional<z.ZodBoolean>;
353
+ published_branches: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
354
+ }, z.core.$strict>>>;
355
+ }, z.core.$strict>>>;
356
+ build_defaults: z.ZodOptional<z.ZodNullable<z.ZodObject<{
357
+ branch_strategy: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
358
+ current: "current";
359
+ batch: "batch";
360
+ "branch-per-ticket": "branch-per-ticket";
361
+ }>>>;
362
+ completion: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
363
+ none: "none";
364
+ pr: "pr";
365
+ "auto-merge": "auto-merge";
366
+ "direct-merge": "direct-merge";
367
+ }>>>;
368
+ provider: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
369
+ auto: "auto";
370
+ local: "local";
371
+ github: "github";
372
+ gitlab: "gitlab";
373
+ }>>>;
374
+ pr_ready: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
375
+ merge_method: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
376
+ squash: "squash";
377
+ merge: "merge";
378
+ rebase: "rebase";
379
+ }>>>;
380
+ cleanup: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
381
+ auto_merge_wait: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
382
+ auto_merge_timeout_minutes: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodNumber>>>;
383
+ base_branch: z.ZodOptional<z.ZodOptional<z.ZodString>>;
384
+ branch_prefix: z.ZodOptional<z.ZodOptional<z.ZodString>>;
385
+ branch_policy: z.ZodOptional<z.ZodOptional<z.ZodObject<{
386
+ mode: z.ZodEnum<{
387
+ size: "size";
388
+ global: "global";
389
+ }>;
390
+ global_strategy: z.ZodEnum<{
391
+ current: "current";
392
+ batch: "batch";
393
+ "branch-per-ticket": "branch-per-ticket";
394
+ }>;
395
+ by_size: z.ZodObject<{
396
+ XS: z.ZodEnum<{
397
+ "per-ticket": "per-ticket";
398
+ shared: "shared";
399
+ }>;
400
+ S: z.ZodEnum<{
401
+ "per-ticket": "per-ticket";
402
+ shared: "shared";
403
+ }>;
404
+ M: z.ZodEnum<{
405
+ "per-ticket": "per-ticket";
406
+ shared: "shared";
407
+ }>;
408
+ L: z.ZodEnum<{
409
+ "per-ticket": "per-ticket";
410
+ shared: "shared";
411
+ }>;
412
+ XL: z.ZodEnum<{
413
+ "per-ticket": "per-ticket";
414
+ shared: "shared";
415
+ }>;
416
+ }, z.core.$strict>;
417
+ }, z.core.$strict>>>;
418
+ review: z.ZodOptional<z.ZodOptional<z.ZodObject<{
419
+ title_style: z.ZodEnum<{
420
+ none: "none";
421
+ custom: "custom";
422
+ "ticket-title": "ticket-title";
423
+ conventional: "conventional";
424
+ }>;
425
+ title_template: z.ZodNullable<z.ZodString>;
426
+ description_sections: z.ZodArray<z.ZodString>;
427
+ }, z.core.$strict>>>;
428
+ validation_checklist: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
429
+ }, z.core.$strict>>>;
430
+ future_work: z.ZodArray<z.ZodObject<{
431
+ id: z.ZodNumber;
432
+ disposition: z.ZodEnum<{
433
+ rejected: "rejected";
434
+ accepted: "accepted";
435
+ merged: "merged";
436
+ queued: "queued";
437
+ }>;
438
+ }, z.core.$strict>>;
439
+ next: z.ZodObject<{
440
+ ticket_ids: z.ZodArray<z.ZodString>;
441
+ replace_existing: z.ZodBoolean;
442
+ }, z.core.$strict>;
443
+ }, z.core.$strict>;
71
444
  export declare function readTicketPlanningContext(projectDir: string): TicketPlanningContext;
72
445
  export declare function ticketPlanningFingerprint(projectDir: string): PlanningFingerprint[];
73
446
  export declare function planningFingerprintChanges(projectDir: string, expected: PlanningFingerprint[]): string[];
@@ -10,8 +10,34 @@ import { renderAndWrite } from "./tickets/renderMarkdown.js";
10
10
  import { runAllValidation } from "./tickets/validate.js";
11
11
  import { normalizeDeliveryConfig, validateDeliveryConfig } from "./tickets/delivery.js";
12
12
  import { loadTicketSetupConfig, mergeTicketSetup, saveTicketSetupConfig } from "./tickets/setupConfig.js";
13
+ import { z } from "zod";
14
+ import { documentationPolicyV1ZodSchema as documentationPolicyZodSchema, qaPreparationDepthDecisionZodSchema, zodIssues } from "rafi-spec";
13
15
  export const PROPOSAL_START = "RAFI_PROPOSAL_START";
14
16
  export const PROPOSAL_END = "RAFI_PROPOSAL_END";
17
+ const providerText = (max = 20_000) => z.string().trim().min(1).max(max);
18
+ const identifier = z.string().regex(/^[A-Za-z][A-Za-z0-9-_]{0,127}$/);
19
+ const ticketSourceRef = z.strictObject({ source: providerText(500), item: providerText(2_000), source_id: identifier.optional(), url: z.string().url().nullable().optional(), fingerprint: z.string().regex(/^[a-f0-9]{64}$/).nullable().optional(), note: providerText(2_000).nullable().optional() });
20
+ const ticketDefinitionProposal = z.strictObject({
21
+ qa_preparation: qaPreparationDepthDecisionZodSchema.optional(), id: identifier, order: z.number().int().min(0),
22
+ documentation: documentationPolicyZodSchema.optional(),
23
+ title: providerText(500), area: providerText(500), priority: z.enum(["P0", "P1", "P2", "P3"]), size: z.enum(["XS", "S", "M", "L", "XL"]), risk: z.enum(["Low", "Medium", "High"]),
24
+ depends_on: z.array(identifier).max(200), summary: providerText(), acceptance: z.array(providerText()).min(1).max(200), required_tests: z.array(providerText()).min(1).max(200), likely_files: z.array(providerText(1_000)).max(200),
25
+ rollback: z.string().max(20_000).nullable().optional(), notes: z.string().max(20_000).nullable().optional(),
26
+ external_refs: z.array(z.strictObject({ provider: providerText(100), id: providerText(500), key: providerText(500).nullable().optional(), url: z.string().url().nullable().optional() })).max(100).optional(),
27
+ source_refs: z.array(ticketSourceRef).max(100).optional(), superseded_by: z.array(identifier).max(200).optional(), supersedes: z.array(identifier).max(200).optional(),
28
+ plan_ref: z.strictObject({ plan_id: identifier, revision: z.number().int().min(1), slice_ref: identifier }).optional(),
29
+ });
30
+ const deliveryConfigProposal = z.strictObject({
31
+ version: z.literal(1), plan: z.strictObject({ plan_id: identifier, revision: z.number().int().min(1) }).optional(),
32
+ units: z.array(z.strictObject({ id: identifier, tickets: z.array(identifier).min(1).max(200), branch_mode: z.enum(["current", "per-ticket", "shared"]), completion: z.enum(["pr", "auto-merge", "direct-merge", "none"]).optional(), provider: z.enum(["auto", "github", "gitlab", "local"]).optional(), pr_ready: z.boolean().optional(), merge_method: z.enum(["squash", "merge", "rebase"]).optional(), cleanup: z.boolean().optional(), depends_on: z.array(identifier).max(200).optional(), dependency_mode: z.enum(["combine", "wait", "stack"]).optional() })).max(200),
33
+ stacks: z.array(z.strictObject({ id: identifier, name: providerText(500), units: z.array(identifier).min(1).max(5), status: z.enum(["planned", "in_progress", "partial", "blocked", "awaiting_review", "merged"]).optional(), completed_prefix: z.array(identifier).max(5).optional(), next_ticket: identifier.optional(), review_links: z.array(z.string().url()).max(20).optional(), remote_checked_at: z.string().datetime().optional(), remote_stale: z.boolean().optional(), published_branches: z.record(identifier, providerText(500)).optional() })).max(200).optional(),
34
+ });
35
+ const buildDefaultsProposal = z.strictObject({
36
+ branch_strategy: z.enum(["current", "batch", "branch-per-ticket"]).optional(), completion: z.enum(["pr", "auto-merge", "direct-merge", "none"]).optional(), provider: z.enum(["auto", "github", "gitlab", "local"]).optional(), pr_ready: z.boolean().optional(), merge_method: z.enum(["squash", "merge", "rebase"]).optional(), cleanup: z.boolean().optional(), auto_merge_wait: z.boolean().optional(), auto_merge_timeout_minutes: z.number().int().min(0).nullable().optional(), base_branch: providerText(500).optional(), branch_prefix: providerText(500).optional(), branch_policy: z.strictObject({ mode: z.enum(["global", "size"]), global_strategy: z.enum(["current", "batch", "branch-per-ticket"]), by_size: z.strictObject({ XS: z.enum(["shared", "per-ticket"]), S: z.enum(["shared", "per-ticket"]), M: z.enum(["shared", "per-ticket"]), L: z.enum(["shared", "per-ticket"]), XL: z.enum(["shared", "per-ticket"]) }) }).optional(), review: z.strictObject({ title_style: z.enum(["ticket-title", "conventional", "none", "custom"]), title_template: z.string().max(500).nullable(), description_sections: z.array(providerText(500)).max(50) }).optional(), validation_checklist: z.array(providerText(500)).max(100).optional(),
37
+ });
38
+ export const ticketPlanProposalV1Schema = z.strictObject({
39
+ version: z.literal(1), title: providerText(500), markdown: providerText(100_000), additions: z.array(ticketDefinitionProposal).max(200), edits: z.array(z.strictObject({ id: identifier, patch: ticketDefinitionProposal.partial() })).max(200), supersessions: z.array(z.strictObject({ replaced: z.array(identifier).min(1).max(200), replacements: z.array(identifier).min(1).max(200), reason: providerText() })).max(200), state_changes: z.array(z.strictObject({ id: identifier, status: z.enum(["planned", "next", "in_progress", "blocked", "done", "canceled", "obsolete"]), reason: providerText() })).max(200), source_reconciliation: z.array(z.strictObject({ source: providerText(500), item: providerText(2_000), disposition: z.enum(["mapped", "split", "combined", "deferred", "excluded"]), ticket_ids: z.array(identifier).max(200), reason: providerText().optional() })).max(500), delivery: deliveryConfigProposal.nullable().optional(), build_defaults: buildDefaultsProposal.partial().nullable().optional(), future_work: z.array(z.strictObject({ id: z.number().int().min(0), disposition: z.enum(["accepted", "rejected", "merged", "queued"]) })).max(500), next: z.strictObject({ ticket_ids: z.array(identifier).max(200), replace_existing: z.boolean() }),
40
+ });
15
41
  const TICKET_STATUSES = new Set([
16
42
  "planned", "next", "in_progress", "blocked", "done", "canceled", "obsolete",
17
43
  ]);
@@ -57,13 +83,18 @@ export function extractTicketPlanProposal(output, existingTickets = [], context
57
83
  catch (err) {
58
84
  throw new Error(`planner proposal is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
59
85
  }
60
- const issues = validateTicketPlanProposal(parsed, existingTickets, context);
86
+ const contract = ticketPlanProposalV1Schema.safeParse(parsed);
87
+ if (!contract.success)
88
+ throw new Error(`planner proposal contract validation failed:\n${zodIssues(contract.error).map((issue) => `- ${issue}`).join("\n")}`);
89
+ const issues = validateTicketPlanProposal(contract.data, existingTickets, context);
61
90
  if (issues.length)
62
91
  throw new Error(`invalid planner proposal:\n${issues.map((issue) => `- ${issue}`).join("\n")}`);
63
- return parsed;
92
+ return contract.data;
64
93
  }
65
94
  export function validateTicketPlanProposal(value, existingTickets = [], context = {}) {
66
95
  const issues = [];
96
+ const contract = ticketPlanProposalV1Schema.safeParse(value);
97
+ const contractIssues = contract.success ? [] : zodIssues(contract.error);
67
98
  if (!value || typeof value !== "object" || Array.isArray(value))
68
99
  return ["proposal must be an object"];
69
100
  const proposal = value;
@@ -159,7 +190,7 @@ export function validateTicketPlanProposal(value, existingTickets = [], context
159
190
  issues.push(...detectCycles(staged).map((cycle) => `dependency cycle: ${cycle}`));
160
191
  if (p.delivery)
161
192
  issues.push(...validateDeliveryConfig(p.delivery, staged).map((issue) => `delivery ${issue.path}: ${issue.message}`));
162
- return [...new Set(issues)];
193
+ return [...new Set([...contractIssues, ...issues])];
163
194
  }
164
195
  export function applyApprovedTicketPlan(projectDir, proposal, opts) {
165
196
  const root = resolve(projectDir);
@@ -1,8 +1,9 @@
1
- import type { StructuredPlanV1 } from "rafi-spec";
1
+ import { type StructuredPlanV1 } from "rafi-spec";
2
2
  import type { TicketDef } from "./tickets/ticketSchema.js";
3
3
  import { type DeliveryConfig } from "./tickets/delivery.js";
4
4
  export interface TicketSliceProposal {
5
5
  qa_preparation?: TicketDef["qa_preparation"];
6
+ documentation?: TicketDef["documentation"];
6
7
  slice_ref: string;
7
8
  title: string;
8
9
  area: string;
@@ -33,15 +34,39 @@ export interface TicketPopulationProposalV1 {
33
34
  }
34
35
  export declare const TICKET_POPULATION_PROPOSAL_START = "RAFI_TICKET_POPULATION_PROPOSAL_START";
35
36
  export declare const TICKET_POPULATION_PROPOSAL_END = "RAFI_TICKET_POPULATION_PROPOSAL_END";
37
+ export interface PopulationRiskWaiver {
38
+ ticketId: string;
39
+ reason: string;
40
+ actor: string;
41
+ }
36
42
  export interface MaterializedTicketPopulation {
37
43
  tickets: TicketDef[];
38
44
  delivery: DeliveryConfig;
39
45
  retirements: string[];
40
46
  sliceToTicket: Map<string, string>;
47
+ riskWaivers?: PopulationRiskWaiver[];
48
+ }
49
+ export type PopulationBranchStrategy = "current" | "batch" | "branch-per-ticket";
50
+ /** A recoverable, proposal-local validation failure. Callers can ask Ticket Maker
51
+ * to repair only the listed tickets instead of discarding the whole interview. */
52
+ export declare class TicketPopulationValidationError extends Error {
53
+ readonly repairableRiskTicketIds: string[];
54
+ readonly repairableRiskSliceRefs: string[];
55
+ readonly onlyRepairableRiskFailures: boolean;
56
+ constructor(message: string, repairableRiskTicketIds: string[], repairableRiskSliceRefs: string[], onlyRepairableRiskFailures: boolean);
41
57
  }
58
+ /** Reject a correction that attempts to turn a risk-note repair into a new plan. */
59
+ export declare function assertRiskPlanOnlyCorrection(previous: TicketPopulationProposalV1, corrected: TicketPopulationProposalV1, permittedSliceRefs: string[]): void;
42
60
  export declare function extractTicketPopulationProposal(output: string): TicketPopulationProposalV1;
43
- export declare function validateTicketPopulationProposal(proposal: TicketPopulationProposalV1, plan: StructuredPlanV1, existing: TicketDef[]): string[];
44
- export declare function materializeTicketPopulation(proposal: TicketPopulationProposalV1, plan: StructuredPlanV1, existing: TicketDef[]): MaterializedTicketPopulation;
61
+ export declare function validateTicketPopulationProposal(proposal: TicketPopulationProposalV1, plan: StructuredPlanV1, existing: TicketDef[], options?: {
62
+ branchStrategy?: PopulationBranchStrategy;
63
+ }): string[];
64
+ export declare function materializeTicketPopulation(proposal: TicketPopulationProposalV1, plan: StructuredPlanV1, existing: TicketDef[], options?: {
65
+ waiveRiskTicketIds?: string[];
66
+ waiverReason?: string;
67
+ waiverActor?: string;
68
+ branchStrategy?: PopulationBranchStrategy;
69
+ }): MaterializedTicketPopulation;
45
70
  export declare function authorizeTicketRetirements(retirements: string[], input: {
46
71
  interactiveConfirmed?: boolean;
47
72
  authorizedIds?: string[];