@intentius/chant 0.85.0 → 0.87.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/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +13 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +13 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/sessions.d.ts +23 -0
- package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -0
- package/dist/workspace/checks/records.d.ts +1 -0
- package/dist/workspace/checks/records.d.ts.map +1 -1
- package/dist/workspace/checks.d.ts +4 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +14 -1
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/conformance/index.d.ts +211 -0
- package/dist/workspace/conformance/index.d.ts.map +1 -0
- package/dist/workspace/conformance/vitest.d.ts +11 -0
- package/dist/workspace/conformance/vitest.d.ts.map +1 -0
- package/dist/workspace/declaration.d.ts +28 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +40 -0
- package/dist/workspace/declared-kinds.d.ts +43 -0
- package/dist/workspace/declared-kinds.d.ts.map +1 -0
- package/dist/workspace/graph-cli.d.ts +11 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/intent-cli.d.ts +2 -1
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-joins.d.ts +45 -8
- package/dist/workspace/intent-joins.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +71 -7
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/ls.d.ts +31 -1
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/reason-codes.d.ts +47 -4
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/record-sessions.d.ts +51 -0
- package/dist/workspace/record-sessions.d.ts.map +1 -0
- package/dist/workspace/record-source.d.ts +2 -0
- package/dist/workspace/record-source.d.ts.map +1 -1
- package/dist/workspace/records-cli.d.ts +71 -4
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-since.d.ts +90 -0
- package/dist/workspace/records-since.d.ts.map +1 -0
- package/dist/workspace/records-write.d.ts +171 -0
- package/dist/workspace/records-write.d.ts.map +1 -0
- package/dist/workspace/records.d.ts +244 -15
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/runtimes.d.ts +60 -0
- package/dist/workspace/runtimes.d.ts.map +1 -0
- package/dist/workspace/status-gates.d.ts +90 -0
- package/dist/workspace/status-gates.d.ts.map +1 -0
- package/dist/workspace/status.d.ts +17 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/trust/seal.d.ts +85 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -0
- package/dist/workspace/trust/ssh-commit.d.ts +7 -0
- package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
- package/dist/workspace/work.d.ts +56 -0
- package/dist/workspace/work.d.ts.map +1 -0
- package/package.json +19 -1
- package/src/cli/main.ts +55 -3
- package/src/cli/registry.ts +13 -1
- package/src/lifecycle/gate-ledger.ts +14 -0
- package/src/workspace/__fixtures__/sessions.ts +66 -0
- package/src/workspace/checks/records.ts +19 -0
- package/src/workspace/checks.test.ts +2 -0
- package/src/workspace/checks.ts +7 -1
- package/src/workspace/composites.schema.json +65 -3
- package/src/workspace/composites.test.ts +95 -5
- package/src/workspace/composites.ts +28 -7
- package/src/workspace/conformance/__fixture__/app/package.json +7 -0
- package/src/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
- package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +32 -0
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +376 -0
- package/src/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
- package/src/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
- package/src/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
- package/src/workspace/conformance/__fixture__/delivery/package.json +7 -0
- package/src/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
- package/src/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
- package/src/workspace/conformance/conformance.test.ts +149 -0
- package/src/workspace/conformance/index.mjs +31 -0
- package/src/workspace/conformance/index.ts +453 -0
- package/src/workspace/conformance/vitest.ts +62 -0
- package/src/workspace/declaration.schema.json +40 -0
- package/src/workspace/declaration.ts +62 -0
- package/src/workspace/declared-kinds.test.ts +321 -0
- package/src/workspace/declared-kinds.ts +76 -0
- package/src/workspace/graph-cli.ts +8 -0
- package/src/workspace/intent-cli.ts +29 -6
- package/src/workspace/intent-gaps.test.ts +217 -0
- package/src/workspace/intent-joins.test.ts +60 -0
- package/src/workspace/intent-joins.ts +71 -19
- package/src/workspace/intent.schema.json +304 -7
- package/src/workspace/intent.test.ts +99 -0
- package/src/workspace/intent.ts +365 -46
- package/src/workspace/ls.schema.json +34 -0
- package/src/workspace/ls.ts +69 -4
- package/src/workspace/read-contract.test.ts +30 -9
- package/src/workspace/reason-codes.test.ts +16 -4
- package/src/workspace/reason-codes.ts +55 -4
- package/src/workspace/record-assets.test.ts +3 -1
- package/src/workspace/record-sessions.ts +105 -0
- package/src/workspace/record-source.ts +14 -5
- package/src/workspace/records-amend.schema.json +167 -0
- package/src/workspace/records-cli.ts +308 -19
- package/src/workspace/records-contract.test.ts +57 -2
- package/src/workspace/records-formats.test.ts +640 -0
- package/src/workspace/records-new.schema.json +158 -0
- package/src/workspace/records-quorum.test.ts +196 -0
- package/src/workspace/records-review.schema.json +227 -0
- package/src/workspace/records-sessions.test.ts +108 -0
- package/src/workspace/records-since.schema.json +193 -0
- package/src/workspace/records-since.test.ts +174 -0
- package/src/workspace/records-since.ts +259 -0
- package/src/workspace/records-write-contract.test.ts +125 -0
- package/src/workspace/records-write.test.ts +373 -0
- package/src/workspace/records-write.ts +765 -0
- package/src/workspace/records.schema.json +202 -9
- package/src/workspace/records.ts +700 -41
- package/src/workspace/runtimes.ts +107 -0
- package/src/workspace/status-contract.test.ts +163 -0
- package/src/workspace/status-gates.ts +215 -0
- package/src/workspace/status.schema.json +69 -3
- package/src/workspace/status.ts +35 -2
- package/src/workspace/trust/seal.test.ts +232 -0
- package/src/workspace/trust/seal.ts +195 -0
- package/src/workspace/trust/ssh-commit.ts +2 -2
- package/src/workspace/work.test.ts +390 -0
- package/src/workspace/work.ts +163 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://intentius.io/chant/schemas/workspace/intent/v1/intent.schema.json",
|
|
4
4
|
"title": "chant workspace graph --intent output",
|
|
5
|
-
"description": "What `chant workspace graph --intent <region> --json` prints: the intent graph over one region of a workspace (#2651, #2650 section C1, #2524 D8 and D15). The region, the commits that touched it, the decisions whose constrains cover it and their supersession chains, the artifacts those decisions pin, the units, contracts and evidence a plugin joins to the commits, the member links of the region's member, and findings as nodes with closed codes. chant emits it and a reader such as hud draws it. Readers ignore fields and node or edge kinds they do not know; a field is only ever added within a version. The finding, reason and error codes are closed lists. Contract version 1 is written by chant 0.81.0 and newer, and this document was added to it by #2651; a chant without --intent refuses the flag. Every code is in the one closed list of `reason-codes.ts`.",
|
|
5
|
+
"description": "What `chant workspace graph --intent <region> --json` prints: the intent graph over one region of a workspace (#2651, #2650 section C1, #2524 D8 and D15). The region, the commits that touched it, the decisions whose constrains cover it and their supersession chains, the work items whose constrains cover it (#2683), the artifacts those decisions pin, the units, contracts and evidence a plugin joins to the commits, the member links of the region's member, and findings as nodes with closed codes. chant emits it and a reader such as hud draws it. Readers ignore fields and node or edge kinds they do not know; a field is only ever added within a version. The finding, reason and error codes are closed lists. Contract version 1 is written by chant 0.81.0 and newer, and this document was added to it by #2651; a chant without --intent refuses the flag. Every code is in the one closed list of `reason-codes.ts`.",
|
|
6
6
|
"oneOf": [
|
|
7
7
|
{
|
|
8
8
|
"$ref": "#/$defs/result"
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
},
|
|
117
117
|
"name": {
|
|
118
118
|
"type": "string",
|
|
119
|
-
"description": "The kind's name: the record kind's name, or the file's name without .kind.mjs for a plugin with no records. A plugin's findings use it as their namespace, plugin:<name>:<code> (#2656). Added within version 1, so an older document may lack it."
|
|
119
|
+
"description": "The kind's name: the file's commitJoinsName export when it has one (#2663), else the record kind's name, or the file's name without .kind.mjs for a plugin with no records. A plugin's findings use it as their namespace, plugin:<name>:<code> (#2656). Added within version 1, so an older document may lack it."
|
|
120
120
|
},
|
|
121
121
|
"records": {
|
|
122
122
|
"type": [
|
|
@@ -126,6 +126,7 @@
|
|
|
126
126
|
"description": "The record kind's name, or null for a plugin with no records."
|
|
127
127
|
},
|
|
128
128
|
"joins": {
|
|
129
|
+
"description": "The form of the file's commitJoins export: a function commitJoins(commit, context), whose context has read(path) for a file and list(dir) for a directory's entries, both from the workspace root in the tree read (#2663); data, naming the trailers and record paths core reads, with every value of the evidence trailer read; or null when it has none.",
|
|
129
130
|
"enum": [
|
|
130
131
|
"function",
|
|
131
132
|
"data",
|
|
@@ -204,6 +205,9 @@
|
|
|
204
205
|
{
|
|
205
206
|
"$ref": "#/$defs/decision"
|
|
206
207
|
},
|
|
208
|
+
{
|
|
209
|
+
"$ref": "#/$defs/work"
|
|
210
|
+
},
|
|
207
211
|
{
|
|
208
212
|
"$ref": "#/$defs/artifact"
|
|
209
213
|
},
|
|
@@ -713,6 +717,240 @@
|
|
|
713
717
|
}
|
|
714
718
|
}
|
|
715
719
|
},
|
|
720
|
+
"work": {
|
|
721
|
+
"description": "A work item (#2683), a record of a kind with a work block: in the graph when its constrains cover the region as a decision's would, or when a work item there implements, needs or addresses it. Read only when a work kind is passed with --kind.",
|
|
722
|
+
"type": "object",
|
|
723
|
+
"required": [
|
|
724
|
+
"id",
|
|
725
|
+
"kind",
|
|
726
|
+
"recordKind",
|
|
727
|
+
"record",
|
|
728
|
+
"path",
|
|
729
|
+
"title",
|
|
730
|
+
"state",
|
|
731
|
+
"closed",
|
|
732
|
+
"valid",
|
|
733
|
+
"reasons",
|
|
734
|
+
"provenance",
|
|
735
|
+
"owner",
|
|
736
|
+
"ready",
|
|
737
|
+
"blockedBy",
|
|
738
|
+
"implements",
|
|
739
|
+
"needs",
|
|
740
|
+
"source",
|
|
741
|
+
"supersededBy",
|
|
742
|
+
"constrains",
|
|
743
|
+
"warnings"
|
|
744
|
+
],
|
|
745
|
+
"properties": {
|
|
746
|
+
"id": {
|
|
747
|
+
"type": "string",
|
|
748
|
+
"pattern": "^record:"
|
|
749
|
+
},
|
|
750
|
+
"kind": {
|
|
751
|
+
"const": "work"
|
|
752
|
+
},
|
|
753
|
+
"recordKind": {
|
|
754
|
+
"type": "string"
|
|
755
|
+
},
|
|
756
|
+
"record": {
|
|
757
|
+
"type": "string"
|
|
758
|
+
},
|
|
759
|
+
"path": {
|
|
760
|
+
"type": "string",
|
|
761
|
+
"description": "The record file, from the repository root."
|
|
762
|
+
},
|
|
763
|
+
"title": {
|
|
764
|
+
"type": [
|
|
765
|
+
"string",
|
|
766
|
+
"null"
|
|
767
|
+
]
|
|
768
|
+
},
|
|
769
|
+
"state": {
|
|
770
|
+
"type": [
|
|
771
|
+
"string",
|
|
772
|
+
"null"
|
|
773
|
+
]
|
|
774
|
+
},
|
|
775
|
+
"closed": {
|
|
776
|
+
"type": "boolean",
|
|
777
|
+
"description": "Whether the kind counts the state as closed, such as done or dropped."
|
|
778
|
+
},
|
|
779
|
+
"valid": {
|
|
780
|
+
"type": "boolean"
|
|
781
|
+
},
|
|
782
|
+
"reasons": {
|
|
783
|
+
"type": "array",
|
|
784
|
+
"items": {
|
|
785
|
+
"type": "object",
|
|
786
|
+
"required": [
|
|
787
|
+
"code",
|
|
788
|
+
"message"
|
|
789
|
+
],
|
|
790
|
+
"properties": {
|
|
791
|
+
"code": {
|
|
792
|
+
"enum": [
|
|
793
|
+
"record-unparseable",
|
|
794
|
+
"record-schema-invalid",
|
|
795
|
+
"record-id-duplicate",
|
|
796
|
+
"record-supersedes-unknown",
|
|
797
|
+
"record-supersedes-conflict"
|
|
798
|
+
]
|
|
799
|
+
},
|
|
800
|
+
"message": {
|
|
801
|
+
"type": "string"
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
},
|
|
806
|
+
"provenance": {
|
|
807
|
+
"type": "object",
|
|
808
|
+
"required": [
|
|
809
|
+
"level",
|
|
810
|
+
"commit",
|
|
811
|
+
"reason"
|
|
812
|
+
],
|
|
813
|
+
"properties": {
|
|
814
|
+
"level": {
|
|
815
|
+
"enum": [
|
|
816
|
+
"attested",
|
|
817
|
+
"attested-unverifiable-here",
|
|
818
|
+
"adopted",
|
|
819
|
+
"unattested"
|
|
820
|
+
]
|
|
821
|
+
},
|
|
822
|
+
"commit": {
|
|
823
|
+
"type": [
|
|
824
|
+
"string",
|
|
825
|
+
"null"
|
|
826
|
+
],
|
|
827
|
+
"pattern": "^[0-9a-f]{40,64}$"
|
|
828
|
+
},
|
|
829
|
+
"reason": {
|
|
830
|
+
"type": "string"
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
"owner": {
|
|
835
|
+
"type": [
|
|
836
|
+
"string",
|
|
837
|
+
"null"
|
|
838
|
+
],
|
|
839
|
+
"description": "The principal the record names as its owner, or null."
|
|
840
|
+
},
|
|
841
|
+
"ready": {
|
|
842
|
+
"type": "boolean",
|
|
843
|
+
"description": "As records reports it: valid, not superseded, in the kind's open state, and every need done."
|
|
844
|
+
},
|
|
845
|
+
"blockedBy": {
|
|
846
|
+
"type": "array",
|
|
847
|
+
"items": {
|
|
848
|
+
"$ref": "#/$defs/workLink"
|
|
849
|
+
},
|
|
850
|
+
"description": "Each need that is not done, with its state."
|
|
851
|
+
},
|
|
852
|
+
"implements": {
|
|
853
|
+
"type": "array",
|
|
854
|
+
"items": {
|
|
855
|
+
"$ref": "#/$defs/workLink"
|
|
856
|
+
},
|
|
857
|
+
"description": "Each decision the item implements, with its state."
|
|
858
|
+
},
|
|
859
|
+
"needs": {
|
|
860
|
+
"type": "array",
|
|
861
|
+
"items": {
|
|
862
|
+
"type": "string"
|
|
863
|
+
},
|
|
864
|
+
"description": "The work ids the item's needs list names."
|
|
865
|
+
},
|
|
866
|
+
"source": {
|
|
867
|
+
"description": "The gap the item came from, when its source names one: a finding code, the region it fired on, and optionally the decision and artifact it concerned. Null for an item whose source is an issue or the workspace.",
|
|
868
|
+
"oneOf": [
|
|
869
|
+
{
|
|
870
|
+
"type": "null"
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
"type": "object",
|
|
874
|
+
"required": [
|
|
875
|
+
"finding",
|
|
876
|
+
"region"
|
|
877
|
+
],
|
|
878
|
+
"properties": {
|
|
879
|
+
"finding": {
|
|
880
|
+
"type": "string"
|
|
881
|
+
},
|
|
882
|
+
"region": {
|
|
883
|
+
"type": "string"
|
|
884
|
+
},
|
|
885
|
+
"decision": {
|
|
886
|
+
"type": "string"
|
|
887
|
+
},
|
|
888
|
+
"artifact": {
|
|
889
|
+
"type": "string"
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
]
|
|
894
|
+
},
|
|
895
|
+
"supersededBy": {
|
|
896
|
+
"type": [
|
|
897
|
+
"string",
|
|
898
|
+
"null"
|
|
899
|
+
]
|
|
900
|
+
},
|
|
901
|
+
"constrains": {
|
|
902
|
+
"type": "array",
|
|
903
|
+
"description": "The entries that cover the region, with their granularity, matched as a decision's are. Empty for an item in the graph only through a link.",
|
|
904
|
+
"items": {
|
|
905
|
+
"type": "object",
|
|
906
|
+
"required": [
|
|
907
|
+
"entry",
|
|
908
|
+
"granularity"
|
|
909
|
+
],
|
|
910
|
+
"properties": {
|
|
911
|
+
"entry": {
|
|
912
|
+
"type": "string"
|
|
913
|
+
},
|
|
914
|
+
"granularity": {
|
|
915
|
+
"enum": [
|
|
916
|
+
"path",
|
|
917
|
+
"member",
|
|
918
|
+
"contract",
|
|
919
|
+
"issue"
|
|
920
|
+
]
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
"warnings": {
|
|
926
|
+
"type": "array",
|
|
927
|
+
"description": "The item's work warnings as records reports them, and work-done-gap-open: the item is done and the finding in its source still fires on its region. records raises it too, by walking the source's region with this code (#2686).",
|
|
928
|
+
"items": {
|
|
929
|
+
"type": "object",
|
|
930
|
+
"required": [
|
|
931
|
+
"code",
|
|
932
|
+
"message"
|
|
933
|
+
],
|
|
934
|
+
"properties": {
|
|
935
|
+
"code": {
|
|
936
|
+
"enum": [
|
|
937
|
+
"work-needs-unknown",
|
|
938
|
+
"work-implements-unknown",
|
|
939
|
+
"work-needs-cycle",
|
|
940
|
+
"work-implements-undecided",
|
|
941
|
+
"work-done-unpinned",
|
|
942
|
+
"work-closed-without-date",
|
|
943
|
+
"work-done-gap-open"
|
|
944
|
+
]
|
|
945
|
+
},
|
|
946
|
+
"message": {
|
|
947
|
+
"type": "string"
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
},
|
|
716
954
|
"artifact": {
|
|
717
955
|
"description": "A workspace file a decision in the graph pins. Artifacts reach the region only through decisions (#2549).",
|
|
718
956
|
"type": "object",
|
|
@@ -850,14 +1088,19 @@
|
|
|
850
1088
|
"intent-commit-bare",
|
|
851
1089
|
"intent-pin-drifted",
|
|
852
1090
|
"intent-pin-missing",
|
|
1091
|
+
"intent-pin-stale",
|
|
853
1092
|
"intent-artifact-unpinned",
|
|
854
1093
|
"intent-decision-superseded-live",
|
|
855
1094
|
"intent-decision-provisional",
|
|
1095
|
+
"intent-decision-contested",
|
|
856
1096
|
"intent-constraint-coarse",
|
|
857
1097
|
"intent-constraint-lost",
|
|
858
1098
|
"intent-evidence-unpinned",
|
|
859
1099
|
"intent-trailer-unverified",
|
|
860
|
-
"intent-region-unconstrained"
|
|
1100
|
+
"intent-region-unconstrained",
|
|
1101
|
+
"intent-decision-unimplemented",
|
|
1102
|
+
"intent-work-blocked",
|
|
1103
|
+
"intent-work-open-decided-code"
|
|
861
1104
|
]
|
|
862
1105
|
},
|
|
863
1106
|
{
|
|
@@ -887,11 +1130,42 @@
|
|
|
887
1130
|
"type": "string"
|
|
888
1131
|
},
|
|
889
1132
|
"description": "For a plugin's finding: the refs as the plugin gave them. Those that name a node in the graph are resolved to its id in concerns, after the commit the finding was returned for."
|
|
1133
|
+
},
|
|
1134
|
+
"openConcerns": {
|
|
1135
|
+
"type": "object",
|
|
1136
|
+
"description": "Added by #2686, on intent-decision-contested only: how many open concerns the decision's quorum reports, dissents neither addressed nor withdrawn, and the principals who raised them, normalised as the quorum compares them.",
|
|
1137
|
+
"required": [
|
|
1138
|
+
"count",
|
|
1139
|
+
"principals"
|
|
1140
|
+
],
|
|
1141
|
+
"properties": {
|
|
1142
|
+
"count": {
|
|
1143
|
+
"type": "integer",
|
|
1144
|
+
"minimum": 1
|
|
1145
|
+
},
|
|
1146
|
+
"principals": {
|
|
1147
|
+
"type": "array",
|
|
1148
|
+
"items": {
|
|
1149
|
+
"type": "string"
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
"addressed": {
|
|
1155
|
+
"type": "boolean",
|
|
1156
|
+
"description": "Added by #2683, present when a work kind was read: whether a work item addresses the finding, because the item's source names this finding code on a region that contains or is contained by this one, or because the item implements a decision the finding concerns. A finding with addressed false is work nobody has taken yet."
|
|
1157
|
+
},
|
|
1158
|
+
"addressedBy": {
|
|
1159
|
+
"type": "array",
|
|
1160
|
+
"items": {
|
|
1161
|
+
"$ref": "#/$defs/workLink"
|
|
1162
|
+
},
|
|
1163
|
+
"description": "Added by #2683, present when a work kind was read: the work items addressing the finding, each with its state. Each has an addressed-by edge from the finding."
|
|
890
1164
|
}
|
|
891
1165
|
}
|
|
892
1166
|
},
|
|
893
1167
|
"edge": {
|
|
894
|
-
"description": "constrains: decision to region, file or contract. pins: decision to artifact. touched-by: region to commit. produced-by: commit to unit. serves: unit to contract. supersedes: the newer decision to the one it replaces. cites-evidence: unit, contract or decision to evidence. links: consumer member to producer member. within: commit to a decision whose path window it falls in.",
|
|
1168
|
+
"description": "constrains: decision or work item to region, file or contract. pins: decision to artifact. touched-by: region to commit. produced-by: commit to unit. serves: unit to contract. supersedes: the newer decision to the one it replaces. cites-evidence: unit, contract or decision to evidence. links: consumer member to producer member. within: commit to a decision whose path window it falls in, or to a work item whose window it falls in. implements: work item to the decision it carries out. needs: work item to a work item it waits on. addressed-by: finding to a work item that addresses it.",
|
|
895
1169
|
"oneOf": [
|
|
896
1170
|
{
|
|
897
1171
|
"$ref": "#/$defs/constrainsEdge"
|
|
@@ -1105,13 +1379,16 @@
|
|
|
1105
1379
|
"serves",
|
|
1106
1380
|
"supersedes",
|
|
1107
1381
|
"cites-evidence",
|
|
1108
|
-
"links"
|
|
1382
|
+
"links",
|
|
1383
|
+
"implements",
|
|
1384
|
+
"needs",
|
|
1385
|
+
"addressed-by"
|
|
1109
1386
|
]
|
|
1110
1387
|
}
|
|
1111
1388
|
}
|
|
1112
1389
|
},
|
|
1113
1390
|
"withinEdge": {
|
|
1114
|
-
"description": "A commit made inside a decision's window, from the commit that added the decision's record until the one that added its successor (#2656). state is decided when the decision's own unit made the commit, and decided-by-window otherwise.",
|
|
1391
|
+
"description": "A commit made inside a decision's window, from the commit that added the decision's record until the one that added its successor (#2656). state is decided when the decision's own unit made the commit, and decided-by-window otherwise. Added by #2683: a commit made inside a work item's window, from the commit that added the record to the commit that closed it, that commit included, or to the revision read while it is open, has state worked. A worked edge leaves the commit's own state as the decisions set it.",
|
|
1115
1392
|
"type": "object",
|
|
1116
1393
|
"required": [
|
|
1117
1394
|
"kind",
|
|
@@ -1132,10 +1409,30 @@
|
|
|
1132
1409
|
"state": {
|
|
1133
1410
|
"enum": [
|
|
1134
1411
|
"decided",
|
|
1135
|
-
"decided-by-window"
|
|
1412
|
+
"decided-by-window",
|
|
1413
|
+
"worked"
|
|
1136
1414
|
]
|
|
1137
1415
|
}
|
|
1138
1416
|
}
|
|
1417
|
+
},
|
|
1418
|
+
"workLink": {
|
|
1419
|
+
"type": "object",
|
|
1420
|
+
"required": [
|
|
1421
|
+
"id",
|
|
1422
|
+
"state"
|
|
1423
|
+
],
|
|
1424
|
+
"properties": {
|
|
1425
|
+
"id": {
|
|
1426
|
+
"type": "string"
|
|
1427
|
+
},
|
|
1428
|
+
"state": {
|
|
1429
|
+
"type": [
|
|
1430
|
+
"string",
|
|
1431
|
+
"null"
|
|
1432
|
+
],
|
|
1433
|
+
"description": "The linked record's state, or null when no record has the id."
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1139
1436
|
}
|
|
1140
1437
|
}
|
|
1141
1438
|
}
|
|
@@ -443,6 +443,8 @@ describe("findings the fixture does not raise (#2651)", () => {
|
|
|
443
443
|
expect(findings(doc).map(([c]) => c)).toEqual([
|
|
444
444
|
"intent-commit-undecided",
|
|
445
445
|
"intent-commit-bare",
|
|
446
|
+
// dec-002 supersedes dec-001 and pins the spec at the hash dec-001 pinned, unchanged since (#2686).
|
|
447
|
+
"intent-pin-stale",
|
|
446
448
|
"intent-decision-provisional",
|
|
447
449
|
"intent-constraint-coarse",
|
|
448
450
|
"intent-constraint-lost",
|
|
@@ -564,3 +566,100 @@ describe("reads that fail, and parts that can't be read (#2651)", () => {
|
|
|
564
566
|
expect(parseRegion("a/b.ts:0")).toHaveProperty("error");
|
|
565
567
|
});
|
|
566
568
|
});
|
|
569
|
+
|
|
570
|
+
describe("commitJoins lists records and names its findings (#2663)", () => {
|
|
571
|
+
test("a plugin joins commits by listing its records, with no trailer at all (#2663)", async () => {
|
|
572
|
+
const SCAN = `
|
|
573
|
+
export function commitJoins(commit, context) {
|
|
574
|
+
const walk = (dir) => (context.list(dir) ?? []).flatMap((p) => (p.endsWith("/") ? walk(p) : [p]));
|
|
575
|
+
for (const path of walk("unit-records")) {
|
|
576
|
+
const id = path.split("/").at(-1).replace(/\\.(json|md)$/, "");
|
|
577
|
+
const text = context.read(path);
|
|
578
|
+
if (path.endsWith(".json")) {
|
|
579
|
+
const record = JSON.parse(text);
|
|
580
|
+
if (record.result?.commit !== commit.sha) continue;
|
|
581
|
+
const probe = { missing: context.list("nope"), escape: context.list(".."), file: context.list(path), root: context.list(".").includes("unit-records/") };
|
|
582
|
+
return { unit: { id, path, probe }, contract: { id: record.contract } };
|
|
583
|
+
}
|
|
584
|
+
if (text.includes(commit.sha)) return { unit: { id, path } };
|
|
585
|
+
}
|
|
586
|
+
return undefined;
|
|
587
|
+
}
|
|
588
|
+
`;
|
|
589
|
+
writeFiles(root, {
|
|
590
|
+
"plugins/scan.kind.mjs": SCAN,
|
|
591
|
+
"unit-records/U-0100.json": JSON.stringify({ contract: "C-100", result: { commit: sha.c2 } }),
|
|
592
|
+
"unit-records/archive/U-0104.md": `---\nid: U-0104\n---\n\nLanded as ${sha.c4}.\n`,
|
|
593
|
+
});
|
|
594
|
+
commit(["record the units after their commits"]);
|
|
595
|
+
try {
|
|
596
|
+
const doc = await walk("app/server.mjs", { kinds: [KIND, "plugins/scan.kind.mjs"] });
|
|
597
|
+
// c4 carries no trailer; the markdown record in a subdirectory names it.
|
|
598
|
+
expect(node(doc, `commit:${sha.c4}`)).toMatchObject({ trailers: {} });
|
|
599
|
+
expect(doc.edges).toContainEqual({ kind: "produced-by", from: `commit:${sha.c4}`, to: "unit:U-0104" });
|
|
600
|
+
expect(node(doc, "unit:U-0104")).toMatchObject({ data: { path: "unit-records/archive/U-0104.md" } });
|
|
601
|
+
expect(doc.edges).toContainEqual({ kind: "produced-by", from: `commit:${sha.c2}`, to: "unit:U-0100" });
|
|
602
|
+
expect(doc.edges).toContainEqual({ kind: "serves", from: "unit:U-0100", to: "contract:C-100" });
|
|
603
|
+
expect(node(doc, "unit:U-0100")).toMatchObject({ data: { path: "unit-records/U-0100.json", probe: { root: true } } });
|
|
604
|
+
// Not a directory there, or outside the workspace: undefined.
|
|
605
|
+
expect((node(doc, "unit:U-0100") as { data: unknown }).data).toMatchObject({ probe: { missing: undefined, escape: undefined, file: undefined, root: true } });
|
|
606
|
+
expect(node(doc, `commit:${sha.c2b}`) && doc.edges.some((e) => e.kind === "produced-by" && e.from === `commit:${sha.c2b}`)).toBe(false);
|
|
607
|
+
expect(doc.reasons).toEqual([]);
|
|
608
|
+
|
|
609
|
+
// At c4 the records were not written yet: list answers from the tree read, so nothing joins.
|
|
610
|
+
const before = await walk("app/server.mjs", { kinds: [KIND, "plugins/scan.kind.mjs"], at: sha.c4 });
|
|
611
|
+
expect(before.nodes.filter((n) => n.kind === "unit")).toEqual([]);
|
|
612
|
+
expect(before.reasons).toEqual([]);
|
|
613
|
+
} finally {
|
|
614
|
+
git(root, "reset", "-q", "--hard", sha.c4);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
test("commitJoinsName names a plugin's findings apart from its record kind's name (#2663)", async () => {
|
|
619
|
+
const NAMED = (name: string) => `
|
|
620
|
+
export { recordKind } from "./decision.kind.mjs";
|
|
621
|
+
export const commitJoinsName = ${JSON.stringify(name)};
|
|
622
|
+
export function commitJoins(commit) {
|
|
623
|
+
if (commit.trailers["Unit"]?.[0] !== "U-0002") return undefined;
|
|
624
|
+
return { findings: [{ code: "plugin:studio:contract-moved", message: "moved", refs: [commit.sha] }] };
|
|
625
|
+
}
|
|
626
|
+
`;
|
|
627
|
+
writeFiles(root, { "decisions/studio.kind.mjs": NAMED("studio"), "decisions/other.kind.mjs": NAMED("other") });
|
|
628
|
+
commit(["name the findings"]);
|
|
629
|
+
try {
|
|
630
|
+
const doc = await walk("app/server.mjs", { kinds: ["decisions/studio.kind.mjs"] });
|
|
631
|
+
expect(doc.kinds).toEqual([{ file: "decisions/studio.kind.mjs", name: "studio", records: "decision", joins: "function" }]);
|
|
632
|
+
expect(doc.reasons).toEqual([]);
|
|
633
|
+
expect(doc.nodes).toContainEqual(expect.objectContaining({ kind: "finding", code: "plugin:studio:contract-moved", concerns: [`commit:${sha.c2b}`] }));
|
|
634
|
+
// The decisions still come from the record kind called decision.
|
|
635
|
+
expect(node(doc, "record:decision/dec-001")).toBeDefined();
|
|
636
|
+
|
|
637
|
+
// Under another name, the same code is outside the namespace, and the record kind's name is no longer it either.
|
|
638
|
+
const { doc: other, failed } = await intentGraph({ cwd: root, region: "app/server.mjs", kinds: [join(root, "decisions/other.kind.mjs")] });
|
|
639
|
+
expectValid(other);
|
|
640
|
+
if ("error" in other) throw new Error(other.error.message);
|
|
641
|
+
expect(failed).toBe(true);
|
|
642
|
+
expect(other.reasons).toEqual([{ code: "intent-plugin-failed", message: expect.stringContaining("plugin:other:<code>") }]);
|
|
643
|
+
} finally {
|
|
644
|
+
git(root, "reset", "-q", "--hard", sha.c4);
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
test("a malformed commitJoinsName is kind-invalid (#2663)", async () => {
|
|
649
|
+
writeFiles(root, { "plugins/badname.kind.mjs": `export const commitJoinsName = "a:b";\nexport function commitJoins() {}\n`, "plugins/nameonly.kind.mjs": `export const commitJoinsName = "x";\n` });
|
|
650
|
+
commit(["malformed names"]);
|
|
651
|
+
try {
|
|
652
|
+
for (const [file, text] of [
|
|
653
|
+
["plugins/badname.kind.mjs", "no colon or space"],
|
|
654
|
+
["plugins/nameonly.kind.mjs", "no commitJoins"],
|
|
655
|
+
]) {
|
|
656
|
+
const { doc } = await intentGraph({ cwd: root, region: "app/server.mjs", kinds: [join(root, file)] });
|
|
657
|
+
expectValid(doc);
|
|
658
|
+
expect("error" in doc && doc.error.code).toBe("kind-invalid");
|
|
659
|
+
expect("error" in doc && doc.error.message).toContain(text);
|
|
660
|
+
}
|
|
661
|
+
} finally {
|
|
662
|
+
git(root, "reset", "-q", "--hard", sha.c4);
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
});
|