@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,703 @@
1
+ import {
2
+ acceptanceCriterionById,
3
+ bugById,
4
+ buildDefaultWriteScope,
5
+ componentById,
6
+ documentById,
7
+ domainById,
8
+ ensureContextSelection,
9
+ getJourneyDoc,
10
+ getStatement,
11
+ getWorkflowDoc,
12
+ pitchById,
13
+ relatedCapabilitiesForEntity,
14
+ relatedCapabilitiesForProjection,
15
+ relatedEntitiesForDomain,
16
+ relatedComponentsForProjection,
17
+ relatedJourneysForCapability,
18
+ relatedProjectionsForCapability,
19
+ relatedProjectionsForComponent,
20
+ relatedProjectionsForDomain,
21
+ relatedProjectionsForEntity,
22
+ relatedRulesForDomain,
23
+ relatedRulesForTarget,
24
+ relatedShapesForComponent,
25
+ relatedShapesForEntity,
26
+ relatedShapesForProjection,
27
+ relatedVerificationsForDomain,
28
+ relatedWorkflowDocsForCapability,
29
+ relatedEntitiesForProjection,
30
+ recommendedVerificationTargets,
31
+ requirementById,
32
+ summarizeAcceptanceCriterion,
33
+ summarizeBug,
34
+ summarizeById,
35
+ summarizeDocsByIds,
36
+ summarizeDocument,
37
+ summarizeDomain,
38
+ summarizePitch,
39
+ summarizeProjection,
40
+ summarizeRequirement,
41
+ summarizeStatementsByIds,
42
+ summarizeTask,
43
+ taskById,
44
+ verificationIdsForTarget
45
+ } from "./shared.js";
46
+ import {
47
+ defaultOwnershipBoundary,
48
+ reviewBoundaryForAcceptanceCriterion,
49
+ reviewBoundaryForBug,
50
+ reviewBoundaryForCapability,
51
+ reviewBoundaryForDocument,
52
+ reviewBoundaryForDomain,
53
+ reviewBoundaryForEntity,
54
+ reviewBoundaryForJourneyDoc,
55
+ reviewBoundaryForPitch,
56
+ reviewBoundaryForRequirement,
57
+ reviewBoundaryForTask,
58
+ reviewBoundaryForWorkflowDoc
59
+ } from "../../policy/review-boundaries.js";
60
+
61
+ function capabilitySlice(graph, capabilityId) {
62
+ const capability = getStatement(graph, "capability", capabilityId);
63
+ const shapes = [...new Set([...(capability.input || []).map((item) => item.id), ...(capability.output || []).map((item) => item.id)])].sort();
64
+ const entities = [...new Set([
65
+ ...(capability.reads || []).map((item) => item.id),
66
+ ...(capability.creates || []).map((item) => item.id),
67
+ ...(capability.updates || []).map((item) => item.id),
68
+ ...(capability.deletes || []).map((item) => item.id)
69
+ ])].sort();
70
+ const rules = relatedRulesForTarget(graph, capabilityId);
71
+ const workflows = relatedWorkflowDocsForCapability(graph, capabilityId).map((doc) => doc.id).sort();
72
+ const projections = relatedProjectionsForCapability(graph, capabilityId);
73
+ const journeys = relatedJourneysForCapability(graph, capabilityId).map((doc) => doc.id).sort();
74
+ const verifications = verificationIdsForTarget(graph, [capabilityId, ...projections, ...shapes, ...entities]);
75
+
76
+ return {
77
+ type: "context_slice",
78
+ version: 1,
79
+ focus: {
80
+ kind: "capability",
81
+ id: capabilityId
82
+ },
83
+ summary: summarizeById(graph, capabilityId),
84
+ depends_on: {
85
+ shapes,
86
+ entities,
87
+ rules,
88
+ workflows,
89
+ projections,
90
+ journeys,
91
+ verifications
92
+ },
93
+ related: {
94
+ shapes: summarizeStatementsByIds(graph, shapes),
95
+ entities: summarizeStatementsByIds(graph, entities),
96
+ rules: summarizeStatementsByIds(graph, rules),
97
+ workflows: summarizeDocsByIds(graph, workflows),
98
+ journeys: summarizeDocsByIds(graph, journeys),
99
+ projections: summarizeStatementsByIds(graph, projections)
100
+ },
101
+ verification: summarizeStatementsByIds(graph, verifications),
102
+ verification_targets: recommendedVerificationTargets(graph, [capabilityId, ...projections, ...shapes, ...entities], {
103
+ rationale: "Capability slice should point agents at the smallest verification set covering affected API/UI/DB surfaces."
104
+ }),
105
+ write_scope: buildDefaultWriteScope(),
106
+ review_boundary: reviewBoundaryForCapability(capability),
107
+ ownership_boundary: defaultOwnershipBoundary()
108
+ };
109
+ }
110
+
111
+ function workflowSlice(graph, workflowId) {
112
+ const workflow = getWorkflowDoc(graph, workflowId);
113
+ const capabilities = [...(workflow.relatedCapabilities || [])].sort();
114
+ const entities = [...new Set(capabilities.flatMap((capabilityId) => {
115
+ const capability = getStatement(graph, "capability", capabilityId);
116
+ return [
117
+ ...(capability.reads || []).map((item) => item.id),
118
+ ...(capability.creates || []).map((item) => item.id),
119
+ ...(capability.updates || []).map((item) => item.id),
120
+ ...(capability.deletes || []).map((item) => item.id)
121
+ ];
122
+ }))].sort();
123
+ const rules = [...new Set(capabilities.flatMap((capabilityId) => relatedRulesForTarget(graph, capabilityId)))].sort();
124
+ const journeys = (graph.docs || [])
125
+ .filter((doc) => doc.kind === "journey" && (doc.relatedWorkflows || []).includes(workflowId))
126
+ .map((doc) => doc.id)
127
+ .sort();
128
+ const verifications = verificationIdsForTarget(graph, [...capabilities, ...entities, workflowId]);
129
+
130
+ return {
131
+ type: "context_slice",
132
+ version: 1,
133
+ focus: {
134
+ kind: "workflow",
135
+ id: workflowId
136
+ },
137
+ summary: summarizeById(graph, workflowId),
138
+ depends_on: {
139
+ capabilities,
140
+ entities,
141
+ rules,
142
+ journeys,
143
+ verifications
144
+ },
145
+ related: {
146
+ capabilities: summarizeStatementsByIds(graph, capabilities),
147
+ entities: summarizeStatementsByIds(graph, entities),
148
+ rules: summarizeStatementsByIds(graph, rules),
149
+ journeys: summarizeDocsByIds(graph, journeys)
150
+ },
151
+ verification: summarizeStatementsByIds(graph, verifications),
152
+ verification_targets: recommendedVerificationTargets(graph, [...capabilities, ...entities, workflowId], {
153
+ rationale: "Workflow changes should re-run workflow-linked verification and human review on semantic behavior."
154
+ }),
155
+ write_scope: buildDefaultWriteScope(),
156
+ review_boundary: reviewBoundaryForWorkflowDoc(workflow),
157
+ ownership_boundary: defaultOwnershipBoundary()
158
+ };
159
+ }
160
+
161
+ function projectionSlice(graph, projectionId) {
162
+ const projection = getStatement(graph, "projection", projectionId);
163
+ const capabilities = relatedCapabilitiesForProjection(projection);
164
+ const entities = relatedEntitiesForProjection(projection);
165
+ const shapes = relatedShapesForProjection(projection);
166
+ const components = relatedComponentsForProjection(graph, projection);
167
+ const rules = [...new Set(capabilities.flatMap((capabilityId) => relatedRulesForTarget(graph, capabilityId)))].sort();
168
+ const verifications = verificationIdsForTarget(graph, [projectionId, ...capabilities, ...entities, ...shapes, ...components]);
169
+
170
+ return {
171
+ type: "context_slice",
172
+ version: 1,
173
+ focus: {
174
+ kind: "projection",
175
+ id: projectionId
176
+ },
177
+ summary: summarizeProjection(projection),
178
+ depends_on: {
179
+ entities,
180
+ shapes,
181
+ capabilities,
182
+ components,
183
+ rules,
184
+ verifications
185
+ },
186
+ related: {
187
+ entities: summarizeStatementsByIds(graph, entities),
188
+ shapes: summarizeStatementsByIds(graph, shapes),
189
+ capabilities: summarizeStatementsByIds(graph, capabilities),
190
+ components: summarizeStatementsByIds(graph, components),
191
+ rules: summarizeStatementsByIds(graph, rules)
192
+ },
193
+ verification: summarizeStatementsByIds(graph, verifications),
194
+ verification_targets: recommendedVerificationTargets(graph, [projectionId, ...capabilities, ...entities, ...shapes, ...components], {
195
+ rationale: "Projection slices affect generated contract and runtime surfaces, so verification should follow the projection closure."
196
+ }),
197
+ write_scope: buildDefaultWriteScope(),
198
+ review_boundary: projection.reviewBoundary || {
199
+ automation_class: "review_required",
200
+ reasons: ["projection_surface"]
201
+ },
202
+ ownership_boundary: defaultOwnershipBoundary()
203
+ };
204
+ }
205
+
206
+ function entitySlice(graph, entityId) {
207
+ const entity = getStatement(graph, "entity", entityId);
208
+ const shapes = relatedShapesForEntity(graph, entityId);
209
+ const capabilities = relatedCapabilitiesForEntity(graph, entityId);
210
+ const rules = [...new Set([
211
+ ...relatedRulesForTarget(graph, entityId),
212
+ ...capabilities.flatMap((capabilityId) => relatedRulesForTarget(graph, capabilityId))
213
+ ])].sort();
214
+ const projections = relatedProjectionsForEntity(graph, entityId);
215
+ const verifications = verificationIdsForTarget(graph, [entityId, ...shapes, ...capabilities, ...projections]);
216
+
217
+ return {
218
+ type: "context_slice",
219
+ version: 1,
220
+ focus: {
221
+ kind: "entity",
222
+ id: entityId
223
+ },
224
+ summary: summarizeById(graph, entityId),
225
+ depends_on: {
226
+ shapes,
227
+ capabilities,
228
+ rules,
229
+ projections,
230
+ verifications
231
+ },
232
+ related: {
233
+ shapes: summarizeStatementsByIds(graph, shapes),
234
+ capabilities: summarizeStatementsByIds(graph, capabilities),
235
+ rules: summarizeStatementsByIds(graph, rules),
236
+ projections: summarizeStatementsByIds(graph, projections)
237
+ },
238
+ verification: summarizeStatementsByIds(graph, verifications),
239
+ verification_targets: recommendedVerificationTargets(graph, [entityId, ...shapes, ...capabilities, ...projections], {
240
+ rationale: "Entity changes usually affect schema, projection, and capability semantics together."
241
+ }),
242
+ write_scope: buildDefaultWriteScope(),
243
+ review_boundary: reviewBoundaryForEntity(entity),
244
+ ownership_boundary: defaultOwnershipBoundary()
245
+ };
246
+ }
247
+
248
+ function componentSlice(graph, componentId) {
249
+ const component = componentById(graph, componentId);
250
+ if (!component) {
251
+ throw new Error(`No component found with id '${componentId}'`);
252
+ }
253
+ const dependencyIds = componentDependencyIdsByKind(component);
254
+ const shapes = relatedShapesForComponent(component);
255
+ const entities = dependencyIds.entity;
256
+ const capabilities = dependencyIds.capability;
257
+ const projections = relatedProjectionsForComponent(graph, componentId);
258
+ const componentDependencies = dependencyIds.component;
259
+ const verificationScope = [componentId, ...shapes, ...entities, ...capabilities, ...projections, ...componentDependencies];
260
+ const verifications = verificationIdsForTarget(graph, verificationScope);
261
+
262
+ return {
263
+ type: "context_slice",
264
+ version: 1,
265
+ focus: {
266
+ kind: "component",
267
+ id: componentId
268
+ },
269
+ summary: summarizeById(graph, componentId),
270
+ depends_on: {
271
+ shapes,
272
+ entities,
273
+ capabilities,
274
+ components: componentDependencies,
275
+ projections,
276
+ verifications
277
+ },
278
+ related: {
279
+ shapes: summarizeStatementsByIds(graph, shapes),
280
+ entities: summarizeStatementsByIds(graph, entities),
281
+ capabilities: summarizeStatementsByIds(graph, capabilities),
282
+ components: summarizeStatementsByIds(graph, componentDependencies),
283
+ projections: summarizeStatementsByIds(graph, projections)
284
+ },
285
+ verification: summarizeStatementsByIds(graph, verifications),
286
+ verification_targets: recommendedVerificationTargets(graph, verificationScope, {
287
+ rationale: "Component changes affect every related projection — verification should follow the component contract closure."
288
+ }),
289
+ write_scope: buildDefaultWriteScope(),
290
+ review_boundary: {
291
+ automation_class: "review_required",
292
+ reasons: ["component_surface"]
293
+ },
294
+ ownership_boundary: defaultOwnershipBoundary()
295
+ };
296
+ }
297
+
298
+ function componentDependencyIdsByKind(component) {
299
+ const ids = {
300
+ shape: [],
301
+ entity: [],
302
+ capability: [],
303
+ projection: [],
304
+ component: []
305
+ };
306
+
307
+ for (const dependency of component.dependencies || []) {
308
+ const kind = componentDependencyKind(dependency);
309
+ if (kind && Object.hasOwn(ids, kind)) {
310
+ ids[kind].push(dependency.id);
311
+ }
312
+ }
313
+
314
+ return Object.fromEntries(
315
+ Object.entries(ids).map(([kind, values]) => [kind, [...new Set(values.filter(Boolean))].sort()])
316
+ );
317
+ }
318
+
319
+ function componentDependencyKind(dependency) {
320
+ if (dependency?.target?.kind) {
321
+ return dependency.target.kind;
322
+ }
323
+ const id = String(dependency?.id || "");
324
+ const prefix = id.split("_")[0];
325
+ if (prefix === "proj") {
326
+ return "projection";
327
+ }
328
+ if (prefix === "cap") {
329
+ return "capability";
330
+ }
331
+ return prefix || null;
332
+ }
333
+
334
+ function journeySlice(graph, journeyId) {
335
+ const journey = getJourneyDoc(graph, journeyId);
336
+ const capabilities = [...(journey.relatedCapabilities || [])].sort();
337
+ const workflows = [...(journey.relatedWorkflows || [])].sort();
338
+ const projections = [...(journey.relatedProjections || [])].sort();
339
+ const verifications = verificationIdsForTarget(graph, [...capabilities, ...workflows, ...projections, journeyId]);
340
+
341
+ return {
342
+ type: "context_slice",
343
+ version: 1,
344
+ focus: {
345
+ kind: "journey",
346
+ id: journeyId
347
+ },
348
+ summary: summarizeById(graph, journeyId),
349
+ depends_on: {
350
+ capabilities,
351
+ workflows,
352
+ projections,
353
+ verifications
354
+ },
355
+ related: {
356
+ capabilities: summarizeStatementsByIds(graph, capabilities),
357
+ workflows: summarizeDocsByIds(graph, workflows),
358
+ projections: summarizeStatementsByIds(graph, projections)
359
+ },
360
+ verification: summarizeStatementsByIds(graph, verifications),
361
+ verification_targets: recommendedVerificationTargets(graph, [...capabilities, ...workflows, ...projections, journeyId], {
362
+ rationale: "Journey slices should target workflow-facing verification rather than a full workspace rerun."
363
+ }),
364
+ write_scope: buildDefaultWriteScope(),
365
+ review_boundary: reviewBoundaryForJourneyDoc(journey),
366
+ ownership_boundary: defaultOwnershipBoundary()
367
+ };
368
+ }
369
+
370
+ function domainSlice(graph, domainId) {
371
+ const domain = domainById(graph, domainId);
372
+ if (!domain) {
373
+ throw new Error(`No domain found with id '${domainId}'`);
374
+ }
375
+ const capabilities = [...(domain.members?.capabilities || [])].sort();
376
+ const entities = relatedEntitiesForDomain(graph, domainId);
377
+ const rules = relatedRulesForDomain(graph, domainId);
378
+ const verifications = relatedVerificationsForDomain(graph, domainId);
379
+ const orchestrations = [...(domain.members?.orchestrations || [])].sort();
380
+ const operations = [...(domain.members?.operations || [])].sort();
381
+ const decisions = [...(domain.members?.decisions || [])].sort();
382
+ const projections = relatedProjectionsForDomain(graph, domainId);
383
+
384
+ // Verification targets cover the union of capability/entity/projection IDs in
385
+ // the domain so a domain-scoped change re-runs the right verification set
386
+ // without pulling in the whole workspace.
387
+ const verificationTargets = recommendedVerificationTargets(
388
+ graph,
389
+ [domainId, ...capabilities, ...entities, ...projections],
390
+ {
391
+ rationale:
392
+ "Domain slices should re-run verification covering the domain's capabilities, entities, and platform projections."
393
+ }
394
+ );
395
+
396
+ return {
397
+ type: "context_slice",
398
+ version: 1,
399
+ focus: {
400
+ kind: "domain",
401
+ id: domainId
402
+ },
403
+ summary: summarizeDomain(domain),
404
+ depends_on: {
405
+ capabilities,
406
+ entities,
407
+ rules,
408
+ verifications,
409
+ orchestrations,
410
+ operations,
411
+ decisions,
412
+ projections
413
+ },
414
+ related: {
415
+ capabilities: summarizeStatementsByIds(graph, capabilities),
416
+ entities: summarizeStatementsByIds(graph, entities),
417
+ rules: summarizeStatementsByIds(graph, rules),
418
+ orchestrations: summarizeStatementsByIds(graph, orchestrations),
419
+ operations: summarizeStatementsByIds(graph, operations),
420
+ decisions: summarizeStatementsByIds(graph, decisions),
421
+ projections: summarizeStatementsByIds(graph, projections)
422
+ },
423
+ verification: summarizeStatementsByIds(graph, verifications),
424
+ verification_targets: verificationTargets,
425
+ write_scope: buildDefaultWriteScope(),
426
+ review_boundary: reviewBoundaryForDomain(),
427
+ ownership_boundary: defaultOwnershipBoundary()
428
+ };
429
+ }
430
+
431
+ // Phase 2 — SDLC slices.
432
+ //
433
+ // SDLC slices follow the same shape as feature slices: focus + summary +
434
+ // depends_on + related + verification + write_scope + review_boundary. They
435
+ // give an agent a single payload covering an artifact's chain (pitch →
436
+ // requirement → AC → task → bug → verification → document) without
437
+ // re-walking the graph.
438
+
439
+ function pitchSlice(graph, pitchId) {
440
+ const pitch = pitchById(graph, pitchId);
441
+ if (!pitch) throw new Error(`No pitch found with id '${pitchId}'`);
442
+
443
+ const requirements = (pitch.requirements || []).slice().sort();
444
+ const decisions = [
445
+ ...(pitch.decisions || []).map((d) => (typeof d === "string" ? d : d?.id)).filter(Boolean),
446
+ ...(pitch.decisionsFromPitch || [])
447
+ ];
448
+ const decisionIds = [...new Set(decisions)].sort();
449
+ const affects = (pitch.affects || []).map((a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
450
+ const verifications = verificationIdsForTarget(graph, [pitchId, ...affects]);
451
+
452
+ return {
453
+ type: "context_slice",
454
+ version: 1,
455
+ focus: { kind: "pitch", id: pitchId },
456
+ summary: summarizePitch(pitch),
457
+ depends_on: {
458
+ requirements,
459
+ decisions: decisionIds,
460
+ affects,
461
+ verifications
462
+ },
463
+ related: {
464
+ requirements: summarizeStatementsByIds(graph, requirements),
465
+ decisions: summarizeStatementsByIds(graph, decisionIds),
466
+ affects: summarizeStatementsByIds(graph, affects)
467
+ },
468
+ verification: summarizeStatementsByIds(graph, verifications),
469
+ verification_targets: recommendedVerificationTargets(graph, [pitchId, ...affects], {
470
+ rationale: "Pitch slice covers verification touching any of its affected surfaces."
471
+ }),
472
+ write_scope: buildDefaultWriteScope(),
473
+ review_boundary: reviewBoundaryForPitch(),
474
+ ownership_boundary: defaultOwnershipBoundary()
475
+ };
476
+ }
477
+
478
+ function requirementSlice(graph, requirementId) {
479
+ const req = requirementById(graph, requirementId);
480
+ if (!req) throw new Error(`No requirement found with id '${requirementId}'`);
481
+
482
+ const acceptance = (req.acceptanceCriteria || []).slice().sort();
483
+ const tasks = (req.tasks || []).slice().sort();
484
+ const documents = (req.documents || []).slice().sort();
485
+ const rules = (req.rules || []).slice().sort();
486
+ const introducesRules = (req.introducesRules || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
487
+ const respectsRules = (req.respectsRules || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
488
+ const affects = (req.affects || []).map((a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
489
+ const verifications = verificationIdsForTarget(graph, [requirementId, ...affects, ...acceptance]);
490
+
491
+ return {
492
+ type: "context_slice",
493
+ version: 1,
494
+ focus: { kind: "requirement", id: requirementId },
495
+ summary: summarizeRequirement(req),
496
+ depends_on: {
497
+ pitch: req.pitch?.id || null,
498
+ acceptance_criteria: acceptance,
499
+ tasks,
500
+ documents,
501
+ rules,
502
+ introduces_rules: introducesRules,
503
+ respects_rules: respectsRules,
504
+ affects,
505
+ verifications
506
+ },
507
+ related: {
508
+ acceptance_criteria: summarizeStatementsByIds(graph, acceptance),
509
+ tasks: summarizeStatementsByIds(graph, tasks),
510
+ rules: summarizeStatementsByIds(graph, [...rules, ...introducesRules, ...respectsRules]),
511
+ affects: summarizeStatementsByIds(graph, affects),
512
+ documents: summarizeDocsByIds(graph, documents)
513
+ },
514
+ verification: summarizeStatementsByIds(graph, verifications),
515
+ verification_targets: recommendedVerificationTargets(graph, [requirementId, ...affects, ...acceptance], {
516
+ rationale: "Requirement slice covers verification tied to its acceptance criteria and affected surfaces."
517
+ }),
518
+ write_scope: buildDefaultWriteScope(),
519
+ review_boundary: reviewBoundaryForRequirement(),
520
+ ownership_boundary: defaultOwnershipBoundary()
521
+ };
522
+ }
523
+
524
+ function acceptanceCriterionSlice(graph, acId) {
525
+ const ac = acceptanceCriterionById(graph, acId);
526
+ if (!ac) throw new Error(`No acceptance_criterion found with id '${acId}'`);
527
+
528
+ const tasks = (ac.tasks || []).slice().sort();
529
+ const verifications = (ac.verifications || []).slice().sort();
530
+ const requirementId = ac.requirement?.id || null;
531
+
532
+ return {
533
+ type: "context_slice",
534
+ version: 1,
535
+ focus: { kind: "acceptance_criterion", id: acId },
536
+ summary: summarizeAcceptanceCriterion(ac),
537
+ depends_on: {
538
+ requirement: requirementId,
539
+ tasks,
540
+ verifications
541
+ },
542
+ related: {
543
+ tasks: summarizeStatementsByIds(graph, tasks),
544
+ requirement: requirementId ? summarizeStatementsByIds(graph, [requirementId]) : []
545
+ },
546
+ verification: summarizeStatementsByIds(graph, verifications),
547
+ verification_targets: recommendedVerificationTargets(graph, [acId, ...(requirementId ? [requirementId] : [])], {
548
+ rationale: "AC slice points at verification proving this acceptance criterion."
549
+ }),
550
+ write_scope: buildDefaultWriteScope(),
551
+ review_boundary: reviewBoundaryForAcceptanceCriterion(),
552
+ ownership_boundary: defaultOwnershipBoundary()
553
+ };
554
+ }
555
+
556
+ function taskSlice(graph, taskId) {
557
+ const task = taskById(graph, taskId);
558
+ if (!task) throw new Error(`No task found with id '${taskId}'`);
559
+
560
+ const satisfies = (task.satisfies || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
561
+ const acRefs = (task.acceptanceRefs || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
562
+ const blockedBy = (task.blockedBy || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
563
+ const blocks = (task.blocks || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
564
+ const affects = (task.affects || []).map((a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
565
+ const verifications = verificationIdsForTarget(graph, [taskId, ...affects, ...acRefs]);
566
+
567
+ return {
568
+ type: "context_slice",
569
+ version: 1,
570
+ focus: { kind: "task", id: taskId },
571
+ summary: summarizeTask(task),
572
+ depends_on: {
573
+ satisfies,
574
+ acceptance_refs: acRefs,
575
+ blocked_by: blockedBy,
576
+ blocks,
577
+ affects,
578
+ verifications
579
+ },
580
+ related: {
581
+ satisfies: summarizeStatementsByIds(graph, satisfies),
582
+ acceptance_refs: summarizeStatementsByIds(graph, acRefs),
583
+ blocked_by: summarizeStatementsByIds(graph, blockedBy),
584
+ affects: summarizeStatementsByIds(graph, affects)
585
+ },
586
+ verification: summarizeStatementsByIds(graph, verifications),
587
+ verification_targets: recommendedVerificationTargets(graph, [taskId, ...affects, ...acRefs], {
588
+ rationale: "Task slice points at verification covering the surfaces this task touches."
589
+ }),
590
+ write_scope: buildDefaultWriteScope(),
591
+ review_boundary: reviewBoundaryForTask(),
592
+ ownership_boundary: defaultOwnershipBoundary()
593
+ };
594
+ }
595
+
596
+ function bugSlice(graph, bugId) {
597
+ const bug = bugById(graph, bugId);
598
+ if (!bug) throw new Error(`No bug found with id '${bugId}'`);
599
+
600
+ const violates = (bug.violates || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
601
+ const surfacesRule = (bug.surfacesRule || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
602
+ const fixedIn = (bug.fixedIn || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
603
+ const fixedInVerification = (bug.fixedInVerification || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean).sort();
604
+ const verifiedBy = (bug.verifiedBy || []).slice().sort();
605
+ const affects = (bug.affects || []).map((a) => (typeof a === "string" ? a : a?.id)).filter(Boolean).sort();
606
+ const verifications = [...new Set([...fixedInVerification, ...verifiedBy, ...verificationIdsForTarget(graph, [bugId, ...affects])])].sort();
607
+
608
+ return {
609
+ type: "context_slice",
610
+ version: 1,
611
+ focus: { kind: "bug", id: bugId },
612
+ summary: summarizeBug(bug),
613
+ depends_on: {
614
+ violates,
615
+ surfaces_rule: surfacesRule,
616
+ fixed_in: fixedIn,
617
+ fixed_in_verification: fixedInVerification,
618
+ affects,
619
+ verifications
620
+ },
621
+ related: {
622
+ violates: summarizeStatementsByIds(graph, violates),
623
+ affects: summarizeStatementsByIds(graph, affects),
624
+ fixed_in: summarizeStatementsByIds(graph, fixedIn)
625
+ },
626
+ verification: summarizeStatementsByIds(graph, verifications),
627
+ verification_targets: recommendedVerificationTargets(graph, [bugId, ...affects, ...violates], {
628
+ rationale: "Bug slice points at verification proving the regression is closed."
629
+ }),
630
+ write_scope: buildDefaultWriteScope(),
631
+ review_boundary: reviewBoundaryForBug(),
632
+ ownership_boundary: defaultOwnershipBoundary()
633
+ };
634
+ }
635
+
636
+ function documentSlice(graph, documentId) {
637
+ const doc = documentById(graph, documentId);
638
+ if (!doc) throw new Error(`No document found with id '${documentId}'`);
639
+
640
+ const relatedEntities = (doc.relatedEntities || []).slice().sort();
641
+ const relatedCapabilities = (doc.relatedCapabilities || []).slice().sort();
642
+ const relatedProjections = (doc.relatedProjections || []).slice().sort();
643
+ const relatedRules = (doc.relatedRules || []).slice().sort();
644
+
645
+ return {
646
+ type: "context_slice",
647
+ version: 1,
648
+ focus: { kind: "document", id: documentId },
649
+ summary: summarizeDocument(doc),
650
+ depends_on: {
651
+ related_entities: relatedEntities,
652
+ related_capabilities: relatedCapabilities,
653
+ related_projections: relatedProjections,
654
+ related_rules: relatedRules
655
+ },
656
+ related: {
657
+ entities: summarizeStatementsByIds(graph, relatedEntities),
658
+ capabilities: summarizeStatementsByIds(graph, relatedCapabilities),
659
+ projections: summarizeStatementsByIds(graph, relatedProjections),
660
+ rules: summarizeStatementsByIds(graph, relatedRules)
661
+ },
662
+ verification: [],
663
+ verification_targets: [],
664
+ write_scope: buildDefaultWriteScope(),
665
+ review_boundary: reviewBoundaryForDocument(doc),
666
+ ownership_boundary: defaultOwnershipBoundary()
667
+ };
668
+ }
669
+
670
+ export function generateContextSlice(graph, options = {}) {
671
+ const selection = ensureContextSelection({
672
+ capabilityId: options.capabilityId,
673
+ workflowId: options.workflowId,
674
+ projectionId: options.projectionId,
675
+ componentId: options.componentId,
676
+ entityId: options.entityId,
677
+ journeyId: options.journeyId,
678
+ surfaceId: options.surfaceId,
679
+ domainId: options.domainId,
680
+ pitchId: options.pitchId,
681
+ requirementId: options.requirementId,
682
+ acceptanceId: options.acceptanceId,
683
+ taskId: options.taskId,
684
+ bugId: options.bugId,
685
+ documentId: options.documentId
686
+ });
687
+
688
+ if (selection.kind === "capability") return capabilitySlice(graph, selection.id);
689
+ if (selection.kind === "workflow") return workflowSlice(graph, selection.id);
690
+ if (selection.kind === "projection") return projectionSlice(graph, selection.id);
691
+ if (selection.kind === "component") return componentSlice(graph, selection.id);
692
+ if (selection.kind === "entity") return entitySlice(graph, selection.id);
693
+ if (selection.kind === "journey") return journeySlice(graph, selection.id);
694
+ if (selection.kind === "domain") return domainSlice(graph, selection.id);
695
+ if (selection.kind === "pitch") return pitchSlice(graph, selection.id);
696
+ if (selection.kind === "requirement") return requirementSlice(graph, selection.id);
697
+ if (selection.kind === "acceptance_criterion") return acceptanceCriterionSlice(graph, selection.id);
698
+ if (selection.kind === "task") return taskSlice(graph, selection.id);
699
+ if (selection.kind === "bug") return bugSlice(graph, selection.id);
700
+ if (selection.kind === "document") return documentSlice(graph, selection.id);
701
+
702
+ throw new Error(`Unsupported context slice kind '${selection.kind}'`);
703
+ }