@topogram/cli 0.3.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/ARCHITECTURE.md +67 -0
  2. package/CHANGELOG.md +240 -0
  3. package/README.md +223 -0
  4. package/package.json +51 -0
  5. package/src/adoption/index.js +3 -0
  6. package/src/adoption/plan.js +702 -0
  7. package/src/adoption/reporting.js +464 -0
  8. package/src/adoption/review-groups.js +313 -0
  9. package/src/agent-ops/query-builders.js +5012 -0
  10. package/src/archive/archive.js +141 -0
  11. package/src/archive/compact.js +26 -0
  12. package/src/archive/jsonl.js +70 -0
  13. package/src/archive/resolver-bridge.js +82 -0
  14. package/src/archive/schema.js +87 -0
  15. package/src/archive/unarchive.js +108 -0
  16. package/src/catalog.js +752 -0
  17. package/src/cli/catalog-alias.js +166 -0
  18. package/src/cli.js +9738 -0
  19. package/src/component-behavior.js +173 -0
  20. package/src/example-implementation.js +91 -0
  21. package/src/format.js +19 -0
  22. package/src/generator/adapters.d.ts +4 -0
  23. package/src/generator/adapters.js +325 -0
  24. package/src/generator/api.d.ts +1 -0
  25. package/src/generator/api.js +1196 -0
  26. package/src/generator/check.js +355 -0
  27. package/src/generator/component-conformance.js +767 -0
  28. package/src/generator/components.js +39 -0
  29. package/src/generator/context/bundle.js +291 -0
  30. package/src/generator/context/diff.js +256 -0
  31. package/src/generator/context/digest.js +182 -0
  32. package/src/generator/context/domain-coverage.js +94 -0
  33. package/src/generator/context/domain-page.js +137 -0
  34. package/src/generator/context/index.js +42 -0
  35. package/src/generator/context/report.js +121 -0
  36. package/src/generator/context/shared.js +1397 -0
  37. package/src/generator/context/slice.js +703 -0
  38. package/src/generator/context/task-mode.js +466 -0
  39. package/src/generator/docs.js +327 -0
  40. package/src/generator/index.js +161 -0
  41. package/src/generator/native/parity-bundle.js +311 -0
  42. package/src/generator/output.js +300 -0
  43. package/src/generator/registry.js +482 -0
  44. package/src/generator/runtime/app-bundle.js +456 -0
  45. package/src/generator/runtime/bundle-shared.js +166 -0
  46. package/src/generator/runtime/compile-check.js +163 -0
  47. package/src/generator/runtime/deployment.js +287 -0
  48. package/src/generator/runtime/environment.js +635 -0
  49. package/src/generator/runtime/index.js +32 -0
  50. package/src/generator/runtime/runtime-check.js +554 -0
  51. package/src/generator/runtime/shared.js +515 -0
  52. package/src/generator/runtime/smoke.js +219 -0
  53. package/src/generator/schema.js +204 -0
  54. package/src/generator/sdlc/board.js +66 -0
  55. package/src/generator/sdlc/doc-page.js +53 -0
  56. package/src/generator/sdlc/index.js +23 -0
  57. package/src/generator/sdlc/release-notes.js +62 -0
  58. package/src/generator/sdlc/traceability-matrix.js +65 -0
  59. package/src/generator/shared.js +29 -0
  60. package/src/generator/surfaces/contracts.js +146 -0
  61. package/src/generator/surfaces/databases/contract.js +40 -0
  62. package/src/generator/surfaces/databases/index.js +84 -0
  63. package/src/generator/surfaces/databases/lifecycle-shared.d.ts +1 -0
  64. package/src/generator/surfaces/databases/lifecycle-shared.js +612 -0
  65. package/src/generator/surfaces/databases/migration-plan.js +281 -0
  66. package/src/generator/surfaces/databases/postgres/capabilities.js +14 -0
  67. package/src/generator/surfaces/databases/postgres/drizzle.js +99 -0
  68. package/src/generator/surfaces/databases/postgres/index.js +9 -0
  69. package/src/generator/surfaces/databases/postgres/lifecycle.js +16 -0
  70. package/src/generator/surfaces/databases/postgres/prisma.js +159 -0
  71. package/src/generator/surfaces/databases/postgres/sql-migration.js +102 -0
  72. package/src/generator/surfaces/databases/postgres/sql-schema.js +34 -0
  73. package/src/generator/surfaces/databases/shared.d.ts +1 -0
  74. package/src/generator/surfaces/databases/shared.js +350 -0
  75. package/src/generator/surfaces/databases/snapshot.js +96 -0
  76. package/src/generator/surfaces/databases/sqlite/capabilities.js +14 -0
  77. package/src/generator/surfaces/databases/sqlite/index.js +8 -0
  78. package/src/generator/surfaces/databases/sqlite/lifecycle.js +16 -0
  79. package/src/generator/surfaces/databases/sqlite/prisma.js +143 -0
  80. package/src/generator/surfaces/databases/sqlite/sql-migration.js +65 -0
  81. package/src/generator/surfaces/databases/sqlite/sql-schema.js +27 -0
  82. package/src/generator/surfaces/index.js +25 -0
  83. package/src/generator/surfaces/native/swiftui-app.js +38 -0
  84. package/src/generator/surfaces/native/swiftui-templates/Package.swift.txt +20 -0
  85. package/src/generator/surfaces/native/swiftui-templates/README.generated.md +26 -0
  86. package/src/generator/surfaces/native/swiftui-templates/runtime/DynamicScreens.swift +682 -0
  87. package/src/generator/surfaces/native/swiftui-templates/runtime/TodoAPIClient.swift +156 -0
  88. package/src/generator/surfaces/native/swiftui-templates/runtime/TodoSwiftUIApp.swift +44 -0
  89. package/src/generator/surfaces/native/swiftui-templates/runtime/Visibility.swift +183 -0
  90. package/src/generator/surfaces/services/express.d.ts +1 -0
  91. package/src/generator/surfaces/services/express.js +766 -0
  92. package/src/generator/surfaces/services/hono.d.ts +1 -0
  93. package/src/generator/surfaces/services/hono.js +204 -0
  94. package/src/generator/surfaces/services/index.js +42 -0
  95. package/src/generator/surfaces/services/persistence-wiring.js +240 -0
  96. package/src/generator/surfaces/services/runtime-helpers.js +631 -0
  97. package/src/generator/surfaces/services/server-contract.js +80 -0
  98. package/src/generator/surfaces/services/stateless.d.ts +1 -0
  99. package/src/generator/surfaces/services/stateless.js +97 -0
  100. package/src/generator/surfaces/shared.js +64 -0
  101. package/src/generator/surfaces/web/api-client.js +1 -0
  102. package/src/generator/surfaces/web/forms.js +1 -0
  103. package/src/generator/surfaces/web/index.d.ts +2 -0
  104. package/src/generator/surfaces/web/index.js +53 -0
  105. package/src/generator/surfaces/web/react-components.js +248 -0
  106. package/src/generator/surfaces/web/react.js +538 -0
  107. package/src/generator/surfaces/web/routes.js +1 -0
  108. package/src/generator/surfaces/web/screens.js +1 -0
  109. package/src/generator/surfaces/web/shared.js +369 -0
  110. package/src/generator/surfaces/web/sveltekit-actions.js +28 -0
  111. package/src/generator/surfaces/web/sveltekit-components.js +234 -0
  112. package/src/generator/surfaces/web/sveltekit.js +426 -0
  113. package/src/generator/surfaces/web/ui-web-contract.js +65 -0
  114. package/src/generator/surfaces/web/vanilla.js +239 -0
  115. package/src/generator/verification.js +84 -0
  116. package/src/generator.js +1 -0
  117. package/src/import/core/context.js +52 -0
  118. package/src/import/core/contracts.js +23 -0
  119. package/src/import/core/registry.js +81 -0
  120. package/src/import/core/runner.js +646 -0
  121. package/src/import/core/shared.js +910 -0
  122. package/src/import/enrichers/auth-session.js +18 -0
  123. package/src/import/enrichers/django-rest.js +226 -0
  124. package/src/import/enrichers/doc-linking.js +20 -0
  125. package/src/import/enrichers/rails-controllers.js +246 -0
  126. package/src/import/enrichers/rails-models.js +130 -0
  127. package/src/import/enrichers/workflow-target-state.js +10 -0
  128. package/src/import/extractors/api/aspnet-core.js +304 -0
  129. package/src/import/extractors/api/django-routes.js +318 -0
  130. package/src/import/extractors/api/express.js +154 -0
  131. package/src/import/extractors/api/fastify.js +371 -0
  132. package/src/import/extractors/api/flutter-dio.js +135 -0
  133. package/src/import/extractors/api/generic-route-fallback.js +90 -0
  134. package/src/import/extractors/api/graphql-code-first.js +565 -0
  135. package/src/import/extractors/api/graphql-sdl.js +309 -0
  136. package/src/import/extractors/api/jaxrs.js +303 -0
  137. package/src/import/extractors/api/micronaut.js +213 -0
  138. package/src/import/extractors/api/next-route.js +50 -0
  139. package/src/import/extractors/api/next-server-action.js +51 -0
  140. package/src/import/extractors/api/nextauth.js +52 -0
  141. package/src/import/extractors/api/openapi-code.js +242 -0
  142. package/src/import/extractors/api/openapi.js +232 -0
  143. package/src/import/extractors/api/rails-routes.js +230 -0
  144. package/src/import/extractors/api/react-native-repository.js +128 -0
  145. package/src/import/extractors/api/retrofit.js +103 -0
  146. package/src/import/extractors/api/spring-web.js +372 -0
  147. package/src/import/extractors/api/swift-webapi.js +116 -0
  148. package/src/import/extractors/api/trpc.js +212 -0
  149. package/src/import/extractors/db/django-models.js +232 -0
  150. package/src/import/extractors/db/dotnet-models.js +93 -0
  151. package/src/import/extractors/db/drizzle.js +242 -0
  152. package/src/import/extractors/db/ef-core.js +221 -0
  153. package/src/import/extractors/db/flutter-entities.js +120 -0
  154. package/src/import/extractors/db/jpa.js +120 -0
  155. package/src/import/extractors/db/liquibase.js +180 -0
  156. package/src/import/extractors/db/mybatis-xml.js +145 -0
  157. package/src/import/extractors/db/prisma.js +185 -0
  158. package/src/import/extractors/db/rails-schema.js +175 -0
  159. package/src/import/extractors/db/react-native-entities.js +95 -0
  160. package/src/import/extractors/db/room.js +193 -0
  161. package/src/import/extractors/db/snapshot.js +112 -0
  162. package/src/import/extractors/db/sql.js +180 -0
  163. package/src/import/extractors/db/swiftdata.js +137 -0
  164. package/src/import/extractors/ui/android-compose.js +230 -0
  165. package/src/import/extractors/ui/backend-only.js +70 -0
  166. package/src/import/extractors/ui/blazor.js +227 -0
  167. package/src/import/extractors/ui/flutter-screens.js +152 -0
  168. package/src/import/extractors/ui/maui-xaml.js +135 -0
  169. package/src/import/extractors/ui/next-app-router.js +83 -0
  170. package/src/import/extractors/ui/next-pages-router.js +141 -0
  171. package/src/import/extractors/ui/razor-pages.js +181 -0
  172. package/src/import/extractors/ui/react-native-screens.js +166 -0
  173. package/src/import/extractors/ui/react-router.js +139 -0
  174. package/src/import/extractors/ui/sveltekit.js +123 -0
  175. package/src/import/extractors/ui/swiftui.js +193 -0
  176. package/src/import/extractors/ui/uikit.js +175 -0
  177. package/src/import/extractors/verification/generic.js +290 -0
  178. package/src/import/extractors/workflows/generic.js +137 -0
  179. package/src/import/index.js +7 -0
  180. package/src/import/provenance.js +158 -0
  181. package/src/new-project.js +2107 -0
  182. package/src/parser.js +439 -0
  183. package/src/policy/review-boundaries.js +165 -0
  184. package/src/project-config.js +535 -0
  185. package/src/proofs/backend-parity.js +19 -0
  186. package/src/proofs/contract-audit.js +220 -0
  187. package/src/proofs/ios-parity.js +7 -0
  188. package/src/proofs/issues-parity.js +10 -0
  189. package/src/proofs/web-parity.js +50 -0
  190. package/src/realization/api/build-api-realization.js +5 -0
  191. package/src/realization/api/index.js +1 -0
  192. package/src/realization/backend/build-backend-runtime-realization.js +82 -0
  193. package/src/realization/backend/index.d.ts +1 -0
  194. package/src/realization/backend/index.js +4 -0
  195. package/src/realization/db/build-db-realization.js +17 -0
  196. package/src/realization/db/index.js +3 -0
  197. package/src/realization/db/migration-plan.js +5 -0
  198. package/src/realization/db/snapshot.js +5 -0
  199. package/src/realization/ui/build-ui-shared-realization.js +305 -0
  200. package/src/realization/ui/build-web-realization.js +189 -0
  201. package/src/realization/ui/index.js +2 -0
  202. package/src/reconcile/docs.js +280 -0
  203. package/src/reconcile/index.js +3 -0
  204. package/src/reconcile/journeys.js +441 -0
  205. package/src/resolver/docs.js +1 -0
  206. package/src/resolver/enrich/acceptance-criterion.js +14 -0
  207. package/src/resolver/enrich/bug.js +12 -0
  208. package/src/resolver/enrich/component.js +2 -0
  209. package/src/resolver/enrich/index.js +1 -0
  210. package/src/resolver/enrich/pitch.js +18 -0
  211. package/src/resolver/enrich/requirement.js +20 -0
  212. package/src/resolver/enrich/task.js +16 -0
  213. package/src/resolver/expressions.js +1 -0
  214. package/src/resolver/index.js +2422 -0
  215. package/src/resolver/normalize.js +1 -0
  216. package/src/resolver.js +1 -0
  217. package/src/sdlc/adopt.js +65 -0
  218. package/src/sdlc/check.js +86 -0
  219. package/src/sdlc/dod/acceptance-criterion.js +22 -0
  220. package/src/sdlc/dod/bug.js +26 -0
  221. package/src/sdlc/dod/document.js +23 -0
  222. package/src/sdlc/dod/index.js +25 -0
  223. package/src/sdlc/dod/pitch.js +23 -0
  224. package/src/sdlc/dod/requirement.js +34 -0
  225. package/src/sdlc/dod/task.js +39 -0
  226. package/src/sdlc/explain.js +116 -0
  227. package/src/sdlc/history.js +80 -0
  228. package/src/sdlc/paths.js +11 -0
  229. package/src/sdlc/release.js +106 -0
  230. package/src/sdlc/scaffold.js +89 -0
  231. package/src/sdlc/status-filter.js +54 -0
  232. package/src/sdlc/transition.js +112 -0
  233. package/src/sdlc/transitions/acceptance-criterion.js +28 -0
  234. package/src/sdlc/transitions/bug.js +31 -0
  235. package/src/sdlc/transitions/document.js +29 -0
  236. package/src/sdlc/transitions/index.js +56 -0
  237. package/src/sdlc/transitions/pitch.js +34 -0
  238. package/src/sdlc/transitions/requirement.js +31 -0
  239. package/src/sdlc/transitions/task.js +34 -0
  240. package/src/template-trust.js +597 -0
  241. package/src/validator/expressions.js +1 -0
  242. package/src/validator/index.js +3424 -0
  243. package/src/validator/kinds.js +346 -0
  244. package/src/validator/per-kind/acceptance-criterion.js +91 -0
  245. package/src/validator/per-kind/bug.js +77 -0
  246. package/src/validator/per-kind/component.js +274 -0
  247. package/src/validator/per-kind/domain.js +205 -0
  248. package/src/validator/per-kind/pitch.js +101 -0
  249. package/src/validator/per-kind/requirement.js +75 -0
  250. package/src/validator/per-kind/task.js +96 -0
  251. package/src/validator/registry.js +1 -0
  252. package/src/validator/utils.js +12 -0
  253. package/src/validator.js +1 -0
  254. package/src/workflows.js +7597 -0
  255. package/src/workspace-docs.js +265 -0
  256. package/template-helpers/react.js +5 -0
  257. package/template-helpers/sveltekit.js +5 -0
@@ -0,0 +1,346 @@
1
+ export const STATEMENT_KINDS = new Set([
2
+ "term",
3
+ "actor",
4
+ "role",
5
+ "enum",
6
+ "entity",
7
+ "shape",
8
+ "rule",
9
+ "capability",
10
+ "component",
11
+ "decision",
12
+ "projection",
13
+ "orchestration",
14
+ "verification",
15
+ "operation",
16
+ "domain",
17
+ "pitch",
18
+ "requirement",
19
+ "acceptance_criterion",
20
+ "task",
21
+ "bug"
22
+ ]);
23
+
24
+ export const IDENTIFIER_PATTERN = /^[a-z][a-z0-9_]*$/;
25
+ export const DOMAIN_IDENTIFIER_PATTERN = /^dom_[a-z][a-z0-9_]*$/;
26
+ export const PITCH_IDENTIFIER_PATTERN = /^pitch_[a-z][a-z0-9_]*$/;
27
+ export const REQUIREMENT_IDENTIFIER_PATTERN = /^req_[a-z][a-z0-9_]*$/;
28
+ export const ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN = /^ac_[a-z][a-z0-9_]*$/;
29
+ export const TASK_IDENTIFIER_PATTERN = /^task_[a-z][a-z0-9_]*$/;
30
+ export const BUG_IDENTIFIER_PATTERN = /^bug_[a-z][a-z0-9_]*$/;
31
+ export const DOCUMENT_IDENTIFIER_PATTERN = /^doc_[a-z][a-z0-9_]*$/;
32
+
33
+ export const GLOBAL_STATUSES = new Set(["draft", "proposed", "active", "deprecated"]);
34
+ export const DECISION_STATUSES = new Set(["draft", "proposed", "accepted", "rejected", "deprecated"]);
35
+ export const RULE_SEVERITIES = new Set(["error", "warning", "info"]);
36
+
37
+ // Phase 2 SDLC status sets (per-kind state machines).
38
+ export const PITCH_STATUSES = new Set(["draft", "shaped", "submitted", "approved", "rejected"]);
39
+ export const REQUIREMENT_STATUSES = new Set(["draft", "in-review", "approved", "superseded"]);
40
+ export const ACCEPTANCE_CRITERION_STATUSES = new Set(["draft", "approved", "superseded"]);
41
+ export const TASK_STATUSES = new Set(["unclaimed", "claimed", "in-progress", "done", "blocked"]);
42
+ export const BUG_STATUSES = new Set(["open", "in-progress", "fixed", "verified", "wont-fix"]);
43
+
44
+ export const PRIORITY_VALUES = new Set(["critical", "high", "medium", "low"]);
45
+ export const WORK_TYPES = new Set([
46
+ "implementation",
47
+ "review",
48
+ "testing",
49
+ "integration",
50
+ "design",
51
+ "documentation",
52
+ "bugfix"
53
+ ]);
54
+ export const BUG_SEVERITIES = new Set(["critical", "high", "medium", "low"]);
55
+ export const DOC_TYPES = new Set([
56
+ "user-guide",
57
+ "api",
58
+ "architecture",
59
+ "operations",
60
+ "getting-started",
61
+ "reference",
62
+ "development"
63
+ ]);
64
+ export const AUDIENCES = new Set(["developers", "operators", "end-users", "all"]);
65
+
66
+ // Per-kind status table — used by `validateStatus` to dispatch the
67
+ // allowed status set without long if/else chains.
68
+ export const STATUS_SETS_BY_KIND = {
69
+ decision: DECISION_STATUSES,
70
+ pitch: PITCH_STATUSES,
71
+ requirement: REQUIREMENT_STATUSES,
72
+ acceptance_criterion: ACCEPTANCE_CRITERION_STATUSES,
73
+ task: TASK_STATUSES,
74
+ bug: BUG_STATUSES
75
+ };
76
+ export const VERIFICATION_METHODS = new Set(["smoke", "runtime", "contract", "journey", "manual"]);
77
+ export const UI_SCREEN_KINDS = new Set(["list", "detail", "form", "dashboard", "job_status", "board", "calendar", "feed", "inbox", "settings", "wizard", "report", "analytics"]);
78
+ export const UI_COLLECTION_PRESENTATIONS = new Set(["table", "data_grid", "cards", "list", "board", "calendar", "gallery"]);
79
+ export const UI_NAVIGATION_PATTERNS = new Set([
80
+ "primary",
81
+ "tabs",
82
+ "stack_navigation",
83
+ "bottom_tabs",
84
+ "segmented_control",
85
+ "command_palette",
86
+ "split_view",
87
+ "navigation_rail"
88
+ ]);
89
+ export const UI_REGION_KINDS = new Set([
90
+ "hero",
91
+ "toolbar",
92
+ "filters",
93
+ "search",
94
+ "results",
95
+ "summary",
96
+ "metadata",
97
+ "aside",
98
+ "related",
99
+ "activity",
100
+ "comments",
101
+ "timeline",
102
+ "tabs",
103
+ "bulk_actions",
104
+ "footer_actions"
105
+ ]);
106
+ export const UI_PATTERN_KINDS = new Set([
107
+ "resource_table",
108
+ "data_grid_view",
109
+ "resource_cards",
110
+ "detail_panel",
111
+ "edit_form",
112
+ "lookup_select",
113
+ "action_bar",
114
+ "status_badge",
115
+ "summary_stats",
116
+ "activity_feed",
117
+ "comment_thread",
118
+ "timeline_view",
119
+ "board_view",
120
+ "calendar_view",
121
+ "settings_section",
122
+ "wizard_stepper",
123
+ "audit_log",
124
+ "search_results",
125
+ "empty_state_panel",
126
+ "inspector_pane",
127
+ "master_detail"
128
+ ]);
129
+
130
+ // Kinds that may carry an optional singular `domain dom_x` field. Keep this
131
+ // set in sync with the `allowed[]` arrays in FIELD_SPECS below; the cross-kind
132
+ // validator in `validator/index.js` consults this set when checking the
133
+ // reference target. Phase 2 added the SDLC kinds (pitch, requirement, task,
134
+ // bug) to this set; acceptance_criterion stays domainless and inherits via
135
+ // its requirement.
136
+ export const DOMAIN_TAGGABLE_KINDS = new Set([
137
+ "capability",
138
+ "entity",
139
+ "rule",
140
+ "verification",
141
+ "orchestration",
142
+ "operation",
143
+ "decision",
144
+ "pitch",
145
+ "requirement",
146
+ "task",
147
+ "bug"
148
+ ]);
149
+
150
+ export const FIELD_SPECS = {
151
+ term: {
152
+ required: ["name", "description", "status"],
153
+ allowed: ["name", "description", "aliases", "excludes", "status"]
154
+ },
155
+ actor: {
156
+ required: ["name", "description", "status"],
157
+ allowed: ["name", "description", "status"]
158
+ },
159
+ role: {
160
+ required: ["name", "description", "status"],
161
+ allowed: ["name", "description", "status"]
162
+ },
163
+ enum: {
164
+ required: ["values"],
165
+ allowed: ["values"]
166
+ },
167
+ entity: {
168
+ required: ["name", "description", "fields", "status"],
169
+ allowed: ["name", "description", "fields", "keys", "relations", "invariants", "uses_terms", "domain", "status"]
170
+ },
171
+ shape: {
172
+ required: ["name", "description", "status"],
173
+ allowed: ["name", "description", "include", "exclude", "rename", "overrides", "fields", "derived_from", "status"]
174
+ },
175
+ rule: {
176
+ required: ["name", "description", "applies_to", "status"],
177
+ allowed: ["name", "description", "applies_to", "actors", "roles", "condition", "requirement", "from_requirement", "severity", "source_of_truth", "domain", "status"]
178
+ },
179
+ capability: {
180
+ required: ["name", "description", "status"],
181
+ allowed: ["name", "description", "actors", "roles", "reads", "creates", "updates", "deletes", "input", "output", "domain", "status"]
182
+ },
183
+ component: {
184
+ required: ["name", "description", "props", "status"],
185
+ allowed: ["name", "description", "category", "props", "events", "slots", "behavior", "behaviors", "patterns", "regions", "lookups", "dependencies", "version", "approvals", "status"]
186
+ },
187
+ decision: {
188
+ required: ["name", "description", "status"],
189
+ allowed: ["name", "description", "context", "consequences", "pitch", "supersedes", "domain", "status"]
190
+ },
191
+ projection: {
192
+ required: ["name", "description", "platform", "realizes", "outputs", "status"],
193
+ allowed: [
194
+ "name",
195
+ "description",
196
+ "platform",
197
+ "realizes",
198
+ "outputs",
199
+ "http",
200
+ "http_errors",
201
+ "http_fields",
202
+ "http_responses",
203
+ "http_preconditions",
204
+ "http_idempotency",
205
+ "http_cache",
206
+ "http_delete",
207
+ "http_async",
208
+ "http_status",
209
+ "http_download",
210
+ "http_authz",
211
+ "http_callbacks",
212
+ "ui_screens",
213
+ "ui_collections",
214
+ "ui_actions",
215
+ "ui_visibility",
216
+ "ui_lookups",
217
+ "ui_routes",
218
+ "ui_web",
219
+ "ui_ios",
220
+ "ui_app_shell",
221
+ "ui_navigation",
222
+ "ui_screen_regions",
223
+ "ui_components",
224
+ "db_tables",
225
+ "db_columns",
226
+ "db_keys",
227
+ "db_indexes",
228
+ "db_relations",
229
+ "db_lifecycle",
230
+ "generator_defaults",
231
+ "status"
232
+ ]
233
+ },
234
+ orchestration: {
235
+ required: ["name", "description", "inputs", "steps", "outputs", "status"],
236
+ allowed: ["name", "description", "inputs", "steps", "outputs", "domain", "status"]
237
+ },
238
+ verification: {
239
+ required: ["name", "description", "validates", "method", "scenarios", "status"],
240
+ allowed: [
241
+ "name",
242
+ "description",
243
+ "validates",
244
+ "method",
245
+ "scenarios",
246
+ "requirement_refs",
247
+ "acceptance_refs",
248
+ "fixes_bugs",
249
+ "domain",
250
+ "status"
251
+ ]
252
+ },
253
+ operation: {
254
+ required: ["name", "description", "observes", "metrics", "alerts", "status"],
255
+ allowed: ["name", "description", "observes", "metrics", "alerts", "domain", "status"]
256
+ },
257
+ domain: {
258
+ required: ["name", "description", "status"],
259
+ allowed: ["name", "description", "in_scope", "out_of_scope", "owners", "parent_domain", "aliases", "status"]
260
+ },
261
+ pitch: {
262
+ required: ["name", "description", "status", "priority"],
263
+ allowed: [
264
+ "name",
265
+ "description",
266
+ "status",
267
+ "priority",
268
+ "appetite",
269
+ "problem",
270
+ "solution_sketch",
271
+ "rabbit_holes",
272
+ "no_go_areas",
273
+ "affects",
274
+ "decisions",
275
+ "domain",
276
+ "updated",
277
+ "approvals"
278
+ ]
279
+ },
280
+ requirement: {
281
+ required: ["name", "description", "status", "priority"],
282
+ allowed: [
283
+ "name",
284
+ "description",
285
+ "status",
286
+ "priority",
287
+ "pitch",
288
+ "affects",
289
+ "introduces_rules",
290
+ "respects_rules",
291
+ "supersedes",
292
+ "domain",
293
+ "updated",
294
+ "approvals"
295
+ ]
296
+ },
297
+ acceptance_criterion: {
298
+ required: ["name", "description", "status", "requirement"],
299
+ allowed: ["name", "description", "status", "requirement", "supersedes", "updated"]
300
+ },
301
+ task: {
302
+ required: ["name", "description", "status", "priority", "work_type"],
303
+ allowed: [
304
+ "name",
305
+ "description",
306
+ "status",
307
+ "priority",
308
+ "work_type",
309
+ "affects",
310
+ "satisfies",
311
+ "acceptance_refs",
312
+ "blocks",
313
+ "blocked_by",
314
+ "claimed_by",
315
+ "introduces_decisions",
316
+ "modifies",
317
+ "introduces",
318
+ "removes",
319
+ "domain",
320
+ "updated"
321
+ ]
322
+ },
323
+ bug: {
324
+ required: ["name", "description", "status", "severity", "priority"],
325
+ allowed: [
326
+ "name",
327
+ "description",
328
+ "status",
329
+ "severity",
330
+ "priority",
331
+ "affects",
332
+ "violates",
333
+ "surfaces_rule",
334
+ "introduced_in",
335
+ "fixed_in",
336
+ "fixed_in_release",
337
+ "fixed_in_verification",
338
+ "reproduction",
339
+ "modifies",
340
+ "introduces",
341
+ "removes",
342
+ "domain",
343
+ "updated"
344
+ ]
345
+ }
346
+ };
@@ -0,0 +1,91 @@
1
+ import {
2
+ ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN
3
+ } from "../kinds.js";
4
+ import {
5
+ pushError,
6
+ symbolValue,
7
+ symbolValues
8
+ } from "../utils.js";
9
+
10
+ function validateAcIdentifier(errors, statement) {
11
+ if (!ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN.test(statement.id)) {
12
+ pushError(
13
+ errors,
14
+ `Acceptance criterion identifier '${statement.id}' must match ${ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN.source}`,
15
+ statement.loc
16
+ );
17
+ }
18
+ }
19
+
20
+ function validateRequirementRef(errors, statement, fieldMap, registry) {
21
+ // Generic reference validator skips `requirement` (it's overloaded with
22
+ // rule.requirement which is a string condition); validate the kind=requirement
23
+ // reference here.
24
+ const field = fieldMap.get("requirement")?.[0];
25
+ if (!field) return;
26
+ const id = symbolValue(field.value);
27
+ if (!id) {
28
+ pushError(
29
+ errors,
30
+ `Field 'requirement' on acceptance_criterion ${statement.id} must be a single symbol`,
31
+ field.loc
32
+ );
33
+ return;
34
+ }
35
+ const target = registry.get(id);
36
+ if (!target) {
37
+ pushError(
38
+ errors,
39
+ `Acceptance criterion ${statement.id} requirement references missing requirement '${id}'`,
40
+ field.loc
41
+ );
42
+ return;
43
+ }
44
+ if (target.kind !== "requirement") {
45
+ pushError(
46
+ errors,
47
+ `Acceptance criterion ${statement.id} requirement must reference requirement, found ${target.kind} '${target.id}'`,
48
+ field.loc
49
+ );
50
+ }
51
+ }
52
+
53
+ function validateSupersedes(errors, statement, fieldMap, registry) {
54
+ const field = fieldMap.get("supersedes")?.[0];
55
+ if (!field) return;
56
+ for (const id of symbolValues(field.value)) {
57
+ if (id === statement.id) {
58
+ pushError(
59
+ errors,
60
+ `Acceptance criterion ${statement.id} cannot supersede itself`,
61
+ field.loc
62
+ );
63
+ continue;
64
+ }
65
+ const target = registry.get(id);
66
+ if (!target) {
67
+ pushError(
68
+ errors,
69
+ `Acceptance criterion ${statement.id} supersedes references missing acceptance_criterion '${id}'`,
70
+ field.loc
71
+ );
72
+ continue;
73
+ }
74
+ if (target.kind !== "acceptance_criterion") {
75
+ pushError(
76
+ errors,
77
+ `Acceptance criterion ${statement.id} supersedes must reference acceptance_criterion, found ${target.kind} '${target.id}'`,
78
+ field.loc
79
+ );
80
+ }
81
+ }
82
+ }
83
+
84
+ export function validateAcceptanceCriterion(errors, statement, fieldMap, registry) {
85
+ if (statement.kind !== "acceptance_criterion") {
86
+ return;
87
+ }
88
+ validateAcIdentifier(errors, statement);
89
+ validateRequirementRef(errors, statement, fieldMap, registry);
90
+ validateSupersedes(errors, statement, fieldMap, registry);
91
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ BUG_IDENTIFIER_PATTERN,
3
+ PRIORITY_VALUES,
4
+ BUG_SEVERITIES
5
+ } from "../kinds.js";
6
+ import {
7
+ pushError,
8
+ symbolValue,
9
+ symbolValues
10
+ } from "../utils.js";
11
+
12
+ function validateBugIdentifier(errors, statement) {
13
+ if (!BUG_IDENTIFIER_PATTERN.test(statement.id)) {
14
+ pushError(
15
+ errors,
16
+ `Bug identifier '${statement.id}' must match ${BUG_IDENTIFIER_PATTERN.source}`,
17
+ statement.loc
18
+ );
19
+ }
20
+ }
21
+
22
+ function validatePriority(errors, statement, fieldMap) {
23
+ const field = fieldMap.get("priority")?.[0];
24
+ if (!field) return;
25
+ if (field.value.type !== "symbol") {
26
+ pushError(errors, `Field 'priority' on bug ${statement.id} must be a symbol`, field.loc);
27
+ return;
28
+ }
29
+ if (!PRIORITY_VALUES.has(field.value.value)) {
30
+ pushError(
31
+ errors,
32
+ `Invalid priority '${field.value.value}' on bug ${statement.id}`,
33
+ field.loc
34
+ );
35
+ }
36
+ }
37
+
38
+ function validateSeverity(errors, statement, fieldMap) {
39
+ const field = fieldMap.get("severity")?.[0];
40
+ if (!field) return;
41
+ if (field.value.type !== "symbol") {
42
+ pushError(errors, `Field 'severity' on bug ${statement.id} must be a symbol`, field.loc);
43
+ return;
44
+ }
45
+ if (!BUG_SEVERITIES.has(field.value.value)) {
46
+ pushError(
47
+ errors,
48
+ `Invalid severity '${field.value.value}' on bug ${statement.id}`,
49
+ field.loc
50
+ );
51
+ }
52
+ }
53
+
54
+ function validateFixedInVerificationOnVerified(errors, statement, fieldMap) {
55
+ // A bug in `verified` status must point at the verification that proved
56
+ // the fix; this lets release-notes assemble a closed-loop record.
57
+ const statusField = fieldMap.get("status")?.[0];
58
+ if (!statusField || statusField.value.type !== "symbol") return;
59
+ if (statusField.value.value !== "verified") return;
60
+ if (!fieldMap.has("fixed_in_verification")) {
61
+ pushError(
62
+ errors,
63
+ `Bug ${statement.id} status 'verified' requires field 'fixed_in_verification'`,
64
+ statusField.loc
65
+ );
66
+ }
67
+ }
68
+
69
+ export function validateBug(errors, statement, fieldMap, registry) {
70
+ if (statement.kind !== "bug") {
71
+ return;
72
+ }
73
+ validateBugIdentifier(errors, statement);
74
+ validatePriority(errors, statement, fieldMap);
75
+ validateSeverity(errors, statement, fieldMap);
76
+ validateFixedInVerificationOnVerified(errors, statement, fieldMap);
77
+ }