@topogram/cli 0.3.63 → 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.
- package/package.json +1 -1
- package/src/adoption/plan/index.js +703 -0
- package/src/adoption/plan.d.ts +6 -0
- package/src/adoption/plan.js +12 -703
- package/src/adoption/reporting.d.ts +10 -0
- package/src/adoption/review-groups.d.ts +6 -0
- package/src/agent-brief.d.ts +3 -0
- package/src/agent-brief.js +495 -0
- package/src/agent-ops/query-builders/auth.js +375 -0
- package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
- package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
- package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
- package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
- package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
- package/src/agent-ops/query-builders/change-risk.js +25 -0
- package/src/agent-ops/query-builders/common.js +149 -0
- package/src/agent-ops/query-builders/maintained-risk.js +539 -0
- package/src/agent-ops/query-builders/maintained-shared.js +120 -0
- package/src/agent-ops/query-builders/multi-agent.js +547 -0
- package/src/agent-ops/query-builders/projection-impacts.js +514 -0
- package/src/agent-ops/query-builders/work-packets.js +417 -0
- package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
- package/src/agent-ops/query-builders/workflow-context.js +398 -0
- package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
- package/src/agent-ops/query-builders/workflow-presets.js +341 -0
- package/src/agent-ops/query-builders.d.ts +26 -0
- package/src/agent-ops/query-builders.js +42 -5021
- package/src/archive/archive.d.ts +2 -0
- package/src/archive/compact.d.ts +1 -0
- package/src/archive/unarchive.d.ts +1 -0
- package/src/catalog/constants.js +10 -0
- package/src/catalog/copy.js +60 -0
- package/src/catalog/diagnostics.js +15 -0
- package/src/catalog/entries.js +42 -0
- package/src/catalog/files.js +67 -0
- package/src/catalog/provenance.js +122 -0
- package/src/catalog/source.js +150 -0
- package/src/catalog/validation.js +252 -0
- package/src/catalog.d.ts +12 -0
- package/src/catalog.js +18 -750
- package/src/cli/catalog-alias.d.ts +1 -0
- package/src/cli/command-parser.js +38 -0
- package/src/cli/command-parsers/core.js +102 -0
- package/src/cli/command-parsers/generator.js +39 -0
- package/src/cli/command-parsers/import.js +44 -0
- package/src/cli/command-parsers/legacy-workflow.js +21 -0
- package/src/cli/command-parsers/project.js +47 -0
- package/src/cli/command-parsers/sdlc.js +47 -0
- package/src/cli/command-parsers/shared.js +51 -0
- package/src/cli/command-parsers/template.js +48 -0
- package/src/cli/commands/agent.js +47 -0
- package/src/cli/commands/catalog/check.js +31 -0
- package/src/cli/commands/catalog/copy.js +59 -0
- package/src/cli/commands/catalog/doctor.js +248 -0
- package/src/cli/commands/catalog/help.js +21 -0
- package/src/cli/commands/catalog/list.js +52 -0
- package/src/cli/commands/catalog/runner.js +92 -0
- package/src/cli/commands/catalog/shared.js +17 -0
- package/src/cli/commands/catalog/show.js +134 -0
- package/src/cli/commands/catalog.js +32 -0
- package/src/cli/commands/check.js +268 -0
- package/src/cli/commands/doctor.js +268 -0
- package/src/cli/commands/emit.js +149 -0
- package/src/cli/commands/generate.js +96 -0
- package/src/cli/commands/generator-policy/package-info.js +162 -0
- package/src/cli/commands/generator-policy/payloads.js +372 -0
- package/src/cli/commands/generator-policy/printers.js +159 -0
- package/src/cli/commands/generator-policy/runner.js +81 -0
- package/src/cli/commands/generator-policy/shared.js +39 -0
- package/src/cli/commands/generator-policy.js +17 -0
- package/src/cli/commands/generator.js +443 -0
- package/src/cli/commands/import/adopt.js +170 -0
- package/src/cli/commands/import/check.js +91 -0
- package/src/cli/commands/import/diff.js +84 -0
- package/src/cli/commands/import/help.js +47 -0
- package/src/cli/commands/import/paths.js +277 -0
- package/src/cli/commands/import/plan.js +284 -0
- package/src/cli/commands/import/refresh.js +470 -0
- package/src/cli/commands/import/status-history.js +196 -0
- package/src/cli/commands/import/workspace.js +230 -0
- package/src/cli/commands/import-runner.js +157 -0
- package/src/cli/commands/import.js +35 -0
- package/src/cli/commands/inspect.js +55 -0
- package/src/cli/commands/new.js +94 -0
- package/src/cli/commands/package/constants.js +17 -0
- package/src/cli/commands/package/doctor.js +240 -0
- package/src/cli/commands/package/help.js +27 -0
- package/src/cli/commands/package/lockfile.js +135 -0
- package/src/cli/commands/package/npm.js +97 -0
- package/src/cli/commands/package/reporting.js +35 -0
- package/src/cli/commands/package/runner.js +33 -0
- package/src/cli/commands/package/shared.js +9 -0
- package/src/cli/commands/package/update-cli.js +252 -0
- package/src/cli/commands/package/versions.js +35 -0
- package/src/cli/commands/package.js +31 -0
- package/src/cli/commands/query/change-plan.js +68 -0
- package/src/cli/commands/query/definitions.js +202 -0
- package/src/cli/commands/query/import-adopt.js +121 -0
- package/src/cli/commands/query/runner/artifacts.js +102 -0
- package/src/cli/commands/query/runner/boundaries.js +211 -0
- package/src/cli/commands/query/runner/change.js +182 -0
- package/src/cli/commands/query/runner/import-adopt.js +111 -0
- package/src/cli/commands/query/runner/index.js +31 -0
- package/src/cli/commands/query/runner/output.js +12 -0
- package/src/cli/commands/query/runner/workflow.js +241 -0
- package/src/cli/commands/query/runner.js +3 -0
- package/src/cli/commands/query/workflow-context.js +5 -0
- package/src/cli/commands/query/workspace.js +274 -0
- package/src/cli/commands/query.js +11 -0
- package/src/cli/commands/release-rollout.js +257 -0
- package/src/cli/commands/release-shared.js +528 -0
- package/src/cli/commands/release-status.js +429 -0
- package/src/cli/commands/release.js +107 -0
- package/src/cli/commands/sdlc.js +168 -0
- package/src/cli/commands/setup.js +76 -0
- package/src/cli/commands/source.js +291 -0
- package/src/cli/commands/template/baseline.js +100 -0
- package/src/cli/commands/template/check.js +466 -0
- package/src/cli/commands/template/constants.js +8 -0
- package/src/cli/commands/template/diagnostics.js +26 -0
- package/src/cli/commands/template/help.js +28 -0
- package/src/cli/commands/template/lifecycle.js +404 -0
- package/src/cli/commands/template/list-show.js +287 -0
- package/src/cli/commands/template/policy.js +422 -0
- package/src/cli/commands/template/shared.js +127 -0
- package/src/cli/commands/template/updates.js +352 -0
- package/src/cli/commands/template-runner.js +198 -0
- package/src/cli/commands/template.js +43 -0
- package/src/cli/commands/trust.js +219 -0
- package/src/cli/commands/version.js +40 -0
- package/src/cli/commands/widget.js +168 -0
- package/src/cli/commands/workflow.js +63 -0
- package/src/cli/dispatcher.js +392 -0
- package/src/cli/help-dispatch.js +188 -0
- package/src/cli/help.js +296 -0
- package/src/cli/migration-guidance.js +59 -0
- package/src/cli/options.js +96 -0
- package/src/cli/output-safety.js +107 -0
- package/src/cli/path-normalization.js +29 -0
- package/src/cli.js +47 -11711
- package/src/example-implementation.d.ts +2 -0
- package/src/format.d.ts +1 -0
- package/src/generator/api/contracts.js +497 -0
- package/src/generator/api/metadata.js +221 -0
- package/src/generator/api/openapi.js +559 -0
- package/src/generator/api/schema.js +124 -0
- package/src/generator/api/types.d.ts +98 -0
- package/src/generator/api.js +3 -1195
- package/src/generator/check.d.ts +1 -0
- package/src/generator/context/bundle.d.ts +1 -0
- package/src/generator/context/shared/domain-sdlc.js +282 -0
- package/src/generator/context/shared/maintained-boundary.js +665 -0
- package/src/generator/context/shared/metrics.js +85 -0
- package/src/generator/context/shared/primitives.js +64 -0
- package/src/generator/context/shared/relationships.js +453 -0
- package/src/generator/context/shared/summaries.js +263 -0
- package/src/generator/context/shared/types.d.ts +207 -0
- package/src/generator/context/shared.d.ts +44 -0
- package/src/generator/context/shared.js +80 -1390
- package/src/generator/context/slice/core.js +397 -0
- package/src/generator/context/slice/sdlc.js +417 -0
- package/src/generator/context/slice/ui-packets.js +183 -0
- package/src/generator/context/slice.js +2 -859
- package/src/generator/native/parity-bundle.js +2 -1
- package/src/generator/registry/index.js +507 -0
- package/src/generator/registry.js +18 -504
- package/src/generator/runtime/environment/index.js +666 -0
- package/src/generator/runtime/environment.js +4 -666
- package/src/generator/runtime/runtime-check/index.js +554 -0
- package/src/generator/runtime/runtime-check.js +4 -554
- package/src/generator/runtime/shared/index.js +572 -0
- package/src/generator/runtime/shared.js +19 -570
- package/src/generator/shared.d.ts +2 -0
- package/src/generator/surfaces/shared.d.ts +3 -0
- package/src/generator/surfaces/web/html-escape.js +22 -0
- package/src/generator/surfaces/web/react.js +10 -8
- package/src/generator/surfaces/web/sveltekit.js +7 -5
- package/src/generator/surfaces/web/vanilla.js +8 -4
- package/src/generator/widget-conformance/behavior-report.js +258 -0
- package/src/generator/widget-conformance/checks.js +371 -0
- package/src/generator/widget-conformance/projection-context.js +200 -0
- package/src/generator/widget-conformance/report.js +166 -0
- package/src/generator/widget-conformance/types.d.ts +121 -0
- package/src/generator/widget-conformance.js +3 -824
- package/src/generator.d.ts +2 -0
- package/src/github-client.js +520 -0
- package/src/import/core/context.d.ts +3 -0
- package/src/import/core/contracts.d.ts +1 -0
- package/src/import/core/registry.d.ts +4 -0
- package/src/import/core/runner/candidates.js +217 -0
- package/src/import/core/runner/options.js +22 -0
- package/src/import/core/runner/reports.js +50 -0
- package/src/import/core/runner/run.js +79 -0
- package/src/import/core/runner/tracks.js +150 -0
- package/src/import/core/runner/ui-drafts.js +337 -0
- package/src/import/core/runner.js +3 -698
- package/src/import/core/shared/api-routes.js +221 -0
- package/src/import/core/shared/candidates.js +97 -0
- package/src/import/core/shared/files.js +177 -0
- package/src/import/core/shared/next-app.js +389 -0
- package/src/import/core/shared/types.d.ts +51 -0
- package/src/import/core/shared/ui-routes.js +230 -0
- package/src/import/core/shared.js +67 -910
- package/src/import/extractors/api/flutter-dio.js +4 -8
- package/src/import/extractors/api/react-native-repository.js +4 -8
- package/src/import/index.d.ts +4 -0
- package/src/import/provenance.d.ts +4 -0
- package/src/new-project/constants.js +128 -0
- package/src/new-project/create.js +83 -0
- package/src/new-project/json.js +28 -0
- package/src/new-project/metadata.js +96 -0
- package/src/new-project/package-spec.js +161 -0
- package/src/new-project/project-files.js +348 -0
- package/src/new-project/template-policy.js +269 -0
- package/src/new-project/template-resolution.js +368 -0
- package/src/new-project/template-snapshots.js +430 -0
- package/src/new-project/template-updates.js +512 -0
- package/src/new-project/types.d.ts +83 -0
- package/src/new-project.js +6 -2188
- package/src/npm-safety.js +79 -0
- package/src/parser.d.ts +87 -0
- package/src/parser.js +118 -0
- package/src/path-helpers.d.ts +1 -0
- package/src/path-helpers.js +20 -0
- package/src/policy/review-boundaries.d.ts +15 -0
- package/src/project-config/index.js +564 -0
- package/src/project-config.js +19 -560
- package/src/reconcile/docs.d.ts +8 -0
- package/src/reconcile/journeys.d.ts +1 -0
- package/src/resolver/enrich/acceptance-criterion.js +2 -0
- package/src/resolver/enrich/bug.js +2 -0
- package/src/resolver/enrich/pitch.js +2 -0
- package/src/resolver/enrich/requirement.js +2 -0
- package/src/resolver/enrich/task.js +2 -0
- package/src/resolver/index.js +19 -2089
- package/src/resolver/normalize.js +384 -1
- package/src/resolver/plans.js +168 -0
- package/src/resolver/projections-api.js +494 -0
- package/src/resolver/projections-db.js +133 -0
- package/src/resolver/projections-ui.js +317 -0
- package/src/resolver/shapes.js +251 -0
- package/src/resolver/shared.js +278 -0
- package/src/resolver/widgets.js +132 -0
- package/src/resolver.d.ts +1 -0
- package/src/runtime-support.js +29 -0
- package/src/sdlc/adopt.d.ts +1 -0
- package/src/sdlc/check.d.ts +1 -0
- package/src/sdlc/explain.d.ts +1 -0
- package/src/sdlc/release.d.ts +1 -0
- package/src/sdlc/scaffold.d.ts +1 -0
- package/src/sdlc/transition.d.ts +1 -0
- package/src/template-trust/constants.js +62 -0
- package/src/template-trust/content.js +258 -0
- package/src/template-trust/diff.js +92 -0
- package/src/template-trust/policy.js +61 -0
- package/src/template-trust/record.js +90 -0
- package/src/template-trust/status.js +182 -0
- package/src/template-trust.js +24 -687
- package/src/text-helpers.d.ts +7 -0
- package/src/text-helpers.js +245 -0
- package/src/topogram-config.js +306 -0
- package/src/topogram-types.d.ts +69 -0
- package/src/validator/common.js +488 -0
- package/src/validator/data-model.js +237 -0
- package/src/validator/docs.js +167 -0
- package/src/validator/expressions.js +146 -1
- package/src/validator/index.d.ts +23 -0
- package/src/validator/index.js +32 -3585
- package/src/validator/kinds.d.ts +41 -0
- package/src/validator/kinds.js +2 -0
- package/src/validator/model-helpers.js +46 -0
- package/src/validator/per-kind/acceptance-criterion.js +5 -0
- package/src/validator/per-kind/bug.js +6 -0
- package/src/validator/per-kind/domain.js +15 -2
- package/src/validator/per-kind/pitch.js +7 -0
- package/src/validator/per-kind/requirement.js +5 -0
- package/src/validator/per-kind/task.js +7 -0
- package/src/validator/per-kind/widget.js +14 -0
- package/src/validator/projections/api-http-async.js +410 -0
- package/src/validator/projections/api-http-authz.js +88 -0
- package/src/validator/projections/api-http-core.js +205 -0
- package/src/validator/projections/api-http-policies.js +339 -0
- package/src/validator/projections/api-http-responses.js +233 -0
- package/src/validator/projections/api-http.js +44 -0
- package/src/validator/projections/db.js +353 -0
- package/src/validator/projections/generator-defaults.js +45 -0
- package/src/validator/projections/helpers.js +87 -0
- package/src/validator/projections/ui-helpers.js +214 -0
- package/src/validator/projections/ui-navigation.js +344 -0
- package/src/validator/projections/ui-structure.js +364 -0
- package/src/validator/projections/ui-widgets.js +493 -0
- package/src/validator/projections/ui.js +46 -0
- package/src/validator/registry.js +48 -1
- package/src/validator/utils.d.ts +20 -0
- package/src/validator/utils.js +115 -12
- package/src/validator.d.ts +2 -0
- package/src/widget-behavior.d.ts +1 -0
- package/src/workflows/adoption/index.js +26 -0
- package/src/workflows/docs-generate.js +262 -0
- package/src/workflows/docs-scan.js +703 -0
- package/src/workflows/docs.js +15 -0
- package/src/workflows/import-app/api/collect.js +221 -0
- package/src/workflows/import-app/api/openapi.js +257 -0
- package/src/workflows/import-app/api/routes.js +327 -0
- package/src/workflows/import-app/api/sources.js +22 -0
- package/src/workflows/import-app/api.js +4 -0
- package/src/workflows/import-app/db.js +538 -0
- package/src/workflows/import-app/index.js +30 -0
- package/src/workflows/import-app/shared.js +218 -0
- package/src/workflows/import-app/ui.js +443 -0
- package/src/workflows/import-app/workflow.js +159 -0
- package/src/workflows/reconcile/adoption-plan/build.js +208 -0
- package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
- package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
- package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
- package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
- package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
- package/src/workflows/reconcile/adoption-plan.js +32 -0
- package/src/workflows/reconcile/auth/closures.js +115 -0
- package/src/workflows/reconcile/auth/formatters.js +142 -0
- package/src/workflows/reconcile/auth/inference.js +330 -0
- package/src/workflows/reconcile/auth/roles.js +122 -0
- package/src/workflows/reconcile/auth.js +37 -0
- package/src/workflows/reconcile/bundle-core/index.js +600 -0
- package/src/workflows/reconcile/bundle-core.js +14 -0
- package/src/workflows/reconcile/bundle-shared.js +75 -0
- package/src/workflows/reconcile/candidate-model.js +477 -0
- package/src/workflows/reconcile/canonical-surface.js +264 -0
- package/src/workflows/reconcile/gap-report.js +333 -0
- package/src/workflows/reconcile/ids.js +6 -0
- package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
- package/src/workflows/reconcile/impacts/indexes.js +101 -0
- package/src/workflows/reconcile/impacts/patches.js +252 -0
- package/src/workflows/reconcile/impacts/reports.js +80 -0
- package/src/workflows/reconcile/impacts.js +16 -0
- package/src/workflows/reconcile/index.js +7 -0
- package/src/workflows/reconcile/renderers.js +461 -0
- package/src/workflows/reconcile/summary.js +90 -0
- package/src/workflows/reconcile/workflow.js +309 -0
- package/src/workflows/shared.js +189 -0
- package/src/workflows/types.d.ts +93 -0
- package/src/workflows.d.ts +1 -0
- package/src/workflows.js +10 -7652
- package/src/workspace-docs.d.ts +29 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getJourneyDoc,
|
|
3
|
+
getStatement,
|
|
4
|
+
getWorkflowDoc,
|
|
5
|
+
relatedProjectionsForCapability,
|
|
6
|
+
relatedProjectionsForEntity,
|
|
7
|
+
relatedProjectionsForWidget,
|
|
8
|
+
relatedShapesForProjection,
|
|
9
|
+
relatedWidgetsForProjection,
|
|
10
|
+
widgetById
|
|
11
|
+
} from "../../generator/context/shared.js";
|
|
12
|
+
import { generatorDefaultsMap } from "../../generator/surfaces/shared.js";
|
|
13
|
+
import {
|
|
14
|
+
stableSortedStrings,
|
|
15
|
+
targetWidgetId
|
|
16
|
+
} from "./common.js";
|
|
17
|
+
export function projectionKindForImpact(projection) {
|
|
18
|
+
if (!projection) return "unknown";
|
|
19
|
+
if ((projection.http || []).length > 0 || projection.type === "api" || projection.type === "backend") {
|
|
20
|
+
return "api";
|
|
21
|
+
}
|
|
22
|
+
if (
|
|
23
|
+
(projection.uiRoutes || []).length > 0 ||
|
|
24
|
+
(projection.uiWeb || []).length > 0 ||
|
|
25
|
+
(projection.uiIos || []).length > 0 ||
|
|
26
|
+
(projection.uiScreens || []).length > 0 ||
|
|
27
|
+
projection.type === "web_surface" ||
|
|
28
|
+
projection.type === "ios_surface" ||
|
|
29
|
+
projection.type === "ui_contract"
|
|
30
|
+
) {
|
|
31
|
+
return "ui";
|
|
32
|
+
}
|
|
33
|
+
if (
|
|
34
|
+
(projection.dbTables || []).length > 0 ||
|
|
35
|
+
(projection.dbColumns || []).length > 0 ||
|
|
36
|
+
(projection.dbRelations || []).length > 0 ||
|
|
37
|
+
String(projection.type || "").startsWith("db_")
|
|
38
|
+
) {
|
|
39
|
+
return "db";
|
|
40
|
+
}
|
|
41
|
+
return "unknown";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function projectionSummaryForImpact(projection) {
|
|
45
|
+
if (!projection) return null;
|
|
46
|
+
return {
|
|
47
|
+
projection_id: projection.id,
|
|
48
|
+
kind: projectionKindForImpact(projection),
|
|
49
|
+
type: projection.type || null,
|
|
50
|
+
outputs: stableSortedStrings(projection.outputs || [])
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function projectionById(graph, projectionId) {
|
|
55
|
+
return (graph?.byKind?.projection || []).find((projection) => projection.id === projectionId) || null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function impactsFromProjectionIds(graph, projectionIds, impactSource, reasonBuilder) {
|
|
59
|
+
return projectionIds
|
|
60
|
+
.map((projectionId) => {
|
|
61
|
+
const projection = projectionById(graph, projectionId);
|
|
62
|
+
if (!projection) return null;
|
|
63
|
+
return {
|
|
64
|
+
...projectionSummaryForImpact(projection),
|
|
65
|
+
impact_source: impactSource,
|
|
66
|
+
reason: reasonBuilder(projection)
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function addImpact(map, impact) {
|
|
73
|
+
if (!impact?.projection_id) return;
|
|
74
|
+
const existing = map.get(impact.projection_id);
|
|
75
|
+
if (!existing) {
|
|
76
|
+
map.set(impact.projection_id, {
|
|
77
|
+
...impact,
|
|
78
|
+
impact_sources: [impact.impact_source],
|
|
79
|
+
reasons: [impact.reason]
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const priority = [
|
|
85
|
+
"direct_projection_change",
|
|
86
|
+
"selected_projection",
|
|
87
|
+
"changed_capability",
|
|
88
|
+
"changed_entity",
|
|
89
|
+
"changed_shape",
|
|
90
|
+
"changed_widget",
|
|
91
|
+
"changed_rule",
|
|
92
|
+
"changed_workflow",
|
|
93
|
+
"changed_journey",
|
|
94
|
+
"selected_rule",
|
|
95
|
+
"selected_capability",
|
|
96
|
+
"selected_entity",
|
|
97
|
+
"selected_workflow",
|
|
98
|
+
"selected_journey"
|
|
99
|
+
];
|
|
100
|
+
existing.impact_sources = stableSortedStrings([...(existing.impact_sources || []), impact.impact_source]);
|
|
101
|
+
existing.reasons = stableSortedStrings([...(existing.reasons || []), impact.reason]);
|
|
102
|
+
const currentPriority = priority.indexOf(existing.impact_source);
|
|
103
|
+
const nextPriority = priority.indexOf(impact.impact_source);
|
|
104
|
+
if (currentPriority === -1 || (nextPriority !== -1 && nextPriority < currentPriority)) {
|
|
105
|
+
existing.impact_source = impact.impact_source;
|
|
106
|
+
existing.reason = impact.reason;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function projectionImpactsFromRule(graph, ruleId, selected = false) {
|
|
111
|
+
let rule;
|
|
112
|
+
try {
|
|
113
|
+
rule = getStatement(graph, "rule", ruleId);
|
|
114
|
+
} catch {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
const impacts = [];
|
|
118
|
+
for (const target of rule.appliesTo || []) {
|
|
119
|
+
if (target.id?.startsWith("cap_")) {
|
|
120
|
+
impacts.push(...impactsFromProjectionIds(
|
|
121
|
+
graph,
|
|
122
|
+
relatedProjectionsForCapability(graph, target.id),
|
|
123
|
+
selected ? "selected_rule" : "changed_rule",
|
|
124
|
+
(projection) => `Projection ${projection.id} is affected because rule ${ruleId} applies to capability ${target.id}.`
|
|
125
|
+
));
|
|
126
|
+
} else if (target.id?.startsWith("entity_")) {
|
|
127
|
+
impacts.push(...impactsFromProjectionIds(
|
|
128
|
+
graph,
|
|
129
|
+
relatedProjectionsForEntity(graph, target.id),
|
|
130
|
+
selected ? "selected_rule" : "changed_rule",
|
|
131
|
+
(projection) => `Projection ${projection.id} is affected because rule ${ruleId} applies to entity ${target.id}.`
|
|
132
|
+
));
|
|
133
|
+
} else if (target.kind === "projection" || target.id?.startsWith("proj_")) {
|
|
134
|
+
impacts.push(...impactsFromProjectionIds(
|
|
135
|
+
graph,
|
|
136
|
+
[target.id],
|
|
137
|
+
selected ? "selected_rule" : "changed_rule",
|
|
138
|
+
() => `Projection ${target.id} is affected because rule ${ruleId} applies directly to that projection.`
|
|
139
|
+
));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return impacts;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function projectionImpactsFromWorkflow(graph, workflowId, selected = false) {
|
|
146
|
+
let workflow;
|
|
147
|
+
try {
|
|
148
|
+
workflow = getWorkflowDoc(graph, workflowId);
|
|
149
|
+
} catch {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
const direct = stableSortedStrings(workflow.relatedProjections || []);
|
|
153
|
+
const viaCapabilities = stableSortedStrings((workflow.relatedCapabilities || []).flatMap((capabilityId) =>
|
|
154
|
+
relatedProjectionsForCapability(graph, capabilityId)
|
|
155
|
+
));
|
|
156
|
+
|
|
157
|
+
return [
|
|
158
|
+
...impactsFromProjectionIds(
|
|
159
|
+
graph,
|
|
160
|
+
direct,
|
|
161
|
+
selected ? "selected_workflow" : "changed_workflow",
|
|
162
|
+
(projection) => `Projection ${projection.id} is affected because workflow ${workflowId} links to that projection directly.`
|
|
163
|
+
),
|
|
164
|
+
...impactsFromProjectionIds(
|
|
165
|
+
graph,
|
|
166
|
+
viaCapabilities.filter((id) => !direct.includes(id)),
|
|
167
|
+
selected ? "selected_workflow" : "changed_workflow",
|
|
168
|
+
(projection) => `Projection ${projection.id} is affected because workflow ${workflowId} includes related capabilities realized by that projection.`
|
|
169
|
+
)
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function projectionImpactsFromJourney(graph, journeyId, selected = false) {
|
|
174
|
+
let journey;
|
|
175
|
+
try {
|
|
176
|
+
journey = getJourneyDoc(graph, journeyId);
|
|
177
|
+
} catch {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
const direct = stableSortedStrings(journey.relatedProjections || []);
|
|
181
|
+
const viaCapabilities = stableSortedStrings((journey.relatedCapabilities || []).flatMap((capabilityId) =>
|
|
182
|
+
relatedProjectionsForCapability(graph, capabilityId)
|
|
183
|
+
));
|
|
184
|
+
const viaWorkflows = stableSortedStrings((journey.relatedWorkflows || []).flatMap((workflowId) => {
|
|
185
|
+
try {
|
|
186
|
+
const workflow = getWorkflowDoc(graph, workflowId);
|
|
187
|
+
return workflow.relatedProjections || [];
|
|
188
|
+
} catch {
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
|
|
193
|
+
return [
|
|
194
|
+
...impactsFromProjectionIds(
|
|
195
|
+
graph,
|
|
196
|
+
direct,
|
|
197
|
+
selected ? "selected_journey" : "changed_journey",
|
|
198
|
+
(projection) => `Projection ${projection.id} is affected because journey ${journeyId} links to that projection directly.`
|
|
199
|
+
),
|
|
200
|
+
...impactsFromProjectionIds(
|
|
201
|
+
graph,
|
|
202
|
+
[...viaCapabilities, ...viaWorkflows].filter((id) => !direct.includes(id)),
|
|
203
|
+
selected ? "selected_journey" : "changed_journey",
|
|
204
|
+
(projection) => `Projection ${projection.id} is affected because journey ${journeyId} links to related workflow or capability surfaces realized by that projection.`
|
|
205
|
+
)
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function projectionImpactsFromShape(graph, shapeId) {
|
|
210
|
+
const directProjectionIds = stableSortedStrings((graph?.byKind?.projection || [])
|
|
211
|
+
.filter((projection) => relatedShapesForProjection(projection).includes(shapeId))
|
|
212
|
+
.map((projection) => projection.id));
|
|
213
|
+
const viaCapabilities = stableSortedStrings((graph?.byKind?.capability || [])
|
|
214
|
+
.filter((capability) => [...(capability.input || []), ...(capability.output || [])].some((item) => item.id === shapeId))
|
|
215
|
+
.flatMap((capability) => relatedProjectionsForCapability(graph, capability.id)));
|
|
216
|
+
|
|
217
|
+
return [
|
|
218
|
+
...impactsFromProjectionIds(
|
|
219
|
+
graph,
|
|
220
|
+
directProjectionIds,
|
|
221
|
+
"changed_shape",
|
|
222
|
+
(projection) => `Projection ${projection.id} is affected because it references changed shape ${shapeId} directly.`
|
|
223
|
+
),
|
|
224
|
+
...impactsFromProjectionIds(
|
|
225
|
+
graph,
|
|
226
|
+
viaCapabilities.filter((id) => !directProjectionIds.includes(id)),
|
|
227
|
+
"changed_shape",
|
|
228
|
+
(projection) => `Projection ${projection.id} is affected because changed shape ${shapeId} is used by related capabilities realized by that projection.`
|
|
229
|
+
)
|
|
230
|
+
];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function projectionImpactsFromWidget(graph, widgetId) {
|
|
234
|
+
const widget = widgetById(graph, widgetId);
|
|
235
|
+
if (!widget) {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return impactsFromProjectionIds(
|
|
240
|
+
graph,
|
|
241
|
+
relatedProjectionsForWidget(graph, widgetId),
|
|
242
|
+
"changed_widget",
|
|
243
|
+
(projection) => `Projection ${projection.id} is affected because widget ${widgetId} is used by that UI surface.`
|
|
244
|
+
).map((impact) => ({
|
|
245
|
+
...impact,
|
|
246
|
+
widget_ids: stableSortedStrings([widgetId])
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function buildProjectionImpacts(graph, { sliceArtifact, diffArtifact }) {
|
|
251
|
+
const impactMap = new Map();
|
|
252
|
+
|
|
253
|
+
if (diffArtifact) {
|
|
254
|
+
for (const entry of diffArtifact.projections || []) {
|
|
255
|
+
addImpact(impactMap, {
|
|
256
|
+
...projectionSummaryForImpact(projectionById(graph, entry.id)),
|
|
257
|
+
impact_source: "direct_projection_change",
|
|
258
|
+
reason: `Projection ${entry.id} changed directly in the semantic diff.`
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
for (const entry of diffArtifact.capabilities || []) {
|
|
263
|
+
for (const impact of impactsFromProjectionIds(
|
|
264
|
+
graph,
|
|
265
|
+
relatedProjectionsForCapability(graph, entry.id),
|
|
266
|
+
"changed_capability",
|
|
267
|
+
(projection) => `Projection ${projection.id} is affected because changed capability ${entry.id} is realized by that projection.`
|
|
268
|
+
)) addImpact(impactMap, impact);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
for (const entry of diffArtifact.entities || []) {
|
|
272
|
+
for (const impact of impactsFromProjectionIds(
|
|
273
|
+
graph,
|
|
274
|
+
relatedProjectionsForEntity(graph, entry.id),
|
|
275
|
+
"changed_entity",
|
|
276
|
+
(projection) => `Projection ${projection.id} is affected because changed entity ${entry.id} participates in that projection.`
|
|
277
|
+
)) addImpact(impactMap, impact);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
for (const entry of diffArtifact.shapes || []) {
|
|
281
|
+
for (const impact of projectionImpactsFromShape(graph, entry.id)) addImpact(impactMap, impact);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
for (const entry of diffArtifact.widgets || diffArtifact.components || []) {
|
|
285
|
+
for (const impact of projectionImpactsFromWidget(graph, entry.id)) addImpact(impactMap, impact);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
for (const entry of diffArtifact.rules || []) {
|
|
289
|
+
for (const impact of projectionImpactsFromRule(graph, entry.id)) addImpact(impactMap, impact);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
for (const entry of diffArtifact.workflows || []) {
|
|
293
|
+
for (const impact of projectionImpactsFromWorkflow(graph, entry.id)) addImpact(impactMap, impact);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
for (const entry of diffArtifact.journeys || []) {
|
|
297
|
+
for (const impact of projectionImpactsFromJourney(graph, entry.id)) addImpact(impactMap, impact);
|
|
298
|
+
}
|
|
299
|
+
} else if (sliceArtifact?.focus) {
|
|
300
|
+
const { kind, id } = sliceArtifact.focus;
|
|
301
|
+
if (kind === "projection") {
|
|
302
|
+
addImpact(impactMap, {
|
|
303
|
+
...projectionSummaryForImpact(projectionById(graph, id)),
|
|
304
|
+
impact_source: "selected_projection",
|
|
305
|
+
reason: `Projection ${id} is the selected focus surface.`
|
|
306
|
+
});
|
|
307
|
+
} else if (kind === "capability") {
|
|
308
|
+
for (const impact of impactsFromProjectionIds(
|
|
309
|
+
graph,
|
|
310
|
+
stableSortedStrings(sliceArtifact.depends_on?.projections || relatedProjectionsForCapability(graph, id)),
|
|
311
|
+
"selected_capability",
|
|
312
|
+
(projection) => `Projection ${projection.id} is in scope because selected capability ${id} is realized by that projection.`
|
|
313
|
+
)) addImpact(impactMap, impact);
|
|
314
|
+
} else if (kind === "entity") {
|
|
315
|
+
for (const impact of impactsFromProjectionIds(
|
|
316
|
+
graph,
|
|
317
|
+
stableSortedStrings(sliceArtifact.depends_on?.projections || relatedProjectionsForEntity(graph, id)),
|
|
318
|
+
"selected_entity",
|
|
319
|
+
(projection) => `Projection ${projection.id} is in scope because selected entity ${id} participates in that projection.`
|
|
320
|
+
)) addImpact(impactMap, impact);
|
|
321
|
+
} else if (kind === "widget") {
|
|
322
|
+
for (const impact of projectionImpactsFromWidget(graph, id)) addImpact(impactMap, impact);
|
|
323
|
+
} else if (kind === "workflow") {
|
|
324
|
+
for (const impact of projectionImpactsFromWorkflow(graph, id, true)) addImpact(impactMap, impact);
|
|
325
|
+
} else if (kind === "journey") {
|
|
326
|
+
for (const impact of projectionImpactsFromJourney(graph, id, true)) addImpact(impactMap, impact);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return [...impactMap.values()]
|
|
331
|
+
.map((impact) => ({
|
|
332
|
+
...impact,
|
|
333
|
+
impact_sources: stableSortedStrings(impact.impact_sources || []),
|
|
334
|
+
reasons: stableSortedStrings(impact.reasons || [])
|
|
335
|
+
}))
|
|
336
|
+
.sort((a, b) => a.projection_id.localeCompare(b.projection_id));
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function buildGeneratorTargets(graph, projectionImpacts = [], diffArtifact = null) {
|
|
340
|
+
const targets = [];
|
|
341
|
+
const addTarget = (target) => {
|
|
342
|
+
if (!target?.target) return;
|
|
343
|
+
if (target.component_id && !target.widget_id) {
|
|
344
|
+
target.widget_id = target.component_id;
|
|
345
|
+
delete target.component_id;
|
|
346
|
+
}
|
|
347
|
+
if (!target.projection_id && !target.widget_id) return;
|
|
348
|
+
if (!targets.some((entry) =>
|
|
349
|
+
entry.target === target.target &&
|
|
350
|
+
entry.projection_id === target.projection_id &&
|
|
351
|
+
targetWidgetId(entry) === targetWidgetId(target)
|
|
352
|
+
)) {
|
|
353
|
+
targets.push(target);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
for (const entry of diffArtifact?.widgets || diffArtifact?.components || []) {
|
|
358
|
+
addTarget({
|
|
359
|
+
target: "ui-widget-contract",
|
|
360
|
+
widget_id: entry.id,
|
|
361
|
+
required: true,
|
|
362
|
+
reason: `Widget ${entry.id} changed directly, so its widget contract should be refreshed.`
|
|
363
|
+
});
|
|
364
|
+
addTarget({
|
|
365
|
+
target: "widget-behavior-report",
|
|
366
|
+
widget_id: entry.id,
|
|
367
|
+
required: true,
|
|
368
|
+
reason: `Widget ${entry.id} changed directly, so behavior realizations should be reviewed across affected projections.`
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
for (const impact of projectionImpacts) {
|
|
373
|
+
const projection = projectionById(graph, impact.projection_id);
|
|
374
|
+
if (!projection) continue;
|
|
375
|
+
const profile = generatorDefaultsMap(projection).profile || null;
|
|
376
|
+
const outputs = stableSortedStrings(projection.outputs || []);
|
|
377
|
+
|
|
378
|
+
if (impact.kind === "api") {
|
|
379
|
+
addTarget({
|
|
380
|
+
target: "api-contract-graph",
|
|
381
|
+
projection_id: impact.projection_id,
|
|
382
|
+
required: true,
|
|
383
|
+
reason: `Projection ${impact.projection_id} is API-facing, so API contract regeneration is required.`
|
|
384
|
+
});
|
|
385
|
+
addTarget({
|
|
386
|
+
target: "server-contract",
|
|
387
|
+
projection_id: impact.projection_id,
|
|
388
|
+
required: true,
|
|
389
|
+
reason: `Projection ${impact.projection_id} is API-facing, so the server contract should stay aligned.`
|
|
390
|
+
});
|
|
391
|
+
addTarget({
|
|
392
|
+
target: "api-contract-debug",
|
|
393
|
+
projection_id: impact.projection_id,
|
|
394
|
+
required: false,
|
|
395
|
+
reason: `Projection ${impact.projection_id} may benefit from API contract debug output during review.`
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (projection.type === "ui_contract") {
|
|
400
|
+
addTarget({
|
|
401
|
+
target: "ui-contract-graph",
|
|
402
|
+
projection_id: impact.projection_id,
|
|
403
|
+
required: true,
|
|
404
|
+
reason: `Projection ${impact.projection_id} is a shared UI surface, so the UI contract should be refreshed.`
|
|
405
|
+
});
|
|
406
|
+
addTarget({
|
|
407
|
+
target: "ui-contract-debug",
|
|
408
|
+
projection_id: impact.projection_id,
|
|
409
|
+
required: false,
|
|
410
|
+
reason: `Projection ${impact.projection_id} may benefit from UI contract debug output during review.`
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const widgetIds = stableSortedStrings([
|
|
415
|
+
...(impact.widget_ids || []),
|
|
416
|
+
...(impact.kind === "ui" ? relatedWidgetsForProjection(graph, projection) : [])
|
|
417
|
+
]);
|
|
418
|
+
|
|
419
|
+
for (const widgetId of widgetIds) {
|
|
420
|
+
addTarget({
|
|
421
|
+
target: "ui-widget-contract",
|
|
422
|
+
widget_id: widgetId,
|
|
423
|
+
projection_id: impact.projection_id,
|
|
424
|
+
required: true,
|
|
425
|
+
reason: `Projection ${impact.projection_id} is affected by widget ${widgetId}, so the widget contract should be refreshed.`
|
|
426
|
+
});
|
|
427
|
+
addTarget({
|
|
428
|
+
target: "widget-behavior-report",
|
|
429
|
+
widget_id: widgetId,
|
|
430
|
+
projection_id: impact.projection_id,
|
|
431
|
+
required: true,
|
|
432
|
+
reason: `Projection ${impact.projection_id} is affected by widget ${widgetId}, so behavior data/event/action wiring should be reviewed.`
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (projection.type === "web_surface") {
|
|
437
|
+
addTarget({
|
|
438
|
+
target: "ui-surface-contract",
|
|
439
|
+
projection_id: impact.projection_id,
|
|
440
|
+
required: true,
|
|
441
|
+
reason: `Projection ${impact.projection_id} is a web UI surface, so the web UI contract should be refreshed.`
|
|
442
|
+
});
|
|
443
|
+
addTarget({
|
|
444
|
+
target: "ui-surface-debug",
|
|
445
|
+
projection_id: impact.projection_id,
|
|
446
|
+
required: false,
|
|
447
|
+
reason: `Projection ${impact.projection_id} may benefit from UI web debug output during review.`
|
|
448
|
+
});
|
|
449
|
+
if (outputs.includes("web_app") && profile === "sveltekit") {
|
|
450
|
+
addTarget({
|
|
451
|
+
target: "sveltekit-app",
|
|
452
|
+
projection_id: impact.projection_id,
|
|
453
|
+
required: false,
|
|
454
|
+
reason: `Projection ${impact.projection_id} emits a web app with SvelteKit profile, so the app scaffold may need regeneration.`
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (projection.type === "ios_surface") {
|
|
460
|
+
addTarget({
|
|
461
|
+
target: "swiftui-app",
|
|
462
|
+
projection_id: impact.projection_id,
|
|
463
|
+
required: false,
|
|
464
|
+
reason: `Projection ${impact.projection_id} is a native iOS UI surface, so the SwiftUI client scaffold may need regeneration.`
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (String(projection.type || "").startsWith("db_")) {
|
|
469
|
+
addTarget({
|
|
470
|
+
target: "db-contract-graph",
|
|
471
|
+
projection_id: impact.projection_id,
|
|
472
|
+
required: true,
|
|
473
|
+
reason: `Projection ${impact.projection_id} is database-facing, so the DB contract graph should be refreshed.`
|
|
474
|
+
});
|
|
475
|
+
addTarget({
|
|
476
|
+
target: "db-contract-debug",
|
|
477
|
+
projection_id: impact.projection_id,
|
|
478
|
+
required: false,
|
|
479
|
+
reason: `Projection ${impact.projection_id} may benefit from DB contract debug output during review.`
|
|
480
|
+
});
|
|
481
|
+
addTarget({
|
|
482
|
+
target: "db-schema-snapshot",
|
|
483
|
+
projection_id: impact.projection_id,
|
|
484
|
+
required: true,
|
|
485
|
+
reason: `Projection ${impact.projection_id} is database-facing, so the schema snapshot should stay aligned.`
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
const schemaSensitiveDiff = Boolean(
|
|
489
|
+
diffArtifact &&
|
|
490
|
+
(
|
|
491
|
+
(diffArtifact.entities || []).length > 0 ||
|
|
492
|
+
(diffArtifact.shapes || []).length > 0 ||
|
|
493
|
+
(diffArtifact.projections || []).some((entry) => entry.id === impact.projection_id)
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
if (schemaSensitiveDiff) {
|
|
497
|
+
addTarget({
|
|
498
|
+
target: "db-migration-plan",
|
|
499
|
+
projection_id: impact.projection_id,
|
|
500
|
+
required: false,
|
|
501
|
+
reason: `Projection ${impact.projection_id} has schema-sensitive diff inputs, so reviewing a migration plan is recommended.`
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return targets.sort((a, b) => {
|
|
508
|
+
const projectionCompare = String(a.projection_id || "").localeCompare(String(b.projection_id || ""));
|
|
509
|
+
if (projectionCompare !== 0) return projectionCompare;
|
|
510
|
+
const componentCompare = String(targetWidgetId(a) || "").localeCompare(String(targetWidgetId(b) || ""));
|
|
511
|
+
if (componentCompare !== 0) return componentCompare;
|
|
512
|
+
return projectionCompare !== 0 ? projectionCompare : a.target.localeCompare(b.target);
|
|
513
|
+
});
|
|
514
|
+
}
|