@topogram/cli 0.3.54 → 0.3.55

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 (40) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/review-groups.js +3 -3
  3. package/src/agent-ops/query-builders.js +34 -34
  4. package/src/archive/schema.js +1 -1
  5. package/src/cli.js +173 -20
  6. package/src/generator/adapters.js +2 -2
  7. package/src/generator/context/domain-coverage.js +2 -2
  8. package/src/generator/context/shared.js +6 -22
  9. package/src/generator/context/slice.js +10 -10
  10. package/src/generator/docs.js +1 -1
  11. package/src/generator/registry.js +1 -1
  12. package/src/generator/runtime/app-bundle.js +7 -5
  13. package/src/generator/runtime/compile-check.js +3 -1
  14. package/src/generator/runtime/deployment.js +3 -1
  15. package/src/generator/runtime/environment.js +22 -19
  16. package/src/generator/runtime/shared.js +7 -7
  17. package/src/generator/surfaces/contracts.js +1 -1
  18. package/src/generator/surfaces/databases/lifecycle-shared.js +1 -1
  19. package/src/generator/surfaces/databases/postgres/drizzle.js +1 -1
  20. package/src/generator/surfaces/databases/postgres/prisma.js +1 -1
  21. package/src/generator/surfaces/databases/shared.js +3 -3
  22. package/src/generator/surfaces/databases/sqlite/prisma.js +1 -1
  23. package/src/generator/surfaces/services/persistence-wiring.js +1 -1
  24. package/src/generator/surfaces/services/server-contract.js +1 -1
  25. package/src/generator/surfaces/shared.js +1 -1
  26. package/src/generator/surfaces/web/ui-surface-contract.js +1 -1
  27. package/src/generator/widget-conformance.js +6 -6
  28. package/src/generator/widgets.js +1 -1
  29. package/src/generator-policy.js +10 -10
  30. package/src/import/core/runner.js +60 -50
  31. package/src/project-config.js +5 -42
  32. package/src/proofs/contract-audit.js +1 -1
  33. package/src/realization/backend/build-backend-runtime-realization.js +3 -3
  34. package/src/realization/ui/build-ui-shared-realization.js +9 -9
  35. package/src/realization/ui/build-web-realization.js +3 -3
  36. package/src/reconcile/journeys.js +1 -1
  37. package/src/resolver/enrich/widget.js +2 -2
  38. package/src/resolver/index.js +4 -23
  39. package/src/validator/index.js +10 -10
  40. package/src/workflows.js +49 -49
@@ -2449,23 +2449,23 @@ function validateProjectionUiOwnership(errors, statement, fieldMap) {
2449
2449
  return;
2450
2450
  }
2451
2451
 
2452
- const platform = symbolValue(getFieldValue(statement, "type"));
2452
+ const projectionType = symbolValue(getFieldValue(statement, "type"));
2453
2453
  for (const key of SHARED_UI_SEMANTIC_BLOCKS) {
2454
2454
  const field = fieldMap.get(key)?.[0];
2455
2455
  if (!field || field.value.type !== "block") {
2456
2456
  continue;
2457
2457
  }
2458
- if (platform !== "ui_contract") {
2458
+ if (projectionType !== "ui_contract") {
2459
2459
  pushError(
2460
2460
  errors,
2461
- `Projection ${statement.id} ${key} belongs on shared UI projections; concrete UI projections may define screen_routes and platform surface hints only`,
2461
+ `Projection ${statement.id} ${key} belongs on shared UI projections; concrete UI projections may define screen_routes and surface hints only`,
2462
2462
  field.loc
2463
2463
  );
2464
2464
  }
2465
2465
  }
2466
2466
 
2467
2467
  const routesField = fieldMap.get("screen_routes")?.[0];
2468
- if (routesField?.value.type === "block" && !["web_surface", "ios_surface"].includes(platform || "")) {
2468
+ if (routesField?.value.type === "block" && !["web_surface", "ios_surface"].includes(projectionType || "")) {
2469
2469
  pushError(
2470
2470
  errors,
2471
2471
  `Projection ${statement.id} screen_routes belongs on concrete UI projections; shared UI projections own semantic screens and regions`,
@@ -2979,7 +2979,7 @@ function validateProjectionUiRoutes(errors, statement, fieldMap, registry) {
2979
2979
 
2980
2980
  const availableScreens = collectAvailableUiScreenIds(statement, fieldMap, registry);
2981
2981
  const seenPaths = new Set();
2982
- const platform = symbolValue(getFieldValue(statement, "type"));
2982
+ const projectionType = symbolValue(getFieldValue(statement, "type"));
2983
2983
 
2984
2984
  for (const entry of routesField.value.entries) {
2985
2985
  const tokens = blockSymbolItems(entry).map((item) => item.value);
@@ -2999,7 +2999,7 @@ function validateProjectionUiRoutes(errors, statement, fieldMap, registry) {
2999
2999
  pushError(errors, `Projection ${statement.id} screen_routes for '${screenId}' must include a path`, entry.loc);
3000
3000
  continue;
3001
3001
  }
3002
- if ((platform === "web_surface" || platform === "ios_surface") && !routePath.startsWith("/")) {
3002
+ if ((projectionType === "web_surface" || projectionType === "ios_surface") && !routePath.startsWith("/")) {
3003
3003
  pushError(errors, `Projection ${statement.id} screen_routes for '${screenId}' must use an absolute path`, entry.loc);
3004
3004
  }
3005
3005
  if (seenPaths.has(routePath)) {
@@ -3009,7 +3009,7 @@ function validateProjectionUiRoutes(errors, statement, fieldMap, registry) {
3009
3009
  }
3010
3010
  }
3011
3011
 
3012
- function validateProjectionUiSurfaceHints(errors, statement, fieldMap, registry, surfaceBlockKey, expectedPlatform) {
3012
+ function validateProjectionUiSurfaceHints(errors, statement, fieldMap, registry, surfaceBlockKey, expectedProjectionType) {
3013
3013
  if (statement.kind !== "projection") {
3014
3014
  return;
3015
3015
  }
@@ -3019,9 +3019,9 @@ function validateProjectionUiSurfaceHints(errors, statement, fieldMap, registry,
3019
3019
  return;
3020
3020
  }
3021
3021
 
3022
- const platform = symbolValue(getFieldValue(statement, "type"));
3023
- if (platform !== expectedPlatform) {
3024
- pushError(errors, `Projection ${statement.id} may only use '${surfaceBlockKey}' when platform is '${expectedPlatform}'`, surfaceField.loc);
3022
+ const projectionType = symbolValue(getFieldValue(statement, "type"));
3023
+ if (projectionType !== expectedProjectionType) {
3024
+ pushError(errors, `Projection ${statement.id} may only use '${surfaceBlockKey}' when projection type is '${expectedProjectionType}'`, surfaceField.loc);
3025
3025
  return;
3026
3026
  }
3027
3027
 
package/src/workflows.js CHANGED
@@ -1464,14 +1464,14 @@ function renderCandidateUiReportDoc(screen, routes, actions) {
1464
1464
  return renderMarkdownDoc(metadata, body);
1465
1465
  }
1466
1466
 
1467
- function renderCandidateComponent(component) {
1468
- const propName = component.data_prop || "rows";
1469
- const pattern = component.pattern || "search_results";
1470
- const region = component.region || "results";
1467
+ function renderCandidateWidget(widget) {
1468
+ const propName = widget.data_prop || "rows";
1469
+ const pattern = widget.pattern || "search_results";
1470
+ const region = widget.region || "results";
1471
1471
  return ensureTrailingNewline(
1472
1472
  [
1473
- `widget ${component.id_hint} {`,
1474
- ` name "${component.label || component.id_hint}"`,
1473
+ `widget ${widget.id_hint} {`,
1474
+ ` name "${widget.label || widget.id_hint}"`,
1475
1475
  ' description "Candidate reusable widget inferred from imported UI evidence. Review props, behavior, events, and reuse before adoption."',
1476
1476
  " category collection",
1477
1477
  " props {",
@@ -1491,7 +1491,7 @@ function renderProjectionPatchDoc(patch) {
1491
1491
  "",
1492
1492
  `Projection: \`${patch.projection_id}\``,
1493
1493
  `Kind: \`${patch.kind}\``,
1494
- patch.platform ? `Platform: \`${patch.platform}\`` : null,
1494
+ patch.projection_type ? `Projection type: \`${patch.projection_type}\`` : null,
1495
1495
  "",
1496
1496
  patch.reason || "Candidate additive projection patch inferred during reconcile.",
1497
1497
  ""
@@ -1694,7 +1694,7 @@ function buildBundleOperatorSummary(bundle) {
1694
1694
  bundle.id;
1695
1695
  const participants = summarizeBundleParticipants(bundle);
1696
1696
  const capabilityIds = [...new Set((bundle.capabilities || []).map((entry) => entry.id_hint))].slice(0, 4);
1697
- const componentIds = [...new Set((bundle.components || []).map((entry) => entry.id_hint))].slice(0, 4);
1697
+ const widgetIds = [...new Set((bundle.widgets || []).map((entry) => entry.id_hint))].slice(0, 4);
1698
1698
  const screenIds = [...new Set((bundle.screens || []).map((entry) => entry.id_hint))].slice(0, 4);
1699
1699
  const routePaths = [...new Set((bundle.uiRoutes || []).map((entry) => entry.path).filter(Boolean))].slice(0, 4);
1700
1700
  const workflowIds = [...new Set((bundle.workflows || []).map((entry) => entry.id_hint))].slice(0, 4);
@@ -1710,7 +1710,7 @@ function buildBundleOperatorSummary(bundle) {
1710
1710
  const evidenceKinds = [
1711
1711
  (bundle.entities || []).length > 0 ? "entity evidence" : null,
1712
1712
  (bundle.capabilities || []).length > 0 ? "API capability evidence" : null,
1713
- (bundle.components || []).length > 0 ? "UI widget evidence" : null,
1713
+ (bundle.widgets || []).length > 0 ? "UI widget evidence" : null,
1714
1714
  (bundle.screens || []).length > 0 || (bundle.uiRoutes || []).length > 0 ? "UI screen/route evidence" : null,
1715
1715
  (bundle.workflows || []).length > 0 ? "workflow evidence" : null,
1716
1716
  (bundle.docs || []).length > 0 ? "doc evidence" : null,
@@ -1726,7 +1726,7 @@ function buildBundleOperatorSummary(bundle) {
1726
1726
  primaryEntityId,
1727
1727
  participants,
1728
1728
  capabilityIds,
1729
- componentIds,
1729
+ widgetIds,
1730
1730
  screenIds,
1731
1731
  routePaths,
1732
1732
  workflowIds,
@@ -2418,7 +2418,7 @@ function getOrCreateCandidateBundle(bundles, conceptId, label) {
2418
2418
  enums: [],
2419
2419
  capabilities: [],
2420
2420
  shapes: [],
2421
- components: [],
2421
+ widgets: [],
2422
2422
  screens: [],
2423
2423
  uiRoutes: [],
2424
2424
  uiActions: [],
@@ -2715,7 +2715,7 @@ function renderCandidateBundleReadme(bundle, proposalSurfaces = []) {
2715
2715
  `Enums: ${bundle.enums.length}`,
2716
2716
  `Capabilities: ${bundle.capabilities.length}`,
2717
2717
  `Shapes: ${bundle.shapes.length}`,
2718
- `Widgets: ${bundle.components.length}`,
2718
+ `Widgets: ${bundle.widgets.length}`,
2719
2719
  `Screens: ${bundle.screens.length}`,
2720
2720
  `UI routes: ${bundle.uiRoutes.length}`,
2721
2721
  `UI actions: ${bundle.uiActions.length}`,
@@ -2733,7 +2733,7 @@ function renderCandidateBundleReadme(bundle, proposalSurfaces = []) {
2733
2733
  `- Primary entity: ${summary.primaryEntityId ? `\`${summary.primaryEntityId}\`` : "_none_"}`,
2734
2734
  `- Participants: ${summary.participants.label}`,
2735
2735
  `- Main capabilities: ${summarizeBundleSurface(bundle, summary.capabilityIds)}`,
2736
- `- Main widgets: ${summarizeBundleSurface(bundle, summary.componentIds)}`,
2736
+ `- Main widgets: ${summarizeBundleSurface(bundle, summary.widgetIds)}`,
2737
2737
  `- Main screens: ${summarizeBundleSurface(bundle, summary.screenIds)}`,
2738
2738
  `- Main routes: ${summarizeBundleSurface(bundle, summary.routePaths)}`,
2739
2739
  `- Main workflows: ${summarizeBundleSurface(bundle, summary.workflowIds)}`,
@@ -3013,15 +3013,15 @@ function capabilityEntityTargets(capability) {
3013
3013
  }
3014
3014
 
3015
3015
  function projectionKindForImpact(projection) {
3016
- if ((projection.http || []).length > 0 || projection.platform === "api_contract") {
3016
+ if ((projection.http || []).length > 0 || projection.type === "api_contract") {
3017
3017
  return "api";
3018
3018
  }
3019
3019
  if (
3020
3020
  (projection.uiRoutes || []).length > 0 ||
3021
3021
  (projection.uiWeb || []).length > 0 ||
3022
3022
  (projection.uiIos || []).length > 0 ||
3023
- projection.platform === "web_surface" ||
3024
- projection.platform === "ios_surface"
3023
+ projection.type === "web_surface" ||
3024
+ projection.type === "ios_surface"
3025
3025
  ) {
3026
3026
  return "ui";
3027
3027
  }
@@ -3068,7 +3068,7 @@ function buildProjectionEntityIndex(graph) {
3068
3068
 
3069
3069
  return projections.map((projection) => ({
3070
3070
  id: projection.id,
3071
- platform: projection.platform || null,
3071
+ projection_type: projection.type || null,
3072
3072
  kind: projectionKindForImpact(projection),
3073
3073
  realizes: (projection.realizes || []).map((entry) => entry.id),
3074
3074
  entityIds: [...collectEntities(projection.id)].sort()
@@ -3188,7 +3188,7 @@ function buildBundleAdoptionPlan(bundle, canonicalShapeIndex) {
3188
3188
  canonical_rel_path: `verifications/${dashedTopogramId(entry.id_hint)}.tg`
3189
3189
  });
3190
3190
  }
3191
- for (const entry of bundle.components || []) {
3191
+ for (const entry of bundle.widgets || []) {
3192
3192
  steps.push({
3193
3193
  action: "promote_widget",
3194
3194
  item: entry.id_hint,
@@ -3281,7 +3281,7 @@ function buildProjectionImpacts(bundle, projectionIndex) {
3281
3281
  }
3282
3282
  return {
3283
3283
  projection_id: projection.id,
3284
- platform: projection.platform,
3284
+ projection_type: projection.type,
3285
3285
  kind: projection.kind,
3286
3286
  missing_capabilities: missingCapabilities,
3287
3287
  reason: `Projection ${projection.id} already covers the same entity surface but does not realize these imported capabilities.`
@@ -3295,7 +3295,7 @@ function buildUiImpacts(bundle, graph) {
3295
3295
  if ((bundle.screens || []).length === 0) {
3296
3296
  return [];
3297
3297
  }
3298
- const uiProjections = (graph?.byKind.projection || []).filter((projection) => ["ui_contract", "web_surface"].includes(projection.platform));
3298
+ const uiProjections = (graph?.byKind.projection || []).filter((projection) => ["ui_contract", "web_surface"].includes(projection.type));
3299
3299
  const bundleScreenIds = bundle.screens.map((screen) => screen.id_hint);
3300
3300
  return uiProjections
3301
3301
  .map((projection) => {
@@ -3307,7 +3307,7 @@ function buildUiImpacts(bundle, graph) {
3307
3307
  return {
3308
3308
  projection_id: projection.id,
3309
3309
  kind: "ui",
3310
- platform: projection.platform,
3310
+ projection_type: projection.type,
3311
3311
  missing_screens: missingScreens,
3312
3312
  reason: `UI projection ${projection.id} does not currently represent these imported screens.`
3313
3313
  };
@@ -3372,7 +3372,7 @@ function buildProjectionPatchCandidates(bundle) {
3372
3372
  patches.push({
3373
3373
  projection_id: impact.projection_id,
3374
3374
  kind: impact.kind,
3375
- platform: impact.platform,
3375
+ projection_type: impact.projection_type,
3376
3376
  reason: impact.reason,
3377
3377
  missing_realizes: missingRealizes,
3378
3378
  missing_http: missingHttp,
@@ -3402,7 +3402,7 @@ function buildProjectionPatchCandidates(bundle) {
3402
3402
  patches.push({
3403
3403
  projection_id: impact.projection_id,
3404
3404
  kind: impact.kind,
3405
- platform: impact.platform,
3405
+ projection_type: impact.projection_type,
3406
3406
  reason: impact.reason,
3407
3407
  missing_realizes: [],
3408
3408
  missing_http: [],
@@ -3448,7 +3448,7 @@ function buildProjectionPatchCandidates(bundle) {
3448
3448
  patches.push({
3449
3449
  projection_id: impact.projection_id,
3450
3450
  kind: impact.kind,
3451
- platform: impact.platform,
3451
+ projection_type: impact.projection_type,
3452
3452
  reason: `Projection ${impact.projection_id} likely needs claim-based auth rules for the imported ${bundle.label.toLowerCase()} surface.`,
3453
3453
  missing_realizes: relatedCapabilities,
3454
3454
  missing_http: [],
@@ -3494,7 +3494,7 @@ function buildProjectionPatchCandidates(bundle) {
3494
3494
  patches.push({
3495
3495
  projection_id: impact.projection_id,
3496
3496
  kind: impact.kind,
3497
- platform: impact.platform,
3497
+ projection_type: impact.projection_type,
3498
3498
  reason: `Projection ${impact.projection_id} likely needs permission-based auth rules for the imported ${bundle.label.toLowerCase()} surface.`,
3499
3499
  missing_realizes: relatedCapabilities,
3500
3500
  missing_http: [],
@@ -3543,7 +3543,7 @@ function buildProjectionPatchCandidates(bundle) {
3543
3543
  patches.push({
3544
3544
  projection_id: impact.projection_id,
3545
3545
  kind: impact.kind,
3546
- platform: impact.platform,
3546
+ projection_type: impact.projection_type,
3547
3547
  reason: `Projection ${impact.projection_id} likely needs ownership-based auth rules for the imported ${bundle.label.toLowerCase()} surface.`,
3548
3548
  missing_realizes: relatedCapabilities,
3549
3549
  missing_http: [],
@@ -3680,7 +3680,8 @@ function bestContextBundleForCandidate(bundles, candidate) {
3680
3680
  function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3681
3681
  const dbCandidates = appImport.candidates.db || { entities: [], enums: [] };
3682
3682
  const apiCandidates = appImport.candidates.api || { capabilities: [] };
3683
- const uiCandidates = appImport.candidates.ui || { screens: [], routes: [], actions: [], components: [] };
3683
+ const uiCandidates = appImport.candidates.ui || { screens: [], routes: [], actions: [], widgets: [] };
3684
+ const uiWidgetCandidates = uiCandidates.widgets || uiCandidates.components || [];
3684
3685
  const workflowCandidates = appImport.candidates.workflows || { workflows: [], workflow_states: [], workflow_transitions: [] };
3685
3686
  const verificationCandidates = appImport.candidates.verification || { verifications: [], scenarios: [], frameworks: [], scripts: [] };
3686
3687
  const docCandidates = appImport.candidates.docs || [];
@@ -3691,7 +3692,7 @@ function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3691
3692
  const canonicalRoleIds = new Set((graph?.byKind.role || []).map((entry) => entry.id));
3692
3693
  const canonicalEntityIds = new Set((graph?.byKind.entity || []).map((entry) => entry.id));
3693
3694
  const canonicalEnumIds = new Set((graph?.byKind.enum || []).map((entry) => entry.id));
3694
- const canonicalComponentIds = new Set((graph?.byKind.component || []).map((entry) => entry.id));
3695
+ const canonicalWidgetIds = new Set((graph?.byKind.widget || []).map((entry) => entry.id));
3695
3696
  const canonicalUi = collectCanonicalUiSurface(graph || { byKind: { projection: [] } });
3696
3697
  const canonicalWorkflow = collectCanonicalWorkflowSurface(graph || { byKind: { decision: [] }, docs: [] });
3697
3698
  const canonicalDocsByKind = new Map();
@@ -3790,7 +3791,7 @@ function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3790
3791
  const bundle = getOrCreateCandidateBundle(bundles, conceptId, bundleLabelFromConceptId(conceptId || entry.screen_id || entry.id_hint));
3791
3792
  bundle.uiActions.push(entry);
3792
3793
  }
3793
- function componentConceptId(entry) {
3794
+ function widgetConceptId(entry) {
3794
3795
  if (entry.entity_id || entry.concept_id) {
3795
3796
  return entry.entity_id || entry.concept_id;
3796
3797
  }
@@ -3800,13 +3801,13 @@ function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3800
3801
  return `entity_${canonicalCandidateTerm(screenStem || entry.id_hint)}`;
3801
3802
  }
3802
3803
 
3803
- for (const entry of uiCandidates.components || []) {
3804
- if (canonicalComponentIds.has(entry.id_hint)) {
3804
+ for (const entry of uiWidgetCandidates) {
3805
+ if (canonicalWidgetIds.has(entry.id_hint)) {
3805
3806
  continue;
3806
3807
  }
3807
- const conceptId = componentConceptId(entry);
3808
+ const conceptId = widgetConceptId(entry);
3808
3809
  const bundle = getOrCreateCandidateBundle(bundles, conceptId, bundleLabelFromConceptId(conceptId || entry.screen_id || entry.id_hint));
3809
- bundle.components.push(entry);
3810
+ bundle.widgets.push(entry);
3810
3811
  }
3811
3812
  for (const entry of workflowCandidates.workflows || []) {
3812
3813
  if (canonicalWorkflow.workflow_docs.includes(entry.id_hint)) {
@@ -3893,7 +3894,7 @@ function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3893
3894
  bundle.enums.length > 0 ||
3894
3895
  bundle.capabilities.length > 0 ||
3895
3896
  bundle.shapes.length > 0 ||
3896
- bundle.components.length > 0 ||
3897
+ bundle.widgets.length > 0 ||
3897
3898
  bundle.screens.length > 0 ||
3898
3899
  bundle.uiRoutes.length > 0 ||
3899
3900
  bundle.uiActions.length > 0 ||
@@ -3911,7 +3912,7 @@ function buildCandidateModelBundles(graph, appImport, topogramRoot) {
3911
3912
  enums: bundle.enums.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3912
3913
  capabilities: bundle.capabilities.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3913
3914
  shapes: bundle.shapes.sort((a, b) => a.id.localeCompare(b.id)),
3914
- components: bundle.components.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3915
+ widgets: bundle.widgets.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3915
3916
  screens: bundle.screens.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3916
3917
  uiRoutes: bundle.uiRoutes.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
3917
3918
  uiActions: bundle.uiActions.sort((a, b) => a.id_hint.localeCompare(b.id_hint)),
@@ -4013,8 +4014,8 @@ function buildCandidateModelFiles(graph, appImport, topogramRoot) {
4013
4014
  for (const entry of bundle.verifications || []) {
4014
4015
  files[`${bundleRoot}/verifications/${entry.id_hint}.tg`] = renderCandidateVerification(entry, entry.scenarios || []);
4015
4016
  }
4016
- for (const entry of bundle.components || []) {
4017
- files[`${bundleRoot}/widgets/${entry.id_hint}.tg`] = renderCandidateComponent(entry);
4017
+ for (const entry of bundle.widgets || []) {
4018
+ files[`${bundleRoot}/widgets/${entry.id_hint}.tg`] = renderCandidateWidget(entry);
4018
4019
  }
4019
4020
  for (const entry of bundle.docs) {
4020
4021
  if (entry.existing_canonical) {
@@ -4257,7 +4258,7 @@ function projectionImpactsForAdoptionItem(bundle, step) {
4257
4258
  .map((impact) => ({
4258
4259
  projection_id: impact.projection_id,
4259
4260
  kind: impact.kind,
4260
- platform: impact.platform,
4261
+ projection_type: impact.projection_type,
4261
4262
  reason: impact.reason
4262
4263
  }));
4263
4264
  }
@@ -4268,7 +4269,7 @@ function blockingDependenciesForProjectionImpacts(projectionImpacts) {
4268
4269
  id: `projection_review:${impact.projection_id}`,
4269
4270
  projection_id: impact.projection_id,
4270
4271
  kind: impact.kind,
4271
- platform: impact.platform,
4272
+ projection_type: impact.projection_type,
4272
4273
  reason: impact.reason
4273
4274
  }));
4274
4275
  }
@@ -4279,7 +4280,7 @@ function blockingDependenciesForUiImpacts(uiImpacts) {
4279
4280
  id: `ui_review:${impact.projection_id}`,
4280
4281
  projection_id: impact.projection_id,
4281
4282
  kind: impact.kind,
4282
- platform: impact.platform,
4283
+ projection_type: impact.projection_type,
4283
4284
  reason: impact.reason
4284
4285
  }));
4285
4286
  }
@@ -4324,7 +4325,7 @@ function buildAdoptionPlan(bundles) {
4324
4325
  {
4325
4326
  projection_id: step.target,
4326
4327
  kind: step.projection_kind || "api",
4327
- platform: null,
4328
+ projection_type: null,
4328
4329
  reason: `Projection ${step.target} auth rules need explicit review before promotion.`
4329
4330
  }
4330
4331
  ])
@@ -4394,7 +4395,7 @@ function buildAdoptionPlan(bundles) {
4394
4395
  {
4395
4396
  projection_id: patch.projection_id,
4396
4397
  kind: patch.kind,
4397
- platform: patch.platform,
4398
+ projection_type: patch.projection_type,
4398
4399
  missing_capabilities: patch.missing_realizes || []
4399
4400
  }
4400
4401
  ],
@@ -4402,7 +4403,7 @@ function buildAdoptionPlan(bundles) {
4402
4403
  {
4403
4404
  projection_id: patch.projection_id,
4404
4405
  kind: patch.kind,
4405
- platform: patch.platform,
4406
+ projection_type: patch.projection_type,
4406
4407
  missing_screens: patch.missing_screens || []
4407
4408
  }
4408
4409
  ] : [],
@@ -4411,7 +4412,7 @@ function buildAdoptionPlan(bundles) {
4411
4412
  {
4412
4413
  projection_id: patch.projection_id,
4413
4414
  kind: patch.kind,
4414
- platform: patch.platform,
4415
+ projection_type: patch.projection_type,
4415
4416
  reason: patch.reason || `Projection ${patch.projection_id} needs additive review.`
4416
4417
  }
4417
4418
  ])
@@ -6975,7 +6976,7 @@ function collectCanonicalUiSurface(graph) {
6975
6976
  const screens = new Set();
6976
6977
  const routes = new Set();
6977
6978
  for (const projection of graph.byKind.projection || []) {
6978
- if (!["ui_contract", "web_surface"].includes(projection.platform)) {
6979
+ if (!["ui_contract", "web_surface"].includes(projection.type)) {
6979
6980
  continue;
6980
6981
  }
6981
6982
  for (const screen of projection.uiScreens || []) {
@@ -7587,8 +7588,7 @@ function reconcileWorkflow(inputPath, options = {}) {
7587
7588
  enums: bundle.enums.map((entry) => entry.id_hint),
7588
7589
  capabilities: bundle.capabilities.map((entry) => entry.id_hint),
7589
7590
  shapes: bundle.shapes.map((entry) => entry.id),
7590
- components: bundle.components.map((entry) => entry.id_hint),
7591
- widgets: bundle.components.map((entry) => entry.id_hint),
7591
+ widgets: bundle.widgets.map((entry) => entry.id_hint),
7592
7592
  screens: bundle.screens.map((entry) => entry.id_hint),
7593
7593
  workflows: bundle.workflows.map((entry) => entry.id_hint),
7594
7594
  docs: bundle.docs.map((entry) => entry.id),
@@ -7612,11 +7612,11 @@ function reconcileWorkflow(inputPath, options = {}) {
7612
7612
  : "## Promoted Canonical Items";
7613
7613
  files["candidates/reconcile/report.json"] = `${stableStringify(report)}\n`;
7614
7614
  const candidateModelBundlesMarkdown = report.candidate_model_bundles.length
7615
- ? report.candidate_model_bundles.map((bundle) => `- \`${bundle.slug}\` (${bundle.actors.length} actors, ${bundle.roles.length} roles, ${bundle.entities.length} entities, ${bundle.enums.length} enums, ${bundle.capabilities.length} capabilities, ${bundle.shapes.length} shapes, ${bundle.components.length} widgets, ${bundle.screens.length} screens, ${bundle.workflows.length} workflows, ${bundle.docs.length} docs)
7615
+ ? report.candidate_model_bundles.map((bundle) => `- \`${bundle.slug}\` (${bundle.actors.length} actors, ${bundle.roles.length} roles, ${bundle.entities.length} entities, ${bundle.enums.length} enums, ${bundle.capabilities.length} capabilities, ${bundle.shapes.length} shapes, ${bundle.widgets.length} widgets, ${bundle.screens.length} screens, ${bundle.workflows.length} workflows, ${bundle.docs.length} docs)
7616
7616
  - primary concept \`${bundle.operator_summary.primaryConcept}\`${bundle.operator_summary.primaryEntityId ? `, primary entity \`${bundle.operator_summary.primaryEntityId}\`` : ""}
7617
7617
  - participants ${bundle.operator_summary.participants.label}
7618
7618
  - main capabilities ${summarizeBundleSurface(bundle, bundle.operator_summary.capabilityIds)}
7619
- - main widgets ${summarizeBundleSurface(bundle, bundle.operator_summary.componentIds)}
7619
+ - main widgets ${summarizeBundleSurface(bundle, bundle.operator_summary.widgetIds)}
7620
7620
  - main routes ${summarizeBundleSurface(bundle, bundle.operator_summary.routePaths)}
7621
7621
  - candidate maintained seam mappings ${renderMaintainedSeamCandidatesInline(bundle)}
7622
7622
  - permission hints ${bundle.auth_permission_hints?.length ? bundle.auth_permission_hints.map((entry) => formatAuthPermissionHintInline(entry)).join(", ") : "_none_"}