speckeeper 0.10.0 → 0.11.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.
- package/README.md +1 -0
- package/cli-contract.yaml +207 -209
- package/dist/cli.js +1316 -80
- package/dist/cli.js.map +1 -1
- package/dist/{config-api-CLVjdgIP.d.ts → config-api-coyCX1SB.d.ts} +21 -1
- package/dist/dsl/index.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +75 -3
- package/dist/index.js.map +1 -1
- package/docs/cli-reference.md +107 -154
- package/docs/design/cli-commands.md +217 -0
- package/docs/design/functional-requirements.md +101 -3
- package/docs/design/nonfunctional-requirements.md +3 -3
- package/docs/design/test-refs.md +26 -0
- package/docs/model-guide.md +102 -98
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { Command } from 'commander';
|
|
4
3
|
import { readFileSync, existsSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'fs';
|
|
5
|
-
import { dirname, join, resolve, isAbsolute } from 'path';
|
|
4
|
+
import { dirname, join, resolve, basename, isAbsolute } from 'path';
|
|
6
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { isOptionActive, derivePolicy } from 'cli-contracts/policy';
|
|
7
8
|
import chalk4 from 'chalk';
|
|
8
|
-
import { parse } from 'yaml';
|
|
9
|
+
import { stringify, parse } from 'yaml';
|
|
9
10
|
import 'crypto';
|
|
10
11
|
import { glob } from 'glob';
|
|
11
12
|
import nodeSqlParser from 'node-sql-parser';
|
|
@@ -535,6 +536,1108 @@ var init_dsl = __esm({
|
|
|
535
536
|
init_workflows();
|
|
536
537
|
}
|
|
537
538
|
});
|
|
539
|
+
var commandDefinitions = {
|
|
540
|
+
"init": {
|
|
541
|
+
"effects": {
|
|
542
|
+
"riskLevel": "medium",
|
|
543
|
+
"writes": [
|
|
544
|
+
{
|
|
545
|
+
"target": "speckeeper.config.ts, design/ directory",
|
|
546
|
+
"description": "generates config and starter template files",
|
|
547
|
+
"idempotent": false
|
|
548
|
+
}
|
|
549
|
+
]
|
|
550
|
+
},
|
|
551
|
+
"options": [
|
|
552
|
+
{
|
|
553
|
+
"name": "force",
|
|
554
|
+
"schema": {
|
|
555
|
+
"type": "boolean",
|
|
556
|
+
"default": false
|
|
557
|
+
},
|
|
558
|
+
"effects": {
|
|
559
|
+
"riskLevel": "high",
|
|
560
|
+
"writes": [
|
|
561
|
+
{
|
|
562
|
+
"target": "existing project files",
|
|
563
|
+
"description": "overwrites existing config and design files",
|
|
564
|
+
"overwrite": true,
|
|
565
|
+
"destructive": true
|
|
566
|
+
}
|
|
567
|
+
]
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"name": "format",
|
|
572
|
+
"schema": {
|
|
573
|
+
"type": "string",
|
|
574
|
+
"default": "ts",
|
|
575
|
+
"enum": [
|
|
576
|
+
"ts",
|
|
577
|
+
"yaml"
|
|
578
|
+
]
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
"env": {
|
|
583
|
+
"CURSOR_API_KEY": {
|
|
584
|
+
"sensitive": true
|
|
585
|
+
},
|
|
586
|
+
"GEMINI_API_KEY": {
|
|
587
|
+
"sensitive": true
|
|
588
|
+
},
|
|
589
|
+
"OPENAI_API_KEY": {
|
|
590
|
+
"sensitive": true
|
|
591
|
+
},
|
|
592
|
+
"ANTHROPIC_API_KEY": {
|
|
593
|
+
"sensitive": true
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
"build": {
|
|
598
|
+
"effects": {
|
|
599
|
+
"riskLevel": "low",
|
|
600
|
+
"writes": [
|
|
601
|
+
{
|
|
602
|
+
"target": "docs/ directory",
|
|
603
|
+
"description": "generated Markdown documentation files",
|
|
604
|
+
"overwrite": true,
|
|
605
|
+
"idempotent": true
|
|
606
|
+
}
|
|
607
|
+
]
|
|
608
|
+
},
|
|
609
|
+
"options": [
|
|
610
|
+
{
|
|
611
|
+
"name": "config",
|
|
612
|
+
"schema": {
|
|
613
|
+
"type": "string"
|
|
614
|
+
},
|
|
615
|
+
"file": {
|
|
616
|
+
"mode": "read",
|
|
617
|
+
"exists": true,
|
|
618
|
+
"encoding": "utf-8"
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
"name": "output",
|
|
623
|
+
"schema": {
|
|
624
|
+
"type": "string",
|
|
625
|
+
"default": "."
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
"name": "format",
|
|
630
|
+
"schema": {
|
|
631
|
+
"type": "string",
|
|
632
|
+
"default": "both",
|
|
633
|
+
"enum": [
|
|
634
|
+
"markdown",
|
|
635
|
+
"json",
|
|
636
|
+
"both"
|
|
637
|
+
]
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"name": "watch",
|
|
642
|
+
"schema": {
|
|
643
|
+
"type": "boolean",
|
|
644
|
+
"default": false
|
|
645
|
+
},
|
|
646
|
+
"effects": {
|
|
647
|
+
"executionMode": "watch"
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
"name": "verbose",
|
|
652
|
+
"schema": {
|
|
653
|
+
"type": "boolean",
|
|
654
|
+
"default": false
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
],
|
|
658
|
+
"env": {
|
|
659
|
+
"CURSOR_API_KEY": {
|
|
660
|
+
"sensitive": true
|
|
661
|
+
},
|
|
662
|
+
"GEMINI_API_KEY": {
|
|
663
|
+
"sensitive": true
|
|
664
|
+
},
|
|
665
|
+
"OPENAI_API_KEY": {
|
|
666
|
+
"sensitive": true
|
|
667
|
+
},
|
|
668
|
+
"ANTHROPIC_API_KEY": {
|
|
669
|
+
"sensitive": true
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
"lint": {
|
|
674
|
+
"options": [
|
|
675
|
+
{
|
|
676
|
+
"name": "config",
|
|
677
|
+
"schema": {
|
|
678
|
+
"type": "string"
|
|
679
|
+
},
|
|
680
|
+
"file": {
|
|
681
|
+
"mode": "read",
|
|
682
|
+
"exists": true,
|
|
683
|
+
"encoding": "utf-8"
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
"name": "phase",
|
|
688
|
+
"schema": {
|
|
689
|
+
"type": "string",
|
|
690
|
+
"enum": [
|
|
691
|
+
"REQ",
|
|
692
|
+
"HLD",
|
|
693
|
+
"LLD",
|
|
694
|
+
"OPS"
|
|
695
|
+
]
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
"name": "strict",
|
|
700
|
+
"schema": {
|
|
701
|
+
"type": "boolean",
|
|
702
|
+
"default": false
|
|
703
|
+
}
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
"name": "fix",
|
|
707
|
+
"schema": {
|
|
708
|
+
"type": "boolean",
|
|
709
|
+
"default": false
|
|
710
|
+
}
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"name": "format",
|
|
714
|
+
"schema": {
|
|
715
|
+
"type": "string",
|
|
716
|
+
"default": "text",
|
|
717
|
+
"enum": [
|
|
718
|
+
"text",
|
|
719
|
+
"json",
|
|
720
|
+
"github"
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
],
|
|
725
|
+
"env": {
|
|
726
|
+
"CURSOR_API_KEY": {
|
|
727
|
+
"sensitive": true
|
|
728
|
+
},
|
|
729
|
+
"GEMINI_API_KEY": {
|
|
730
|
+
"sensitive": true
|
|
731
|
+
},
|
|
732
|
+
"OPENAI_API_KEY": {
|
|
733
|
+
"sensitive": true
|
|
734
|
+
},
|
|
735
|
+
"ANTHROPIC_API_KEY": {
|
|
736
|
+
"sensitive": true
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
"drift": {
|
|
741
|
+
"options": [
|
|
742
|
+
{
|
|
743
|
+
"name": "config",
|
|
744
|
+
"schema": {
|
|
745
|
+
"type": "string"
|
|
746
|
+
},
|
|
747
|
+
"file": {
|
|
748
|
+
"mode": "read",
|
|
749
|
+
"exists": true,
|
|
750
|
+
"encoding": "utf-8"
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
"name": "update",
|
|
755
|
+
"schema": {
|
|
756
|
+
"type": "boolean",
|
|
757
|
+
"default": false
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
"name": "format",
|
|
762
|
+
"schema": {
|
|
763
|
+
"type": "string",
|
|
764
|
+
"default": "text",
|
|
765
|
+
"enum": [
|
|
766
|
+
"text",
|
|
767
|
+
"json",
|
|
768
|
+
"diff"
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
"name": "fail-on-drift",
|
|
774
|
+
"schema": {
|
|
775
|
+
"type": "boolean",
|
|
776
|
+
"default": false
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
],
|
|
780
|
+
"env": {
|
|
781
|
+
"CURSOR_API_KEY": {
|
|
782
|
+
"sensitive": true
|
|
783
|
+
},
|
|
784
|
+
"GEMINI_API_KEY": {
|
|
785
|
+
"sensitive": true
|
|
786
|
+
},
|
|
787
|
+
"OPENAI_API_KEY": {
|
|
788
|
+
"sensitive": true
|
|
789
|
+
},
|
|
790
|
+
"ANTHROPIC_API_KEY": {
|
|
791
|
+
"sensitive": true
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
"check": {
|
|
796
|
+
"options": [
|
|
797
|
+
{
|
|
798
|
+
"name": "config",
|
|
799
|
+
"schema": {
|
|
800
|
+
"type": "string"
|
|
801
|
+
},
|
|
802
|
+
"file": {
|
|
803
|
+
"mode": "read",
|
|
804
|
+
"exists": true,
|
|
805
|
+
"encoding": "utf-8"
|
|
806
|
+
}
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
"name": "strict",
|
|
810
|
+
"schema": {
|
|
811
|
+
"type": "boolean",
|
|
812
|
+
"default": false
|
|
813
|
+
}
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
"name": "verbose",
|
|
817
|
+
"schema": {
|
|
818
|
+
"type": "boolean",
|
|
819
|
+
"default": false
|
|
820
|
+
}
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
"name": "coverage",
|
|
824
|
+
"schema": {
|
|
825
|
+
"type": "boolean",
|
|
826
|
+
"default": false
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
],
|
|
830
|
+
"env": {
|
|
831
|
+
"CURSOR_API_KEY": {
|
|
832
|
+
"sensitive": true
|
|
833
|
+
},
|
|
834
|
+
"GEMINI_API_KEY": {
|
|
835
|
+
"sensitive": true
|
|
836
|
+
},
|
|
837
|
+
"OPENAI_API_KEY": {
|
|
838
|
+
"sensitive": true
|
|
839
|
+
},
|
|
840
|
+
"ANTHROPIC_API_KEY": {
|
|
841
|
+
"sensitive": true
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
"new": {
|
|
846
|
+
"effects": {
|
|
847
|
+
"riskLevel": "low",
|
|
848
|
+
"writes": [
|
|
849
|
+
{
|
|
850
|
+
"target": "design/ directory",
|
|
851
|
+
"description": "new TypeScript spec file with auto-generated ID",
|
|
852
|
+
"idempotent": false
|
|
853
|
+
}
|
|
854
|
+
]
|
|
855
|
+
},
|
|
856
|
+
"options": [
|
|
857
|
+
{
|
|
858
|
+
"name": "kind",
|
|
859
|
+
"schema": {
|
|
860
|
+
"type": "string"
|
|
861
|
+
}
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
"name": "name",
|
|
865
|
+
"schema": {
|
|
866
|
+
"type": "string"
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
"name": "output",
|
|
871
|
+
"schema": {
|
|
872
|
+
"type": "string"
|
|
873
|
+
}
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
"name": "template",
|
|
877
|
+
"schema": {
|
|
878
|
+
"type": "string"
|
|
879
|
+
},
|
|
880
|
+
"file": {
|
|
881
|
+
"mode": "read",
|
|
882
|
+
"exists": true,
|
|
883
|
+
"encoding": "utf-8"
|
|
884
|
+
}
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
"name": "dry-run",
|
|
888
|
+
"schema": {
|
|
889
|
+
"type": "boolean",
|
|
890
|
+
"default": false
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
],
|
|
894
|
+
"env": {
|
|
895
|
+
"CURSOR_API_KEY": {
|
|
896
|
+
"sensitive": true
|
|
897
|
+
},
|
|
898
|
+
"GEMINI_API_KEY": {
|
|
899
|
+
"sensitive": true
|
|
900
|
+
},
|
|
901
|
+
"OPENAI_API_KEY": {
|
|
902
|
+
"sensitive": true
|
|
903
|
+
},
|
|
904
|
+
"ANTHROPIC_API_KEY": {
|
|
905
|
+
"sensitive": true
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
"impact": {
|
|
910
|
+
"options": [
|
|
911
|
+
{
|
|
912
|
+
"name": "config",
|
|
913
|
+
"schema": {
|
|
914
|
+
"type": "string"
|
|
915
|
+
},
|
|
916
|
+
"file": {
|
|
917
|
+
"mode": "read",
|
|
918
|
+
"exists": true,
|
|
919
|
+
"encoding": "utf-8"
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
"name": "depth",
|
|
924
|
+
"schema": {
|
|
925
|
+
"type": "integer",
|
|
926
|
+
"minimum": 1,
|
|
927
|
+
"default": 3
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "direction",
|
|
932
|
+
"schema": {
|
|
933
|
+
"type": "string",
|
|
934
|
+
"default": "both",
|
|
935
|
+
"enum": [
|
|
936
|
+
"upstream",
|
|
937
|
+
"downstream",
|
|
938
|
+
"both"
|
|
939
|
+
]
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
"name": "format",
|
|
944
|
+
"schema": {
|
|
945
|
+
"type": "string",
|
|
946
|
+
"default": "text",
|
|
947
|
+
"enum": [
|
|
948
|
+
"text",
|
|
949
|
+
"json",
|
|
950
|
+
"mermaid"
|
|
951
|
+
]
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
],
|
|
955
|
+
"env": {
|
|
956
|
+
"CURSOR_API_KEY": {
|
|
957
|
+
"sensitive": true
|
|
958
|
+
},
|
|
959
|
+
"GEMINI_API_KEY": {
|
|
960
|
+
"sensitive": true
|
|
961
|
+
},
|
|
962
|
+
"OPENAI_API_KEY": {
|
|
963
|
+
"sensitive": true
|
|
964
|
+
},
|
|
965
|
+
"ANTHROPIC_API_KEY": {
|
|
966
|
+
"sensitive": true
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
},
|
|
970
|
+
"scaffold": {
|
|
971
|
+
"effects": {
|
|
972
|
+
"riskLevel": "low",
|
|
973
|
+
"writes": [
|
|
974
|
+
{
|
|
975
|
+
"target": "design/ directory",
|
|
976
|
+
"description": "generated _models/ and spec data files",
|
|
977
|
+
"idempotent": false
|
|
978
|
+
}
|
|
979
|
+
]
|
|
980
|
+
},
|
|
981
|
+
"options": [
|
|
982
|
+
{
|
|
983
|
+
"name": "source",
|
|
984
|
+
"schema": {
|
|
985
|
+
"type": "string"
|
|
986
|
+
},
|
|
987
|
+
"file": {
|
|
988
|
+
"mode": "read",
|
|
989
|
+
"exists": true,
|
|
990
|
+
"encoding": "utf-8"
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
"name": "output",
|
|
995
|
+
"schema": {
|
|
996
|
+
"type": "string",
|
|
997
|
+
"default": "design/"
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
"name": "force",
|
|
1002
|
+
"schema": {
|
|
1003
|
+
"type": "boolean",
|
|
1004
|
+
"default": false
|
|
1005
|
+
},
|
|
1006
|
+
"effects": {
|
|
1007
|
+
"riskLevel": "medium",
|
|
1008
|
+
"writes": [
|
|
1009
|
+
{
|
|
1010
|
+
"target": "existing model and spec files",
|
|
1011
|
+
"description": "overwrites existing TypeScript model source files",
|
|
1012
|
+
"overwrite": true
|
|
1013
|
+
}
|
|
1014
|
+
]
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
{
|
|
1018
|
+
"name": "dry-run",
|
|
1019
|
+
"schema": {
|
|
1020
|
+
"type": "boolean",
|
|
1021
|
+
"default": false
|
|
1022
|
+
}
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
"name": "format",
|
|
1026
|
+
"schema": {
|
|
1027
|
+
"type": "string",
|
|
1028
|
+
"default": "ts",
|
|
1029
|
+
"enum": [
|
|
1030
|
+
"ts",
|
|
1031
|
+
"yaml"
|
|
1032
|
+
]
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
],
|
|
1036
|
+
"env": {
|
|
1037
|
+
"CURSOR_API_KEY": {
|
|
1038
|
+
"sensitive": true
|
|
1039
|
+
},
|
|
1040
|
+
"GEMINI_API_KEY": {
|
|
1041
|
+
"sensitive": true
|
|
1042
|
+
},
|
|
1043
|
+
"OPENAI_API_KEY": {
|
|
1044
|
+
"sensitive": true
|
|
1045
|
+
},
|
|
1046
|
+
"ANTHROPIC_API_KEY": {
|
|
1047
|
+
"sensitive": true
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1051
|
+
"convert": {
|
|
1052
|
+
"effects": {
|
|
1053
|
+
"riskLevel": "low",
|
|
1054
|
+
"writes": [
|
|
1055
|
+
{
|
|
1056
|
+
"target": ".yaml output file",
|
|
1057
|
+
"description": "YAML conversion of the TS spec data",
|
|
1058
|
+
"idempotent": true
|
|
1059
|
+
}
|
|
1060
|
+
]
|
|
1061
|
+
},
|
|
1062
|
+
"options": [
|
|
1063
|
+
{
|
|
1064
|
+
"name": "output",
|
|
1065
|
+
"schema": {
|
|
1066
|
+
"type": "string"
|
|
1067
|
+
},
|
|
1068
|
+
"file": {
|
|
1069
|
+
"mode": "write",
|
|
1070
|
+
"encoding": "utf-8"
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
"name": "dry-run",
|
|
1075
|
+
"schema": {
|
|
1076
|
+
"type": "boolean",
|
|
1077
|
+
"default": false
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
],
|
|
1081
|
+
"env": {
|
|
1082
|
+
"CURSOR_API_KEY": {
|
|
1083
|
+
"sensitive": true
|
|
1084
|
+
},
|
|
1085
|
+
"GEMINI_API_KEY": {
|
|
1086
|
+
"sensitive": true
|
|
1087
|
+
},
|
|
1088
|
+
"OPENAI_API_KEY": {
|
|
1089
|
+
"sensitive": true
|
|
1090
|
+
},
|
|
1091
|
+
"ANTHROPIC_API_KEY": {
|
|
1092
|
+
"sensitive": true
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
"audit-requirements": {
|
|
1097
|
+
"effects": {
|
|
1098
|
+
"network": {
|
|
1099
|
+
"description": "LLM API calls to configured provider",
|
|
1100
|
+
"idempotent": true
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
"options": [
|
|
1104
|
+
{
|
|
1105
|
+
"name": "config",
|
|
1106
|
+
"schema": {
|
|
1107
|
+
"type": "string"
|
|
1108
|
+
},
|
|
1109
|
+
"file": {
|
|
1110
|
+
"mode": "read",
|
|
1111
|
+
"exists": true,
|
|
1112
|
+
"encoding": "utf-8"
|
|
1113
|
+
}
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
"name": "adapter",
|
|
1117
|
+
"schema": {
|
|
1118
|
+
"type": "string",
|
|
1119
|
+
"enum": [
|
|
1120
|
+
"cursor",
|
|
1121
|
+
"claude",
|
|
1122
|
+
"openai",
|
|
1123
|
+
"gemini",
|
|
1124
|
+
"mock"
|
|
1125
|
+
]
|
|
1126
|
+
}
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
"name": "model",
|
|
1130
|
+
"schema": {
|
|
1131
|
+
"type": "string"
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
"name": "dry-run",
|
|
1136
|
+
"schema": {
|
|
1137
|
+
"type": "boolean",
|
|
1138
|
+
"default": false
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
"name": "show-prompt",
|
|
1143
|
+
"schema": {
|
|
1144
|
+
"type": "boolean",
|
|
1145
|
+
"default": false
|
|
1146
|
+
}
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
"name": "fail-on",
|
|
1150
|
+
"schema": {
|
|
1151
|
+
"type": "string",
|
|
1152
|
+
"enum": [
|
|
1153
|
+
"warning",
|
|
1154
|
+
"error",
|
|
1155
|
+
"critical"
|
|
1156
|
+
],
|
|
1157
|
+
"default": "error"
|
|
1158
|
+
}
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
"name": "output",
|
|
1162
|
+
"schema": {
|
|
1163
|
+
"type": "string"
|
|
1164
|
+
},
|
|
1165
|
+
"file": {
|
|
1166
|
+
"mode": "write",
|
|
1167
|
+
"encoding": "utf-8"
|
|
1168
|
+
}
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
"name": "report-format",
|
|
1172
|
+
"schema": {
|
|
1173
|
+
"type": "string",
|
|
1174
|
+
"enum": [
|
|
1175
|
+
"json",
|
|
1176
|
+
"text",
|
|
1177
|
+
"yaml"
|
|
1178
|
+
],
|
|
1179
|
+
"default": "json"
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
],
|
|
1183
|
+
"env": {
|
|
1184
|
+
"CURSOR_API_KEY": {
|
|
1185
|
+
"sensitive": true
|
|
1186
|
+
},
|
|
1187
|
+
"GEMINI_API_KEY": {
|
|
1188
|
+
"sensitive": true
|
|
1189
|
+
},
|
|
1190
|
+
"OPENAI_API_KEY": {
|
|
1191
|
+
"sensitive": true
|
|
1192
|
+
},
|
|
1193
|
+
"ANTHROPIC_API_KEY": {
|
|
1194
|
+
"sensitive": true
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
},
|
|
1198
|
+
"propose-trace-links": {
|
|
1199
|
+
"effects": {
|
|
1200
|
+
"network": {
|
|
1201
|
+
"description": "LLM API calls to configured provider",
|
|
1202
|
+
"idempotent": true
|
|
1203
|
+
}
|
|
1204
|
+
},
|
|
1205
|
+
"options": [
|
|
1206
|
+
{
|
|
1207
|
+
"name": "config",
|
|
1208
|
+
"schema": {
|
|
1209
|
+
"type": "string"
|
|
1210
|
+
},
|
|
1211
|
+
"file": {
|
|
1212
|
+
"mode": "read",
|
|
1213
|
+
"exists": true,
|
|
1214
|
+
"encoding": "utf-8"
|
|
1215
|
+
}
|
|
1216
|
+
},
|
|
1217
|
+
{
|
|
1218
|
+
"name": "adapter",
|
|
1219
|
+
"schema": {
|
|
1220
|
+
"type": "string",
|
|
1221
|
+
"enum": [
|
|
1222
|
+
"cursor",
|
|
1223
|
+
"claude",
|
|
1224
|
+
"openai",
|
|
1225
|
+
"gemini",
|
|
1226
|
+
"mock"
|
|
1227
|
+
]
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
"name": "model",
|
|
1232
|
+
"schema": {
|
|
1233
|
+
"type": "string"
|
|
1234
|
+
}
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
"name": "dry-run",
|
|
1238
|
+
"schema": {
|
|
1239
|
+
"type": "boolean",
|
|
1240
|
+
"default": false
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
{
|
|
1244
|
+
"name": "show-prompt",
|
|
1245
|
+
"schema": {
|
|
1246
|
+
"type": "boolean",
|
|
1247
|
+
"default": false
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
{
|
|
1251
|
+
"name": "fail-on",
|
|
1252
|
+
"schema": {
|
|
1253
|
+
"type": "string",
|
|
1254
|
+
"enum": [
|
|
1255
|
+
"warning",
|
|
1256
|
+
"error",
|
|
1257
|
+
"critical"
|
|
1258
|
+
],
|
|
1259
|
+
"default": "error"
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
"name": "output",
|
|
1264
|
+
"schema": {
|
|
1265
|
+
"type": "string"
|
|
1266
|
+
},
|
|
1267
|
+
"file": {
|
|
1268
|
+
"mode": "write",
|
|
1269
|
+
"encoding": "utf-8"
|
|
1270
|
+
}
|
|
1271
|
+
},
|
|
1272
|
+
{
|
|
1273
|
+
"name": "report-format",
|
|
1274
|
+
"schema": {
|
|
1275
|
+
"type": "string",
|
|
1276
|
+
"enum": [
|
|
1277
|
+
"json",
|
|
1278
|
+
"text",
|
|
1279
|
+
"yaml"
|
|
1280
|
+
],
|
|
1281
|
+
"default": "json"
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
],
|
|
1285
|
+
"env": {
|
|
1286
|
+
"CURSOR_API_KEY": {
|
|
1287
|
+
"sensitive": true
|
|
1288
|
+
},
|
|
1289
|
+
"GEMINI_API_KEY": {
|
|
1290
|
+
"sensitive": true
|
|
1291
|
+
},
|
|
1292
|
+
"OPENAI_API_KEY": {
|
|
1293
|
+
"sensitive": true
|
|
1294
|
+
},
|
|
1295
|
+
"ANTHROPIC_API_KEY": {
|
|
1296
|
+
"sensitive": true
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
},
|
|
1300
|
+
"explain-impact": {
|
|
1301
|
+
"effects": {
|
|
1302
|
+
"network": {
|
|
1303
|
+
"description": "LLM API calls to configured provider",
|
|
1304
|
+
"idempotent": true
|
|
1305
|
+
}
|
|
1306
|
+
},
|
|
1307
|
+
"options": [
|
|
1308
|
+
{
|
|
1309
|
+
"name": "adapter",
|
|
1310
|
+
"schema": {
|
|
1311
|
+
"type": "string",
|
|
1312
|
+
"enum": [
|
|
1313
|
+
"cursor",
|
|
1314
|
+
"claude",
|
|
1315
|
+
"openai",
|
|
1316
|
+
"gemini",
|
|
1317
|
+
"mock"
|
|
1318
|
+
]
|
|
1319
|
+
}
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
"name": "model",
|
|
1323
|
+
"schema": {
|
|
1324
|
+
"type": "string"
|
|
1325
|
+
}
|
|
1326
|
+
},
|
|
1327
|
+
{
|
|
1328
|
+
"name": "dry-run",
|
|
1329
|
+
"schema": {
|
|
1330
|
+
"type": "boolean",
|
|
1331
|
+
"default": false
|
|
1332
|
+
}
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
"name": "show-prompt",
|
|
1336
|
+
"schema": {
|
|
1337
|
+
"type": "boolean",
|
|
1338
|
+
"default": false
|
|
1339
|
+
}
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
"name": "fail-on",
|
|
1343
|
+
"schema": {
|
|
1344
|
+
"type": "string",
|
|
1345
|
+
"enum": [
|
|
1346
|
+
"warning",
|
|
1347
|
+
"error",
|
|
1348
|
+
"critical"
|
|
1349
|
+
],
|
|
1350
|
+
"default": "error"
|
|
1351
|
+
}
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
"name": "output",
|
|
1355
|
+
"schema": {
|
|
1356
|
+
"type": "string"
|
|
1357
|
+
},
|
|
1358
|
+
"file": {
|
|
1359
|
+
"mode": "write",
|
|
1360
|
+
"encoding": "utf-8"
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
"name": "report-format",
|
|
1365
|
+
"schema": {
|
|
1366
|
+
"type": "string",
|
|
1367
|
+
"enum": [
|
|
1368
|
+
"json",
|
|
1369
|
+
"text",
|
|
1370
|
+
"yaml"
|
|
1371
|
+
],
|
|
1372
|
+
"default": "json"
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
],
|
|
1376
|
+
"env": {
|
|
1377
|
+
"CURSOR_API_KEY": {
|
|
1378
|
+
"sensitive": true
|
|
1379
|
+
},
|
|
1380
|
+
"GEMINI_API_KEY": {
|
|
1381
|
+
"sensitive": true
|
|
1382
|
+
},
|
|
1383
|
+
"OPENAI_API_KEY": {
|
|
1384
|
+
"sensitive": true
|
|
1385
|
+
},
|
|
1386
|
+
"ANTHROPIC_API_KEY": {
|
|
1387
|
+
"sensitive": true
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
},
|
|
1391
|
+
"propose-acceptance-criteria": {
|
|
1392
|
+
"effects": {
|
|
1393
|
+
"network": {
|
|
1394
|
+
"description": "LLM API calls to configured provider",
|
|
1395
|
+
"idempotent": true
|
|
1396
|
+
}
|
|
1397
|
+
},
|
|
1398
|
+
"options": [
|
|
1399
|
+
{
|
|
1400
|
+
"name": "config",
|
|
1401
|
+
"schema": {
|
|
1402
|
+
"type": "string"
|
|
1403
|
+
},
|
|
1404
|
+
"file": {
|
|
1405
|
+
"mode": "read",
|
|
1406
|
+
"exists": true,
|
|
1407
|
+
"encoding": "utf-8"
|
|
1408
|
+
}
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
"name": "adapter",
|
|
1412
|
+
"schema": {
|
|
1413
|
+
"type": "string",
|
|
1414
|
+
"enum": [
|
|
1415
|
+
"cursor",
|
|
1416
|
+
"claude",
|
|
1417
|
+
"openai",
|
|
1418
|
+
"gemini",
|
|
1419
|
+
"mock"
|
|
1420
|
+
]
|
|
1421
|
+
}
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
"name": "model",
|
|
1425
|
+
"schema": {
|
|
1426
|
+
"type": "string"
|
|
1427
|
+
}
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
"name": "dry-run",
|
|
1431
|
+
"schema": {
|
|
1432
|
+
"type": "boolean",
|
|
1433
|
+
"default": false
|
|
1434
|
+
}
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
"name": "show-prompt",
|
|
1438
|
+
"schema": {
|
|
1439
|
+
"type": "boolean",
|
|
1440
|
+
"default": false
|
|
1441
|
+
}
|
|
1442
|
+
},
|
|
1443
|
+
{
|
|
1444
|
+
"name": "fail-on",
|
|
1445
|
+
"schema": {
|
|
1446
|
+
"type": "string",
|
|
1447
|
+
"enum": [
|
|
1448
|
+
"warning",
|
|
1449
|
+
"error",
|
|
1450
|
+
"critical"
|
|
1451
|
+
],
|
|
1452
|
+
"default": "error"
|
|
1453
|
+
}
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
"name": "output",
|
|
1457
|
+
"schema": {
|
|
1458
|
+
"type": "string"
|
|
1459
|
+
},
|
|
1460
|
+
"file": {
|
|
1461
|
+
"mode": "write",
|
|
1462
|
+
"encoding": "utf-8"
|
|
1463
|
+
}
|
|
1464
|
+
},
|
|
1465
|
+
{
|
|
1466
|
+
"name": "report-format",
|
|
1467
|
+
"schema": {
|
|
1468
|
+
"type": "string",
|
|
1469
|
+
"enum": [
|
|
1470
|
+
"json",
|
|
1471
|
+
"text",
|
|
1472
|
+
"yaml"
|
|
1473
|
+
],
|
|
1474
|
+
"default": "json"
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
],
|
|
1478
|
+
"env": {
|
|
1479
|
+
"CURSOR_API_KEY": {
|
|
1480
|
+
"sensitive": true
|
|
1481
|
+
},
|
|
1482
|
+
"GEMINI_API_KEY": {
|
|
1483
|
+
"sensitive": true
|
|
1484
|
+
},
|
|
1485
|
+
"OPENAI_API_KEY": {
|
|
1486
|
+
"sensitive": true
|
|
1487
|
+
},
|
|
1488
|
+
"ANTHROPIC_API_KEY": {
|
|
1489
|
+
"sensitive": true
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
};
|
|
1494
|
+
function deriveCommandPolicy(commandId, optionValues) {
|
|
1495
|
+
const def = commandDefinitions[commandId];
|
|
1496
|
+
if (!def) throw new Error(`Unknown command: ${commandId}`);
|
|
1497
|
+
const cmdDef = def;
|
|
1498
|
+
const options = {};
|
|
1499
|
+
const activeOptions = [];
|
|
1500
|
+
for (const optDef of cmdDef.options ?? []) {
|
|
1501
|
+
const value = optionValues[optDef.name];
|
|
1502
|
+
const specified = optDef.name in optionValues && value !== void 0;
|
|
1503
|
+
options[optDef.name] = { value, specified, definition: optDef };
|
|
1504
|
+
if (isOptionActive(optDef, value, specified)) {
|
|
1505
|
+
activeOptions.push(optDef.name);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
const policy = derivePolicy({
|
|
1509
|
+
commandId,
|
|
1510
|
+
commandEffects: cmdDef.effects,
|
|
1511
|
+
options,
|
|
1512
|
+
env: cmdDef.env
|
|
1513
|
+
});
|
|
1514
|
+
return { command: commandId, activeOptions, policy };
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
// src/generated/program.ts
|
|
1518
|
+
function createProgram(handlers2, version) {
|
|
1519
|
+
const program = new Command();
|
|
1520
|
+
program.name("speckeeper").version(version, "-V, --version").description("Requirements and design management framework with TypeScript DSL.");
|
|
1521
|
+
program.option("--introspect", "Output derived policy as JSON without executing the command");
|
|
1522
|
+
program.command("init").description("Initialize a new speckeeper project with starter templates.").option("-F, --force", "Overwrite existing files.", false).option("--format <format>", "Spec data format: ts (default) or yaml.", "ts").action(async (opts, cmd) => {
|
|
1523
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1524
|
+
if (globalOpts.introspect) {
|
|
1525
|
+
const policy = deriveCommandPolicy("init", opts);
|
|
1526
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
await handlers2.init(opts, globalOpts);
|
|
1530
|
+
});
|
|
1531
|
+
program.command("build").description("Generate docs/ and specs/ from TypeScript models.").option("-c, --config <path>", "Path to config file.").option("-o, --output <path>", "Base output directory path.", ".").option("-f, --format <format>", "Output format: markdown, json, both.", "both").option("-w, --watch", "Watch for changes and auto-regenerate.", false).option("-v, --verbose", "Show detailed output.", false).action(async (opts, cmd) => {
|
|
1532
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1533
|
+
if (globalOpts.introspect) {
|
|
1534
|
+
const policy = deriveCommandPolicy("build", opts);
|
|
1535
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
await handlers2.build(opts, globalOpts);
|
|
1539
|
+
});
|
|
1540
|
+
program.command("lint").description("Check design integrity (ID duplicates, references, layer violations, etc.).").option("-c, --config <path>", "Path to config file.").option("-p, --phase <phase>", "Phase gate to check against: REQ, HLD, LLD, OPS.").option("-s, --strict", "Treat warnings as errors.", false).option("--fix", "Attempt to fix auto-fixable issues (not yet implemented).", false).option("-f, --format <format>", "Output format: text, json, github.", "text").action(async (opts, cmd) => {
|
|
1541
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1542
|
+
if (globalOpts.introspect) {
|
|
1543
|
+
const policy = deriveCommandPolicy("lint", opts);
|
|
1544
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
await handlers2.lint(opts, globalOpts);
|
|
1548
|
+
});
|
|
1549
|
+
program.command("drift").description("Check if generated files have been manually edited.").option("-c, --config <path>", "Path to config file.").option("-u, --update", "Auto-update if differences are found (not yet implemented).", false).option("-f, --format <format>", "Output format: text, json, diff.", "text").option("--fail-on-drift", "Exit with code 1 if drift is detected (for CI).", false).action(async (opts, cmd) => {
|
|
1550
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1551
|
+
if (globalOpts.introspect) {
|
|
1552
|
+
const policy = deriveCommandPolicy("drift", opts);
|
|
1553
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
await handlers2.drift(opts, globalOpts);
|
|
1557
|
+
});
|
|
1558
|
+
program.command("check").description("Check external SSOT conformance (including custom models).").argument("[type]", "Type of check to run. Filters sources by type.").option("-c, --config <path>", "Path to config file.").option("--strict", "Treat warnings as errors.", false).option("-v, --verbose", "Show detailed output.", false).option("--coverage", "Check if all testable acceptance criteria are covered by TestRefs.", false).action(async (type, opts, cmd) => {
|
|
1559
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1560
|
+
if (globalOpts.introspect) {
|
|
1561
|
+
const policy = deriveCommandPolicy("check", opts);
|
|
1562
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
await handlers2.check(type, opts, globalOpts);
|
|
1566
|
+
});
|
|
1567
|
+
program.command("new").description("Create a new element with auto-generated ID.").argument("<type>", "Element type to create.").option("-k, --kind <kind>", "Sub-kind (e.g. functional, non-functional for requirements).").option("-n, --name <name>", "Name of the element.").option("-o, --output <path>", "Output directory path.").option("-t, --template <path>", "Path to template file.").option("--dry-run", "Preview generated file content without writing.", false).action(async (type, opts, cmd) => {
|
|
1568
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1569
|
+
if (globalOpts.introspect) {
|
|
1570
|
+
const policy = deriveCommandPolicy("new", opts);
|
|
1571
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
await handlers2.new(type, opts, globalOpts);
|
|
1575
|
+
});
|
|
1576
|
+
program.command("impact").description("Analyze impact of changes to an ID.").argument("<id>", "Spec ID to analyze (e.g. REQ-001, ENT-ORDER).").option("-c, --config <path>", "Path to config file.").option("-d, --depth <n>", "Analysis depth (reference tracking level).", "3").option("--direction <direction>", "Analysis direction: upstream, downstream, both.", "both").option("-f, --format <format>", "Output format: text, json, mermaid.", "text").action(async (id, opts, cmd) => {
|
|
1577
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1578
|
+
if (globalOpts.introspect) {
|
|
1579
|
+
const policy = deriveCommandPolicy("impact", opts);
|
|
1580
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
await handlers2.impact(id, opts, globalOpts);
|
|
1584
|
+
});
|
|
1585
|
+
program.command("scaffold").description("Generate _models/ from a Mermaid flowchart definition.").option("-s, --source <path>", "Path to Markdown file containing Mermaid flowchart.").option("-o, --output <path>", "Output directory.", "design/").option("-F, --force", "Overwrite existing files.", false).option("--dry-run", "Preview generated files without writing.", false).option("--format <format>", "Spec data format: ts (default) or yaml.", "ts").action(async (opts, cmd) => {
|
|
1586
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1587
|
+
if (globalOpts.introspect) {
|
|
1588
|
+
const policy = deriveCommandPolicy("scaffold", opts);
|
|
1589
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
await handlers2.scaffold(opts, globalOpts);
|
|
1593
|
+
});
|
|
1594
|
+
program.command("convert").description("Convert a TS spec data file to YAML format.").argument("<file>", "Path to TS spec data file.").option("-o, --output <path>", "Output file path (default: same name with .yaml extension).").option("-n, --dry-run", "Preview conversion without writing.", false).action(async (file, opts, cmd) => {
|
|
1595
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1596
|
+
if (globalOpts.introspect) {
|
|
1597
|
+
const policy = deriveCommandPolicy("convert", opts);
|
|
1598
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
await handlers2.convert(file, opts, globalOpts);
|
|
1602
|
+
});
|
|
1603
|
+
program.command("audit-requirements").description("Run LLM-based requirement quality audit.").option("-c, --config <path>", "Path to config file.").option("-a, --adapter <name>", "SDK adapter to use for LLM execution.").option("--model <name>", "LLM model override.").option("-n, --dry-run", "Output the constructed prompt without calling LLM.", false).option("--show-prompt", "Display the constructed LLM prompt on stderr.", false).option("--fail-on <level>", "Minimum severity that causes a non-zero exit.", "error").option("-o, --output <file>", "Write result to a file instead of stdout.").option("--report-format <fmt>", "Output format for the audit report.", "json").action(async (opts, cmd) => {
|
|
1604
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1605
|
+
if (globalOpts.introspect) {
|
|
1606
|
+
const policy = deriveCommandPolicy("audit-requirements", opts);
|
|
1607
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
await handlers2.auditRequirements(opts, globalOpts);
|
|
1611
|
+
});
|
|
1612
|
+
program.command("propose-trace-links").description("LLM-based traceability link proposal.").option("-c, --config <path>", "Path to config file.").option("-a, --adapter <name>", "SDK adapter to use for LLM execution.").option("--model <name>", "LLM model override.").option("-n, --dry-run", "Output the constructed prompt without calling LLM.", false).option("--show-prompt", "Display the constructed LLM prompt on stderr.", false).option("--fail-on <level>", "Minimum severity that causes a non-zero exit.", "error").option("-o, --output <file>", "Write result to a file instead of stdout.").option("--report-format <fmt>", "Output format for the report.", "json").action(async (opts, cmd) => {
|
|
1613
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1614
|
+
if (globalOpts.introspect) {
|
|
1615
|
+
const policy = deriveCommandPolicy("propose-trace-links", opts);
|
|
1616
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
await handlers2.proposeTraceLinks(opts, globalOpts);
|
|
1620
|
+
});
|
|
1621
|
+
program.command("explain-impact").description("LLM-based explanation of impact analysis output.").option("-a, --adapter <name>", "SDK adapter to use for LLM execution.").option("--model <name>", "LLM model override.").option("-n, --dry-run", "Output the constructed prompt without calling LLM.", false).option("--show-prompt", "Display the constructed LLM prompt on stderr.", false).option("--fail-on <level>", "Minimum severity that causes a non-zero exit.", "error").option("-o, --output <file>", "Write result to a file instead of stdout.").option("--report-format <fmt>", "Output format for the report.", "json").action(async (opts, cmd) => {
|
|
1622
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1623
|
+
if (globalOpts.introspect) {
|
|
1624
|
+
const policy = deriveCommandPolicy("explain-impact", opts);
|
|
1625
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
await handlers2.explainImpact(opts, globalOpts);
|
|
1629
|
+
});
|
|
1630
|
+
program.command("propose-acceptance-criteria").description("LLM-based acceptance criteria proposal.").argument("[specIds...]", "Spec IDs to propose criteria for. Defaults to all specs if omitted.").option("-c, --config <path>", "Path to config file.").option("-a, --adapter <name>", "SDK adapter to use for LLM execution.").option("--model <name>", "LLM model override.").option("-n, --dry-run", "Output the constructed prompt without calling LLM.", false).option("--show-prompt", "Display the constructed LLM prompt on stderr.", false).option("--fail-on <level>", "Minimum severity that causes a non-zero exit.", "error").option("-o, --output <file>", "Write result to a file instead of stdout.").option("--report-format <fmt>", "Output format for the report.", "json").action(async (specIds, opts, cmd) => {
|
|
1631
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
1632
|
+
if (globalOpts.introspect) {
|
|
1633
|
+
const policy = deriveCommandPolicy("propose-acceptance-criteria", opts);
|
|
1634
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
await handlers2.proposeAcceptanceCriteria(specIds, opts, globalOpts);
|
|
1638
|
+
});
|
|
1639
|
+
return program;
|
|
1640
|
+
}
|
|
538
1641
|
var defaultConfig = {
|
|
539
1642
|
srcDir: "src",
|
|
540
1643
|
designDir: "design",
|
|
@@ -1961,6 +3064,8 @@ async function runInit(options = {}) {
|
|
|
1961
3064
|
console.log(chalk4.gray(" Please ensure the package is properly installed."));
|
|
1962
3065
|
return;
|
|
1963
3066
|
}
|
|
3067
|
+
const isYaml = options.format === "yaml";
|
|
3068
|
+
const skipForYaml = /* @__PURE__ */ new Set(["design/requirements.ts"]);
|
|
1964
3069
|
let packageJsonCreated = false;
|
|
1965
3070
|
copyTemplateDir(templatesDir, cwd, projectName, options.force || false, (relativePath, created) => {
|
|
1966
3071
|
if (created) {
|
|
@@ -1971,25 +3076,29 @@ async function runInit(options = {}) {
|
|
|
1971
3076
|
} else {
|
|
1972
3077
|
console.log(chalk4.yellow(` Skipped: ${relativePath} (already exists)`));
|
|
1973
3078
|
}
|
|
1974
|
-
});
|
|
3079
|
+
}, "", isYaml ? skipForYaml : void 0);
|
|
3080
|
+
if (isYaml) {
|
|
3081
|
+
writeYamlInitFiles(cwd, options.force || false);
|
|
3082
|
+
}
|
|
1975
3083
|
console.log("");
|
|
1976
3084
|
console.log(chalk4.cyan(" Project initialized successfully!"));
|
|
1977
3085
|
console.log("");
|
|
3086
|
+
const dataFormat = isYaml ? "design/*.yaml" : "design/*.ts using defineSpecs()";
|
|
1978
3087
|
console.log(" Next steps:");
|
|
1979
3088
|
if (packageJsonCreated) {
|
|
1980
3089
|
console.log(chalk4.gray(" 1. Run `npm install` to install dependencies"));
|
|
1981
|
-
console.log(chalk4.gray(
|
|
3090
|
+
console.log(chalk4.gray(` 2. Add spec data in ${dataFormat}`));
|
|
1982
3091
|
console.log(chalk4.gray(" 3. Import new spec files in design/index.ts"));
|
|
1983
3092
|
console.log(chalk4.gray(" 4. Run `npx speckeeper lint` to validate"));
|
|
1984
3093
|
} else {
|
|
1985
3094
|
console.log(chalk4.gray(" 1. Add speckeeper and zod to your package.json dependencies"));
|
|
1986
3095
|
console.log(chalk4.gray(' 2. Ensure "type": "module" is set in package.json'));
|
|
1987
|
-
console.log(chalk4.gray(
|
|
3096
|
+
console.log(chalk4.gray(` 3. Add spec data in ${dataFormat}`));
|
|
1988
3097
|
console.log(chalk4.gray(" 4. Import new spec files in design/index.ts"));
|
|
1989
3098
|
console.log(chalk4.gray(" 5. Run `npx speckeeper lint` to validate"));
|
|
1990
3099
|
}
|
|
1991
3100
|
}
|
|
1992
|
-
function copyTemplateDir(srcDir, destDir, projectName, force, onFile, relativePath = "") {
|
|
3101
|
+
function copyTemplateDir(srcDir, destDir, projectName, force, onFile, relativePath = "", skipRelPaths) {
|
|
1993
3102
|
const entries = readdirSync(srcDir);
|
|
1994
3103
|
for (const entry of entries) {
|
|
1995
3104
|
const srcPath = join(srcDir, entry);
|
|
@@ -2002,8 +3111,9 @@ function copyTemplateDir(srcDir, destDir, projectName, force, onFile, relativePa
|
|
|
2002
3111
|
mkdirSync(destPath, { recursive: true });
|
|
2003
3112
|
onFile(relPath + "/", true);
|
|
2004
3113
|
}
|
|
2005
|
-
copyTemplateDir(srcPath, destPath, projectName, force, onFile, relPath);
|
|
3114
|
+
copyTemplateDir(srcPath, destPath, projectName, force, onFile, relPath, skipRelPaths);
|
|
2006
3115
|
} else {
|
|
3116
|
+
if (skipRelPaths?.has(relPath)) continue;
|
|
2007
3117
|
if (!force && existsSync(destPath)) {
|
|
2008
3118
|
onFile(relPath, false);
|
|
2009
3119
|
continue;
|
|
@@ -2019,6 +3129,91 @@ function copyTemplateDir(srcDir, destDir, projectName, force, onFile, relativePa
|
|
|
2019
3129
|
}
|
|
2020
3130
|
}
|
|
2021
3131
|
}
|
|
3132
|
+
function writeYamlInitFiles(cwd, force) {
|
|
3133
|
+
const designDir = join(cwd, "design");
|
|
3134
|
+
if (!existsSync(designDir)) {
|
|
3135
|
+
mkdirSync(designDir, { recursive: true });
|
|
3136
|
+
}
|
|
3137
|
+
const reqYaml = join(designDir, "requirements.yaml");
|
|
3138
|
+
if (force || !existsSync(reqYaml)) {
|
|
3139
|
+
writeFileSync(reqYaml, `# Requirements
|
|
3140
|
+
model: requirement
|
|
3141
|
+
specs:
|
|
3142
|
+
- id: REQ-001
|
|
3143
|
+
name: User Authentication
|
|
3144
|
+
type: functional
|
|
3145
|
+
priority: must
|
|
3146
|
+
description: Users can authenticate using email and password
|
|
3147
|
+
acceptanceCriteria:
|
|
3148
|
+
- id: REQ-001-01
|
|
3149
|
+
description: Valid credentials grant access
|
|
3150
|
+
verificationMethod: test
|
|
3151
|
+
- id: REQ-001-02
|
|
3152
|
+
description: Invalid credentials show error message
|
|
3153
|
+
verificationMethod: test
|
|
3154
|
+
`);
|
|
3155
|
+
console.log(chalk4.green(" Created: design/requirements.yaml"));
|
|
3156
|
+
}
|
|
3157
|
+
const indexTs = join(designDir, "index.ts");
|
|
3158
|
+
if (force || !existsSync(indexTs)) {
|
|
3159
|
+
writeFileSync(indexTs, `/**
|
|
3160
|
+
* Design entry point
|
|
3161
|
+
*/
|
|
3162
|
+
import { mergeSpecs, loadYamlDir } from 'speckeeper';
|
|
3163
|
+
import { allModels } from './_models/index.ts';
|
|
3164
|
+
|
|
3165
|
+
const yamlSpecs = loadYamlDir(import.meta.dirname, allModels);
|
|
3166
|
+
|
|
3167
|
+
export default mergeSpecs(...yamlSpecs);
|
|
3168
|
+
`);
|
|
3169
|
+
console.log(chalk4.green(" Created: design/index.ts (yaml mode)"));
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
async function runConvert(file, options = {}) {
|
|
3173
|
+
const filePath = resolve(file);
|
|
3174
|
+
if (!existsSync(filePath)) {
|
|
3175
|
+
console.error(chalk4.red(` Error: File not found: ${filePath}`));
|
|
3176
|
+
process.exit(1);
|
|
3177
|
+
}
|
|
3178
|
+
if (!filePath.endsWith(".ts") && !filePath.endsWith(".js") && !filePath.endsWith(".mjs")) {
|
|
3179
|
+
console.error(chalk4.red(" Error: Source file must be a .ts, .js, or .mjs file"));
|
|
3180
|
+
process.exit(1);
|
|
3181
|
+
}
|
|
3182
|
+
console.log(chalk4.cyan("speckeeper convert"));
|
|
3183
|
+
console.log(chalk4.gray(` Source: ${filePath}`));
|
|
3184
|
+
console.log("");
|
|
3185
|
+
let specModule;
|
|
3186
|
+
try {
|
|
3187
|
+
const imported = await import(filePath);
|
|
3188
|
+
specModule = imported.default ?? imported;
|
|
3189
|
+
} catch (err) {
|
|
3190
|
+
console.error(chalk4.red(` Error: Failed to import ${filePath}`));
|
|
3191
|
+
console.error(chalk4.gray(` ${err instanceof Error ? err.message : String(err)}`));
|
|
3192
|
+
process.exit(1);
|
|
3193
|
+
}
|
|
3194
|
+
if (!specModule?.entries || !Array.isArray(specModule.entries)) {
|
|
3195
|
+
console.error(chalk4.red(" Error: File does not export a valid SpecModule (missing entries array)"));
|
|
3196
|
+
console.error(chalk4.gray(" The file must export a SpecModule via defineSpecs()"));
|
|
3197
|
+
process.exit(1);
|
|
3198
|
+
}
|
|
3199
|
+
const yamlData = specModule.entries.length === 1 ? { model: specModule.entries[0].model.id, specs: specModule.entries[0].data } : { entries: specModule.entries.map((e) => ({ model: e.model.id, specs: e.data })) };
|
|
3200
|
+
const yamlString = stringify(yamlData, {
|
|
3201
|
+
lineWidth: 120,
|
|
3202
|
+
defaultStringType: "PLAIN",
|
|
3203
|
+
defaultKeyType: "PLAIN"
|
|
3204
|
+
});
|
|
3205
|
+
if (options.dryRun) {
|
|
3206
|
+
console.log(chalk4.yellow(" Dry run \u2014 showing conversion result:"));
|
|
3207
|
+
console.log("");
|
|
3208
|
+
console.log(yamlString);
|
|
3209
|
+
return;
|
|
3210
|
+
}
|
|
3211
|
+
const outputPath = options.output ? resolve(options.output) : join(dirname(filePath), basename(filePath).replace(/\.(ts|js|mjs)$/, ".yaml"));
|
|
3212
|
+
writeFileSync(outputPath, yamlString);
|
|
3213
|
+
console.log(chalk4.green(` Created: ${outputPath}`));
|
|
3214
|
+
console.log("");
|
|
3215
|
+
console.log(chalk4.gray(" Remember to update design/index.ts to use loadYamlDir() for YAML files."));
|
|
3216
|
+
}
|
|
2022
3217
|
|
|
2023
3218
|
// src/scaffold/mermaid-parser.ts
|
|
2024
3219
|
function extractMermaidBlocks(markdown) {
|
|
@@ -2549,12 +3744,27 @@ function generateModelFile(node, _incomingEdges, _outgoingEdges, _allNodes) {
|
|
|
2549
3744
|
content
|
|
2550
3745
|
};
|
|
2551
3746
|
}
|
|
2552
|
-
function generateSpecDataFile(node) {
|
|
3747
|
+
function generateSpecDataFile(node, format = "ts") {
|
|
2553
3748
|
const templateInfo = resolveModelTemplate(node.id, node.classes, node.subgraph);
|
|
2554
3749
|
const className = `${templateInfo.modelName}Model`;
|
|
2555
3750
|
const typeName = templateInfo.modelName;
|
|
2556
3751
|
const varName = toCamelCase(templateInfo.modelName) + "s";
|
|
2557
3752
|
const fileName = templateInfo.fileName;
|
|
3753
|
+
if (format === "yaml") {
|
|
3754
|
+
const content2 = `# ${templateInfo.modelName} Specifications
|
|
3755
|
+
#
|
|
3756
|
+
# Generated by speckeeper scaffold \u2014 add your specs below.
|
|
3757
|
+
model: ${templateInfo.fileName}
|
|
3758
|
+
specs:
|
|
3759
|
+
# - id: ${templateInfo.defaultIdPrefix}-001
|
|
3760
|
+
# name: "..."
|
|
3761
|
+
# description: "..."
|
|
3762
|
+
`;
|
|
3763
|
+
return {
|
|
3764
|
+
relativePath: `${fileName}.yaml`,
|
|
3765
|
+
content: content2
|
|
3766
|
+
};
|
|
3767
|
+
}
|
|
2558
3768
|
const content = `/**
|
|
2559
3769
|
* ${templateInfo.modelName} Specifications
|
|
2560
3770
|
*
|
|
@@ -2580,7 +3790,7 @@ export default defineSpecs(
|
|
|
2580
3790
|
function toCamelCase(pascalCase) {
|
|
2581
3791
|
return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
|
|
2582
3792
|
}
|
|
2583
|
-
function generateDesignIndex(speckeeperNodes) {
|
|
3793
|
+
function generateDesignIndex(speckeeperNodes, format = "ts") {
|
|
2584
3794
|
const generated = /* @__PURE__ */ new Set();
|
|
2585
3795
|
const specFiles = [];
|
|
2586
3796
|
for (const node of speckeeperNodes) {
|
|
@@ -2594,6 +3804,21 @@ function generateDesignIndex(speckeeperNodes) {
|
|
|
2594
3804
|
fileName: templateInfo.fileName
|
|
2595
3805
|
});
|
|
2596
3806
|
}
|
|
3807
|
+
if (format === "yaml") {
|
|
3808
|
+
const content2 = `/**
|
|
3809
|
+
* Design entry point \u2014 generated by speckeeper scaffold
|
|
3810
|
+
*
|
|
3811
|
+
* YAML spec files in this directory are auto-discovered by loadYamlDir().
|
|
3812
|
+
*/
|
|
3813
|
+
import { mergeSpecs, loadYamlDir } from 'speckeeper';
|
|
3814
|
+
import { allModels } from './_models';
|
|
3815
|
+
|
|
3816
|
+
const yamlSpecs = loadYamlDir(import.meta.dirname, allModels);
|
|
3817
|
+
|
|
3818
|
+
export default mergeSpecs(...yamlSpecs);
|
|
3819
|
+
`;
|
|
3820
|
+
return { relativePath: "index.ts", content: content2 };
|
|
3821
|
+
}
|
|
2597
3822
|
const imports = specFiles.map((f) => `import ${f.varName} from './${f.fileName}';`).join("\n");
|
|
2598
3823
|
const args = specFiles.map((f) => f.varName).join(", ");
|
|
2599
3824
|
const content = `/**
|
|
@@ -2609,7 +3834,7 @@ export default mergeSpecs(${args});
|
|
|
2609
3834
|
content
|
|
2610
3835
|
};
|
|
2611
3836
|
}
|
|
2612
|
-
function generateAllModelFiles(speckeeperNodes, resolvedEdges, allNodes) {
|
|
3837
|
+
function generateAllModelFiles(speckeeperNodes, resolvedEdges, allNodes, format = "ts") {
|
|
2613
3838
|
const files = [];
|
|
2614
3839
|
const generated = /* @__PURE__ */ new Set();
|
|
2615
3840
|
const templateNodeGroups = /* @__PURE__ */ new Map();
|
|
@@ -2632,9 +3857,9 @@ function generateAllModelFiles(speckeeperNodes, resolvedEdges, allNodes) {
|
|
|
2632
3857
|
resolvedEdges.filter((e) => groupNodeIds.has(e.targetId));
|
|
2633
3858
|
resolvedEdges.filter((e) => groupNodeIds.has(e.sourceId));
|
|
2634
3859
|
files.push(generateModelFile(node));
|
|
2635
|
-
files.push(generateSpecDataFile(node));
|
|
3860
|
+
files.push(generateSpecDataFile(node, format));
|
|
2636
3861
|
}
|
|
2637
|
-
files.push(generateDesignIndex(speckeeperNodes));
|
|
3862
|
+
files.push(generateDesignIndex(speckeeperNodes, format));
|
|
2638
3863
|
return files;
|
|
2639
3864
|
}
|
|
2640
3865
|
|
|
@@ -2727,7 +3952,8 @@ async function scaffoldCommand(options) {
|
|
|
2727
3952
|
);
|
|
2728
3953
|
printDiagnostics(diagnostics);
|
|
2729
3954
|
const outputDir = options.output ? resolve(options.output) : join(process.cwd(), "design");
|
|
2730
|
-
const
|
|
3955
|
+
const specFormat = options.format ?? "ts";
|
|
3956
|
+
const modelFiles = generateAllModelFiles(speckeeperNodes, resolved, flowchart.nodes, specFormat);
|
|
2731
3957
|
const indexFile = generateModelsIndex(modelFiles);
|
|
2732
3958
|
const allFiles = [...modelFiles, indexFile];
|
|
2733
3959
|
console.log("");
|
|
@@ -3330,13 +4556,13 @@ async function commandExplainImpact(opts) {
|
|
|
3330
4556
|
}
|
|
3331
4557
|
}
|
|
3332
4558
|
function readStdin() {
|
|
3333
|
-
return new Promise((
|
|
4559
|
+
return new Promise((resolve4, reject) => {
|
|
3334
4560
|
const chunks = [];
|
|
3335
4561
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
3336
|
-
process.stdin.on("end", () =>
|
|
4562
|
+
process.stdin.on("end", () => resolve4(Buffer.concat(chunks).toString("utf-8")));
|
|
3337
4563
|
process.stdin.on("error", reject);
|
|
3338
4564
|
if (process.stdin.isTTY) {
|
|
3339
|
-
|
|
4565
|
+
resolve4("");
|
|
3340
4566
|
}
|
|
3341
4567
|
});
|
|
3342
4568
|
}
|
|
@@ -3386,68 +4612,78 @@ function getVersion() {
|
|
|
3386
4612
|
return "0.0.0";
|
|
3387
4613
|
}
|
|
3388
4614
|
}
|
|
3389
|
-
var
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
});
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
4615
|
+
var handlers = {
|
|
4616
|
+
init: async (opts) => {
|
|
4617
|
+
await runInit(opts);
|
|
4618
|
+
},
|
|
4619
|
+
build: async (opts) => {
|
|
4620
|
+
await buildCommand(opts);
|
|
4621
|
+
},
|
|
4622
|
+
lint: async (opts) => {
|
|
4623
|
+
await lintCommand(opts);
|
|
4624
|
+
},
|
|
4625
|
+
drift: async (opts) => {
|
|
4626
|
+
await driftCommand(opts);
|
|
4627
|
+
},
|
|
4628
|
+
check: async (type, opts) => {
|
|
4629
|
+
await checkCommand(type, opts);
|
|
4630
|
+
},
|
|
4631
|
+
new: async (type, opts) => {
|
|
4632
|
+
await newCommand({ type, output: opts.output, dryRun: opts.dryRun });
|
|
4633
|
+
},
|
|
4634
|
+
impact: async (id, opts) => {
|
|
4635
|
+
await impactCommand(id, opts);
|
|
4636
|
+
},
|
|
4637
|
+
scaffold: async (opts) => {
|
|
4638
|
+
await scaffoldCommand(opts);
|
|
4639
|
+
},
|
|
4640
|
+
convert: async (file, opts) => {
|
|
4641
|
+
await runConvert(file, opts);
|
|
4642
|
+
},
|
|
4643
|
+
auditRequirements: async (opts) => {
|
|
4644
|
+
await commandAuditRequirements({
|
|
4645
|
+
config: opts.config,
|
|
4646
|
+
adapter: opts.adapter,
|
|
4647
|
+
model: opts.model,
|
|
4648
|
+
dryRun: opts.dryRun,
|
|
4649
|
+
failOn: opts.failOn,
|
|
4650
|
+
output: opts.output,
|
|
4651
|
+
reportFormat: opts.reportFormat
|
|
4652
|
+
});
|
|
4653
|
+
},
|
|
4654
|
+
proposeTraceLinks: async (opts) => {
|
|
4655
|
+
await commandProposeTraceLinks({
|
|
4656
|
+
config: opts.config,
|
|
4657
|
+
adapter: opts.adapter,
|
|
4658
|
+
model: opts.model,
|
|
4659
|
+
dryRun: opts.dryRun,
|
|
4660
|
+
failOn: opts.failOn,
|
|
4661
|
+
output: opts.output,
|
|
4662
|
+
reportFormat: opts.reportFormat
|
|
4663
|
+
});
|
|
4664
|
+
},
|
|
4665
|
+
explainImpact: async (opts) => {
|
|
4666
|
+
await commandExplainImpact({
|
|
4667
|
+
adapter: opts.adapter,
|
|
4668
|
+
model: opts.model,
|
|
4669
|
+
dryRun: opts.dryRun,
|
|
4670
|
+
failOn: opts.failOn,
|
|
4671
|
+
output: opts.output,
|
|
4672
|
+
reportFormat: opts.reportFormat
|
|
4673
|
+
});
|
|
4674
|
+
},
|
|
4675
|
+
proposeAcceptanceCriteria: async (specIds, opts) => {
|
|
4676
|
+
await commandProposeAcceptanceCriteria(specIds, {
|
|
4677
|
+
config: opts.config,
|
|
4678
|
+
adapter: opts.adapter,
|
|
4679
|
+
model: opts.model,
|
|
4680
|
+
dryRun: opts.dryRun,
|
|
4681
|
+
failOn: opts.failOn,
|
|
4682
|
+
output: opts.output,
|
|
4683
|
+
reportFormat: opts.reportFormat
|
|
4684
|
+
});
|
|
4685
|
+
}
|
|
4686
|
+
};
|
|
4687
|
+
createProgram(handlers, getVersion()).parse();
|
|
3452
4688
|
//# sourceMappingURL=cli.js.map
|
|
3453
4689
|
//# sourceMappingURL=cli.js.map
|