@topogram/cli 0.3.64 → 0.3.65

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 (245) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/agent-ops/query-builders/auth.js +375 -0
  5. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  6. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  7. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  8. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  9. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  10. package/src/agent-ops/query-builders/change-risk.js +25 -0
  11. package/src/agent-ops/query-builders/common.js +149 -0
  12. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  13. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  14. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  15. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  16. package/src/agent-ops/query-builders/work-packets.js +417 -0
  17. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  18. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  19. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  20. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  21. package/src/agent-ops/query-builders.d.ts +26 -26
  22. package/src/agent-ops/query-builders.js +42 -5021
  23. package/src/catalog/constants.js +10 -0
  24. package/src/catalog/copy.js +60 -0
  25. package/src/catalog/diagnostics.js +15 -0
  26. package/src/catalog/entries.js +42 -0
  27. package/src/catalog/files.js +67 -0
  28. package/src/catalog/provenance.js +122 -0
  29. package/src/catalog/source.js +150 -0
  30. package/src/catalog/validation.js +252 -0
  31. package/src/catalog.d.ts +2 -0
  32. package/src/catalog.js +18 -746
  33. package/src/cli/commands/catalog/check.js +31 -0
  34. package/src/cli/commands/catalog/copy.js +59 -0
  35. package/src/cli/commands/catalog/doctor.js +248 -0
  36. package/src/cli/commands/catalog/help.js +21 -0
  37. package/src/cli/commands/catalog/list.js +52 -0
  38. package/src/cli/commands/catalog/runner.js +92 -0
  39. package/src/cli/commands/catalog/shared.js +17 -0
  40. package/src/cli/commands/catalog/show.js +134 -0
  41. package/src/cli/commands/catalog.js +30 -615
  42. package/src/cli/commands/generator-policy/package-info.js +162 -0
  43. package/src/cli/commands/generator-policy/payloads.js +372 -0
  44. package/src/cli/commands/generator-policy/printers.js +159 -0
  45. package/src/cli/commands/generator-policy/runner.js +81 -0
  46. package/src/cli/commands/generator-policy/shared.js +39 -0
  47. package/src/cli/commands/generator-policy.js +15 -783
  48. package/src/cli/commands/import/adopt.js +170 -0
  49. package/src/cli/commands/import/check.js +91 -0
  50. package/src/cli/commands/import/diff.js +84 -0
  51. package/src/cli/commands/import/help.js +47 -0
  52. package/src/cli/commands/import/paths.js +277 -0
  53. package/src/cli/commands/import/plan.js +284 -0
  54. package/src/cli/commands/import/refresh.js +470 -0
  55. package/src/cli/commands/import/status-history.js +196 -0
  56. package/src/cli/commands/import/workspace.js +230 -0
  57. package/src/cli/commands/import.js +33 -1732
  58. package/src/cli/commands/package/constants.js +17 -0
  59. package/src/cli/commands/package/doctor.js +240 -0
  60. package/src/cli/commands/package/help.js +27 -0
  61. package/src/cli/commands/package/lockfile.js +135 -0
  62. package/src/cli/commands/package/npm.js +97 -0
  63. package/src/cli/commands/package/reporting.js +35 -0
  64. package/src/cli/commands/package/runner.js +33 -0
  65. package/src/cli/commands/package/shared.js +9 -0
  66. package/src/cli/commands/package/update-cli.js +252 -0
  67. package/src/cli/commands/package/versions.js +35 -0
  68. package/src/cli/commands/package.js +29 -813
  69. package/src/cli/commands/query/change-plan.js +68 -0
  70. package/src/cli/commands/query/definitions.js +202 -0
  71. package/src/cli/commands/query/import-adopt.js +121 -0
  72. package/src/cli/commands/query/runner/artifacts.js +102 -0
  73. package/src/cli/commands/query/runner/boundaries.js +211 -0
  74. package/src/cli/commands/query/runner/change.js +182 -0
  75. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  76. package/src/cli/commands/query/runner/index.js +31 -0
  77. package/src/cli/commands/query/runner/output.js +12 -0
  78. package/src/cli/commands/query/runner/workflow.js +241 -0
  79. package/src/cli/commands/query/runner.js +3 -0
  80. package/src/cli/commands/query/workflow-context.js +5 -0
  81. package/src/cli/commands/query/workspace.js +274 -0
  82. package/src/cli/commands/query.js +9 -1300
  83. package/src/cli/commands/template/baseline.js +100 -0
  84. package/src/cli/commands/template/check.js +466 -0
  85. package/src/cli/commands/template/constants.js +8 -0
  86. package/src/cli/commands/template/diagnostics.js +26 -0
  87. package/src/cli/commands/template/help.js +28 -0
  88. package/src/cli/commands/template/lifecycle.js +404 -0
  89. package/src/cli/commands/template/list-show.js +287 -0
  90. package/src/cli/commands/template/policy.js +422 -0
  91. package/src/cli/commands/template/shared.js +127 -0
  92. package/src/cli/commands/template/updates.js +352 -0
  93. package/src/cli/commands/template.js +41 -2143
  94. package/src/generator/api/contracts.js +497 -0
  95. package/src/generator/api/metadata.js +221 -0
  96. package/src/generator/api/openapi.js +559 -0
  97. package/src/generator/api/schema.js +124 -0
  98. package/src/generator/api/types.d.ts +98 -0
  99. package/src/generator/api.js +3 -1195
  100. package/src/generator/context/shared/domain-sdlc.js +282 -0
  101. package/src/generator/context/shared/maintained-boundary.js +665 -0
  102. package/src/generator/context/shared/metrics.js +85 -0
  103. package/src/generator/context/shared/primitives.js +64 -0
  104. package/src/generator/context/shared/relationships.js +453 -0
  105. package/src/generator/context/shared/summaries.js +263 -0
  106. package/src/generator/context/shared/types.d.ts +207 -0
  107. package/src/generator/context/shared.d.ts +42 -0
  108. package/src/generator/context/shared.js +80 -1390
  109. package/src/generator/context/slice/core.js +397 -0
  110. package/src/generator/context/slice/sdlc.js +417 -0
  111. package/src/generator/context/slice/ui-packets.js +183 -0
  112. package/src/generator/context/slice.js +2 -859
  113. package/src/generator/registry/index.js +507 -0
  114. package/src/generator/registry.js +18 -504
  115. package/src/generator/runtime/environment/index.js +666 -0
  116. package/src/generator/runtime/environment.js +4 -666
  117. package/src/generator/runtime/runtime-check/index.js +554 -0
  118. package/src/generator/runtime/runtime-check.js +4 -554
  119. package/src/generator/runtime/shared/index.js +572 -0
  120. package/src/generator/runtime/shared.js +19 -570
  121. package/src/generator/shared.d.ts +2 -0
  122. package/src/generator/surfaces/shared.d.ts +3 -0
  123. package/src/generator/widget-conformance/behavior-report.js +258 -0
  124. package/src/generator/widget-conformance/checks.js +371 -0
  125. package/src/generator/widget-conformance/projection-context.js +200 -0
  126. package/src/generator/widget-conformance/report.js +166 -0
  127. package/src/generator/widget-conformance/types.d.ts +121 -0
  128. package/src/generator/widget-conformance.js +3 -824
  129. package/src/import/core/context.d.ts +3 -0
  130. package/src/import/core/contracts.d.ts +1 -0
  131. package/src/import/core/registry.d.ts +4 -0
  132. package/src/import/core/runner/candidates.js +217 -0
  133. package/src/import/core/runner/options.js +22 -0
  134. package/src/import/core/runner/reports.js +50 -0
  135. package/src/import/core/runner/run.js +79 -0
  136. package/src/import/core/runner/tracks.js +150 -0
  137. package/src/import/core/runner/ui-drafts.js +337 -0
  138. package/src/import/core/runner.js +3 -698
  139. package/src/import/core/shared/api-routes.js +221 -0
  140. package/src/import/core/shared/candidates.js +97 -0
  141. package/src/import/core/shared/files.js +177 -0
  142. package/src/import/core/shared/next-app.js +389 -0
  143. package/src/import/core/shared/types.d.ts +51 -0
  144. package/src/import/core/shared/ui-routes.js +230 -0
  145. package/src/import/core/shared.js +60 -861
  146. package/src/new-project/constants.js +128 -0
  147. package/src/new-project/create.js +83 -0
  148. package/src/new-project/json.js +28 -0
  149. package/src/new-project/metadata.js +96 -0
  150. package/src/new-project/package-spec.js +161 -0
  151. package/src/new-project/project-files.js +348 -0
  152. package/src/new-project/template-policy.js +269 -0
  153. package/src/new-project/template-resolution.js +368 -0
  154. package/src/new-project/template-snapshots.js +430 -0
  155. package/src/new-project/template-updates.js +512 -0
  156. package/src/new-project/types.d.ts +83 -0
  157. package/src/new-project.js +6 -2277
  158. package/src/parser.d.ts +87 -1
  159. package/src/parser.js +118 -0
  160. package/src/policy/review-boundaries.d.ts +15 -0
  161. package/src/project-config/index.js +564 -0
  162. package/src/project-config.js +19 -561
  163. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  164. package/src/resolver/enrich/bug.js +2 -0
  165. package/src/resolver/enrich/pitch.js +2 -0
  166. package/src/resolver/enrich/requirement.js +2 -0
  167. package/src/resolver/enrich/task.js +2 -0
  168. package/src/resolver/index.js +19 -2089
  169. package/src/resolver/normalize.js +384 -1
  170. package/src/resolver/plans.js +168 -0
  171. package/src/resolver/projections-api.js +494 -0
  172. package/src/resolver/projections-db.js +133 -0
  173. package/src/resolver/projections-ui.js +317 -0
  174. package/src/resolver/shapes.js +251 -0
  175. package/src/resolver/shared.js +278 -0
  176. package/src/resolver/widgets.js +132 -0
  177. package/src/template-trust/constants.js +62 -0
  178. package/src/template-trust/content.js +258 -0
  179. package/src/template-trust/diff.js +92 -0
  180. package/src/template-trust/policy.js +61 -0
  181. package/src/template-trust/record.js +90 -0
  182. package/src/template-trust/status.js +182 -0
  183. package/src/template-trust.js +24 -687
  184. package/src/text-helpers.d.ts +1 -0
  185. package/src/topogram-types.d.ts +69 -0
  186. package/src/validator/common.js +488 -0
  187. package/src/validator/data-model.js +237 -0
  188. package/src/validator/docs.js +167 -0
  189. package/src/validator/expressions.js +146 -1
  190. package/src/validator/index.d.ts +23 -0
  191. package/src/validator/index.js +32 -3585
  192. package/src/validator/kinds.d.ts +41 -0
  193. package/src/validator/kinds.js +2 -0
  194. package/src/validator/model-helpers.js +46 -0
  195. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  196. package/src/validator/per-kind/bug.js +6 -0
  197. package/src/validator/per-kind/domain.js +15 -2
  198. package/src/validator/per-kind/pitch.js +7 -0
  199. package/src/validator/per-kind/requirement.js +5 -0
  200. package/src/validator/per-kind/task.js +7 -0
  201. package/src/validator/per-kind/widget.js +14 -0
  202. package/src/validator/projections/api-http-async.js +410 -0
  203. package/src/validator/projections/api-http-authz.js +88 -0
  204. package/src/validator/projections/api-http-core.js +205 -0
  205. package/src/validator/projections/api-http-policies.js +339 -0
  206. package/src/validator/projections/api-http-responses.js +233 -0
  207. package/src/validator/projections/api-http.js +44 -0
  208. package/src/validator/projections/db.js +353 -0
  209. package/src/validator/projections/generator-defaults.js +45 -0
  210. package/src/validator/projections/helpers.js +87 -0
  211. package/src/validator/projections/ui-helpers.js +214 -0
  212. package/src/validator/projections/ui-navigation.js +344 -0
  213. package/src/validator/projections/ui-structure.js +364 -0
  214. package/src/validator/projections/ui-widgets.js +493 -0
  215. package/src/validator/projections/ui.js +46 -0
  216. package/src/validator/registry.js +48 -1
  217. package/src/validator/utils.d.ts +20 -0
  218. package/src/validator/utils.js +115 -12
  219. package/src/widget-behavior.d.ts +1 -0
  220. package/src/workflows/import-app/api/collect.js +221 -0
  221. package/src/workflows/import-app/api/openapi.js +257 -0
  222. package/src/workflows/import-app/api/routes.js +327 -0
  223. package/src/workflows/import-app/api/sources.js +22 -0
  224. package/src/workflows/import-app/api.js +2 -797
  225. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  226. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  227. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  228. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  229. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  230. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  231. package/src/workflows/reconcile/adoption-plan.js +30 -740
  232. package/src/workflows/reconcile/auth/closures.js +115 -0
  233. package/src/workflows/reconcile/auth/formatters.js +142 -0
  234. package/src/workflows/reconcile/auth/inference.js +330 -0
  235. package/src/workflows/reconcile/auth/roles.js +122 -0
  236. package/src/workflows/reconcile/auth.js +35 -690
  237. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  238. package/src/workflows/reconcile/bundle-core.js +12 -598
  239. package/src/workflows/reconcile/canonical-surface.js +1 -1
  240. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  241. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  242. package/src/workflows/reconcile/impacts/patches.js +252 -0
  243. package/src/workflows/reconcile/impacts/reports.js +80 -0
  244. package/src/workflows/reconcile/impacts.js +14 -623
  245. package/src/workspace-docs.d.ts +29 -0
@@ -0,0 +1,417 @@
1
+ // @ts-check
2
+
3
+ import {
4
+ acceptanceCriterionById,
5
+ bugById,
6
+ buildDefaultWriteScope,
7
+ documentById,
8
+ domainById,
9
+ getJourneyDoc,
10
+ pitchById,
11
+ recommendedVerificationTargets,
12
+ relatedEntitiesForDomain,
13
+ relatedProjectionsForDomain,
14
+ relatedRulesForDomain,
15
+ relatedVerificationsForDomain,
16
+ requirementById,
17
+ summarizeAcceptanceCriterion,
18
+ summarizeBug,
19
+ summarizeById,
20
+ summarizeDocsByIds,
21
+ summarizeDocument,
22
+ summarizeDomain,
23
+ summarizePitch,
24
+ summarizeRequirement,
25
+ summarizeStatementsByIds,
26
+ summarizeTask,
27
+ taskById,
28
+ verificationIdsForTarget
29
+ } from "../shared.js";
30
+ import {
31
+ defaultOwnershipBoundary,
32
+ reviewBoundaryForAcceptanceCriterion,
33
+ reviewBoundaryForBug,
34
+ reviewBoundaryForDocument,
35
+ reviewBoundaryForDomain,
36
+ reviewBoundaryForJourneyDoc,
37
+ reviewBoundaryForPitch,
38
+ reviewBoundaryForRequirement,
39
+ reviewBoundaryForTask
40
+ } from "../../../policy/review-boundaries.js";
41
+
42
+ /**
43
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
44
+ * @param {string} journeyId
45
+ * @returns {any}
46
+ */
47
+ export function journeySlice(graph, journeyId) {
48
+ const journey = getJourneyDoc(graph, journeyId);
49
+ const capabilities = [...(journey.relatedCapabilities || [])].sort();
50
+ const workflows = [...(journey.relatedWorkflows || [])].sort();
51
+ const projections = [...(journey.relatedProjections || [])].sort();
52
+ const verifications = verificationIdsForTarget(graph, [...capabilities, ...workflows, ...projections, journeyId]);
53
+
54
+ return {
55
+ type: "context_slice",
56
+ version: 1,
57
+ focus: {
58
+ kind: "journey",
59
+ id: journeyId
60
+ },
61
+ summary: summarizeById(graph, journeyId),
62
+ depends_on: {
63
+ capabilities,
64
+ workflows,
65
+ projections,
66
+ verifications
67
+ },
68
+ related: {
69
+ capabilities: summarizeStatementsByIds(graph, capabilities),
70
+ workflows: summarizeDocsByIds(graph, workflows),
71
+ projections: summarizeStatementsByIds(graph, projections)
72
+ },
73
+ verification: summarizeStatementsByIds(graph, verifications),
74
+ verification_targets: recommendedVerificationTargets(graph, [...capabilities, ...workflows, ...projections, journeyId], {
75
+ rationale: "Journey slices should target workflow-facing verification rather than a full workspace rerun."
76
+ }),
77
+ write_scope: buildDefaultWriteScope(),
78
+ review_boundary: reviewBoundaryForJourneyDoc(journey),
79
+ ownership_boundary: defaultOwnershipBoundary()
80
+ };
81
+ }
82
+
83
+ /**
84
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
85
+ * @param {string} domainId
86
+ * @returns {any}
87
+ */
88
+ export function domainSlice(graph, domainId) {
89
+ const domain = domainById(graph, domainId);
90
+ if (!domain) {
91
+ throw new Error(`No domain found with id '${domainId}'`);
92
+ }
93
+ const capabilities = [...(domain.members?.capabilities || [])].sort();
94
+ const entities = relatedEntitiesForDomain(graph, domainId);
95
+ const rules = relatedRulesForDomain(graph, domainId);
96
+ const verifications = relatedVerificationsForDomain(graph, domainId);
97
+ const orchestrations = [...(domain.members?.orchestrations || [])].sort();
98
+ const operations = [...(domain.members?.operations || [])].sort();
99
+ const decisions = [...(domain.members?.decisions || [])].sort();
100
+ const projections = relatedProjectionsForDomain(graph, domainId);
101
+
102
+ // Verification targets cover the union of capability/entity/projection IDs in
103
+ // the domain so a domain-scoped change re-runs the right verification set
104
+ // without pulling in the whole workspace.
105
+ const verificationTargets = recommendedVerificationTargets(
106
+ graph,
107
+ [domainId, ...capabilities, ...entities, ...projections],
108
+ {
109
+ rationale:
110
+ "Domain slices should re-run verification covering the domain's capabilities, entities, and projection types."
111
+ }
112
+ );
113
+
114
+ return {
115
+ type: "context_slice",
116
+ version: 1,
117
+ focus: {
118
+ kind: "domain",
119
+ id: domainId
120
+ },
121
+ summary: summarizeDomain(domain),
122
+ depends_on: {
123
+ capabilities,
124
+ entities,
125
+ rules,
126
+ verifications,
127
+ orchestrations,
128
+ operations,
129
+ decisions,
130
+ projections
131
+ },
132
+ related: {
133
+ capabilities: summarizeStatementsByIds(graph, capabilities),
134
+ entities: summarizeStatementsByIds(graph, entities),
135
+ rules: summarizeStatementsByIds(graph, rules),
136
+ orchestrations: summarizeStatementsByIds(graph, orchestrations),
137
+ operations: summarizeStatementsByIds(graph, operations),
138
+ decisions: summarizeStatementsByIds(graph, decisions),
139
+ projections: summarizeStatementsByIds(graph, projections)
140
+ },
141
+ verification: summarizeStatementsByIds(graph, verifications),
142
+ verification_targets: verificationTargets,
143
+ write_scope: buildDefaultWriteScope(),
144
+ review_boundary: reviewBoundaryForDomain(),
145
+ ownership_boundary: defaultOwnershipBoundary()
146
+ };
147
+ }
148
+
149
+ // Phase 2 — SDLC slices.
150
+ //
151
+ // SDLC slices follow the same shape as feature slices: focus + summary +
152
+ // depends_on + related + verification + write_scope + review_boundary. They
153
+ // give an agent a single payload covering an artifact's chain (pitch →
154
+ // requirement → AC → task → bug → verification → document) without
155
+ // re-walking the graph.
156
+
157
+ /**
158
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
159
+ * @param {string} pitchId
160
+ * @returns {any}
161
+ */
162
+ export function pitchSlice(graph, pitchId) {
163
+ const pitch = pitchById(graph, pitchId);
164
+ if (!pitch) throw new Error(`No pitch found with id '${pitchId}'`);
165
+
166
+ const requirements = (pitch.requirements || []).slice().sort();
167
+ const decisions = [
168
+ ...(pitch.decisions || []).map(/** @param {any} d */ (d) => (typeof d === "string" ? d : d?.id)).filter(Boolean),
169
+ ...(pitch.decisionsFromPitch || [])
170
+ ];
171
+ const decisionIds = [...new Set(decisions)].sort();
172
+ const affects = (pitch.affects || []).map(/** @param {any} a */ (a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
173
+ const verifications = verificationIdsForTarget(graph, [pitchId, ...affects]);
174
+
175
+ return {
176
+ type: "context_slice",
177
+ version: 1,
178
+ focus: { kind: "pitch", id: pitchId },
179
+ summary: summarizePitch(pitch),
180
+ depends_on: {
181
+ requirements,
182
+ decisions: decisionIds,
183
+ affects,
184
+ verifications
185
+ },
186
+ related: {
187
+ requirements: summarizeStatementsByIds(graph, requirements),
188
+ decisions: summarizeStatementsByIds(graph, decisionIds),
189
+ affects: summarizeStatementsByIds(graph, affects)
190
+ },
191
+ verification: summarizeStatementsByIds(graph, verifications),
192
+ verification_targets: recommendedVerificationTargets(graph, [pitchId, ...affects], {
193
+ rationale: "Pitch slice covers verification touching any of its affected surfaces."
194
+ }),
195
+ write_scope: buildDefaultWriteScope(),
196
+ review_boundary: reviewBoundaryForPitch(),
197
+ ownership_boundary: defaultOwnershipBoundary()
198
+ };
199
+ }
200
+
201
+ /**
202
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
203
+ * @param {string} requirementId
204
+ * @returns {any}
205
+ */
206
+ export function requirementSlice(graph, requirementId) {
207
+ const req = requirementById(graph, requirementId);
208
+ if (!req) throw new Error(`No requirement found with id '${requirementId}'`);
209
+
210
+ const acceptance = (req.acceptanceCriteria || []).slice().sort();
211
+ const tasks = (req.tasks || []).slice().sort();
212
+ const documents = (req.documents || []).slice().sort();
213
+ const rules = (req.rules || []).slice().sort();
214
+ const introducesRules = (req.introducesRules || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
215
+ const respectsRules = (req.respectsRules || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
216
+ const affects = (req.affects || []).map(/** @param {any} a */ (a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
217
+ const verifications = verificationIdsForTarget(graph, [requirementId, ...affects, ...acceptance]);
218
+
219
+ return {
220
+ type: "context_slice",
221
+ version: 1,
222
+ focus: { kind: "requirement", id: requirementId },
223
+ summary: summarizeRequirement(req),
224
+ depends_on: {
225
+ pitch: req.pitch?.id || null,
226
+ acceptance_criteria: acceptance,
227
+ tasks,
228
+ documents,
229
+ rules,
230
+ introduces_rules: introducesRules,
231
+ respects_rules: respectsRules,
232
+ affects,
233
+ verifications
234
+ },
235
+ related: {
236
+ acceptance_criteria: summarizeStatementsByIds(graph, acceptance),
237
+ tasks: summarizeStatementsByIds(graph, tasks),
238
+ rules: summarizeStatementsByIds(graph, [...rules, ...introducesRules, ...respectsRules]),
239
+ affects: summarizeStatementsByIds(graph, affects),
240
+ documents: summarizeDocsByIds(graph, documents)
241
+ },
242
+ verification: summarizeStatementsByIds(graph, verifications),
243
+ verification_targets: recommendedVerificationTargets(graph, [requirementId, ...affects, ...acceptance], {
244
+ rationale: "Requirement slice covers verification tied to its acceptance criteria and affected surfaces."
245
+ }),
246
+ write_scope: buildDefaultWriteScope(),
247
+ review_boundary: reviewBoundaryForRequirement(),
248
+ ownership_boundary: defaultOwnershipBoundary()
249
+ };
250
+ }
251
+
252
+ /**
253
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
254
+ * @param {string} acId
255
+ * @returns {any}
256
+ */
257
+ export function acceptanceCriterionSlice(graph, acId) {
258
+ const ac = acceptanceCriterionById(graph, acId);
259
+ if (!ac) throw new Error(`No acceptance_criterion found with id '${acId}'`);
260
+
261
+ const tasks = (ac.tasks || []).slice().sort();
262
+ const verifications = (ac.verifications || []).slice().sort();
263
+ const requirementId = ac.requirement?.id || null;
264
+
265
+ return {
266
+ type: "context_slice",
267
+ version: 1,
268
+ focus: { kind: "acceptance_criterion", id: acId },
269
+ summary: summarizeAcceptanceCriterion(ac),
270
+ depends_on: {
271
+ requirement: requirementId,
272
+ tasks,
273
+ verifications
274
+ },
275
+ related: {
276
+ tasks: summarizeStatementsByIds(graph, tasks),
277
+ requirement: requirementId ? summarizeStatementsByIds(graph, [requirementId]) : []
278
+ },
279
+ verification: summarizeStatementsByIds(graph, verifications),
280
+ verification_targets: recommendedVerificationTargets(graph, [acId, ...(requirementId ? [requirementId] : [])], {
281
+ rationale: "AC slice points at verification proving this acceptance criterion."
282
+ }),
283
+ write_scope: buildDefaultWriteScope(),
284
+ review_boundary: reviewBoundaryForAcceptanceCriterion(),
285
+ ownership_boundary: defaultOwnershipBoundary()
286
+ };
287
+ }
288
+
289
+ /**
290
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
291
+ * @param {string} taskId
292
+ * @returns {any}
293
+ */
294
+ export function taskSlice(graph, taskId) {
295
+ const task = taskById(graph, taskId);
296
+ if (!task) throw new Error(`No task found with id '${taskId}'`);
297
+
298
+ const satisfies = (task.satisfies || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
299
+ const acRefs = (task.acceptanceRefs || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
300
+ const blockedBy = (task.blockedBy || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
301
+ const blocks = (task.blocks || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
302
+ const affects = (task.affects || []).map(/** @param {any} a */ (a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
303
+ const verifications = verificationIdsForTarget(graph, [taskId, ...affects, ...acRefs]);
304
+
305
+ return {
306
+ type: "context_slice",
307
+ version: 1,
308
+ focus: { kind: "task", id: taskId },
309
+ summary: summarizeTask(task),
310
+ depends_on: {
311
+ satisfies,
312
+ acceptance_refs: acRefs,
313
+ blocked_by: blockedBy,
314
+ blocks,
315
+ affects,
316
+ verifications
317
+ },
318
+ related: {
319
+ satisfies: summarizeStatementsByIds(graph, satisfies),
320
+ acceptance_refs: summarizeStatementsByIds(graph, acRefs),
321
+ blocked_by: summarizeStatementsByIds(graph, blockedBy),
322
+ affects: summarizeStatementsByIds(graph, affects)
323
+ },
324
+ verification: summarizeStatementsByIds(graph, verifications),
325
+ verification_targets: recommendedVerificationTargets(graph, [taskId, ...affects, ...acRefs], {
326
+ rationale: "Task slice points at verification covering the surfaces this task touches."
327
+ }),
328
+ write_scope: buildDefaultWriteScope(),
329
+ review_boundary: reviewBoundaryForTask(),
330
+ ownership_boundary: defaultOwnershipBoundary()
331
+ };
332
+ }
333
+
334
+ /**
335
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
336
+ * @param {string} bugId
337
+ * @returns {any}
338
+ */
339
+ export function bugSlice(graph, bugId) {
340
+ const bug = bugById(graph, bugId);
341
+ if (!bug) throw new Error(`No bug found with id '${bugId}'`);
342
+
343
+ const violates = (bug.violates || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
344
+ const surfacesRule = (bug.surfacesRule || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
345
+ const fixedIn = (bug.fixedIn || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
346
+ const fixedInVerification = (bug.fixedInVerification || []).map(/** @param {any} r */ (r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
347
+ const verifiedBy = (bug.verifiedBy || []).slice().sort();
348
+ const affects = (bug.affects || []).map(/** @param {any} a */ (a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
349
+ const verifications = [...new Set([...fixedInVerification, ...verifiedBy, ...verificationIdsForTarget(graph, [bugId, ...affects])])].sort();
350
+
351
+ return {
352
+ type: "context_slice",
353
+ version: 1,
354
+ focus: { kind: "bug", id: bugId },
355
+ summary: summarizeBug(bug),
356
+ depends_on: {
357
+ violates,
358
+ surfaces_rule: surfacesRule,
359
+ fixed_in: fixedIn,
360
+ fixed_in_verification: fixedInVerification,
361
+ affects,
362
+ verifications
363
+ },
364
+ related: {
365
+ violates: summarizeStatementsByIds(graph, violates),
366
+ affects: summarizeStatementsByIds(graph, affects),
367
+ fixed_in: summarizeStatementsByIds(graph, fixedIn)
368
+ },
369
+ verification: summarizeStatementsByIds(graph, verifications),
370
+ verification_targets: recommendedVerificationTargets(graph, [bugId, ...affects, ...violates], {
371
+ rationale: "Bug slice points at verification proving the regression is closed."
372
+ }),
373
+ write_scope: buildDefaultWriteScope(),
374
+ review_boundary: reviewBoundaryForBug(),
375
+ ownership_boundary: defaultOwnershipBoundary()
376
+ };
377
+ }
378
+
379
+ /**
380
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
381
+ * @param {string} documentId
382
+ * @returns {any}
383
+ */
384
+ export function documentSlice(graph, documentId) {
385
+ const doc = documentById(graph, documentId);
386
+ if (!doc) throw new Error(`No document found with id '${documentId}'`);
387
+
388
+ const relatedEntities = (doc.relatedEntities || []).slice().sort();
389
+ const relatedCapabilities = (doc.relatedCapabilities || []).slice().sort();
390
+ const relatedProjections = (doc.relatedProjections || []).slice().sort();
391
+ const relatedRules = (doc.relatedRules || []).slice().sort();
392
+
393
+ return {
394
+ type: "context_slice",
395
+ version: 1,
396
+ focus: { kind: "document", id: documentId },
397
+ summary: summarizeDocument(doc),
398
+ depends_on: {
399
+ related_entities: relatedEntities,
400
+ related_capabilities: relatedCapabilities,
401
+ related_projections: relatedProjections,
402
+ related_rules: relatedRules
403
+ },
404
+ related: {
405
+ entities: summarizeStatementsByIds(graph, relatedEntities),
406
+ capabilities: summarizeStatementsByIds(graph, relatedCapabilities),
407
+ projections: summarizeStatementsByIds(graph, relatedProjections),
408
+ rules: summarizeStatementsByIds(graph, relatedRules)
409
+ },
410
+ verification: [],
411
+ verification_targets: [],
412
+ write_scope: buildDefaultWriteScope(),
413
+ review_boundary: reviewBoundaryForDocument(doc),
414
+ ownership_boundary: defaultOwnershipBoundary()
415
+ };
416
+ }
417
+
@@ -0,0 +1,183 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
5
+ * @param {import("../shared/types.d.ts").ContextProjection} projection
6
+ * @returns {any}
7
+ */
8
+ export function uiAgentPacketForProjection(graph, projection) {
9
+ const projectionType = projection.type || projection.type || null;
10
+ if (projectionType !== "ui_contract" && !String(projectionType || "").endsWith("_surface")) {
11
+ return null;
12
+ }
13
+ const sharedProjection = projectionType === "ui_contract"
14
+ ? projection
15
+ : sharedUiProjectionFor(graph, projection);
16
+ const ownerProjection = sharedProjection || projection;
17
+ return {
18
+ type: "ui_agent_packet",
19
+ version: 1,
20
+ ownership: {
21
+ widgetPlacement: "ui_contract",
22
+ designIntent: "ui_contract",
23
+ concreteSurfaceOwns: ["routes", "surface_hints"]
24
+ },
25
+ sharedProjection: sharedProjection
26
+ ? {
27
+ id: sharedProjection.id,
28
+ name: sharedProjection.name || sharedProjection.id
29
+ }
30
+ : null,
31
+ screens: (ownerProjection.uiScreens || []).map(/** @param {any} screen */ (screen) => ({
32
+ id: screen.id,
33
+ kind: screen.kind,
34
+ title: screen.title || screen.id
35
+ })),
36
+ routes: (projection.uiRoutes || []).map(/** @param {any} route */ (route) => ({
37
+ screenId: route.screenId,
38
+ path: route.path
39
+ })),
40
+ widgets: (ownerProjection.widgetBindings || []).map(/** @param {import("../shared/types.d.ts").ContextWidgetUsage} usage */ (usage) => widgetUsagePacket(usage, ownerProjection)),
41
+ designTokens: designIntentPacket(ownerProjection),
42
+ requiredGates: uiRequiredGates(projection.id)
43
+ };
44
+ }
45
+
46
+ /**
47
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
48
+ * @param {import("../shared/types.d.ts").ContextWidget} widget
49
+ * @param {Iterable<string>} projectionIds
50
+ * @returns {any}
51
+ */
52
+ export function uiAgentPacketForWidget(graph, widget, projectionIds) {
53
+ const projectionSet = new Set(projectionIds);
54
+ const sourceUsages = /** @type {any[]} */ ([]);
55
+ for (const projection of graph.byKind.projection || []) {
56
+ for (const usage of projection.widgetBindings || []) {
57
+ if (usage.widget?.id !== widget.id) continue;
58
+ const projectionType = projection.type || projection.type || null;
59
+ sourceUsages.push({
60
+ projection: {
61
+ id: projection.id,
62
+ type: projectionType,
63
+ ownership: projectionType === "ui_contract" ? "owner" : "concrete"
64
+ },
65
+ usage: widgetUsagePacket(usage, projection),
66
+ designTokens: designIntentPacket(projection)
67
+ });
68
+ projectionSet.add(projection.id);
69
+ }
70
+ }
71
+
72
+ return {
73
+ type: "ui_agent_packet",
74
+ version: 1,
75
+ ownership: {
76
+ widgetContract: "widget",
77
+ widgetPlacement: "ui_contract",
78
+ concreteSurfacesInherit: true
79
+ },
80
+ widget: {
81
+ id: widget.id,
82
+ name: widget.name || widget.id,
83
+ category: widget.category || null,
84
+ patterns: widget.widgetContract?.patterns || [],
85
+ regions: widget.widgetContract?.regions || [],
86
+ behaviors: widget.widgetContract?.behaviors || []
87
+ },
88
+ sourceUsages,
89
+ inheritedBy: [...projectionSet]
90
+ .filter((projectionId) => !sourceUsages.some(/** @param {any} entry */ (entry) => entry.projection.id === projectionId))
91
+ .sort(),
92
+ requiredGates: uiRequiredGates(null, widget.id)
93
+ };
94
+ }
95
+
96
+ /**
97
+ * @param {import("../shared/types.d.ts").ContextGraph} graph
98
+ * @param {import("../shared/types.d.ts").ContextProjection} projection
99
+ * @returns {any}
100
+ */
101
+ function sharedUiProjectionFor(graph, projection) {
102
+ for (const reference of projection.realizes || []) {
103
+ const candidate = (graph.byKind.projection || []).find(/** @param {any} entry */ (entry) => entry.id === reference.id);
104
+ if ((candidate?.type || candidate?.type) === "ui_contract") {
105
+ return candidate;
106
+ }
107
+ }
108
+ return null;
109
+ }
110
+
111
+ /**
112
+ * @param {import("../shared/types.d.ts").ContextWidgetUsage} usage
113
+ * @param {import("../shared/types.d.ts").ContextProjection | null} projection
114
+ * @returns {any}
115
+ */
116
+ function widgetUsagePacket(usage, projection = null) {
117
+ const screen = (projection?.uiScreens || []).find(/** @param {any} entry */ (entry) => entry.id === usage.screenId) || null;
118
+ const region = (projection?.uiScreenRegions || []).find(/** @param {any} entry */ (entry) =>
119
+ entry.screenId === usage.screenId && entry.region === usage.region
120
+ ) || null;
121
+ return {
122
+ screenId: usage.screenId || null,
123
+ screen: screen
124
+ ? {
125
+ id: screen.id,
126
+ kind: screen.kind || null,
127
+ title: screen.title || screen.id
128
+ }
129
+ : null,
130
+ region: usage.region || null,
131
+ regionContract: region
132
+ ? {
133
+ name: region.region || null,
134
+ pattern: region.pattern || null,
135
+ placement: region.placement || null,
136
+ title: region.title || null,
137
+ state: region.state || null,
138
+ variant: region.variant || null
139
+ }
140
+ : null,
141
+ widgetId: usage.widget?.id || null,
142
+ dataBindings: (usage.dataBindings || []).map(/** @param {any} binding */ (binding) => ({
143
+ prop: binding.prop || null,
144
+ source: binding.source?.id || binding.source || null
145
+ })),
146
+ eventBindings: (usage.eventBindings || []).map(/** @param {any} binding */ (binding) => ({
147
+ event: binding.event || null,
148
+ action: binding.action || null,
149
+ target: binding.target?.id || binding.target || null
150
+ }))
151
+ };
152
+ }
153
+
154
+ /**
155
+ * @param {import("../shared/types.d.ts").ContextProjection} projection
156
+ * @returns {any}
157
+ */
158
+ function designIntentPacket(projection) {
159
+ return (projection.uiDesign || []).map(/** @param {any} entry */ (entry) => ({
160
+ key: entry.key,
161
+ role: entry.role,
162
+ value: entry.value
163
+ }));
164
+ }
165
+
166
+ /**
167
+ * @param {string | null} projectionId
168
+ * @param {string | null} widgetId
169
+ * @returns {any}
170
+ */
171
+ function uiRequiredGates(projectionId = null, widgetId = null) {
172
+ return [
173
+ { command: "topogram check", reason: "Validate shared UI ownership, taxonomy, references, and topology." },
174
+ {
175
+ command: `topogram widget check${projectionId ? ` --projection ${projectionId}` : ""}${widgetId ? ` --widget ${widgetId}` : ""}`,
176
+ reason: "Validate widget placement, props, events, regions, and patterns."
177
+ },
178
+ {
179
+ command: `topogram widget behavior${projectionId ? ` --projection ${projectionId}` : ""}${widgetId ? ` --widget ${widgetId}` : ""}`,
180
+ reason: "Inspect behavior realizations and partial bindings before code changes."
181
+ }
182
+ ];
183
+ }