@suss/intent-ir 0.33.1 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,98 +1,21 @@
1
1
  import { z } from 'zod';
2
2
  import { EffectRelation, BoundaryBinding, TypeShape } from '@suss/ir-core';
3
+ export { TEST_TITLE_SEPARATOR } from '@suss/ir-core';
3
4
 
4
- declare const IntentFindingKindSchema: z.ZodEnum<{
5
- uncoveredOutcome: "uncoveredOutcome";
6
- unimplementedBoundary: "unimplementedBoundary";
7
- outcomeShapeMismatch: "outcomeShapeMismatch";
8
- undeclaredOutcome: "undeclaredOutcome";
9
- unkeyableBoundary: "unkeyableBoundary";
10
- renamedBoundary: "renamedBoundary";
11
- unreadInputField: "unreadInputField";
12
- undeclaredInputRead: "undeclaredInputRead";
13
- unlinkedScenario: "unlinkedScenario";
14
- danglingScenarioLink: "danglingScenarioLink";
15
- ambiguousScenarioLink: "ambiguousScenarioLink";
16
- undescribedOutcome: "undescribedOutcome";
17
- }>;
18
- type IntentFindingKind = z.infer<typeof IntentFindingKindSchema>;
19
- declare const IntentFindingSeveritySchema: z.ZodEnum<{
20
- error: "error";
21
- warning: "warning";
22
- info: "info";
23
- }>;
24
- type IntentFindingSeverity = z.infer<typeof IntentFindingSeveritySchema>;
25
- /** Which intent (and, when relevant, which outcome) a finding concerns. */
26
- declare const IntentRefSchema: z.ZodObject<{
27
- name: z.ZodString;
28
- outcomeId: z.ZodOptional<z.ZodString>;
29
- }, z.core.$strip>;
30
- type IntentRef = z.infer<typeof IntentRefSchema>;
31
5
  /**
32
- * Suppression annotation stamped by the .sussignore pipeline. Kept
33
- * structurally identical to the behavioural `Finding.suppressed` shape
34
- * so @suss/ir-core's shared suppression pipeline operates on both.
6
+ * The intent file format a team writes, or `suss infer` drafts. There
7
+ * are two top-level forms, told apart by `kind`:
8
+ *
9
+ * kind: boundary system intent: what one boundary should do, as
10
+ * outcomes named by id.
11
+ * kind: prd outcome intent: human scenarios (when / expect)
12
+ * that refer to system-intent outcomes by id.
13
+ *
14
+ * Boundaries reuse @suss/ir-core's vocabulary, so intent and behavior
15
+ * describe a boundary the same way. A transition says how it ends and
16
+ * what it did, as DESIGN.md explains. `intentDocToSummary` normalizes a
17
+ * document into the form the checker compares against code.
35
18
  */
36
- declare const IntentFindingSuppressionSchema: z.ZodObject<{
37
- reason: z.ZodString;
38
- effect: z.ZodEnum<{
39
- mark: "mark";
40
- downgrade: "downgrade";
41
- hide: "hide";
42
- }>;
43
- originalSeverity: z.ZodOptional<z.ZodEnum<{
44
- error: "error";
45
- warning: "warning";
46
- info: "info";
47
- }>>;
48
- }, z.core.$strip>;
49
- type IntentFindingSuppression = z.infer<typeof IntentFindingSuppressionSchema>;
50
- declare const IntentFindingSchema: z.ZodObject<{
51
- kind: z.ZodEnum<{
52
- uncoveredOutcome: "uncoveredOutcome";
53
- unimplementedBoundary: "unimplementedBoundary";
54
- outcomeShapeMismatch: "outcomeShapeMismatch";
55
- undeclaredOutcome: "undeclaredOutcome";
56
- unkeyableBoundary: "unkeyableBoundary";
57
- renamedBoundary: "renamedBoundary";
58
- unreadInputField: "unreadInputField";
59
- undeclaredInputRead: "undeclaredInputRead";
60
- unlinkedScenario: "unlinkedScenario";
61
- danglingScenarioLink: "danglingScenarioLink";
62
- ambiguousScenarioLink: "ambiguousScenarioLink";
63
- undescribedOutcome: "undescribedOutcome";
64
- }>;
65
- severity: z.ZodEnum<{
66
- error: "error";
67
- warning: "warning";
68
- info: "info";
69
- }>;
70
- boundary: z.ZodString;
71
- intent: z.ZodObject<{
72
- name: z.ZodString;
73
- outcomeId: z.ZodOptional<z.ZodString>;
74
- }, z.core.$strip>;
75
- code: z.ZodOptional<z.ZodString>;
76
- scenario: z.ZodOptional<z.ZodObject<{
77
- title: z.ZodOptional<z.ZodString>;
78
- link: z.ZodOptional<z.ZodString>;
79
- }, z.core.$strip>>;
80
- message: z.ZodString;
81
- suppressed: z.ZodOptional<z.ZodObject<{
82
- reason: z.ZodString;
83
- effect: z.ZodEnum<{
84
- mark: "mark";
85
- downgrade: "downgrade";
86
- hide: "hide";
87
- }>;
88
- originalSeverity: z.ZodOptional<z.ZodEnum<{
89
- error: "error";
90
- warning: "warning";
91
- info: "info";
92
- }>>;
93
- }, z.core.$strip>>;
94
- }, z.core.$strip>;
95
- type IntentFinding = z.infer<typeof IntentFindingSchema>;
96
19
 
97
20
  declare const IntentSourceSchema: z.ZodDefault<z.ZodEnum<{
98
21
  author: "author";
@@ -110,18 +33,25 @@ declare const IntentSourceSchema: z.ZodDefault<z.ZodEnum<{
110
33
  */
111
34
  declare function blanksLeftEmpty(doc: unknown, failedFields: string[]): string[];
112
35
  /**
113
- * The same draft with a placeholder written into each blank, so a
114
- * reader after the parts a draft does state can validate it and have
115
- * them. Nothing that fills the blanks this way should show them to
116
- * anybody: the words are suss's, not the team's.
36
+ * The same draft with a placeholder in each blank, so a reader that
37
+ * wants the parts a draft does state can validate it and get them. Code
38
+ * that fills blanks this way must not show the placeholders to anybody,
39
+ * since those words come from suss and not from the team.
117
40
  */
118
41
  declare function fillBlanks(doc: unknown, blanks: string[]): unknown;
119
- interface AuthoredShape {
42
+ type AuthoredShape = {
120
43
  type: z.infer<typeof PrimitiveTypeName> | "array" | "object";
121
44
  items?: AuthoredShape | undefined;
122
45
  properties?: Record<string, AuthoredShape> | undefined;
123
46
  required?: string[] | undefined;
124
- }
47
+ } | {
48
+ const: AuthoredConstant;
49
+ } | {
50
+ properties: Record<string, AuthoredShape>;
51
+ required?: string[] | undefined;
52
+ };
53
+ /** A literal a value has to equal, such as a finding kind or a flag that is always true. */
54
+ type AuthoredConstant = string | number | boolean | null;
125
55
  declare const BodyShapeSchema: z.ZodUnion<readonly [z.ZodType<AuthoredShape, unknown, z.core.$ZodTypeInternals<AuthoredShape, unknown>>, z.ZodObject<{
126
56
  properties: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<AuthoredShape, unknown, z.core.$ZodTypeInternals<AuthoredShape, unknown>>>>;
127
57
  required: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -434,8 +364,26 @@ type DeclaredEffect = Partial<Record<EffectRelation, string>> & {
434
364
  fields?: string[];
435
365
  /** What it picks the item out by. */
436
366
  by?: string | string[];
367
+ /** The shape of what it writes, such as the report a command prints. */
368
+ shape?: BodyShape;
369
+ /**
370
+ * Where the value of a column under `fields` or `by` comes from, by
371
+ * column: `{ tenant_id: input.headers.x-tenant-id }`. Only a `results`
372
+ * line takes it.
373
+ */
374
+ from?: Record<string, string>;
437
375
  };
376
+ /** What a source written in `from` starts with. */
377
+ declare const INPUT_SOURCE_PREFIX = "input.";
378
+ /** An effect as a change list states one, which says nothing of sources. */
379
+ declare const EffectLineSchema: z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>;
380
+ /** A `results` line, which can also say where a column's value comes from. */
438
381
  declare const EffectOutcomeSchema: z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>;
382
+ /** One `always` line: an effect, and the outcomes that do not have to have it. */
383
+ type DeclaredAlways = DeclaredEffect & {
384
+ except?: string[];
385
+ };
386
+ declare const AlwaysEffectSchema: z.ZodUnion<[z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>, ...z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>[]]>;
439
387
  /** One clause of a structured `when`, or the sentence for a guard that maps to none. */
440
388
  type WhenClause = string | ({
441
389
  where?: string;
@@ -465,6 +413,7 @@ declare const BoundaryTransitionSchema: z.ZodObject<{
465
413
  throws: z.ZodOptional<z.ZodPreprocess<z.ZodObject<{
466
414
  errorType: z.ZodOptional<z.ZodString>;
467
415
  }, z.core.$strip>>>;
416
+ exits: z.ZodOptional<z.ZodNumber>;
468
417
  results: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>>>;
469
418
  }, z.core.$strict>;
470
419
  declare const BoundaryIntentSchema: z.ZodObject<{
@@ -696,14 +645,18 @@ declare const BoundaryIntentSchema: z.ZodObject<{
696
645
  throws: z.ZodOptional<z.ZodPreprocess<z.ZodObject<{
697
646
  errorType: z.ZodOptional<z.ZodString>;
698
647
  }, z.core.$strip>>>;
648
+ exits: z.ZodOptional<z.ZodNumber>;
699
649
  results: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>>>;
700
650
  }, z.core.$strict>>;
651
+ always: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>, ...z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>[]]>>>;
701
652
  }, z.core.$strict>;
702
653
  declare const PrdScenarioSchema: z.ZodObject<{
703
654
  title: z.ZodOptional<z.ZodString>;
704
655
  when: z.ZodString;
705
656
  expect: z.ZodString;
706
657
  link: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
658
+ coveredBy: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
659
+ about: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
707
660
  }, z.core.$strict>;
708
661
  declare const PrdSchema: z.ZodObject<{
709
662
  kind: z.ZodLiteral<"prd">;
@@ -720,6 +673,8 @@ declare const PrdSchema: z.ZodObject<{
720
673
  when: z.ZodString;
721
674
  expect: z.ZodString;
722
675
  link: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
676
+ coveredBy: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
677
+ about: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
723
678
  }, z.core.$strict>>;
724
679
  }, z.core.$strict>;
725
680
  declare const IntentDocSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -951,8 +906,10 @@ declare const IntentDocSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
951
906
  throws: z.ZodOptional<z.ZodPreprocess<z.ZodObject<{
952
907
  errorType: z.ZodOptional<z.ZodString>;
953
908
  }, z.core.$strip>>>;
909
+ exits: z.ZodOptional<z.ZodNumber>;
954
910
  results: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>>>;
955
911
  }, z.core.$strict>>;
912
+ always: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>, ...z.ZodType<DeclaredAlways, unknown, z.core.$ZodTypeInternals<DeclaredAlways, unknown>>[]]>>>;
956
913
  }, z.core.$strict>, z.ZodObject<{
957
914
  kind: z.ZodLiteral<"prd">;
958
915
  title: z.ZodString;
@@ -968,6 +925,8 @@ declare const IntentDocSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
968
925
  when: z.ZodString;
969
926
  expect: z.ZodString;
970
927
  link: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
928
+ coveredBy: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
929
+ about: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
971
930
  }, z.core.$strict>>;
972
931
  }, z.core.$strict>], "kind">;
973
932
  type IntentDoc = z.infer<typeof IntentDocSchema>;
@@ -997,26 +956,79 @@ declare const PrimitiveTypeName: z.ZodEnum<{
997
956
  }>;
998
957
  type PrimitiveTypeName = z.infer<typeof PrimitiveTypeName>;
999
958
 
959
+ /**
960
+ * How a PRD scenario spells the test that covers it, the way the test
961
+ * runner prints it. vitest and RSpec write the file, each describe or
962
+ * context title, then the test's own title, joined with ` > `. pytest
963
+ * prints a node id, the file, any class, then the test function, joined
964
+ * with `::`. Both come apart into the same file and title path, and a
965
+ * test unit's name is that title path joined with ` > `, so one lookup
966
+ * serves every runner.
967
+ */
968
+
969
+ /** What separates the file, a class and a test function in a pytest node id. */
970
+ declare const NODE_ID_SEPARATOR = "::";
971
+ /** One `coveredBy` entry, split into the test file and its title path. */
972
+ interface CoveringTestSpelling {
973
+ /** The entry as the author wrote it. */
974
+ spelledAs: string;
975
+ /** The test file, with the workspace in front when the author wrote one. */
976
+ file: string;
977
+ /** The suite titles, outermost first, then the test's own title. Empty when the entry has none. */
978
+ titles: string[];
979
+ }
980
+ declare function toCoveringTest(spelledAs: string): CoveringTestSpelling;
981
+
982
+ /**
983
+ * The normalized intent form the checker compares against behavioral
984
+ * summaries.
985
+ *
986
+ * The authoring schema is built to be easy to write, and this form is
987
+ * built to be easy to check: boundaries as @suss/ir-core
988
+ * `BoundaryBinding`s, body shapes as `TypeShape`s, and one flat
989
+ * outcome list per boundary intent.
990
+ */
991
+
1000
992
  /**
1001
993
  * How a boundary outcome ends. `effect` is an outcome that declares
1002
994
  * only what it did, which is what a queue consumer or a table writer
1003
995
  * has to say instead of a status.
1004
996
  */
1005
- type IntentOutcomeKind = "response" | "return" | "throw" | "effect";
997
+ type IntentOutcomeKind = "response" | "return" | "throw" | "exit" | "effect";
1006
998
  /** One effect an outcome has, in the verbs `suss ask` asks with. */
1007
999
  interface IntentEffect {
1008
1000
  does: EffectRelation;
1009
- /** The boundary it reaches, as the author spelled it. */
1001
+ /** The boundary it reaches, as the author wrote it. */
1010
1002
  names: string;
1011
1003
  /** The columns it touches. Empty when the doc states none. */
1012
1004
  fields: string[];
1013
1005
  /** What it picks the item out by. Empty when the doc states none. */
1014
1006
  by: string[];
1007
+ /** The shape of what it writes, when the doc states one. */
1008
+ shape?: TypeShape;
1009
+ /** Where the value of each column the doc gives a source for comes from. */
1010
+ from?: IntentValueSource[];
1011
+ }
1012
+ /** Where a `results` line says one column's value comes from. */
1013
+ interface IntentValueSource {
1014
+ /** The column, one the line lists under `fields` or `by`. */
1015
+ column: string;
1016
+ /** The path off the boundary's input: `input.headers.x-tenant-id` is `["headers", "x-tenant-id"]`. */
1017
+ path: string[];
1015
1018
  }
1016
1019
  /**
1017
- * One clause of what a branch turned on. A clause whose subject is a
1018
- * boundary is the one the checker compares; the rest carry through for
1019
- * a reader.
1020
+ * An effect every transition producing a declared outcome has. A
1021
+ * `results` line is satisfied by one transition; this is satisfied only
1022
+ * when none of them lacks it.
1023
+ */
1024
+ interface IntentAlways {
1025
+ effect: IntentEffect;
1026
+ /** The outcome ids whose transitions do not have to have it. */
1027
+ except: string[];
1028
+ }
1029
+ /**
1030
+ * One clause of what a branch turned on. The checker compares a clause
1031
+ * whose subject is a boundary, and the rest are kept for a reader.
1020
1032
  */
1021
1033
  interface IntentCondition {
1022
1034
  /** The boundary the guard read, when the clause says one. */
@@ -1029,14 +1041,14 @@ interface IntentCondition {
1029
1041
  said: string;
1030
1042
  }
1031
1043
  interface IntentOutcome {
1032
- /** Author-declared id PRD scenarios reference. */
1044
+ /** The id the author gave the outcome, which PRD scenarios link to. */
1033
1045
  id: string;
1034
1046
  /** What the branch turned on, as one line, for a reader. */
1035
1047
  when: string;
1036
1048
  /** The same, clause by clause, for the checker to compare. */
1037
1049
  conditions: IntentCondition[];
1038
1050
  kind: IntentOutcomeKind;
1039
- /** Set only for `response` outcomes (REST status code). */
1051
+ /** The REST status code of a `response` outcome, or the exit code of an `exit` one. */
1040
1052
  status: number | null;
1041
1053
  /** Response / return body shape, when declared. */
1042
1054
  body: TypeShape | null;
@@ -1067,6 +1079,8 @@ interface BoundaryIntentSummary {
1067
1079
  /** Empty for a doc with no `receives` block, which states nothing about the input. */
1068
1080
  receives: IntentInputField[];
1069
1081
  outcomes: IntentOutcome[];
1082
+ /** Empty for a doc with no `always` block. */
1083
+ always: IntentAlways[];
1070
1084
  }
1071
1085
  interface PrdScenarioSummary {
1072
1086
  title: string | null;
@@ -1076,6 +1090,10 @@ interface PrdScenarioSummary {
1076
1090
  expect: string;
1077
1091
  /** Qualified outcome refs (`<intent-name>.<outcome-id>`); empty when unlinked. */
1078
1092
  link: string[];
1093
+ /** The tests the scenario lists as covering it. Empty when it lists none. */
1094
+ coveredBy: CoveringTestSpelling[];
1095
+ /** What a covering test has to reach. Empty means the PRD's linked boundaries. */
1096
+ about: string[];
1079
1097
  }
1080
1098
  interface PrdSummary {
1081
1099
  kind: "prd";
@@ -1089,5 +1107,247 @@ type IntentSummary = BoundaryIntentSummary | PrdSummary;
1089
1107
  declare function intentDocToSummary(doc: IntentDoc): IntentSummary;
1090
1108
  declare function toBoundaryBinding(boundary: Boundary): BoundaryBinding;
1091
1109
  declare function toReceives(boundary: Boundary): IntentInputField[];
1110
+ /** One `results` line, or a change list's effect, in the form the checker compares. */
1111
+ declare function toIntentEffect(declared: DeclaredEffect): IntentEffect;
1112
+
1113
+ /**
1114
+ * The change list: the behavior changes an agent says it will make for
1115
+ * one request, written before it edits anything.
1116
+ *
1117
+ * It takes the boundary intent vocabulary line by line. A subject is a
1118
+ * boundary spelled the way `suss ask` spells it, or an effect written the
1119
+ * way a `results` line is. Each entry adds one verb, `adds`, `removes` or
1120
+ * `changes`, and leaves out `when`, `purpose` and `audience`, which an
1121
+ * agent cannot know before it has written the code. `explained` lists the
1122
+ * changes the agent made without being asked and keeps, each with why.
1123
+ *
1124
+ * The CLI compares a list with two readings of the code and says which
1125
+ * entries are done, and which changes nobody asked for.
1126
+ */
1127
+
1128
+ declare const VERBS: readonly ["adds", "removes", "changes"];
1129
+ type ChangeVerb = (typeof VERBS)[number];
1130
+ declare const ChangeEntrySchema: z.ZodObject<{
1131
+ asked: z.ZodOptional<z.ZodString>;
1132
+ note: z.ZodOptional<z.ZodString>;
1133
+ adds: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1134
+ removes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1135
+ changes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1136
+ outcomes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
1137
+ returns: "returns";
1138
+ throws: "throws";
1139
+ }>, z.ZodObject<{
1140
+ throws: z.ZodString;
1141
+ }, z.core.$strict>]>>>;
1142
+ at: z.ZodOptional<z.ZodString>;
1143
+ }, z.core.$strict>;
1144
+ declare const ExplainedEntrySchema: z.ZodObject<{
1145
+ why: z.ZodString;
1146
+ adds: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1147
+ removes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1148
+ changes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1149
+ outcomes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
1150
+ returns: "returns";
1151
+ throws: "throws";
1152
+ }>, z.ZodObject<{
1153
+ throws: z.ZodString;
1154
+ }, z.core.$strict>]>>>;
1155
+ at: z.ZodOptional<z.ZodString>;
1156
+ }, z.core.$strict>;
1157
+ declare const ChangeListSchema: z.ZodObject<{
1158
+ asked: z.ZodOptional<z.ZodString>;
1159
+ changes: z.ZodDefault<z.ZodArray<z.ZodObject<{
1160
+ asked: z.ZodOptional<z.ZodString>;
1161
+ note: z.ZodOptional<z.ZodString>;
1162
+ adds: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1163
+ removes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1164
+ changes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1165
+ outcomes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
1166
+ returns: "returns";
1167
+ throws: "throws";
1168
+ }>, z.ZodObject<{
1169
+ throws: z.ZodString;
1170
+ }, z.core.$strict>]>>>;
1171
+ at: z.ZodOptional<z.ZodString>;
1172
+ }, z.core.$strict>>>;
1173
+ explained: z.ZodDefault<z.ZodArray<z.ZodObject<{
1174
+ why: z.ZodString;
1175
+ adds: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1176
+ removes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1177
+ changes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodUnion<[z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>, ...z.ZodType<DeclaredEffect, unknown, z.core.$ZodTypeInternals<DeclaredEffect, unknown>>[]]>]>>;
1178
+ outcomes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
1179
+ returns: "returns";
1180
+ throws: "throws";
1181
+ }>, z.ZodObject<{
1182
+ throws: z.ZodString;
1183
+ }, z.core.$strict>]>>>;
1184
+ at: z.ZodOptional<z.ZodString>;
1185
+ }, z.core.$strict>>>;
1186
+ }, z.core.$strict>;
1187
+ type ChangeList = z.infer<typeof ChangeListSchema>;
1188
+ type ChangeEntry = z.infer<typeof ChangeEntrySchema>;
1189
+ type ExplainedEntry = z.infer<typeof ExplainedEntrySchema>;
1190
+ /** What an entry is about: a boundary by its spelling, or an effect. */
1191
+ type ChangeSubject = {
1192
+ kind: "boundary";
1193
+ names: string;
1194
+ } | {
1195
+ kind: "effect";
1196
+ effect: IntentEffect;
1197
+ };
1198
+ /** An outcome an entry lists, in the terms the intent checker compares. */
1199
+ type ChangeOutcome = Pick<IntentOutcome, "kind" | "status" | "errorType">;
1200
+ interface IntentChange {
1201
+ verb: ChangeVerb;
1202
+ subject: ChangeSubject;
1203
+ outcomes: ChangeOutcome[];
1204
+ /** The boundary an effect happens at. Null means any boundary. */
1205
+ at: string | null;
1206
+ /** The developer's words that asked for the entry: its own quote, or else the list's. */
1207
+ asked: string | null;
1208
+ note: string | null;
1209
+ }
1210
+ interface ExplainedChange {
1211
+ verb: ChangeVerb;
1212
+ subject: ChangeSubject;
1213
+ outcomes: ChangeOutcome[];
1214
+ at: string | null;
1215
+ why: string;
1216
+ }
1217
+ interface ChangeListSummary {
1218
+ asked: string | null;
1219
+ changes: IntentChange[];
1220
+ explained: ExplainedChange[];
1221
+ }
1222
+ /** A change list, or each place where it does not fit the schema. */
1223
+ type ParsedChangeList = {
1224
+ ok: true;
1225
+ list: ChangeListSummary;
1226
+ } | {
1227
+ ok: false;
1228
+ problems: Array<{
1229
+ path: string;
1230
+ message: string;
1231
+ }>;
1232
+ };
1233
+ /** Validates a change list that is already parsed from YAML or JSON, and converts it. */
1234
+ declare function parseChangeList(raw: unknown): ParsedChangeList;
1235
+ declare function changeListToSummary(list: ChangeList): ChangeListSummary;
1236
+
1237
+ /**
1238
+ * The findings the intent checker emits.
1239
+ *
1240
+ * A behavioral `Finding` compares two peers, a provider and a consumer,
1241
+ * each with a source location. An intent finding checks coverage from
1242
+ * one side: the team declared something, and the question is whether
1243
+ * the code does it. Intent is identified by a name and an outcome id,
1244
+ * with no file or range, so an intent finding has its own fields, and
1245
+ * PRD scenario findings add to them.
1246
+ */
1247
+
1248
+ declare const IntentFindingKindSchema: z.ZodEnum<{
1249
+ uncoveredOutcome: "uncoveredOutcome";
1250
+ unimplementedBoundary: "unimplementedBoundary";
1251
+ outcomeShapeMismatch: "outcomeShapeMismatch";
1252
+ undeclaredOutcome: "undeclaredOutcome";
1253
+ unkeyableBoundary: "unkeyableBoundary";
1254
+ renamedBoundary: "renamedBoundary";
1255
+ pathWithoutEffect: "pathWithoutEffect";
1256
+ valueFromElsewhere: "valueFromElsewhere";
1257
+ unreadInputField: "unreadInputField";
1258
+ undeclaredInputRead: "undeclaredInputRead";
1259
+ unlinkedScenario: "unlinkedScenario";
1260
+ danglingScenarioLink: "danglingScenarioLink";
1261
+ ambiguousScenarioLink: "ambiguousScenarioLink";
1262
+ missingCoveringTest: "missingCoveringTest";
1263
+ testMissesSubject: "testMissesSubject";
1264
+ coveringTestSkipped: "coveringTestSkipped";
1265
+ undescribedOutcome: "undescribedOutcome";
1266
+ }>;
1267
+ type IntentFindingKind = z.infer<typeof IntentFindingKindSchema>;
1268
+ declare const IntentFindingSeveritySchema: z.ZodEnum<{
1269
+ error: "error";
1270
+ warning: "warning";
1271
+ info: "info";
1272
+ }>;
1273
+ type IntentFindingSeverity = z.infer<typeof IntentFindingSeveritySchema>;
1274
+ /** Which intent (and, when relevant, which outcome) a finding concerns. */
1275
+ declare const IntentRefSchema: z.ZodObject<{
1276
+ name: z.ZodString;
1277
+ outcomeId: z.ZodOptional<z.ZodString>;
1278
+ }, z.core.$strip>;
1279
+ type IntentRef = z.infer<typeof IntentRefSchema>;
1280
+ /**
1281
+ * The annotation the `.sussignore` pipeline adds to a matched finding.
1282
+ * It stays structurally identical to the behavioral
1283
+ * `Finding.suppressed`, so @suss/ir-core's shared suppression pipeline
1284
+ * works on both.
1285
+ */
1286
+ declare const IntentFindingSuppressionSchema: z.ZodObject<{
1287
+ reason: z.ZodString;
1288
+ effect: z.ZodEnum<{
1289
+ mark: "mark";
1290
+ downgrade: "downgrade";
1291
+ hide: "hide";
1292
+ }>;
1293
+ originalSeverity: z.ZodOptional<z.ZodEnum<{
1294
+ error: "error";
1295
+ warning: "warning";
1296
+ info: "info";
1297
+ }>>;
1298
+ }, z.core.$strip>;
1299
+ type IntentFindingSuppression = z.infer<typeof IntentFindingSuppressionSchema>;
1300
+ declare const IntentFindingSchema: z.ZodObject<{
1301
+ kind: z.ZodEnum<{
1302
+ uncoveredOutcome: "uncoveredOutcome";
1303
+ unimplementedBoundary: "unimplementedBoundary";
1304
+ outcomeShapeMismatch: "outcomeShapeMismatch";
1305
+ undeclaredOutcome: "undeclaredOutcome";
1306
+ unkeyableBoundary: "unkeyableBoundary";
1307
+ renamedBoundary: "renamedBoundary";
1308
+ pathWithoutEffect: "pathWithoutEffect";
1309
+ valueFromElsewhere: "valueFromElsewhere";
1310
+ unreadInputField: "unreadInputField";
1311
+ undeclaredInputRead: "undeclaredInputRead";
1312
+ unlinkedScenario: "unlinkedScenario";
1313
+ danglingScenarioLink: "danglingScenarioLink";
1314
+ ambiguousScenarioLink: "ambiguousScenarioLink";
1315
+ missingCoveringTest: "missingCoveringTest";
1316
+ testMissesSubject: "testMissesSubject";
1317
+ coveringTestSkipped: "coveringTestSkipped";
1318
+ undescribedOutcome: "undescribedOutcome";
1319
+ }>;
1320
+ severity: z.ZodEnum<{
1321
+ error: "error";
1322
+ warning: "warning";
1323
+ info: "info";
1324
+ }>;
1325
+ boundary: z.ZodString;
1326
+ intent: z.ZodObject<{
1327
+ name: z.ZodString;
1328
+ outcomeId: z.ZodOptional<z.ZodString>;
1329
+ }, z.core.$strip>;
1330
+ code: z.ZodOptional<z.ZodString>;
1331
+ scenario: z.ZodOptional<z.ZodObject<{
1332
+ title: z.ZodOptional<z.ZodString>;
1333
+ link: z.ZodOptional<z.ZodString>;
1334
+ coveredBy: z.ZodOptional<z.ZodString>;
1335
+ }, z.core.$strip>>;
1336
+ message: z.ZodString;
1337
+ suppressed: z.ZodOptional<z.ZodObject<{
1338
+ reason: z.ZodString;
1339
+ effect: z.ZodEnum<{
1340
+ mark: "mark";
1341
+ downgrade: "downgrade";
1342
+ hide: "hide";
1343
+ }>;
1344
+ originalSeverity: z.ZodOptional<z.ZodEnum<{
1345
+ error: "error";
1346
+ warning: "warning";
1347
+ info: "info";
1348
+ }>>;
1349
+ }, z.core.$strip>>;
1350
+ }, z.core.$strip>;
1351
+ type IntentFinding = z.infer<typeof IntentFindingSchema>;
1092
1352
 
1093
- export { ACCEPTS_NULL, type AuthoredBoundary, type AuthoredInputField, type AuthoredReceives, type AuthoredRestReceives, type AuthoredShape, type BodyShape, BodyShapeSchema, type Boundary, type BoundaryIntent, type BoundaryIntentSummary, BoundarySchema, type BoundaryTransition, type EffectOutcome, type IntentCondition, type IntentDoc, IntentDocSchema, type IntentEffect, type IntentFinding, type IntentFindingKind, IntentFindingKindSchema, IntentFindingSchema, type IntentFindingSeverity, IntentFindingSeveritySchema, type IntentFindingSuppression, IntentFindingSuppressionSchema, type IntentInputField, type IntentOutcome, type IntentOutcomeKind, type IntentRef, IntentRefSchema, type IntentSource, IntentSourceSchema, type IntentSummary, type Prd, type PrdScenario, type PrdScenarioSummary, type PrdSummary, PrimitiveTypeName, type When, type WhenClause, blanksLeftEmpty, fillBlanks, intentDocToSummary, toBoundaryBinding, toReceives };
1353
+ export { ACCEPTS_NULL, AlwaysEffectSchema, type AuthoredBoundary, type AuthoredConstant, type AuthoredInputField, type AuthoredReceives, type AuthoredRestReceives, type AuthoredShape, type BodyShape, BodyShapeSchema, type Boundary, type BoundaryIntent, type BoundaryIntentSummary, BoundarySchema, type BoundaryTransition, type ChangeEntry, type ChangeList, ChangeListSchema, type ChangeListSummary, type ChangeOutcome, type ChangeSubject, type ChangeVerb, type CoveringTestSpelling, type DeclaredAlways, type DeclaredEffect, EffectLineSchema, type EffectOutcome, EffectOutcomeSchema, type ExplainedChange, type ExplainedEntry, INPUT_SOURCE_PREFIX, type IntentAlways, type IntentChange, type IntentCondition, type IntentDoc, IntentDocSchema, type IntentEffect, type IntentFinding, type IntentFindingKind, IntentFindingKindSchema, IntentFindingSchema, type IntentFindingSeverity, IntentFindingSeveritySchema, type IntentFindingSuppression, IntentFindingSuppressionSchema, type IntentInputField, type IntentOutcome, type IntentOutcomeKind, type IntentRef, IntentRefSchema, type IntentSource, IntentSourceSchema, type IntentSummary, type IntentValueSource, NODE_ID_SEPARATOR, type ParsedChangeList, type Prd, type PrdScenario, type PrdScenarioSummary, type PrdSummary, PrimitiveTypeName, type When, type WhenClause, blanksLeftEmpty, changeListToSummary, fillBlanks, intentDocToSummary, parseChangeList, toBoundaryBinding, toCoveringTest, toIntentEffect, toReceives };