@popoverai/dotrequirements 0.24.2 → 0.24.3
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.
- package/README.md +0 -1
- package/dist/codebase-to-spec/cache.d.ts +6 -0
- package/dist/codebase-to-spec/cache.js +1 -0
- package/dist/codebase-to-spec/dispatch.d.ts +69 -0
- package/dist/codebase-to-spec/dispatch.js +484 -0
- package/dist/codebase-to-spec/schemas.d.ts +375 -0
- package/dist/codebase-to-spec/schemas.js +133 -0
- package/dist/codebase-to-spec/skill-install.d.ts +36 -12
- package/dist/codebase-to-spec/skill-install.js +127 -26
- package/dist/commands/codebase-to-spec/compose-orchestrator.d.ts +14 -0
- package/dist/commands/codebase-to-spec/compose-orchestrator.js +54 -0
- package/dist/commands/codebase-to-spec/dispatch-context.d.ts +12 -0
- package/dist/commands/codebase-to-spec/dispatch-context.js +22 -0
- package/dist/commands/codebase-to-spec/dispatch-editor.d.ts +16 -0
- package/dist/commands/codebase-to-spec/dispatch-editor.js +71 -0
- package/dist/commands/codebase-to-spec/dispatch-planner.d.ts +19 -0
- package/dist/commands/codebase-to-spec/dispatch-planner.js +90 -0
- package/dist/commands/codebase-to-spec/dispatch-spec.d.ts +16 -0
- package/dist/commands/codebase-to-spec/dispatch-spec.js +59 -0
- package/dist/commands/codebase-to-spec/index.js +56 -1
- package/dist/commands/codebase-to-spec/present-orchestrator.d.ts +20 -0
- package/dist/commands/codebase-to-spec/present-orchestrator.js +81 -0
- package/dist/commands/codebase-to-spec/skill-install.js +12 -1
- package/dist/templates/agents/cts-worker.md +9 -0
- package/dist/templates/hooks/cts-worker-persona.sh +76 -0
- package/dist/templates/skills/codebase-to-spec/SKILL.md +159 -68
- package/package.json +1 -1
|
@@ -337,5 +337,380 @@ export declare const SPEC_REVIEW_JSON_SCHEMA: {
|
|
|
337
337
|
readonly required: readonly ["coverage_gaps", "framing_errors", "cross_area_issues", "internal_mechanics_drift", "revisions", "verdict"];
|
|
338
338
|
readonly additionalProperties: false;
|
|
339
339
|
};
|
|
340
|
+
export declare const ConversationalCustomerSchema: z.ZodObject<{
|
|
341
|
+
description: z.ZodString;
|
|
342
|
+
}, "strip", z.ZodTypeAny, {
|
|
343
|
+
description: string;
|
|
344
|
+
}, {
|
|
345
|
+
description: string;
|
|
346
|
+
}>;
|
|
347
|
+
export type ConversationalCustomer = z.infer<typeof ConversationalCustomerSchema>;
|
|
348
|
+
/**
|
|
349
|
+
* One entry in the review thread (project-level or per-area). Discriminated
|
|
350
|
+
* on `result`:
|
|
351
|
+
*
|
|
352
|
+
* - `approved`: no revisions required.
|
|
353
|
+
* - `needs-revision`: must include a non-empty `revisions` list — each
|
|
354
|
+
* entry is a clear, actionable instruction for the next planner pass.
|
|
355
|
+
*/
|
|
356
|
+
export declare const ConversationalReviewEntrySchema: z.ZodDiscriminatedUnion<"result", [z.ZodObject<{
|
|
357
|
+
result: z.ZodLiteral<"approved">;
|
|
358
|
+
}, "strip", z.ZodTypeAny, {
|
|
359
|
+
result: "approved";
|
|
360
|
+
}, {
|
|
361
|
+
result: "approved";
|
|
362
|
+
}>, z.ZodObject<{
|
|
363
|
+
result: z.ZodLiteral<"needs-revision">;
|
|
364
|
+
revisions: z.ZodArray<z.ZodString, "many">;
|
|
365
|
+
}, "strip", z.ZodTypeAny, {
|
|
366
|
+
revisions: string[];
|
|
367
|
+
result: "needs-revision";
|
|
368
|
+
}, {
|
|
369
|
+
revisions: string[];
|
|
370
|
+
result: "needs-revision";
|
|
371
|
+
}>]>;
|
|
372
|
+
export type ConversationalReviewEntry = z.infer<typeof ConversationalReviewEntrySchema>;
|
|
373
|
+
/**
|
|
374
|
+
* Review state. Used both at the project level (outline.review) and per
|
|
375
|
+
* area (area.review). `result` mirrors the latest thread entry's result
|
|
376
|
+
* so callers can query state without walking the thread.
|
|
377
|
+
*/
|
|
378
|
+
export declare const ConversationalReviewSchema: z.ZodObject<{
|
|
379
|
+
result: z.ZodEnum<["approved", "needs-revision"]>;
|
|
380
|
+
thread: z.ZodArray<z.ZodDiscriminatedUnion<"result", [z.ZodObject<{
|
|
381
|
+
result: z.ZodLiteral<"approved">;
|
|
382
|
+
}, "strip", z.ZodTypeAny, {
|
|
383
|
+
result: "approved";
|
|
384
|
+
}, {
|
|
385
|
+
result: "approved";
|
|
386
|
+
}>, z.ZodObject<{
|
|
387
|
+
result: z.ZodLiteral<"needs-revision">;
|
|
388
|
+
revisions: z.ZodArray<z.ZodString, "many">;
|
|
389
|
+
}, "strip", z.ZodTypeAny, {
|
|
390
|
+
revisions: string[];
|
|
391
|
+
result: "needs-revision";
|
|
392
|
+
}, {
|
|
393
|
+
revisions: string[];
|
|
394
|
+
result: "needs-revision";
|
|
395
|
+
}>]>, "many">;
|
|
396
|
+
}, "strip", z.ZodTypeAny, {
|
|
397
|
+
result: "approved" | "needs-revision";
|
|
398
|
+
thread: ({
|
|
399
|
+
result: "approved";
|
|
400
|
+
} | {
|
|
401
|
+
revisions: string[];
|
|
402
|
+
result: "needs-revision";
|
|
403
|
+
})[];
|
|
404
|
+
}, {
|
|
405
|
+
result: "approved" | "needs-revision";
|
|
406
|
+
thread: ({
|
|
407
|
+
result: "approved";
|
|
408
|
+
} | {
|
|
409
|
+
revisions: string[];
|
|
410
|
+
result: "needs-revision";
|
|
411
|
+
})[];
|
|
412
|
+
}>;
|
|
413
|
+
export type ConversationalReview = z.infer<typeof ConversationalReviewSchema>;
|
|
414
|
+
export declare const ConversationalAreaSchema: z.ZodObject<{
|
|
415
|
+
name: z.ZodString;
|
|
416
|
+
prefix: z.ZodString;
|
|
417
|
+
description: z.ZodString;
|
|
418
|
+
source_files: z.ZodArray<z.ZodString, "many">;
|
|
419
|
+
customers: z.ZodArray<z.ZodObject<{
|
|
420
|
+
description: z.ZodString;
|
|
421
|
+
}, "strip", z.ZodTypeAny, {
|
|
422
|
+
description: string;
|
|
423
|
+
}, {
|
|
424
|
+
description: string;
|
|
425
|
+
}>, "many">;
|
|
426
|
+
/**
|
|
427
|
+
* Per-area review state — same shape as the project-level review.
|
|
428
|
+
* Optional: planner output doesn't include it; CA adds it after reviewing
|
|
429
|
+
* a partial. Tracks the per-area iteration loop (specify → review →
|
|
430
|
+
* editor → re-review → approved) the same way `outline.review` tracks
|
|
431
|
+
* the outline iteration loop.
|
|
432
|
+
*/
|
|
433
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
434
|
+
result: z.ZodEnum<["approved", "needs-revision"]>;
|
|
435
|
+
thread: z.ZodArray<z.ZodDiscriminatedUnion<"result", [z.ZodObject<{
|
|
436
|
+
result: z.ZodLiteral<"approved">;
|
|
437
|
+
}, "strip", z.ZodTypeAny, {
|
|
438
|
+
result: "approved";
|
|
439
|
+
}, {
|
|
440
|
+
result: "approved";
|
|
441
|
+
}>, z.ZodObject<{
|
|
442
|
+
result: z.ZodLiteral<"needs-revision">;
|
|
443
|
+
revisions: z.ZodArray<z.ZodString, "many">;
|
|
444
|
+
}, "strip", z.ZodTypeAny, {
|
|
445
|
+
revisions: string[];
|
|
446
|
+
result: "needs-revision";
|
|
447
|
+
}, {
|
|
448
|
+
revisions: string[];
|
|
449
|
+
result: "needs-revision";
|
|
450
|
+
}>]>, "many">;
|
|
451
|
+
}, "strip", z.ZodTypeAny, {
|
|
452
|
+
result: "approved" | "needs-revision";
|
|
453
|
+
thread: ({
|
|
454
|
+
result: "approved";
|
|
455
|
+
} | {
|
|
456
|
+
revisions: string[];
|
|
457
|
+
result: "needs-revision";
|
|
458
|
+
})[];
|
|
459
|
+
}, {
|
|
460
|
+
result: "approved" | "needs-revision";
|
|
461
|
+
thread: ({
|
|
462
|
+
result: "approved";
|
|
463
|
+
} | {
|
|
464
|
+
revisions: string[];
|
|
465
|
+
result: "needs-revision";
|
|
466
|
+
})[];
|
|
467
|
+
}>>;
|
|
468
|
+
}, "strip", z.ZodTypeAny, {
|
|
469
|
+
prefix: string;
|
|
470
|
+
name: string;
|
|
471
|
+
description: string;
|
|
472
|
+
customers: {
|
|
473
|
+
description: string;
|
|
474
|
+
}[];
|
|
475
|
+
source_files: string[];
|
|
476
|
+
review?: {
|
|
477
|
+
result: "approved" | "needs-revision";
|
|
478
|
+
thread: ({
|
|
479
|
+
result: "approved";
|
|
480
|
+
} | {
|
|
481
|
+
revisions: string[];
|
|
482
|
+
result: "needs-revision";
|
|
483
|
+
})[];
|
|
484
|
+
} | undefined;
|
|
485
|
+
}, {
|
|
486
|
+
prefix: string;
|
|
487
|
+
name: string;
|
|
488
|
+
description: string;
|
|
489
|
+
customers: {
|
|
490
|
+
description: string;
|
|
491
|
+
}[];
|
|
492
|
+
source_files: string[];
|
|
493
|
+
review?: {
|
|
494
|
+
result: "approved" | "needs-revision";
|
|
495
|
+
thread: ({
|
|
496
|
+
result: "approved";
|
|
497
|
+
} | {
|
|
498
|
+
revisions: string[];
|
|
499
|
+
result: "needs-revision";
|
|
500
|
+
})[];
|
|
501
|
+
} | undefined;
|
|
502
|
+
}>;
|
|
503
|
+
export type ConversationalArea = z.infer<typeof ConversationalAreaSchema>;
|
|
504
|
+
export declare const ConversationalOutlineSchema: z.ZodObject<{
|
|
505
|
+
title: z.ZodString;
|
|
506
|
+
defaultPrefix: z.ZodString;
|
|
507
|
+
summary: z.ZodString;
|
|
508
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
509
|
+
result: z.ZodEnum<["approved", "needs-revision"]>;
|
|
510
|
+
thread: z.ZodArray<z.ZodDiscriminatedUnion<"result", [z.ZodObject<{
|
|
511
|
+
result: z.ZodLiteral<"approved">;
|
|
512
|
+
}, "strip", z.ZodTypeAny, {
|
|
513
|
+
result: "approved";
|
|
514
|
+
}, {
|
|
515
|
+
result: "approved";
|
|
516
|
+
}>, z.ZodObject<{
|
|
517
|
+
result: z.ZodLiteral<"needs-revision">;
|
|
518
|
+
revisions: z.ZodArray<z.ZodString, "many">;
|
|
519
|
+
}, "strip", z.ZodTypeAny, {
|
|
520
|
+
revisions: string[];
|
|
521
|
+
result: "needs-revision";
|
|
522
|
+
}, {
|
|
523
|
+
revisions: string[];
|
|
524
|
+
result: "needs-revision";
|
|
525
|
+
}>]>, "many">;
|
|
526
|
+
}, "strip", z.ZodTypeAny, {
|
|
527
|
+
result: "approved" | "needs-revision";
|
|
528
|
+
thread: ({
|
|
529
|
+
result: "approved";
|
|
530
|
+
} | {
|
|
531
|
+
revisions: string[];
|
|
532
|
+
result: "needs-revision";
|
|
533
|
+
})[];
|
|
534
|
+
}, {
|
|
535
|
+
result: "approved" | "needs-revision";
|
|
536
|
+
thread: ({
|
|
537
|
+
result: "approved";
|
|
538
|
+
} | {
|
|
539
|
+
revisions: string[];
|
|
540
|
+
result: "needs-revision";
|
|
541
|
+
})[];
|
|
542
|
+
}>>;
|
|
543
|
+
areas: z.ZodArray<z.ZodObject<{
|
|
544
|
+
name: z.ZodString;
|
|
545
|
+
prefix: z.ZodString;
|
|
546
|
+
description: z.ZodString;
|
|
547
|
+
source_files: z.ZodArray<z.ZodString, "many">;
|
|
548
|
+
customers: z.ZodArray<z.ZodObject<{
|
|
549
|
+
description: z.ZodString;
|
|
550
|
+
}, "strip", z.ZodTypeAny, {
|
|
551
|
+
description: string;
|
|
552
|
+
}, {
|
|
553
|
+
description: string;
|
|
554
|
+
}>, "many">;
|
|
555
|
+
/**
|
|
556
|
+
* Per-area review state — same shape as the project-level review.
|
|
557
|
+
* Optional: planner output doesn't include it; CA adds it after reviewing
|
|
558
|
+
* a partial. Tracks the per-area iteration loop (specify → review →
|
|
559
|
+
* editor → re-review → approved) the same way `outline.review` tracks
|
|
560
|
+
* the outline iteration loop.
|
|
561
|
+
*/
|
|
562
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
563
|
+
result: z.ZodEnum<["approved", "needs-revision"]>;
|
|
564
|
+
thread: z.ZodArray<z.ZodDiscriminatedUnion<"result", [z.ZodObject<{
|
|
565
|
+
result: z.ZodLiteral<"approved">;
|
|
566
|
+
}, "strip", z.ZodTypeAny, {
|
|
567
|
+
result: "approved";
|
|
568
|
+
}, {
|
|
569
|
+
result: "approved";
|
|
570
|
+
}>, z.ZodObject<{
|
|
571
|
+
result: z.ZodLiteral<"needs-revision">;
|
|
572
|
+
revisions: z.ZodArray<z.ZodString, "many">;
|
|
573
|
+
}, "strip", z.ZodTypeAny, {
|
|
574
|
+
revisions: string[];
|
|
575
|
+
result: "needs-revision";
|
|
576
|
+
}, {
|
|
577
|
+
revisions: string[];
|
|
578
|
+
result: "needs-revision";
|
|
579
|
+
}>]>, "many">;
|
|
580
|
+
}, "strip", z.ZodTypeAny, {
|
|
581
|
+
result: "approved" | "needs-revision";
|
|
582
|
+
thread: ({
|
|
583
|
+
result: "approved";
|
|
584
|
+
} | {
|
|
585
|
+
revisions: string[];
|
|
586
|
+
result: "needs-revision";
|
|
587
|
+
})[];
|
|
588
|
+
}, {
|
|
589
|
+
result: "approved" | "needs-revision";
|
|
590
|
+
thread: ({
|
|
591
|
+
result: "approved";
|
|
592
|
+
} | {
|
|
593
|
+
revisions: string[];
|
|
594
|
+
result: "needs-revision";
|
|
595
|
+
})[];
|
|
596
|
+
}>>;
|
|
597
|
+
}, "strip", z.ZodTypeAny, {
|
|
598
|
+
prefix: string;
|
|
599
|
+
name: string;
|
|
600
|
+
description: string;
|
|
601
|
+
customers: {
|
|
602
|
+
description: string;
|
|
603
|
+
}[];
|
|
604
|
+
source_files: string[];
|
|
605
|
+
review?: {
|
|
606
|
+
result: "approved" | "needs-revision";
|
|
607
|
+
thread: ({
|
|
608
|
+
result: "approved";
|
|
609
|
+
} | {
|
|
610
|
+
revisions: string[];
|
|
611
|
+
result: "needs-revision";
|
|
612
|
+
})[];
|
|
613
|
+
} | undefined;
|
|
614
|
+
}, {
|
|
615
|
+
prefix: string;
|
|
616
|
+
name: string;
|
|
617
|
+
description: string;
|
|
618
|
+
customers: {
|
|
619
|
+
description: string;
|
|
620
|
+
}[];
|
|
621
|
+
source_files: string[];
|
|
622
|
+
review?: {
|
|
623
|
+
result: "approved" | "needs-revision";
|
|
624
|
+
thread: ({
|
|
625
|
+
result: "approved";
|
|
626
|
+
} | {
|
|
627
|
+
revisions: string[];
|
|
628
|
+
result: "needs-revision";
|
|
629
|
+
})[];
|
|
630
|
+
} | undefined;
|
|
631
|
+
}>, "many">;
|
|
632
|
+
}, "strip", z.ZodTypeAny, {
|
|
633
|
+
title: string;
|
|
634
|
+
defaultPrefix: string;
|
|
635
|
+
summary: string;
|
|
636
|
+
areas: {
|
|
637
|
+
prefix: string;
|
|
638
|
+
name: string;
|
|
639
|
+
description: string;
|
|
640
|
+
customers: {
|
|
641
|
+
description: string;
|
|
642
|
+
}[];
|
|
643
|
+
source_files: string[];
|
|
644
|
+
review?: {
|
|
645
|
+
result: "approved" | "needs-revision";
|
|
646
|
+
thread: ({
|
|
647
|
+
result: "approved";
|
|
648
|
+
} | {
|
|
649
|
+
revisions: string[];
|
|
650
|
+
result: "needs-revision";
|
|
651
|
+
})[];
|
|
652
|
+
} | undefined;
|
|
653
|
+
}[];
|
|
654
|
+
review?: {
|
|
655
|
+
result: "approved" | "needs-revision";
|
|
656
|
+
thread: ({
|
|
657
|
+
result: "approved";
|
|
658
|
+
} | {
|
|
659
|
+
revisions: string[];
|
|
660
|
+
result: "needs-revision";
|
|
661
|
+
})[];
|
|
662
|
+
} | undefined;
|
|
663
|
+
}, {
|
|
664
|
+
title: string;
|
|
665
|
+
defaultPrefix: string;
|
|
666
|
+
summary: string;
|
|
667
|
+
areas: {
|
|
668
|
+
prefix: string;
|
|
669
|
+
name: string;
|
|
670
|
+
description: string;
|
|
671
|
+
customers: {
|
|
672
|
+
description: string;
|
|
673
|
+
}[];
|
|
674
|
+
source_files: string[];
|
|
675
|
+
review?: {
|
|
676
|
+
result: "approved" | "needs-revision";
|
|
677
|
+
thread: ({
|
|
678
|
+
result: "approved";
|
|
679
|
+
} | {
|
|
680
|
+
revisions: string[];
|
|
681
|
+
result: "needs-revision";
|
|
682
|
+
})[];
|
|
683
|
+
} | undefined;
|
|
684
|
+
}[];
|
|
685
|
+
review?: {
|
|
686
|
+
result: "approved" | "needs-revision";
|
|
687
|
+
thread: ({
|
|
688
|
+
result: "approved";
|
|
689
|
+
} | {
|
|
690
|
+
revisions: string[];
|
|
691
|
+
result: "needs-revision";
|
|
692
|
+
})[];
|
|
693
|
+
} | undefined;
|
|
694
|
+
}>;
|
|
695
|
+
export type ConversationalOutline = z.infer<typeof ConversationalOutlineSchema>;
|
|
696
|
+
/**
|
|
697
|
+
* Parse YAML text against the conversational outline schema. Throws with
|
|
698
|
+
* a descriptive message on parse or validation failure.
|
|
699
|
+
*/
|
|
700
|
+
export declare function parseConversationalOutline(text: string): ConversationalOutline;
|
|
701
|
+
/**
|
|
702
|
+
* Adapt a conversational orchestrator outline to the legacy Outline shape
|
|
703
|
+
* for use with stages that still take the legacy schema (compose, present).
|
|
704
|
+
*
|
|
705
|
+
* Discards orchestrator-only fields (review); maps `source_files` → `files`;
|
|
706
|
+
* bridges the customer-shape difference by synthesizing a `name` from each
|
|
707
|
+
* conversational customer's description.
|
|
708
|
+
*/
|
|
709
|
+
export declare function conversationalOutlineToLegacy(outline: ConversationalOutline): Outline;
|
|
710
|
+
/**
|
|
711
|
+
* Serialize a conversational outline back to YAML text. Uses literal-block
|
|
712
|
+
* multi-line strings (`|`) where possible for readability.
|
|
713
|
+
*/
|
|
714
|
+
export declare function stringifyConversationalOutline(outline: ConversationalOutline): string;
|
|
340
715
|
export declare function parseSpecReview(text: string): SpecReview;
|
|
341
716
|
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -189,6 +189,139 @@ export const SPEC_REVIEW_JSON_SCHEMA = {
|
|
|
189
189
|
],
|
|
190
190
|
additionalProperties: false,
|
|
191
191
|
};
|
|
192
|
+
// ---------- Conversational orchestrator outline (Phase 2b refactor) ----------
|
|
193
|
+
//
|
|
194
|
+
// The conversational orchestrator uses a single evolving `outline.yaml` as
|
|
195
|
+
// the pipeline's substrate. The outline carries both the behavioral spec
|
|
196
|
+
// content (areas, customers, source_files) AND its own lifecycle state
|
|
197
|
+
// (review.result + review.thread). This is distinct from the legacy
|
|
198
|
+
// `OutlineSchema` above, which the `cts run` pipeline still uses.
|
|
199
|
+
//
|
|
200
|
+
// Field naming uses "result" rather than "verdict" deliberately: review is
|
|
201
|
+
// a collaborative interaction with the worker, not a juridical ruling.
|
|
202
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
203
|
+
export const ConversationalCustomerSchema = z.object({
|
|
204
|
+
description: z.string().min(1),
|
|
205
|
+
});
|
|
206
|
+
/**
|
|
207
|
+
* One entry in the review thread (project-level or per-area). Discriminated
|
|
208
|
+
* on `result`:
|
|
209
|
+
*
|
|
210
|
+
* - `approved`: no revisions required.
|
|
211
|
+
* - `needs-revision`: must include a non-empty `revisions` list — each
|
|
212
|
+
* entry is a clear, actionable instruction for the next planner pass.
|
|
213
|
+
*/
|
|
214
|
+
export const ConversationalReviewEntrySchema = z.discriminatedUnion("result", [
|
|
215
|
+
z.object({
|
|
216
|
+
result: z.literal("approved"),
|
|
217
|
+
}),
|
|
218
|
+
z.object({
|
|
219
|
+
result: z.literal("needs-revision"),
|
|
220
|
+
revisions: z.array(z.string()).min(1),
|
|
221
|
+
}),
|
|
222
|
+
]);
|
|
223
|
+
/**
|
|
224
|
+
* Review state. Used both at the project level (outline.review) and per
|
|
225
|
+
* area (area.review). `result` mirrors the latest thread entry's result
|
|
226
|
+
* so callers can query state without walking the thread.
|
|
227
|
+
*/
|
|
228
|
+
export const ConversationalReviewSchema = z.object({
|
|
229
|
+
result: z.enum(["approved", "needs-revision"]),
|
|
230
|
+
thread: z.array(ConversationalReviewEntrySchema).min(1),
|
|
231
|
+
});
|
|
232
|
+
export const ConversationalAreaSchema = z.object({
|
|
233
|
+
name: z.string().min(1),
|
|
234
|
+
prefix: z
|
|
235
|
+
.string()
|
|
236
|
+
.regex(/^[A-Z][A-Z0-9_]*$/, "prefix must be uppercase alphanumeric/underscore"),
|
|
237
|
+
description: z.string().min(1),
|
|
238
|
+
source_files: z.array(z.string()).min(0),
|
|
239
|
+
customers: z.array(ConversationalCustomerSchema).min(1),
|
|
240
|
+
/**
|
|
241
|
+
* Per-area review state — same shape as the project-level review.
|
|
242
|
+
* Optional: planner output doesn't include it; CA adds it after reviewing
|
|
243
|
+
* a partial. Tracks the per-area iteration loop (specify → review →
|
|
244
|
+
* editor → re-review → approved) the same way `outline.review` tracks
|
|
245
|
+
* the outline iteration loop.
|
|
246
|
+
*/
|
|
247
|
+
review: ConversationalReviewSchema.optional(),
|
|
248
|
+
});
|
|
249
|
+
export const ConversationalOutlineSchema = z.object({
|
|
250
|
+
title: z.string().min(1),
|
|
251
|
+
defaultPrefix: z
|
|
252
|
+
.string()
|
|
253
|
+
.regex(/^[A-Z][A-Z0-9_]*$/, "defaultPrefix must be uppercase alphanumeric/underscore"),
|
|
254
|
+
summary: z.string().min(1),
|
|
255
|
+
review: ConversationalReviewSchema.optional(),
|
|
256
|
+
areas: z.array(ConversationalAreaSchema).min(1),
|
|
257
|
+
});
|
|
258
|
+
/**
|
|
259
|
+
* Parse YAML text against the conversational outline schema. Throws with
|
|
260
|
+
* a descriptive message on parse or validation failure.
|
|
261
|
+
*/
|
|
262
|
+
export function parseConversationalOutline(text) {
|
|
263
|
+
let raw;
|
|
264
|
+
try {
|
|
265
|
+
raw = parseYaml(text);
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
throw new Error(`Outline YAML is invalid: ${err instanceof Error ? err.message : String(err)}`);
|
|
269
|
+
}
|
|
270
|
+
return ConversationalOutlineSchema.parse(raw);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Synthesize a short customer `name` from a conversational customer's
|
|
274
|
+
* `description`. The orchestrator's `ConversationalCustomerSchema` only
|
|
275
|
+
* carries description, but the legacy `CustomerSchema` requires both
|
|
276
|
+
* `name` and `description`. Adapter use only — downstream compose/present
|
|
277
|
+
* stages don't read `name`, so this is a schema-shape bridge, not a
|
|
278
|
+
* semantic field.
|
|
279
|
+
*
|
|
280
|
+
* Heuristic: descriptions like "Priya, a CTS pipeline operator" yield
|
|
281
|
+
* "Priya" via first comma-segment. Otherwise truncate to 40 chars.
|
|
282
|
+
*/
|
|
283
|
+
function synthesizeCustomerName(description) {
|
|
284
|
+
const firstSegment = description.split(",")[0]?.trim() ?? "";
|
|
285
|
+
if (firstSegment.length > 0 && firstSegment.length <= 40) {
|
|
286
|
+
return firstSegment;
|
|
287
|
+
}
|
|
288
|
+
return description.slice(0, 40).trim() || description;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Adapt a conversational orchestrator outline to the legacy Outline shape
|
|
292
|
+
* for use with stages that still take the legacy schema (compose, present).
|
|
293
|
+
*
|
|
294
|
+
* Discards orchestrator-only fields (review); maps `source_files` → `files`;
|
|
295
|
+
* bridges the customer-shape difference by synthesizing a `name` from each
|
|
296
|
+
* conversational customer's description.
|
|
297
|
+
*/
|
|
298
|
+
export function conversationalOutlineToLegacy(outline) {
|
|
299
|
+
return {
|
|
300
|
+
title: outline.title,
|
|
301
|
+
defaultPrefix: outline.defaultPrefix,
|
|
302
|
+
summary: outline.summary,
|
|
303
|
+
areas: outline.areas.map((a) => ({
|
|
304
|
+
name: a.name,
|
|
305
|
+
description: a.description,
|
|
306
|
+
prefix: a.prefix,
|
|
307
|
+
files: a.source_files,
|
|
308
|
+
customers: a.customers.map((c) => ({
|
|
309
|
+
name: synthesizeCustomerName(c.description),
|
|
310
|
+
description: c.description,
|
|
311
|
+
})),
|
|
312
|
+
})),
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Serialize a conversational outline back to YAML text. Uses literal-block
|
|
317
|
+
* multi-line strings (`|`) where possible for readability.
|
|
318
|
+
*/
|
|
319
|
+
export function stringifyConversationalOutline(outline) {
|
|
320
|
+
return stringifyYaml(outline, {
|
|
321
|
+
lineWidth: 0,
|
|
322
|
+
blockQuote: "literal",
|
|
323
|
+
});
|
|
324
|
+
}
|
|
192
325
|
export function parseSpecReview(text) {
|
|
193
326
|
const trimmed = text.trim();
|
|
194
327
|
let raw;
|
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skill installation logic for the codebase-to-spec skill.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Ships as a bundle: SKILL.md + cts-worker agent definition + persona-
|
|
5
|
+
* injection hook script + hook registration in `.claude/settings.local.json`.
|
|
6
|
+
* The skill body (the conversational orchestrator) DEPENDS on the companion
|
|
7
|
+
* files — installing just the skill without them would leave Task dispatches
|
|
8
|
+
* unable to resolve their persona. For `project` scope, all four pieces are
|
|
9
|
+
* installed in one shot. For `global` and `custom` scopes, only the skill
|
|
10
|
+
* body is installed; the companions are project-scoped by CC convention.
|
|
8
11
|
*
|
|
9
12
|
* Host portability (CTS-SKILL-5): the install logic supports any host that
|
|
10
13
|
* follows the Agent Skills format. The default target is Claude Code's
|
|
11
14
|
* convention; `--target-dir` lets users place the skill anywhere.
|
|
12
15
|
*
|
|
13
16
|
* Requirements covered:
|
|
14
|
-
* - CTS-SKILL-1
|
|
15
|
-
* -
|
|
16
|
-
* Agent Skills format support
|
|
17
|
+
* - CTS-SKILL-1, CTS-SKILL-5
|
|
18
|
+
* - CTSO-CLI-1 (bundles the agent + hook that PreToolUse-injects persona bodies)
|
|
17
19
|
*/
|
|
18
20
|
export type SkillInstallScope = "project" | "global" | "custom";
|
|
19
21
|
export interface SkillInstallOptions {
|
|
20
22
|
/**
|
|
21
23
|
* Where to install:
|
|
22
24
|
* - `project` (default): `<projectRoot>/.claude/skills/codebase-to-spec/`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* (plus companions under `<projectRoot>/.claude/agents/` and
|
|
26
|
+
* `<projectRoot>/.claude/hooks/`, and hook registration in
|
|
27
|
+
* `<projectRoot>/.claude/settings.local.json`)
|
|
28
|
+
* - `global`: `~/.claude/skills/codebase-to-spec/` (skill body only)
|
|
29
|
+
* - `custom`: requires `targetDir` (skill body only)
|
|
25
30
|
*/
|
|
26
31
|
scope?: SkillInstallScope;
|
|
27
32
|
/** Required when `scope === 'custom'`. The skill directory will be created here. */
|
|
28
33
|
targetDir?: string;
|
|
29
34
|
/** Project root (used when scope === 'project'). Defaults to cwd. */
|
|
30
35
|
projectRoot?: string;
|
|
31
|
-
/** Overwrite existing SKILL.md if present. Default false. */
|
|
36
|
+
/** Overwrite existing SKILL.md / agent / hook if present. Default false. */
|
|
32
37
|
overwrite?: boolean;
|
|
33
38
|
}
|
|
34
39
|
export interface SkillInstallResult {
|
|
@@ -38,6 +43,13 @@ export interface SkillInstallResult {
|
|
|
38
43
|
installed: boolean;
|
|
39
44
|
/** True if an existing file was replaced. */
|
|
40
45
|
overwrote: boolean;
|
|
46
|
+
/** Companion files installed alongside the skill (project scope only). */
|
|
47
|
+
companions?: {
|
|
48
|
+
agentPath: string;
|
|
49
|
+
hookScriptPath: string;
|
|
50
|
+
settingsPath: string;
|
|
51
|
+
hookRegistered: boolean;
|
|
52
|
+
};
|
|
41
53
|
}
|
|
42
54
|
/**
|
|
43
55
|
* Resolve the directory in which the skill should live, given the user's
|
|
@@ -50,8 +62,20 @@ export declare function resolveSkillDir(options: SkillInstallOptions): string;
|
|
|
50
62
|
*/
|
|
51
63
|
export declare function loadSkillTemplate(): string;
|
|
52
64
|
/**
|
|
53
|
-
*
|
|
54
|
-
|
|
65
|
+
* Load the bundled cts-worker agent definition template.
|
|
66
|
+
*/
|
|
67
|
+
export declare function loadAgentTemplate(): string;
|
|
68
|
+
/**
|
|
69
|
+
* Load the bundled persona-injection hook script template.
|
|
70
|
+
*/
|
|
71
|
+
export declare function loadHookTemplate(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Install (or refuse to overwrite) the codebase-to-spec skill bundle.
|
|
74
|
+
*
|
|
75
|
+
* For `project` scope: installs skill body, cts-worker agent, persona hook
|
|
76
|
+
* script, and registers the hook in settings.local.json.
|
|
77
|
+
*
|
|
78
|
+
* For `global` and `custom` scopes: installs only the skill body.
|
|
55
79
|
*/
|
|
56
80
|
export declare function installSkill(options?: SkillInstallOptions): SkillInstallResult;
|
|
57
81
|
//# sourceMappingURL=skill-install.d.ts.map
|