@topogram/cli 0.3.51 → 0.3.52

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 (77) hide show
  1. package/ARCHITECTURE.md +4 -4
  2. package/CHANGELOG.md +11 -11
  3. package/package.json +1 -1
  4. package/src/adoption/plan.js +2 -2
  5. package/src/agent-ops/query-builders.js +42 -33
  6. package/src/cli.js +174 -129
  7. package/src/generator/adapters.d.ts +1 -0
  8. package/src/generator/adapters.js +64 -39
  9. package/src/generator/check.js +19 -12
  10. package/src/generator/context/diff.js +9 -9
  11. package/src/generator/context/domain-coverage.js +11 -10
  12. package/src/generator/context/domain-page.js +6 -6
  13. package/src/generator/context/shared.js +37 -21
  14. package/src/generator/context/slice.js +70 -65
  15. package/src/generator/index.js +12 -12
  16. package/src/generator/output.js +21 -20
  17. package/src/generator/registry.js +61 -49
  18. package/src/generator/runtime/app-bundle.js +15 -15
  19. package/src/generator/runtime/compile-check.js +7 -7
  20. package/src/generator/runtime/deployment.js +9 -9
  21. package/src/generator/runtime/environment.js +39 -39
  22. package/src/generator/runtime/runtime-check.js +5 -5
  23. package/src/generator/runtime/shared.js +40 -38
  24. package/src/generator/runtime/smoke.js +5 -5
  25. package/src/generator/surfaces/databases/contract.js +1 -1
  26. package/src/generator/surfaces/databases/lifecycle-shared.js +6 -5
  27. package/src/generator/surfaces/databases/postgres/drizzle.js +3 -2
  28. package/src/generator/surfaces/databases/postgres/prisma.js +3 -2
  29. package/src/generator/surfaces/databases/shared.js +3 -2
  30. package/src/generator/surfaces/databases/snapshot.js +1 -1
  31. package/src/generator/surfaces/databases/sqlite/prisma.js +3 -2
  32. package/src/generator/surfaces/native/swiftui-app.js +3 -3
  33. package/src/generator/surfaces/native/swiftui-templates/Package.swift.txt +1 -1
  34. package/src/generator/surfaces/native/swiftui-templates/README.generated.md +3 -3
  35. package/src/generator/surfaces/native/swiftui-templates/runtime/DynamicScreens.swift +3 -3
  36. package/src/generator/surfaces/services/persistence-wiring.js +3 -2
  37. package/src/generator/surfaces/services/server-contract.js +4 -4
  38. package/src/generator/surfaces/shared.js +2 -2
  39. package/src/generator/surfaces/web/design-intent.js +1 -1
  40. package/src/generator/surfaces/web/index.js +7 -7
  41. package/src/generator/surfaces/web/{react-components.js → react-widgets.js} +53 -53
  42. package/src/generator/surfaces/web/react.js +36 -36
  43. package/src/generator/surfaces/web/{sveltekit-components.js → sveltekit-widgets.js} +53 -53
  44. package/src/generator/surfaces/web/sveltekit.js +34 -34
  45. package/src/generator/surfaces/web/{ui-web-contract.js → ui-surface-contract.js} +8 -8
  46. package/src/generator/surfaces/web/vanilla.js +6 -6
  47. package/src/generator/{component-conformance.js → widget-conformance.js} +129 -128
  48. package/src/generator/widgets.js +40 -0
  49. package/src/generator-policy.js +10 -12
  50. package/src/import/core/runner.js +34 -34
  51. package/src/import/core/shared.js +1 -1
  52. package/src/import/extractors/ui/android-compose.js +1 -1
  53. package/src/import/extractors/ui/blazor.js +1 -1
  54. package/src/import/extractors/ui/razor-pages.js +1 -1
  55. package/src/import/extractors/ui/react-router.js +4 -4
  56. package/src/import/extractors/ui/sveltekit.js +4 -4
  57. package/src/import/extractors/ui/swiftui.js +1 -1
  58. package/src/import/extractors/ui/uikit.js +1 -1
  59. package/src/new-project.js +19 -18
  60. package/src/project-config.js +92 -42
  61. package/src/proofs/contract-audit.js +1 -1
  62. package/src/proofs/ios-parity.js +1 -1
  63. package/src/proofs/issues-parity.js +1 -1
  64. package/src/realization/backend/build-backend-runtime-realization.js +2 -2
  65. package/src/realization/ui/build-ui-shared-realization.js +33 -33
  66. package/src/realization/ui/build-web-realization.js +23 -20
  67. package/src/reconcile/journeys.js +1 -1
  68. package/src/resolver/index.js +148 -65
  69. package/src/validator/index.js +473 -423
  70. package/src/validator/kinds.js +36 -36
  71. package/src/validator/per-kind/{component.js → widget.js} +47 -47
  72. package/src/{component-behavior.js → widget-behavior.js} +3 -3
  73. package/src/workflows.js +39 -38
  74. package/template-helpers/react.js +4 -4
  75. package/template-helpers/sveltekit.js +4 -4
  76. package/src/generator/components.js +0 -39
  77. /package/src/resolver/enrich/{component.js → widget.js} +0 -0
package/ARCHITECTURE.md CHANGED
@@ -33,7 +33,7 @@ Topogram turns a `.tg` workspace into generated artifacts and apps through five
33
33
  Generator adapters
34
34
  - Own stack-specific realization such as React, SvelteKit, Hono, Express,
35
35
  Postgres, SQLite, Prisma, Drizzle, SwiftUI, or future Android files.
36
- - Consume normalized contracts, topology component metadata, and optional
36
+ - Consume normalized contracts, topology runtime metadata, widget contracts, and optional
37
37
  implementation hooks.
38
38
  - Return generated files and diagnostics through the shared generator interface.
39
39
 
@@ -42,9 +42,9 @@ Workspace `implementation/`
42
42
  - Can include seed data, custom page renderers, repository implementations, and runtime-check specifics.
43
43
  - Must not be treated as engine contracts.
44
44
 
45
- `component` statements live in the semantic graph beside entities, capabilities,
46
- shapes, and projections. They produce `componentContract` resolver enrichment
47
- and can be emitted through the `ui-component-contract` generator target without
45
+ `widget` statements live in the semantic graph beside entities, capabilities,
46
+ shapes, and projections. They produce `widgetContract` resolver enrichment
47
+ and can be emitted through the `ui-widget-contract` generator target without
48
48
  requiring an implementation provider.
49
49
 
50
50
  ## Stable Internal Contracts
package/CHANGELOG.md CHANGED
@@ -36,17 +36,17 @@
36
36
 
37
37
  ## 0.3.13 - 2026-05-01
38
38
 
39
- - Add `topogram component check` as a user-facing alias for component
39
+ - Add `topogram widget check` as a user-facing alias for component
40
40
  conformance reports. The command prints a human summary by default, supports
41
- `--projection`, `--component`, and `--json`, and exits non-zero when
41
+ `--projection`, `--widget`, and `--json`, and exits non-zero when
42
42
  conformance errors are present.
43
43
 
44
44
  ## 0.3.12 - 2026-05-01
45
45
 
46
- - Add `component-conformance-report` generator target. The report compares
47
- `projection.ui_components` usage against component contracts, includes
46
+ - Add `widget-conformance-report` generator target. The report compares
47
+ `projection.widget_bindings` usage against component contracts, includes
48
48
  inherited shared-UI usages for concrete web projections, supports
49
- `--projection` and `--component` filters, and reports repair-oriented checks
49
+ `--projection` and `--widget` filters, and reports repair-oriented checks
50
50
  for missing required props, event action context, component status, approvals,
51
51
  write scope, and projection/component impact.
52
52
 
@@ -159,7 +159,7 @@
159
159
  generators (board/release-notes/traceability), state-machine
160
160
  transitions, DoD rules, archive load/save, transition round-trips
161
161
  (rewrite + history sidecar), and release dry-run output.
162
- - Add `projection.ui_components` so projections explicitly own component
162
+ - Add `projection.widget_bindings` so projections explicitly own component
163
163
  placement and wiring. Component usage validates screen, region, component,
164
164
  prop, event, data-source, and event-target references.
165
165
  - Remove `component.consumers` from the component grammar before external
@@ -168,7 +168,7 @@
168
168
  - Add structured component `behaviors { ... }` alongside the shorthand
169
169
  `behavior [...]`, with validation for supported stack-agnostic behavior
170
170
  kinds and behavior references to component props/events.
171
- - Emit `approvals` and normalized `behaviors` in `ui-component-contract`
171
+ - Emit `approvals` and normalized `behaviors` in `ui-widget-contract`
172
172
  artifacts.
173
173
  - Include component usage metadata in generated UI contracts. Concrete web
174
174
  projections that realize a shared UI projection now inherit the shared
@@ -180,18 +180,18 @@
180
180
 
181
181
  - Add `component` statement kind for reusable UI/service component contracts
182
182
  (props, events, slots, patterns, regions, dependencies, consumers).
183
- - Add `ui-component-contract` generator target that emits stable JSON per
184
- component or for the whole workspace; selectable via `--component <id>`.
183
+ - Add `ui-widget-contract` generator target that emits stable JSON per
184
+ component or for the whole workspace; selectable via `--widget <id>`.
185
185
  - `context-diff` now emits a `components` section, and changed components
186
186
  fan out into `affected_generated_surfaces.projections` so consumer
187
187
  projections show up in diff payloads.
188
- - `context-slice --component <id>` returns a first-class component slice with
188
+ - `context-slice --widget <id>` returns a first-class component slice with
189
189
  `focus.kind === "component"`, dependent shapes/projections/verifications,
190
190
  and a `component_surface` review boundary; the same selector flows through
191
191
  `verification-targets`, `change-plan`, `risk-summary`, `review-packet`,
192
192
  `proceed-decision`, `next-action`, `single-agent-plan`, and
193
193
  `resolved-workflow-context`.
194
- - `topogram generate ... --generate ui-component-contract --component <id>`
194
+ - `topogram generate ... --generate ui-widget-contract --widget <id>`
195
195
  now errors loudly when the id does not match any component (previously it
196
196
  wrote a `null` artifact).
197
197
  - Component prop defaults preserve real values: `default true`, `default false`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topogram/cli",
3
- "version": "0.3.51",
3
+ "version": "0.3.52",
4
4
  "description": "Topogram CLI for checking Topogram workspaces and generating app bundles.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -6,7 +6,7 @@ import {
6
6
  reviewBoundaryForImportProposal
7
7
  } from "../policy/review-boundaries.js";
8
8
 
9
- const ADOPT_SELECTORS = new Set(["from-plan", "actors", "roles", "enums", "shapes", "entities", "capabilities", "components", "docs", "journeys", "workflows", "verification", "ui"]);
9
+ const ADOPT_SELECTORS = new Set(["from-plan", "actors", "roles", "enums", "shapes", "entities", "capabilities", "widgets", "docs", "journeys", "workflows", "verification", "ui"]);
10
10
 
11
11
  function stableSortedStrings(values) {
12
12
  return [...new Set((values || []).filter(Boolean))].sort();
@@ -355,7 +355,7 @@ export function selectorMatchesItem(selector, item) {
355
355
  if (selector === "shapes") return item.kind === "shape";
356
356
  if (selector === "entities") return item.kind === "entity";
357
357
  if (selector === "capabilities") return item.kind === "capability";
358
- if (selector === "components") return item.kind === "component";
358
+ if (selector === "widgets") return item.kind === "widget";
359
359
  if (selector === "docs") return item.track === "docs";
360
360
  if (selector === "journeys") return item.track === "docs" && String(item.canonical_rel_path || "").startsWith("docs/journeys/");
361
361
  if (selector === "workflows") return item.track === "workflows" || item.kind === "decision";
@@ -138,24 +138,29 @@ function stableOrderedUnion(values = []) {
138
138
  return result;
139
139
  }
140
140
 
141
+ function targetWidgetId(target = {}) {
142
+ return target.widget_id || target.component_id || null;
143
+ }
144
+
141
145
  function componentBehaviorArtifactPath(target = {}) {
142
- if (target.target !== "component-behavior-report") {
146
+ if (target.target !== "widget-behavior-report") {
143
147
  return null;
144
148
  }
145
- const suffix = [target.projection_id, target.component_id].filter(Boolean).join(".");
146
- return suffix ? `${suffix}.component-behavior-report.json` : "component-behavior-report.json";
149
+ const suffix = [target.projection_id, targetWidgetId(target)].filter(Boolean).join(".");
150
+ return suffix ? `${suffix}.widget-behavior-report.json` : "widget-behavior-report.json";
147
151
  }
148
152
 
149
153
  function componentBehaviorQueryCommand(target = {}) {
150
- if (target.target !== "component-behavior-report") {
154
+ if (target.target !== "widget-behavior-report") {
151
155
  return null;
152
156
  }
153
- const parts = ["topogram", "query", "component-behavior", "./topogram"];
157
+ const parts = ["topogram", "query", "widget-behavior", "./topogram"];
154
158
  if (target.projection_id) {
155
159
  parts.push("--projection", target.projection_id);
156
160
  }
157
- if (target.component_id) {
158
- parts.push("--component", target.component_id);
161
+ const widgetId = targetWidgetId(target);
162
+ if (widgetId) {
163
+ parts.push("--widget", widgetId);
159
164
  }
160
165
  parts.push("--json");
161
166
  return parts.join(" ");
@@ -169,10 +174,10 @@ function recommendedArtifactQueriesFromGeneratorTargets(generatorTargets = []) {
169
174
  if (!command || seen.has(command)) continue;
170
175
  seen.add(command);
171
176
  queries.push({
172
- query: "component-behavior",
177
+ query: "widget-behavior",
173
178
  target: target.target,
174
179
  projection_id: target.projection_id || null,
175
- component_id: target.component_id || null,
180
+ widget_id: targetWidgetId(target),
176
181
  command
177
182
  });
178
183
  }
@@ -1340,9 +1345,9 @@ function projectionKindForImpact(projection) {
1340
1345
  (projection.uiWeb || []).length > 0 ||
1341
1346
  (projection.uiIos || []).length > 0 ||
1342
1347
  (projection.uiScreens || []).length > 0 ||
1343
- projection.platform === "ui_web" ||
1344
- projection.platform === "ui_ios" ||
1345
- projection.platform === "ui_shared"
1348
+ projection.platform === "web_surface" ||
1349
+ projection.platform === "ios_surface" ||
1350
+ projection.platform === "ui_contract"
1346
1351
  ) {
1347
1352
  return "ui";
1348
1353
  }
@@ -1634,7 +1639,7 @@ function buildProjectionImpacts(graph, { sliceArtifact, diffArtifact }) {
1634
1639
  "selected_entity",
1635
1640
  (projection) => `Projection ${projection.id} is in scope because selected entity ${id} participates in that projection.`
1636
1641
  )) addImpact(impactMap, impact);
1637
- } else if (kind === "component") {
1642
+ } else if (kind === "widget") {
1638
1643
  for (const impact of projectionImpactsFromComponent(graph, id)) addImpact(impactMap, impact);
1639
1644
  } else if (kind === "workflow") {
1640
1645
  for (const impact of projectionImpactsFromWorkflow(graph, id, true)) addImpact(impactMap, impact);
@@ -1656,11 +1661,15 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1656
1661
  const targets = [];
1657
1662
  const addTarget = (target) => {
1658
1663
  if (!target?.target) return;
1659
- if (!target.projection_id && !target.component_id) return;
1664
+ if (target.component_id && !target.widget_id) {
1665
+ target.widget_id = target.component_id;
1666
+ delete target.component_id;
1667
+ }
1668
+ if (!target.projection_id && !target.widget_id) return;
1660
1669
  if (!targets.some((entry) =>
1661
1670
  entry.target === target.target &&
1662
1671
  entry.projection_id === target.projection_id &&
1663
- entry.component_id === target.component_id
1672
+ targetWidgetId(entry) === targetWidgetId(target)
1664
1673
  )) {
1665
1674
  targets.push(target);
1666
1675
  }
@@ -1668,16 +1677,16 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1668
1677
 
1669
1678
  for (const entry of diffArtifact?.components || []) {
1670
1679
  addTarget({
1671
- target: "ui-component-contract",
1672
- component_id: entry.id,
1680
+ target: "ui-widget-contract",
1681
+ widget_id: entry.id,
1673
1682
  required: true,
1674
- reason: `Component ${entry.id} changed directly, so its component contract should be refreshed.`
1683
+ reason: `Widget ${entry.id} changed directly, so its widget contract should be refreshed.`
1675
1684
  });
1676
1685
  addTarget({
1677
- target: "component-behavior-report",
1678
- component_id: entry.id,
1686
+ target: "widget-behavior-report",
1687
+ widget_id: entry.id,
1679
1688
  required: true,
1680
- reason: `Component ${entry.id} changed directly, so behavior realizations should be reviewed across affected projections.`
1689
+ reason: `Widget ${entry.id} changed directly, so behavior realizations should be reviewed across affected projections.`
1681
1690
  });
1682
1691
  }
1683
1692
 
@@ -1708,7 +1717,7 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1708
1717
  });
1709
1718
  }
1710
1719
 
1711
- if (projection.platform === "ui_shared") {
1720
+ if (projection.platform === "ui_contract") {
1712
1721
  addTarget({
1713
1722
  target: "ui-contract-graph",
1714
1723
  projection_id: impact.projection_id,
@@ -1730,30 +1739,30 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1730
1739
 
1731
1740
  for (const componentId of componentIds) {
1732
1741
  addTarget({
1733
- target: "ui-component-contract",
1734
- component_id: componentId,
1742
+ target: "ui-widget-contract",
1743
+ widget_id: componentId,
1735
1744
  projection_id: impact.projection_id,
1736
1745
  required: true,
1737
- reason: `Projection ${impact.projection_id} is affected by component ${componentId}, so the component contract should be refreshed.`
1746
+ reason: `Projection ${impact.projection_id} is affected by widget ${componentId}, so the widget contract should be refreshed.`
1738
1747
  });
1739
1748
  addTarget({
1740
- target: "component-behavior-report",
1741
- component_id: componentId,
1749
+ target: "widget-behavior-report",
1750
+ widget_id: componentId,
1742
1751
  projection_id: impact.projection_id,
1743
1752
  required: true,
1744
- reason: `Projection ${impact.projection_id} is affected by component ${componentId}, so behavior data/event/action wiring should be reviewed.`
1753
+ reason: `Projection ${impact.projection_id} is affected by widget ${componentId}, so behavior data/event/action wiring should be reviewed.`
1745
1754
  });
1746
1755
  }
1747
1756
 
1748
- if (projection.platform === "ui_web") {
1757
+ if (projection.platform === "web_surface") {
1749
1758
  addTarget({
1750
- target: "ui-web-contract",
1759
+ target: "ui-surface-contract",
1751
1760
  projection_id: impact.projection_id,
1752
1761
  required: true,
1753
1762
  reason: `Projection ${impact.projection_id} is a web UI surface, so the web UI contract should be refreshed.`
1754
1763
  });
1755
1764
  addTarget({
1756
- target: "ui-web-debug",
1765
+ target: "ui-surface-debug",
1757
1766
  projection_id: impact.projection_id,
1758
1767
  required: false,
1759
1768
  reason: `Projection ${impact.projection_id} may benefit from UI web debug output during review.`
@@ -1768,7 +1777,7 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1768
1777
  }
1769
1778
  }
1770
1779
 
1771
- if (projection.platform === "ui_ios") {
1780
+ if (projection.platform === "ios_surface") {
1772
1781
  addTarget({
1773
1782
  target: "swiftui-app",
1774
1783
  projection_id: impact.projection_id,
@@ -1819,7 +1828,7 @@ function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = nul
1819
1828
  return targets.sort((a, b) => {
1820
1829
  const projectionCompare = String(a.projection_id || "").localeCompare(String(b.projection_id || ""));
1821
1830
  if (projectionCompare !== 0) return projectionCompare;
1822
- const componentCompare = String(a.component_id || "").localeCompare(String(b.component_id || ""));
1831
+ const componentCompare = String(targetWidgetId(a) || "").localeCompare(String(targetWidgetId(b) || ""));
1823
1832
  if (componentCompare !== 0) return componentCompare;
1824
1833
  return projectionCompare !== 0 ? projectionCompare : a.target.localeCompare(b.target);
1825
1834
  });