@tea-agent/loop-agent 0.16.0 → 0.16.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +7 -51
  3. package/README.md +1 -1
  4. package/dist/application/evaluation/candidate.js +6 -23
  5. package/dist/application/evaluation/types.js +0 -522
  6. package/dist/cli/command-definitions.js +3 -19
  7. package/dist/commands/eval.js +13 -1176
  8. package/dist/commands/init.js +1 -4
  9. package/dist/executors/dag-pi-executor.js +44 -4
  10. package/dist/worker/delivery/verification-bundle.js +2 -13
  11. package/dist/worker/feature/review.js +2 -3
  12. package/dist/worker/outcomes/adapters.js +1 -4
  13. package/dist/worker/outcomes/gate.js +11 -10
  14. package/dist/worker/outcomes/projector.js +1 -10
  15. package/dist/worker/outcomes/types.js +0 -3
  16. package/dist/worker/run-task/run-task.js +4 -23
  17. package/dist/worker/task-graph/ready-planner.js +8 -14
  18. package/dist/worker/task-graph/task-graph-schema.js +3 -5
  19. package/dist/workflows/dag/frontend-implementation-contract.js +77 -0
  20. package/dist/workflows/dag/init-hybrid.js +47 -3
  21. package/dist/workflows/dag/knowledge-curator.js +0 -3
  22. package/dist/workflows/dag/node-execution.js +4 -11
  23. package/dist/workflows/dag/prompt.js +1 -1
  24. package/dist/workflows/dag/runner.js +16 -43
  25. package/dist/workflows/dag/skill-snapshot.js +7 -11
  26. package/dist/workflows/dag/types.js +1 -18
  27. package/docs/init-surface.manifest.json +0 -3
  28. package/docs/templates/agent-dag.schema.json +5 -0
  29. package/docs/templates/product-line/AGENTS.md +0 -1
  30. package/docs/templates/product-line/README.md +0 -17
  31. package/docs/templates/product-line/acceptance.yaml +0 -9
  32. package/docs/templates/product-line/task-graph.yaml +0 -8
  33. package/docs/templates/product-line/task.yaml +0 -4
  34. package/package.json +1 -1
  35. package/skills/frontend-implementation/references/node-contracts.md +3 -3
  36. package/skills/loop-agent/references/hybrid-dag.md +1 -1
  37. package/dist/application/evaluation/alias.js +0 -184
  38. package/dist/application/evaluation/budget.js +0 -192
  39. package/dist/application/evaluation/campaign-hash.js +0 -47
  40. package/dist/application/evaluation/campaign-matrix.js +0 -372
  41. package/dist/application/evaluation/campaign-scorecard.js +0 -135
  42. package/dist/application/evaluation/campaign.js +0 -370
  43. package/dist/application/evaluation/corpus-hash.js +0 -38
  44. package/dist/application/evaluation/corpus.js +0 -56
  45. package/dist/application/evaluation/experiment.js +0 -294
  46. package/dist/application/evaluation/ignition.js +0 -198
  47. package/dist/application/evaluation/integrity-audit.js +0 -162
  48. package/dist/application/evaluation/outer-loop.js +0 -132
  49. package/dist/application/evaluation/pi-cell-executor.js +0 -39
  50. package/dist/application/evaluation/private-verifier.js +0 -46
  51. package/dist/application/evaluation/promotion-policy.js +0 -151
  52. package/dist/application/evaluation/proposer.js +0 -98
  53. package/dist/infrastructure/evaluation/alias-store.js +0 -199
  54. package/dist/infrastructure/evaluation/campaign-store.js +0 -154
  55. package/dist/infrastructure/evaluation/corpus-store.js +0 -181
  56. package/dist/infrastructure/evaluation/experiment-store.js +0 -124
  57. package/dist/infrastructure/evaluation/ignition-store.js +0 -82
  58. package/dist/infrastructure/evaluation/private-verifier-store.js +0 -145
  59. package/dist/infrastructure/evaluation/proposer-store.js +0 -78
  60. package/dist/worker/outcomes/evidence-tokens.js +0 -29
  61. package/dist/workflows/dag/budget-enforcement.js +0 -67
  62. package/dist/workflows/dag/context-policy.js +0 -137
  63. package/docs/templates/evaluation/campaign-budget-v1.json +0 -12
  64. package/docs/templates/evaluation/campaign-dogfood-v0.json +0 -24
  65. package/docs/templates/evaluation/campaign-evidence-v1.json +0 -44
  66. package/docs/templates/evaluation/context-policy-baseline-v1.json +0 -17
  67. package/docs/templates/evaluation/context-policy-role-specialized-v1.json +0 -28
  68. package/docs/templates/evaluation/corpus-dogfood-v0.manifest.json +0 -118
  69. package/docs/templates/evaluation/matrix-dag-dry-run-v1.json +0 -21
  70. package/docs/templates/evaluation/matrix-fixture-v1.json +0 -10
  71. package/docs/templates/evaluation/private-verifier-dogfood-v0.json +0 -16
  72. package/docs/templates/product-line/feature.yaml +0 -11
@@ -1,5 +1,4 @@
1
1
  import { z } from "zod";
2
- import { campaignBudgetSchema } from "./budget.js";
3
2
  export const evalSplitSchema = z.enum(["public", "private", "held_out"]);
4
3
  export const replayEvidenceRefSchema = z
5
4
  .object({
@@ -129,524 +128,3 @@ export const lifecycleEventSchema = z
129
128
  eventHash: z.string().regex(/^[a-f0-9]{64}$/),
130
129
  })
131
130
  .strict();
132
- // --- Incumbent Alias + Promotion Decision (M2 W2.4) ---
133
- export const aliasNameSchema = z
134
- .string()
135
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "alias must be one safe path segment");
136
- export const incumbentAliasSchema = z
137
- .object({
138
- schemaVersion: z.literal(1),
139
- alias: aliasNameSchema,
140
- candidateId: candidateIdSchema,
141
- bundleHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
142
- updatedAt: z.string().min(1),
143
- updatedByDecisionId: z.string().min(1),
144
- previousCandidateId: candidateIdSchema.nullable(),
145
- })
146
- .strict();
147
- export const aliasHistoryEventSchema = z
148
- .object({
149
- schemaVersion: z.literal(1),
150
- seq: z.number().int().positive(),
151
- decisionId: z.string().min(1),
152
- action: z.enum(["promote", "rollback"]),
153
- fromCandidateId: candidateIdSchema.nullable(),
154
- toCandidateId: candidateIdSchema,
155
- toBundleHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
156
- at: z.string().min(1),
157
- })
158
- .strict();
159
- export const promotionDecisionSchema = z
160
- .object({
161
- schemaVersion: z.literal(1),
162
- decisionId: z.string().min(1),
163
- alias: aliasNameSchema,
164
- action: z.enum(["promote", "rollback"]),
165
- fromCandidateId: candidateIdSchema.nullable(),
166
- toCandidateId: candidateIdSchema,
167
- toBundleHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
168
- reason: z.string().min(1),
169
- actor: z.literal("human"),
170
- humanRequired: z.literal(true),
171
- applied: z.boolean(),
172
- createdAt: z.string().min(1),
173
- campaignId: z.string().min(1).nullable().optional(),
174
- })
175
- .strict();
176
- // --- Corpus Manifest (W1.5) ---
177
- export const corpusIdSchema = z
178
- .string()
179
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "corpusId must be one safe path segment");
180
- export const corpusTaskClassSchema = z.enum([
181
- "docs",
182
- "bugfix",
183
- "implement",
184
- "frontend",
185
- "backend-test",
186
- "fullstack",
187
- "bootstrap",
188
- "refactor",
189
- ]);
190
- export const corpusTaskSchema = z
191
- .object({
192
- taskRef: z
193
- .string()
194
- .min(1)
195
- .regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/, "taskRef must be a safe relative id (letters, numbers, . _ - /)")
196
- .refine((value) => !value.includes(".."), "taskRef must not contain .."),
197
- class: corpusTaskClassSchema,
198
- split: evalSplitSchema,
199
- seeds: z
200
- .array(z.number().int().nonnegative())
201
- .min(2)
202
- .max(3)
203
- .superRefine((seeds, ctx) => {
204
- const seen = new Set();
205
- for (let i = 0; i < seeds.length; i += 1) {
206
- const seed = seeds[i];
207
- if (seen.has(seed)) {
208
- ctx.addIssue({
209
- code: z.ZodIssueCode.custom,
210
- message: `duplicate seed ${seed}`,
211
- path: [i],
212
- });
213
- }
214
- seen.add(seed);
215
- }
216
- }),
217
- description: z.string().optional(),
218
- featureId: z.string().min(1).optional(),
219
- })
220
- .strict();
221
- function refineCorpusTasks(manifest, ctx) {
222
- const refs = new Set();
223
- const classes = new Set();
224
- const splits = new Set();
225
- for (let i = 0; i < manifest.tasks.length; i += 1) {
226
- const task = manifest.tasks[i];
227
- if (refs.has(task.taskRef)) {
228
- ctx.addIssue({
229
- code: z.ZodIssueCode.custom,
230
- message: `duplicate taskRef: ${task.taskRef}`,
231
- path: ["tasks", i, "taskRef"],
232
- });
233
- }
234
- refs.add(task.taskRef);
235
- classes.add(task.class);
236
- splits.add(task.split);
237
- }
238
- if (classes.size < 3) {
239
- ctx.addIssue({
240
- code: z.ZodIssueCode.custom,
241
- message: "corpus requires at least 3 distinct task classes",
242
- path: ["tasks"],
243
- });
244
- }
245
- for (const required of ["public", "private", "held_out"]) {
246
- if (!splits.has(required)) {
247
- ctx.addIssue({
248
- code: z.ZodIssueCode.custom,
249
- message: `corpus requires at least one ${required} task`,
250
- path: ["tasks"],
251
- });
252
- }
253
- }
254
- }
255
- const corpusManifestObjectSchema = z
256
- .object({
257
- schemaVersion: z.literal(1),
258
- corpusId: corpusIdSchema,
259
- createdAt: z.string().min(1),
260
- description: z.string().optional(),
261
- tasks: z.array(corpusTaskSchema).min(12).max(20),
262
- corpusHash: z
263
- .string()
264
- .regex(/^(sha256:)?[a-f0-9]{64}$/i)
265
- .optional(),
266
- })
267
- .strict();
268
- export const corpusManifestInputSchema = corpusManifestObjectSchema.superRefine(refineCorpusTasks);
269
- export const corpusManifestSchema = z
270
- .object({
271
- schemaVersion: z.literal(1),
272
- corpusId: corpusIdSchema,
273
- createdAt: z.string().min(1),
274
- description: z.string().optional(),
275
- tasks: z.array(corpusTaskSchema).min(12).max(20),
276
- corpusHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
277
- })
278
- .strict()
279
- .superRefine(refineCorpusTasks);
280
- // --- Private Verifier + Campaign (M4) ---
281
- export const privateVerifierIdSchema = z
282
- .string()
283
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "privateVerifierId must be one safe path segment");
284
- export const privateVerifierCheckSchema = z
285
- .object({
286
- checkId: z
287
- .string()
288
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "checkId must be a safe id"),
289
- kind: z.literal("shell"),
290
- command: z.array(z.string().min(1)).min(1),
291
- cwd: z.string().min(1).default("."),
292
- timeoutMs: z.number().int().positive().max(3_600_000).default(60_000),
293
- expectedExitCode: z.number().int().default(0),
294
- })
295
- .strict();
296
- export const privateVerifierManifestInputSchema = z
297
- .object({
298
- schemaVersion: z.literal(1),
299
- privateVerifierId: privateVerifierIdSchema,
300
- createdAt: z.string().min(1),
301
- description: z.string().optional(),
302
- checks: z.array(privateVerifierCheckSchema).min(1),
303
- manifestHash: z
304
- .string()
305
- .regex(/^(sha256:)?[a-f0-9]{64}$/i)
306
- .optional(),
307
- })
308
- .strict();
309
- export const privateVerifierManifestSchema = privateVerifierManifestInputSchema
310
- .extend({
311
- manifestHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
312
- })
313
- .strict();
314
- export const campaignIdSchema = z
315
- .string()
316
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "campaignId must be one safe path segment");
317
- export const campaignStatusSchema = z.enum([
318
- "prepared",
319
- "running",
320
- "completed",
321
- "invalid",
322
- "aborted",
323
- ]);
324
- export const campaignEvaluatorIntegritySchema = z
325
- .object({
326
- corpusHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
327
- privateVerifierManifestHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
328
- budgetHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
329
- scoringRulesHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
330
- })
331
- .strict();
332
- function refineCampaignCandidates(manifest, ctx) {
333
- if (manifest.budget.mode !== "hard") {
334
- ctx.addIssue({
335
- code: z.ZodIssueCode.custom,
336
- message: "campaign budget.mode must be hard (record-only campaigns cannot enter promotion path)",
337
- path: ["budget", "mode"],
338
- });
339
- }
340
- if (manifest.challengerCandidateIds.includes(manifest.incumbentCandidateId)) {
341
- ctx.addIssue({
342
- code: z.ZodIssueCode.custom,
343
- message: "challengerCandidateIds must not include incumbentCandidateId",
344
- path: ["challengerCandidateIds"],
345
- });
346
- }
347
- const seen = new Set();
348
- for (let i = 0; i < manifest.challengerCandidateIds.length; i += 1) {
349
- const id = manifest.challengerCandidateIds[i];
350
- if (seen.has(id)) {
351
- ctx.addIssue({
352
- code: z.ZodIssueCode.custom,
353
- message: `duplicate challengerCandidateId: ${id}`,
354
- path: ["challengerCandidateIds", i],
355
- });
356
- }
357
- seen.add(id);
358
- }
359
- }
360
- const campaignManifestObjectSchema = z
361
- .object({
362
- schemaVersion: z.literal(1),
363
- campaignId: campaignIdSchema,
364
- createdAt: z.string().min(1),
365
- status: campaignStatusSchema.default("prepared"),
366
- controllerFingerprint: z.string().min(1).optional(),
367
- policyVersion: z.string().min(1).default("promotion-policy-v1"),
368
- incumbentCandidateId: candidateIdSchema,
369
- challengerCandidateIds: z.array(candidateIdSchema).min(1),
370
- corpusId: corpusIdSchema,
371
- corpusHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
372
- privateVerifierId: privateVerifierIdSchema,
373
- privateVerifierManifestHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
374
- budget: campaignBudgetSchema,
375
- seeds: z.array(z.number().int().nonnegative()).min(1).optional(),
376
- notes: z.string().optional(),
377
- evaluatorIntegrity: campaignEvaluatorIntegritySchema.optional(),
378
- })
379
- .strict();
380
- export const campaignManifestInputSchema = campaignManifestObjectSchema.superRefine(refineCampaignCandidates);
381
- export const campaignManifestSchema = z
382
- .object({
383
- schemaVersion: z.literal(1),
384
- campaignId: campaignIdSchema,
385
- createdAt: z.string().min(1),
386
- status: campaignStatusSchema,
387
- controllerFingerprint: z.string().min(1).optional(),
388
- policyVersion: z.string().min(1),
389
- incumbentCandidateId: candidateIdSchema,
390
- challengerCandidateIds: z.array(candidateIdSchema).min(1),
391
- corpusId: corpusIdSchema,
392
- corpusHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
393
- privateVerifierId: privateVerifierIdSchema,
394
- privateVerifierManifestHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
395
- budget: campaignBudgetSchema,
396
- seeds: z.array(z.number().int().nonnegative()).min(1).optional(),
397
- notes: z.string().optional(),
398
- evaluatorIntegrity: campaignEvaluatorIntegritySchema,
399
- })
400
- .strict()
401
- .superRefine(refineCampaignCandidates);
402
- export const campaignCellExecutionRoleSchema = z.enum([
403
- "candidate_run",
404
- "private_verify",
405
- "promotion_gate_only",
406
- ]);
407
- export const campaignPlanCellSchema = z
408
- .object({
409
- cellId: z.string().min(1),
410
- candidateId: candidateIdSchema,
411
- bundleHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
412
- taskRef: z.string().min(1),
413
- seed: z.number().int().nonnegative(),
414
- split: evalSplitSchema,
415
- executionRole: campaignCellExecutionRoleSchema,
416
- /** Controller-only flag; never serialized into candidate DAG prompts. */
417
- privateVerifierAttached: z.boolean(),
418
- })
419
- .strict();
420
- export const campaignPlanSchema = z
421
- .object({
422
- schemaVersion: z.literal(1),
423
- campaignId: campaignIdSchema,
424
- planHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
425
- createdAt: z.string().min(1),
426
- cells: z.array(campaignPlanCellSchema).min(1),
427
- })
428
- .strict();
429
- // --- Campaign Evidence + Promotion Policy (M5) ---
430
- export const campaignEvidenceCellSchema = z
431
- .object({
432
- cellId: z.string().min(1).optional(),
433
- candidateId: candidateIdSchema,
434
- taskRef: z.string().min(1),
435
- seed: z.number().int().nonnegative(),
436
- split: evalSplitSchema,
437
- verifyPassed: z.boolean(),
438
- runId: z.string().min(1).optional(),
439
- score: z.number().optional(),
440
- })
441
- .strict();
442
- export const campaignEvidenceDiffSchema = z
443
- .object({
444
- path: z.string().min(1),
445
- unifiedDiff: z.string(),
446
- })
447
- .strict();
448
- export const campaignEvidenceSchema = z
449
- .object({
450
- schemaVersion: z.literal(1),
451
- campaignId: campaignIdSchema,
452
- challengerCandidateId: candidateIdSchema,
453
- cells: z.array(campaignEvidenceCellSchema).min(1),
454
- diffs: z.array(campaignEvidenceDiffSchema).default([]),
455
- verifyCommands: z
456
- .object({
457
- incumbent: z.array(z.string().min(1)).default([]),
458
- challenger: z.array(z.string().min(1)).default([]),
459
- })
460
- .strict()
461
- .default({ incumbent: [], challenger: [] }),
462
- budgetStatus: z
463
- .object({
464
- incumbent: z.enum(["ok", "breached", "missing"]),
465
- challenger: z.enum(["ok", "breached", "missing"]),
466
- })
467
- .strict()
468
- .default({ incumbent: "missing", challenger: "missing" }),
469
- })
470
- .strict();
471
- // --- Learned Guidance Experiment (M6) ---
472
- export const experimentIdSchema = z
473
- .string()
474
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "experimentId must be one safe path segment");
475
- export const experimentPatternEvidenceSchema = z
476
- .object({
477
- key: z.string().min(1),
478
- failureClass: z.string().min(1),
479
- fixScopeShape: z.string().min(1),
480
- invariant: z.string().min(1),
481
- count: z.number().int().positive(),
482
- sourceRunIds: z.array(z.string().min(1)).default([]),
483
- whenToApply: z.string().min(1),
484
- whenNotToApply: z.string().min(1),
485
- })
486
- .strict();
487
- export const experimentDispositionSchema = z
488
- .object({
489
- status: z.enum(["accepted", "rejected"]),
490
- at: z.string().min(1),
491
- reason: z.string().min(1),
492
- campaignId: campaignIdSchema.optional(),
493
- scorecardPlanHash: z.string().min(1).optional(),
494
- heldOutNonRegression: z
495
- .enum(["pass", "fail", "insufficient", "review"])
496
- .optional(),
497
- })
498
- .strict();
499
- export const experimentRecordSchema = z
500
- .object({
501
- schemaVersion: z.literal(1),
502
- experimentId: experimentIdSchema,
503
- candidateId: candidateIdSchema,
504
- source: z.literal("knowledge-curate"),
505
- createdAt: z.string().min(1),
506
- proposalPath: z.string().min(1),
507
- proposalSha256: z.string().regex(/^sha256:[a-f0-9]{64}$/),
508
- patterns: z.array(experimentPatternEvidenceSchema).default([]),
509
- status: z.enum(["experimenting", "accepted", "rejected"]),
510
- disposition: experimentDispositionSchema.optional(),
511
- })
512
- .strict();
513
- // --- Outer-loop Proposer + Candidate Matrix (M7) ---
514
- export const proposerRunIdSchema = z
515
- .string()
516
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "proposerRunId must be one safe path segment");
517
- export const proposerProposalSchema = z
518
- .object({
519
- candidateId: candidateIdSchema,
520
- experimentId: experimentIdSchema,
521
- proposalPath: z.string().min(1),
522
- bundleHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
523
- status: z.literal("proposed_experimenting"),
524
- })
525
- .strict();
526
- export const proposerRunSchema = z
527
- .object({
528
- schemaVersion: z.literal(1),
529
- proposerRunId: proposerRunIdSchema,
530
- source: z.literal("knowledge-curate"),
531
- createdAt: z.string().min(1),
532
- maxCandidates: z.number().int().positive(),
533
- proposals: z.array(proposerProposalSchema),
534
- skippedReasons: z.array(z.string().min(1)).default([]),
535
- /** Always false: proposer must never promote aliases. */
536
- autoPromote: z.literal(false),
537
- })
538
- .strict();
539
- export const matrixModeSchema = z.enum([
540
- "dry-run",
541
- "stub",
542
- "pi-plan",
543
- "pi",
544
- ]);
545
- export const matrixCellResultSchema = z
546
- .object({
547
- cellId: z.string().min(1),
548
- candidateId: candidateIdSchema,
549
- taskRef: z.string().min(1),
550
- seed: z.number().int().nonnegative(),
551
- split: evalSplitSchema,
552
- executionRole: z.enum([
553
- "candidate_run",
554
- "private_verify",
555
- "promotion_gate_only",
556
- ]),
557
- mode: matrixModeSchema,
558
- verifyPassed: z.boolean().optional(),
559
- runId: z.string().min(1).optional(),
560
- jobPath: z.string().min(1).optional(),
561
- detail: z.string().optional(),
562
- skipped: z.boolean().default(false),
563
- })
564
- .strict();
565
- export const matrixRunSchema = z
566
- .object({
567
- schemaVersion: z.literal(1),
568
- campaignId: campaignIdSchema,
569
- planHash: z.string().min(1),
570
- mode: matrixModeSchema,
571
- createdAt: z.string().min(1),
572
- cells: z.array(matrixCellResultSchema),
573
- privateCheckCount: z.number().int().nonnegative(),
574
- privateCheckFailed: z.number().int().nonnegative(),
575
- evidencePath: z.string().min(1).optional(),
576
- /** Always false: matrix must never promote aliases. */
577
- autoPromote: z.literal(false),
578
- })
579
- .strict();
580
- export const matrixFixtureSchema = z
581
- .object({
582
- schemaVersion: z.literal(1),
583
- defaultVerifyPassed: z.boolean().default(false),
584
- results: z
585
- .array(z
586
- .object({
587
- cellId: z.string().min(1).optional(),
588
- candidateId: candidateIdSchema.optional(),
589
- taskRef: z.string().min(1).optional(),
590
- seed: z.number().int().nonnegative().optional(),
591
- split: evalSplitSchema.optional(),
592
- verifyPassed: z.boolean(),
593
- runId: z.string().min(1).optional(),
594
- })
595
- .strict())
596
- .default([]),
597
- })
598
- .strict();
599
- // --- Ignition research gate (M8) ---
600
- export const ignitionIdSchema = z
601
- .string()
602
- .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "ignitionId must be one safe path segment");
603
- export const ignitionGenerationSchema = z
604
- .object({
605
- generation: z.number().int().nonnegative(),
606
- parentCandidateId: candidateIdSchema.nullable(),
607
- proposerRunId: proposerRunIdSchema,
608
- proposedCandidateIds: z.array(candidateIdSchema).default([]),
609
- proposalCount: z.number().int().nonnegative(),
610
- campaignId: campaignIdSchema.optional(),
611
- promotionEligible: z.boolean().optional(),
612
- heldOutNonRegression: z
613
- .enum(["pass", "fail", "insufficient", "review"])
614
- .optional(),
615
- privateImprovement: z
616
- .enum(["pass", "fail", "insufficient", "review"])
617
- .optional(),
618
- recordedAt: z.string().min(1),
619
- })
620
- .strict();
621
- export const ignitionVerdictSchema = z.enum([
622
- "insufficient_evidence",
623
- "trend_positive",
624
- "trend_flat",
625
- "trend_negative",
626
- "inconclusive",
627
- ]);
628
- export const ignitionReportSchema = z
629
- .object({
630
- schemaVersion: z.literal(1),
631
- ignitionId: ignitionIdSchema,
632
- createdAt: z.string().min(1),
633
- updatedAt: z.string().min(1),
634
- generations: z.array(ignitionGenerationSchema).default([]),
635
- metrics: z
636
- .object({
637
- generationCount: z.number().int().nonnegative(),
638
- meanProposalsPerGeneration: z.number().nonnegative(),
639
- proposalYieldDelta: z.number().nullable(),
640
- scorecardObservedRate: z.number().nullable(),
641
- minGenerationsForSignal: z.number().int().positive(),
642
- sampleSufficient: z.boolean(),
643
- })
644
- .strict(),
645
- verdict: ignitionVerdictSchema,
646
- reasons: z.array(z.string().min(1)).default([]),
647
- /** Research gate only — never authorizes product RSI Level 1 claims. */
648
- rsiLevel1ClaimAllowed: z.literal(false),
649
- /** Always false — ignition never promotes. */
650
- autoPromote: z.literal(false),
651
- })
652
- .strict();
@@ -77,23 +77,7 @@ const INIT_SUBCOMMANDS = [
77
77
  "update",
78
78
  ];
79
79
  const EXAMPLES_SUBCOMMANDS = ["list", "show", "copy"];
80
- const EVAL_SUBCOMMANDS = [
81
- "replay",
82
- "report",
83
- "candidate",
84
- "alias",
85
- "promote",
86
- "rollback",
87
- "corpus",
88
- "context-policy",
89
- "budget",
90
- "private-verifier",
91
- "campaign",
92
- "experiment",
93
- "propose",
94
- "outer-loop",
95
- "ignition",
96
- ];
80
+ const EVAL_SUBCOMMANDS = ["replay", "report", "candidate"];
97
81
  const CLOSEOUT_SUBCOMMANDS = ["task"];
98
82
  const PLAN_SUBCOMMANDS = ["list", "create", "complete", "check"];
99
83
  const SPINE_SUBCOMMANDS = ["audit"];
@@ -216,8 +200,8 @@ export const COMMAND_DEFINITIONS = [
216
200
  name: "eval",
217
201
  adapter: "required",
218
202
  tier: "operator",
219
- intent: "Replay completed DAG evidence, manage Candidate Registry and corpus contracts, and human-gate incumbent alias promote/rollback without live campaigns.",
220
- usage: "eval <…|propose|outer-loop|ignition> ...; propose from-curate; outer-loop run; campaign matrix; ignition <record|evaluate|show|list>; promote remains human-gated (no auto-promote; ignition never claims RSI Level 1)",
203
+ intent: "Replay completed DAG evidence and manage immutable Candidate Registry lifecycle without live model execution or promotion.",
204
+ usage: "eval <replay|report|candidate> ...; candidate <register|show|list|transition> [--json|--markdown]",
221
205
  subcommands: [...EVAL_SUBCOMMANDS],
222
206
  handler: async ({ repoRoot, subcommand, rest }) => {
223
207
  await runEval(repoRoot, [subcommand, ...rest].filter((arg) => Boolean(arg)));