@topogram/cli 0.3.64 → 0.3.66
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 +716 -0
- package/src/adoption/plan.js +12 -703
- package/src/adoption/reporting.js +1 -1
- package/src/agent-brief.js +7 -21
- 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 +677 -0
- package/src/agent-ops/query-builders/workflow-presets.js +341 -0
- package/src/agent-ops/query-builders.d.ts +26 -26
- package/src/agent-ops/query-builders.js +42 -5021
- package/src/archive/jsonl.js +2 -2
- package/src/archive/resolver-bridge.js +1 -1
- package/src/archive/unarchive.js +2 -1
- package/src/catalog/constants.js +10 -0
- package/src/catalog/copy.js +65 -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 +123 -0
- package/src/catalog/source.js +150 -0
- package/src/catalog/validation.js +252 -0
- package/src/catalog.d.ts +2 -0
- package/src/catalog.js +18 -746
- package/src/cli/command-parsers/project.js +3 -0
- package/src/cli/command-parsers/shared.js +1 -1
- package/src/cli/commands/agent.js +2 -2
- 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 +30 -615
- package/src/cli/commands/check.js +3 -3
- package/src/cli/commands/doctor.js +2 -9
- 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 +15 -783
- 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 +269 -0
- package/src/cli/commands/import/plan.js +292 -0
- package/src/cli/commands/import/refresh.js +471 -0
- package/src/cli/commands/import/status-history.js +196 -0
- package/src/cli/commands/import/workspace.js +233 -0
- package/src/cli/commands/import.js +33 -1732
- package/src/cli/commands/migrate.js +153 -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 +29 -813
- 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 +270 -0
- package/src/cli/commands/query.js +9 -1300
- package/src/cli/commands/source.js +3 -12
- package/src/cli/commands/template/baseline.js +100 -0
- package/src/cli/commands/template/check.js +467 -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 +6 -6
- package/src/cli/commands/template.js +41 -2143
- package/src/cli/commands/trust.js +1 -1
- package/src/cli/commands/workflow.js +6 -1
- package/src/cli/dispatcher.js +6 -1
- package/src/cli/help.js +15 -14
- package/src/cli/migration-guidance.js +1 -1
- package/src/cli/output-safety.js +2 -1
- package/src/cli/path-normalization.js +3 -13
- 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/context/domain-page.js +1 -1
- 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 +42 -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/context/task-mode.js +2 -2
- 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/sdlc/doc-page.js +1 -1
- package/src/generator/shared.d.ts +2 -0
- package/src/generator/surfaces/databases/lifecycle-shared.js +1 -1
- package/src/generator/surfaces/native/swiftui-templates/README.generated.md +1 -1
- package/src/generator/surfaces/shared.d.ts +3 -0
- 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/import/core/context.d.ts +3 -0
- package/src/import/core/context.js +5 -7
- 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 +337 -0
- package/src/import/core/runner/options.js +22 -0
- package/src/import/core/runner/reports.js +51 -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 +393 -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 +60 -861
- package/src/new-project/constants.js +128 -0
- package/src/new-project/create.js +90 -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 +351 -0
- package/src/new-project/template-policy.js +269 -0
- package/src/new-project/template-resolution.js +370 -0
- package/src/new-project/template-snapshots.js +442 -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 -2277
- package/src/parser.d.ts +87 -1
- package/src/parser.js +118 -0
- package/src/policy/review-boundaries.d.ts +15 -0
- package/src/project-config/index.js +591 -0
- package/src/project-config.js +19 -561
- 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/sdlc/adopt.js +6 -5
- package/src/sdlc/paths.js +3 -5
- package/src/sdlc/scaffold.js +2 -1
- 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 +1 -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/widget-behavior.d.ts +1 -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 +2 -797
- package/src/workflows/reconcile/adoption-plan/build.js +212 -0
- package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
- package/src/workflows/reconcile/adoption-plan/outputs.js +153 -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 +30 -740
- 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 +35 -690
- package/src/workflows/reconcile/bundle-core/index.js +600 -0
- package/src/workflows/reconcile/bundle-core.js +12 -598
- package/src/workflows/reconcile/candidate-model.js +18 -2
- package/src/workflows/reconcile/canonical-surface.js +1 -1
- package/src/workflows/reconcile/impacts/adoption-plan.js +196 -0
- package/src/workflows/reconcile/impacts/indexes.js +105 -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 +14 -623
- package/src/workflows/reconcile/renderers.js +41 -6
- package/src/workflows/shared.js +5 -11
- package/src/workspace-docs.d.ts +29 -0
- package/src/workspace-paths.js +328 -0
|
@@ -1,1397 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import { parseDocFile } from "../../workspace-docs.js";
|
|
5
|
-
import {
|
|
6
|
-
defaultOwnershipBoundary,
|
|
7
|
-
ownershipBoundaryForMaintainedSurface,
|
|
8
|
-
reviewBoundaryForCapability as reviewBoundaryForCapabilityPolicy,
|
|
9
|
-
reviewBoundaryForEntity as reviewBoundaryForEntityPolicy,
|
|
10
|
-
reviewBoundaryForJourneyDoc as reviewBoundaryForJourneyDocPolicy,
|
|
11
|
-
reviewBoundaryForMaintainedClassification,
|
|
12
|
-
reviewBoundaryForProjection as reviewBoundaryForProjectionPolicy,
|
|
13
|
-
reviewBoundaryForWorkflowDoc as reviewBoundaryForWorkflowDocPolicy
|
|
14
|
-
} from "../../policy/review-boundaries.js";
|
|
15
|
-
|
|
16
|
-
const bundledRepoRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..", "..", "..", "..");
|
|
17
|
-
|
|
18
|
-
function stableSortedStrings(values) {
|
|
19
|
-
return [...new Set((values || []).filter(Boolean))].sort();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function seamIdHint(value) {
|
|
23
|
-
return String(value || "")
|
|
24
|
-
.trim()
|
|
25
|
-
.toLowerCase()
|
|
26
|
-
.replace(/[^a-z0-9]+/g, "_")
|
|
27
|
-
.replace(/^_+|_+$/g, "") || "maintained_surface";
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function titleCaseWords(value) {
|
|
31
|
-
return String(value || "")
|
|
32
|
-
.split(/[_\-\s]+/)
|
|
33
|
-
.filter(Boolean)
|
|
34
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
35
|
-
.join(" ");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function refIds(items) {
|
|
39
|
-
return stableSortedStrings((items || []).map((item) => item?.id || item?.target?.id));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function docIds(items) {
|
|
43
|
-
return stableSortedStrings((items || []).map((item) => item?.id));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function summarizeField(field) {
|
|
47
|
-
return {
|
|
48
|
-
name: field.name || null,
|
|
49
|
-
type: field.fieldType || null,
|
|
50
|
-
requiredness: field.requiredness || null,
|
|
51
|
-
defaultValue: field.defaultValue ?? null
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function summarizeProjection(projection) {
|
|
56
|
-
return {
|
|
57
|
-
id: projection.id,
|
|
58
|
-
kind: projection.kind,
|
|
59
|
-
name: projection.name || projection.id,
|
|
60
|
-
description: projection.description || null,
|
|
61
|
-
type: projection.type || null,
|
|
62
|
-
realizes: refIds(projection.realizes),
|
|
63
|
-
outputs: stableSortedStrings(projection.outputs || []),
|
|
64
|
-
uiScreens: stableSortedStrings((projection.uiScreens || []).map((screen) => screen.id)),
|
|
65
|
-
widgetBindings: stableSortedStrings((projection.widgetBindings || []).map((entry) => entry.widget?.id).filter(Boolean)),
|
|
66
|
-
dbTables: stableSortedStrings((projection.dbTables || []).map((table) => table.table || table.entity?.id)),
|
|
67
|
-
httpCapabilities: stableSortedStrings((projection.http || []).map((entry) => entry.capability?.id)),
|
|
68
|
-
reviewBoundary: reviewBoundaryForProjectionPolicy(projection),
|
|
69
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function summarizeRule(rule) {
|
|
74
|
-
return {
|
|
75
|
-
id: rule.id,
|
|
76
|
-
kind: rule.kind,
|
|
77
|
-
name: rule.name || rule.id,
|
|
78
|
-
description: rule.description || null,
|
|
79
|
-
appliesTo: refIds(rule.appliesTo),
|
|
80
|
-
actors: refIds(rule.actors),
|
|
81
|
-
roles: refIds(rule.roles),
|
|
82
|
-
severity: rule.severity || null,
|
|
83
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function summarizeVerification(verification) {
|
|
88
|
-
return {
|
|
89
|
-
id: verification.id,
|
|
90
|
-
kind: verification.kind,
|
|
91
|
-
name: verification.name || verification.id,
|
|
92
|
-
description: verification.description || null,
|
|
93
|
-
method: verification.method || null,
|
|
94
|
-
validates: refIds(verification.validates),
|
|
95
|
-
scenarios: stableSortedStrings(verification.scenarios || []),
|
|
96
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function summarizeJourneyDoc(doc) {
|
|
101
|
-
return {
|
|
102
|
-
id: doc.id,
|
|
103
|
-
kind: doc.kind,
|
|
104
|
-
title: doc.title || doc.id,
|
|
105
|
-
summary: doc.summary || null,
|
|
106
|
-
relatedCapabilities: stableSortedStrings(doc.relatedCapabilities || []),
|
|
107
|
-
relatedWorkflows: stableSortedStrings(doc.relatedWorkflows || []),
|
|
108
|
-
relatedProjections: stableSortedStrings(doc.relatedProjections || []),
|
|
109
|
-
reviewRequired: Boolean(doc.reviewRequired),
|
|
110
|
-
reviewBoundary: doc.kind === "workflow" ? reviewBoundaryForWorkflowDocPolicy(doc) : reviewBoundaryForJourneyDocPolicy(doc),
|
|
111
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function summarizeComponent(statement) {
|
|
116
|
-
return {
|
|
117
|
-
id: statement.id,
|
|
118
|
-
kind: statement.kind,
|
|
119
|
-
name: statement.name || statement.id,
|
|
120
|
-
description: statement.description || null,
|
|
121
|
-
category: statement.category || null,
|
|
122
|
-
version: statement.version || null,
|
|
123
|
-
status: statement.status || null,
|
|
124
|
-
props: (statement.props || []).map((prop) => ({
|
|
125
|
-
name: prop.name ?? null,
|
|
126
|
-
type: prop.fieldType ?? null,
|
|
127
|
-
requiredness: prop.requiredness ?? null,
|
|
128
|
-
defaultValue: prop.defaultValue ?? null
|
|
129
|
-
})),
|
|
130
|
-
events: (statement.events || []).map((event) => ({
|
|
131
|
-
id: event.id ?? null,
|
|
132
|
-
shape: event.shape?.id ?? null
|
|
133
|
-
})),
|
|
134
|
-
slots: (statement.slots || []).map((slot) => ({
|
|
135
|
-
id: slot.id ?? null,
|
|
136
|
-
description: slot.description ?? null
|
|
137
|
-
})),
|
|
138
|
-
behavior: stableSortedStrings(statement.behavior || []),
|
|
139
|
-
behaviors: (statement.behaviors || []).map((behavior) => ({
|
|
140
|
-
kind: behavior.kind || null,
|
|
141
|
-
directives: behavior.directives || {},
|
|
142
|
-
source: behavior.source || null
|
|
143
|
-
})),
|
|
144
|
-
patterns: stableSortedStrings(statement.patterns || []),
|
|
145
|
-
regions: stableSortedStrings(statement.regions || []),
|
|
146
|
-
approvals: stableSortedStrings(statement.approvals || []),
|
|
147
|
-
lookups: refIds(statement.lookups),
|
|
148
|
-
dependencies: refIds(statement.dependencies),
|
|
149
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function summarizeStatement(statement) {
|
|
154
|
-
switch (statement.kind) {
|
|
155
|
-
case "entity":
|
|
156
|
-
return {
|
|
157
|
-
id: statement.id,
|
|
158
|
-
kind: statement.kind,
|
|
159
|
-
name: statement.name || statement.id,
|
|
160
|
-
description: statement.description || null,
|
|
161
|
-
fields: (statement.fields || []).map(summarizeField),
|
|
162
|
-
relations: (statement.relations || []).map((relation) => ({
|
|
163
|
-
type: relation.type || null,
|
|
164
|
-
sourceField: relation.sourceField || null,
|
|
165
|
-
target: relation.target?.id || null
|
|
166
|
-
})),
|
|
167
|
-
keys: stableSortedStrings((statement.keys || []).map((key) => key.name)),
|
|
168
|
-
reviewBoundary: reviewBoundaryForEntityPolicy(statement),
|
|
169
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
170
|
-
};
|
|
171
|
-
case "widget":
|
|
172
|
-
return summarizeComponent(statement);
|
|
173
|
-
case "shape":
|
|
174
|
-
return {
|
|
175
|
-
id: statement.id,
|
|
176
|
-
kind: statement.kind,
|
|
177
|
-
name: statement.name || statement.id,
|
|
178
|
-
description: statement.description || null,
|
|
179
|
-
derivedFrom: refIds(statement.derivedFrom),
|
|
180
|
-
include: stableSortedStrings(statement.include || []),
|
|
181
|
-
exclude: stableSortedStrings(statement.exclude || []),
|
|
182
|
-
fields: (statement.projectedFields || statement.fields || []).map(summarizeField),
|
|
183
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
184
|
-
};
|
|
185
|
-
case "capability":
|
|
186
|
-
return {
|
|
187
|
-
id: statement.id,
|
|
188
|
-
kind: statement.kind,
|
|
189
|
-
name: statement.name || statement.id,
|
|
190
|
-
description: statement.description || null,
|
|
191
|
-
actors: refIds(statement.actors),
|
|
192
|
-
roles: refIds(statement.roles),
|
|
193
|
-
reads: refIds(statement.reads),
|
|
194
|
-
creates: refIds(statement.creates),
|
|
195
|
-
updates: refIds(statement.updates),
|
|
196
|
-
deletes: refIds(statement.deletes),
|
|
197
|
-
input: refIds(statement.input),
|
|
198
|
-
output: refIds(statement.output),
|
|
199
|
-
reviewBoundary: reviewBoundaryForCapabilityPolicy(statement),
|
|
200
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
201
|
-
};
|
|
202
|
-
case "rule":
|
|
203
|
-
return summarizeRule(statement);
|
|
204
|
-
case "projection":
|
|
205
|
-
return summarizeProjection(statement);
|
|
206
|
-
case "verification":
|
|
207
|
-
return summarizeVerification(statement);
|
|
208
|
-
case "enum":
|
|
209
|
-
return {
|
|
210
|
-
id: statement.id,
|
|
211
|
-
kind: statement.kind,
|
|
212
|
-
name: statement.name || statement.id,
|
|
213
|
-
values: stableSortedStrings(statement.values || []),
|
|
214
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
215
|
-
};
|
|
216
|
-
case "actor":
|
|
217
|
-
case "role":
|
|
218
|
-
return {
|
|
219
|
-
id: statement.id,
|
|
220
|
-
kind: statement.kind,
|
|
221
|
-
name: statement.name || statement.id,
|
|
222
|
-
description: statement.description || null,
|
|
223
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
224
|
-
};
|
|
225
|
-
default:
|
|
226
|
-
return {
|
|
227
|
-
id: statement.id,
|
|
228
|
-
kind: statement.kind,
|
|
229
|
-
name: statement.name || statement.id,
|
|
230
|
-
description: statement.description || null,
|
|
231
|
-
ownership_boundary: defaultOwnershipBoundary()
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
export function reviewBoundaryForCapability(capability) {
|
|
237
|
-
return reviewBoundaryForCapabilityPolicy(capability);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export function reviewBoundaryForProjection(projection) {
|
|
241
|
-
return reviewBoundaryForProjectionPolicy(projection);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export function reviewBoundaryForEntity(entity) {
|
|
245
|
-
return reviewBoundaryForEntityPolicy(entity);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export function graphCounts(graph) {
|
|
249
|
-
return Object.fromEntries(
|
|
250
|
-
Object.entries(graph.byKind || {})
|
|
251
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
252
|
-
.map(([kind, statements]) => [kind, statements.length])
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function groupBy(items, keyFn) {
|
|
257
|
-
const grouped = {};
|
|
258
|
-
for (const item of items) {
|
|
259
|
-
const key = keyFn(item);
|
|
260
|
-
if (!Object.hasOwn(grouped, key)) {
|
|
261
|
-
grouped[key] = [];
|
|
262
|
-
}
|
|
263
|
-
grouped[key].push(item);
|
|
264
|
-
}
|
|
265
|
-
return grouped;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export function buildIndexes(graph) {
|
|
269
|
-
const statementById = new Map((graph.statements || []).map((statement) => [statement.id, statement]));
|
|
270
|
-
const docsById = new Map((graph.docs || []).map((doc) => [doc.id, doc]));
|
|
271
|
-
const docsByKind = groupBy(graph.docs || [], (doc) => doc.kind || "unknown");
|
|
272
|
-
|
|
273
|
-
return {
|
|
274
|
-
statementById,
|
|
275
|
-
docsById,
|
|
276
|
-
docsByKind
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function relatedDocs(graph, predicate) {
|
|
281
|
-
return (graph.docs || []).filter(predicate);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function verificationsFor(graph, predicate) {
|
|
285
|
-
return stableSortedStrings(
|
|
286
|
-
(graph.byKind.verification || [])
|
|
287
|
-
.filter((verification) => (verification.validates || []).some((target) => predicate(target.id)))
|
|
288
|
-
.map((verification) => verification.id)
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
export function relatedJourneysForCapability(graph, capabilityId) {
|
|
293
|
-
return relatedDocs(
|
|
294
|
-
graph,
|
|
295
|
-
(doc) => doc.kind === "journey" && (doc.relatedCapabilities || []).includes(capabilityId)
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function relatedWorkflowDocsForCapability(graph, capabilityId) {
|
|
300
|
-
return relatedDocs(
|
|
301
|
-
graph,
|
|
302
|
-
(doc) => doc.kind === "workflow" && (doc.relatedCapabilities || []).includes(capabilityId)
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export function relatedRulesForTarget(graph, targetId) {
|
|
307
|
-
return stableSortedStrings(
|
|
308
|
-
(graph.byKind.rule || [])
|
|
309
|
-
.filter((rule) => (rule.appliesTo || []).some((target) => target.id === targetId))
|
|
310
|
-
.map((rule) => rule.id)
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
export function relatedProjectionsForCapability(graph, capabilityId) {
|
|
315
|
-
return stableSortedStrings(
|
|
316
|
-
(graph.byKind.projection || [])
|
|
317
|
-
.filter((projection) => (projection.realizes || []).some((target) => target.id === capabilityId))
|
|
318
|
-
.map((projection) => projection.id)
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
export function relatedCapabilitiesForEntity(graph, entityId) {
|
|
323
|
-
return stableSortedStrings(
|
|
324
|
-
(graph.byKind.capability || [])
|
|
325
|
-
.filter(
|
|
326
|
-
(capability) =>
|
|
327
|
-
refIds(capability.reads).includes(entityId) ||
|
|
328
|
-
refIds(capability.creates).includes(entityId) ||
|
|
329
|
-
refIds(capability.updates).includes(entityId) ||
|
|
330
|
-
refIds(capability.deletes).includes(entityId)
|
|
331
|
-
)
|
|
332
|
-
.map((capability) => capability.id)
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export function relatedShapesForEntity(graph, entityId) {
|
|
337
|
-
return stableSortedStrings(
|
|
338
|
-
(graph.byKind.shape || [])
|
|
339
|
-
.filter((shape) => refIds(shape.derivedFrom).includes(entityId))
|
|
340
|
-
.map((shape) => shape.id)
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export function relatedProjectionsForEntity(graph, entityId) {
|
|
345
|
-
return stableSortedStrings(
|
|
346
|
-
(graph.byKind.projection || [])
|
|
347
|
-
.filter((projection) => {
|
|
348
|
-
const dbMatches = (projection.dbTables || []).some((entry) => entry.entity?.id === entityId);
|
|
349
|
-
const httpMatches = (projection.http || []).some((entry) => entry.entity?.id === entityId);
|
|
350
|
-
return dbMatches || httpMatches;
|
|
351
|
-
})
|
|
352
|
-
.map((projection) => projection.id)
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
export function relatedCapabilitiesForProjection(projection) {
|
|
357
|
-
const ids = [
|
|
358
|
-
...(projection.realizes || []).map((entry) => entry.id),
|
|
359
|
-
...(projection.http || []).map((entry) => entry.capability?.id),
|
|
360
|
-
...(projection.uiActions || []).map((entry) => entry.capability?.id),
|
|
361
|
-
...(projection.uiVisibility || []).map((entry) => entry.capability?.id),
|
|
362
|
-
...(projection.uiLookups || []).map((entry) => entry.capability?.id)
|
|
363
|
-
];
|
|
364
|
-
return stableSortedStrings(ids);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export function relatedEntitiesForProjection(projection) {
|
|
368
|
-
const ids = [
|
|
369
|
-
...(projection.dbTables || []).map((entry) => entry.entity?.id),
|
|
370
|
-
...(projection.dbColumns || []).map((entry) => entry.entity?.id),
|
|
371
|
-
...(projection.dbRelations || []).map((entry) => entry.source?.id),
|
|
372
|
-
...(projection.dbRelations || []).map((entry) => entry.target?.id)
|
|
373
|
-
];
|
|
374
|
-
return stableSortedStrings(ids);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
export function relatedShapesForProjection(projection) {
|
|
378
|
-
const ids = [
|
|
379
|
-
...(projection.uiScreens || []).map((entry) => entry.viewShape?.id),
|
|
380
|
-
...(projection.uiScreens || []).map((entry) => entry.editShape?.id),
|
|
381
|
-
...(projection.uiCollections || []).map((entry) => entry.itemShape?.id),
|
|
382
|
-
...(projection.httpResponses || []).map((entry) => entry.shape?.id),
|
|
383
|
-
...(projection.http || []).map((entry) => entry.requestShape?.id)
|
|
384
|
-
];
|
|
385
|
-
return stableSortedStrings(ids);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export function relatedProjectionsForShape(graph, shapeId) {
|
|
389
|
-
const directProjectionIds = stableSortedStrings((graph?.byKind?.projection || [])
|
|
390
|
-
.filter((projection) => relatedShapesForProjection(projection).includes(shapeId))
|
|
391
|
-
.map((projection) => projection.id));
|
|
392
|
-
const viaCapabilities = stableSortedStrings((graph?.byKind?.capability || [])
|
|
393
|
-
.filter((capability) => [...(capability.input || []), ...(capability.output || [])].some((item) => item.id === shapeId))
|
|
394
|
-
.flatMap((capability) => relatedProjectionsForCapability(graph, capability.id)));
|
|
395
|
-
|
|
396
|
-
return stableSortedStrings([...directProjectionIds, ...viaCapabilities]);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function widgetById(graph, widgetId) {
|
|
400
|
-
return (graph?.byKind?.widget || []).find((widget) => widget.id === widgetId) || null;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
function projectionById(graph, projectionId) {
|
|
404
|
-
return (graph?.byKind?.projection || []).find((projection) => projection.id === projectionId) || null;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function realizedProjectionIds(projection) {
|
|
408
|
-
return stableSortedStrings((projection?.realizes || [])
|
|
409
|
-
.filter((target) => target.target?.kind === "projection" || String(target.id || "").startsWith("proj_"))
|
|
410
|
-
.map((target) => target.id));
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function downstreamProjectionIds(graph, projectionIds) {
|
|
414
|
-
const visited = new Set(projectionIds);
|
|
415
|
-
const queue = [...projectionIds];
|
|
416
|
-
|
|
417
|
-
while (queue.length > 0) {
|
|
418
|
-
const currentId = queue.shift();
|
|
419
|
-
for (const projection of graph?.byKind?.projection || []) {
|
|
420
|
-
if (visited.has(projection.id)) {
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
if (realizedProjectionIds(projection).includes(currentId)) {
|
|
424
|
-
visited.add(projection.id);
|
|
425
|
-
queue.push(projection.id);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return stableSortedStrings([...visited]);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
export function relatedWidgetsForProjection(graph, projection) {
|
|
434
|
-
const directIds = (projection?.widgetBindings || []).map((entry) => entry.widget?.id).filter(Boolean);
|
|
435
|
-
const inheritedIds = realizedProjectionIds(projection)
|
|
436
|
-
.map((projectionId) => projectionById(graph, projectionId))
|
|
437
|
-
.filter(Boolean)
|
|
438
|
-
.flatMap((realizedProjection) => relatedWidgetsForProjection(graph, realizedProjection));
|
|
439
|
-
return stableSortedStrings([...directIds, ...inheritedIds]);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
export function relatedShapesForWidget(widget) {
|
|
443
|
-
if (!widget) return [];
|
|
444
|
-
const ids = [
|
|
445
|
-
...(widget.events || []).map((event) => event.shape?.id),
|
|
446
|
-
...(widget.lookups || [])
|
|
447
|
-
.filter((lookup) => lookup?.target?.kind === "shape" || String(lookup?.id || "").startsWith("shape_"))
|
|
448
|
-
.map((lookup) => lookup.id),
|
|
449
|
-
...(widget.dependencies || [])
|
|
450
|
-
.filter((dependency) => referenceKind(dependency) === "shape")
|
|
451
|
-
.map((dependency) => dependency.id)
|
|
452
|
-
];
|
|
453
|
-
return stableSortedStrings(ids);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
export function relatedProjectionsForWidget(graph, widgetId) {
|
|
457
|
-
const widget = widgetById(graph, widgetId);
|
|
458
|
-
if (!widget) return [];
|
|
459
|
-
const explicitProjectionIds = stableSortedStrings((graph?.byKind?.projection || [])
|
|
460
|
-
.filter((projection) => (projection.widgetBindings || []).some((entry) => entry.widget?.id === widgetId))
|
|
461
|
-
.map((projection) => projection.id));
|
|
462
|
-
const dependencyProjectionIds = stableSortedStrings((widget.dependencies || []).flatMap((dependency) => {
|
|
463
|
-
const kind = referenceKind(dependency);
|
|
464
|
-
if (kind === "projection") {
|
|
465
|
-
return [dependency.id];
|
|
466
|
-
}
|
|
467
|
-
if (kind === "capability") {
|
|
468
|
-
return relatedProjectionsForCapability(graph, dependency.id);
|
|
469
|
-
}
|
|
470
|
-
if (kind === "entity") {
|
|
471
|
-
return relatedProjectionsForEntity(graph, dependency.id);
|
|
472
|
-
}
|
|
473
|
-
if (kind === "shape") {
|
|
474
|
-
return relatedProjectionsForShape(graph, dependency.id);
|
|
475
|
-
}
|
|
476
|
-
return [];
|
|
477
|
-
}));
|
|
478
|
-
const widgetPatterns = new Set(widget.patterns || []);
|
|
479
|
-
const widgetRegions = new Set(widget.regions || []);
|
|
480
|
-
const viaUiRegions = stableSortedStrings((graph?.byKind?.projection || [])
|
|
481
|
-
.filter((projection) => (projection.uiScreenRegions || []).some((region) =>
|
|
482
|
-
(region.pattern && widgetPatterns.has(region.pattern)) ||
|
|
483
|
-
(region.region && widgetRegions.has(region.region))
|
|
484
|
-
))
|
|
485
|
-
.map((projection) => projection.id));
|
|
486
|
-
|
|
487
|
-
return downstreamProjectionIds(graph, stableSortedStrings([...explicitProjectionIds, ...dependencyProjectionIds, ...viaUiRegions]));
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function referenceKind(reference) {
|
|
491
|
-
if (reference?.target?.kind) {
|
|
492
|
-
return reference.target.kind;
|
|
493
|
-
}
|
|
494
|
-
const id = String(reference?.id || "");
|
|
495
|
-
const prefix = id.split("_")[0];
|
|
496
|
-
if (prefix === "proj") {
|
|
497
|
-
return "projection";
|
|
498
|
-
}
|
|
499
|
-
if (prefix === "cap") {
|
|
500
|
-
return "capability";
|
|
501
|
-
}
|
|
502
|
-
return prefix || null;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
export function verificationIdsForTarget(graph, targetIds) {
|
|
506
|
-
const set = new Set(targetIds || []);
|
|
507
|
-
return verificationsFor(graph, (targetId) => set.has(targetId));
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
export function summarizeDoc(doc) {
|
|
511
|
-
return summarizeJourneyDoc(doc);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
export function summarizeById(graph, id) {
|
|
515
|
-
const statement = (graph.statements || []).find((item) => item.id === id);
|
|
516
|
-
if (statement) {
|
|
517
|
-
return summarizeStatement(statement);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const doc = (graph.docs || []).find((item) => item.id === id);
|
|
521
|
-
return doc ? summarizeDoc(doc) : null;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
export function summarizeStatementsByIds(graph, ids) {
|
|
525
|
-
return stableSortedStrings(ids).map((id) => summarizeById(graph, id)).filter(Boolean);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
export function summarizeDocsByIds(graph, ids) {
|
|
529
|
-
return stableSortedStrings(ids)
|
|
530
|
-
.map((id) => (graph.docs || []).find((doc) => doc.id === id))
|
|
531
|
-
.filter(Boolean)
|
|
532
|
-
.map(summarizeDoc);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
export function workspaceInventory(graph) {
|
|
536
|
-
return {
|
|
537
|
-
capabilities: stableSortedStrings((graph.byKind.capability || []).map((item) => item.id)),
|
|
538
|
-
workflows: stableSortedStrings((graph.docs || []).filter((doc) => doc.kind === "workflow").map((doc) => doc.id)),
|
|
539
|
-
journeys: stableSortedStrings((graph.docs || []).filter((doc) => doc.kind === "journey").map((doc) => doc.id)),
|
|
540
|
-
entities: stableSortedStrings((graph.byKind.entity || []).map((item) => item.id)),
|
|
541
|
-
projections: stableSortedStrings((graph.byKind.projection || []).map((item) => item.id)),
|
|
542
|
-
widgets: stableSortedStrings((graph.byKind.widget || []).map((item) => item.id)),
|
|
543
|
-
verifications: stableSortedStrings((graph.byKind.verification || []).map((item) => item.id)),
|
|
544
|
-
domains: stableSortedStrings((graph.byKind.domain || []).map((item) => item.id)),
|
|
545
|
-
pitches: stableSortedStrings((graph.byKind.pitch || []).map((item) => item.id)),
|
|
546
|
-
requirements: stableSortedStrings((graph.byKind.requirement || []).map((item) => item.id)),
|
|
547
|
-
acceptance_criteria: stableSortedStrings((graph.byKind.acceptance_criterion || []).map((item) => item.id)),
|
|
548
|
-
tasks: stableSortedStrings((graph.byKind.task || []).map((item) => item.id)),
|
|
549
|
-
bugs: stableSortedStrings((graph.byKind.bug || []).map((item) => item.id)),
|
|
550
|
-
documents: stableSortedStrings((graph.docs || []).map((doc) => doc.id))
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
export function ensureContextSelection(options = {}) {
|
|
555
|
-
const selectors = [
|
|
556
|
-
options.capabilityId ? ["capability", options.capabilityId] : null,
|
|
557
|
-
options.workflowId ? ["workflow", options.workflowId] : null,
|
|
558
|
-
options.projectionId ? ["projection", options.projectionId] : null,
|
|
559
|
-
(options.widgetId || options.componentId) ? ["widget", options.widgetId || options.componentId] : null,
|
|
560
|
-
options.entityId ? ["entity", options.entityId] : null,
|
|
561
|
-
options.journeyId ? ["journey", options.journeyId] : null,
|
|
562
|
-
options.surfaceId ? ["surface", options.surfaceId] : null,
|
|
563
|
-
options.domainId ? ["domain", options.domainId] : null,
|
|
564
|
-
options.pitchId ? ["pitch", options.pitchId] : null,
|
|
565
|
-
options.requirementId ? ["requirement", options.requirementId] : null,
|
|
566
|
-
options.acceptanceId ? ["acceptance_criterion", options.acceptanceId] : null,
|
|
567
|
-
options.taskId ? ["task", options.taskId] : null,
|
|
568
|
-
options.bugId ? ["bug", options.bugId] : null,
|
|
569
|
-
options.documentId ? ["document", options.documentId] : null
|
|
570
|
-
].filter(Boolean);
|
|
571
|
-
|
|
572
|
-
if (selectors.length !== 1) {
|
|
573
|
-
throw new Error(
|
|
574
|
-
"Context selection requires exactly one of --capability, --workflow, --projection, --widget, --entity, --journey, --surface, --domain, --pitch, --requirement, --acceptance, --task, --bug, or --document"
|
|
575
|
-
);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
return {
|
|
579
|
-
kind: selectors[0][0],
|
|
580
|
-
id: selectors[0][1]
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
export function domainById(graph, domainId) {
|
|
585
|
-
return (graph?.byKind?.domain || []).find((domain) => domain.id === domainId) || null;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
export function summarizeDomain(domain) {
|
|
589
|
-
if (!domain) return null;
|
|
590
|
-
const members = domain.members || {};
|
|
591
|
-
return {
|
|
592
|
-
id: domain.id,
|
|
593
|
-
kind: "domain",
|
|
594
|
-
name: domain.name,
|
|
595
|
-
description: domain.description,
|
|
596
|
-
status: domain.status,
|
|
597
|
-
in_scope: [...(domain.inScope || [])],
|
|
598
|
-
out_of_scope: [...(domain.outOfScope || [])],
|
|
599
|
-
aliases: [...(domain.aliases || [])],
|
|
600
|
-
parent_domain: domain.parentDomain ? domain.parentDomain.id : null,
|
|
601
|
-
members_count: Object.values(members).reduce((total, list) => total + list.length, 0)
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
export function domainsByStatement(graph) {
|
|
606
|
-
const map = new Map();
|
|
607
|
-
for (const statement of (graph?.statements || [])) {
|
|
608
|
-
if (statement.resolvedDomain && statement.resolvedDomain.id) {
|
|
609
|
-
map.set(statement.id, statement.resolvedDomain.id);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return map;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
export function relatedCapabilitiesForDomain(graph, domainId) {
|
|
616
|
-
const domain = domainById(graph, domainId);
|
|
617
|
-
if (!domain) return [];
|
|
618
|
-
return [...(domain.members?.capabilities || [])].sort();
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
export function relatedEntitiesForDomain(graph, domainId) {
|
|
622
|
-
const domain = domainById(graph, domainId);
|
|
623
|
-
if (!domain) return [];
|
|
624
|
-
return [...(domain.members?.entities || [])].sort();
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
export function relatedRulesForDomain(graph, domainId) {
|
|
628
|
-
const domain = domainById(graph, domainId);
|
|
629
|
-
if (!domain) return [];
|
|
630
|
-
return [...(domain.members?.rules || [])].sort();
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
export function relatedVerificationsForDomain(graph, domainId) {
|
|
634
|
-
const domain = domainById(graph, domainId);
|
|
635
|
-
if (!domain) return [];
|
|
636
|
-
return [...(domain.members?.verifications || [])].sort();
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
export function relatedProjectionsForDomain(graph, domainId) {
|
|
640
|
-
const capabilityIds = new Set(relatedCapabilitiesForDomain(graph, domainId));
|
|
641
|
-
if (capabilityIds.size === 0) return [];
|
|
642
|
-
const projectionIds = (graph?.byKind?.projection || [])
|
|
643
|
-
.filter((projection) => (projection.realizes || []).some((entry) => capabilityIds.has(entry.id)))
|
|
644
|
-
.map((projection) => projection.id);
|
|
645
|
-
return stableSortedStrings(projectionIds);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// Phase 2 SDLC look-up helpers. Mirror the existing `*ById` pattern.
|
|
649
|
-
export function pitchById(graph, id) {
|
|
650
|
-
return (graph?.byKind?.pitch || []).find((s) => s.id === id) || null;
|
|
651
|
-
}
|
|
652
|
-
export function requirementById(graph, id) {
|
|
653
|
-
return (graph?.byKind?.requirement || []).find((s) => s.id === id) || null;
|
|
654
|
-
}
|
|
655
|
-
export function acceptanceCriterionById(graph, id) {
|
|
656
|
-
return (graph?.byKind?.acceptance_criterion || []).find((s) => s.id === id) || null;
|
|
657
|
-
}
|
|
658
|
-
export function taskById(graph, id) {
|
|
659
|
-
return (graph?.byKind?.task || []).find((s) => s.id === id) || null;
|
|
660
|
-
}
|
|
661
|
-
export function bugById(graph, id) {
|
|
662
|
-
return (graph?.byKind?.bug || []).find((s) => s.id === id) || null;
|
|
663
|
-
}
|
|
664
|
-
export function documentById(graph, id) {
|
|
665
|
-
return (graph?.docs || []).find((doc) => doc.id === id) || null;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
export function summarizePitch(pitch) {
|
|
669
|
-
if (!pitch) return null;
|
|
670
|
-
return {
|
|
671
|
-
id: pitch.id,
|
|
672
|
-
name: pitch.name,
|
|
673
|
-
status: pitch.status,
|
|
674
|
-
priority: pitch.priority,
|
|
675
|
-
appetite: pitch.appetite,
|
|
676
|
-
domain: pitch.resolvedDomain ? pitch.resolvedDomain.id : null
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
export function summarizeRequirement(req) {
|
|
680
|
-
if (!req) return null;
|
|
681
|
-
return {
|
|
682
|
-
id: req.id,
|
|
683
|
-
name: req.name,
|
|
684
|
-
status: req.status,
|
|
685
|
-
priority: req.priority,
|
|
686
|
-
pitch: req.pitch?.id || null,
|
|
687
|
-
domain: req.resolvedDomain ? req.resolvedDomain.id : null
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
export function summarizeAcceptanceCriterion(ac) {
|
|
691
|
-
if (!ac) return null;
|
|
692
|
-
return {
|
|
693
|
-
id: ac.id,
|
|
694
|
-
name: ac.name,
|
|
695
|
-
status: ac.status,
|
|
696
|
-
requirement: ac.requirement?.id || null
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
export function summarizeTask(task) {
|
|
700
|
-
if (!task) return null;
|
|
701
|
-
return {
|
|
702
|
-
id: task.id,
|
|
703
|
-
name: task.name,
|
|
704
|
-
status: task.status,
|
|
705
|
-
priority: task.priority,
|
|
706
|
-
work_type: task.workType,
|
|
707
|
-
claimed_by: (task.claimedBy || []).map((r) => (typeof r === "string" ? r : r?.id)).filter(Boolean),
|
|
708
|
-
domain: task.resolvedDomain ? task.resolvedDomain.id : null
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
export function summarizeBug(bug) {
|
|
712
|
-
if (!bug) return null;
|
|
713
|
-
return {
|
|
714
|
-
id: bug.id,
|
|
715
|
-
name: bug.name,
|
|
716
|
-
status: bug.status,
|
|
717
|
-
severity: bug.severity,
|
|
718
|
-
priority: bug.priority,
|
|
719
|
-
domain: bug.resolvedDomain ? bug.resolvedDomain.id : null
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
export function summarizeDocument(doc) {
|
|
723
|
-
if (!doc) return null;
|
|
724
|
-
return {
|
|
725
|
-
id: doc.id,
|
|
726
|
-
title: doc.title,
|
|
727
|
-
kind: doc.kind,
|
|
728
|
-
status: doc.status,
|
|
729
|
-
domain: doc.domain || null
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
export function getWorkflowDoc(graph, workflowId) {
|
|
734
|
-
const doc = (graph.docs || []).find((item) => item.kind === "workflow" && item.id === workflowId);
|
|
735
|
-
if (!doc) {
|
|
736
|
-
throw new Error(`No workflow doc found with id '${workflowId}'`);
|
|
737
|
-
}
|
|
738
|
-
return doc;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
export function getJourneyDoc(graph, journeyId) {
|
|
742
|
-
const doc = (graph.docs || []).find((item) => item.kind === "journey" && item.id === journeyId);
|
|
743
|
-
if (!doc) {
|
|
744
|
-
throw new Error(`No journey doc found with id '${journeyId}'`);
|
|
745
|
-
}
|
|
746
|
-
return doc;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
export function getStatement(graph, kind, id) {
|
|
750
|
-
const statement = (graph.byKind[kind] || []).find((item) => item.id === id);
|
|
751
|
-
if (!statement) {
|
|
752
|
-
throw new Error(`No ${kind} found with id '${id}'`);
|
|
753
|
-
}
|
|
754
|
-
return statement;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
export function repoRootFromGraph(graph) {
|
|
758
|
-
let current = path.resolve(graph.root);
|
|
759
|
-
while (true) {
|
|
760
|
-
if (fs.existsSync(path.join(current, "examples", "maintained", "proof-app")) && fs.existsSync(path.join(current, "engine"))) {
|
|
761
|
-
return current;
|
|
762
|
-
}
|
|
763
|
-
const parent = path.dirname(current);
|
|
764
|
-
if (parent === current) {
|
|
765
|
-
if (
|
|
766
|
-
fs.existsSync(path.join(bundledRepoRoot, "examples", "maintained", "proof-app")) &&
|
|
767
|
-
fs.existsSync(path.join(bundledRepoRoot, "engine"))
|
|
768
|
-
) {
|
|
769
|
-
return bundledRepoRoot;
|
|
770
|
-
}
|
|
771
|
-
return path.resolve(graph.root, "..", "..");
|
|
772
|
-
}
|
|
773
|
-
current = parent;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function workspaceRootFromGraph(graph) {
|
|
778
|
-
const root = path.resolve(graph.root);
|
|
779
|
-
return path.basename(root) === "topogram" ? path.dirname(root) : root;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
function collectMaintainedProofDocPaths(workspaceRoot) {
|
|
783
|
-
const candidateDirs = [
|
|
784
|
-
path.join(workspaceRoot, "proof"),
|
|
785
|
-
path.join(workspaceRoot, "docs", "proof")
|
|
786
|
-
];
|
|
787
|
-
const proofFiles = [];
|
|
788
|
-
|
|
789
|
-
for (const dirPath of candidateDirs) {
|
|
790
|
-
if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) {
|
|
791
|
-
continue;
|
|
792
|
-
}
|
|
793
|
-
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
794
|
-
if (entry.isFile() && /^maintained-.*\.md$/.test(entry.name)) {
|
|
795
|
-
proofFiles.push(path.join(dirPath, entry.name));
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
return stableSortedStrings(proofFiles);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
function readLocalMaintainedProofMetadataFromWorkspace(workspaceRoot) {
|
|
804
|
-
return collectMaintainedProofDocPaths(workspaceRoot)
|
|
805
|
-
.map((filePath) => parseDocFile(filePath, workspaceRoot))
|
|
806
|
-
.filter((doc) => !doc.parseError)
|
|
807
|
-
.map((doc) => {
|
|
808
|
-
const classification = doc.metadata.classification || null;
|
|
809
|
-
const maintainedFiles = stableSortedStrings(doc.metadata.maintained_files || []);
|
|
810
|
-
const emittedDependencies = stableSortedStrings(doc.metadata.emitted_dependencies || []);
|
|
811
|
-
const humanOwnedSeams = stableSortedStrings(doc.metadata.human_owned_seams || []);
|
|
812
|
-
|
|
813
|
-
if (!classification || maintainedFiles.length === 0 || emittedDependencies.length === 0 || humanOwnedSeams.length === 0) {
|
|
814
|
-
return null;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
return {
|
|
818
|
-
classification,
|
|
819
|
-
maintainedFiles,
|
|
820
|
-
emittedDependencies,
|
|
821
|
-
humanOwnedSeams,
|
|
822
|
-
seamFamilyId: doc.metadata.seam_family_id || null,
|
|
823
|
-
seamFamilyLabel: doc.metadata.seam_family_label || null,
|
|
824
|
-
exists: true,
|
|
825
|
-
absolutePath: doc.file,
|
|
826
|
-
relativePath: doc.relativePath,
|
|
827
|
-
reviewBoundary: reviewBoundaryForMaintainedClassification(classification),
|
|
828
|
-
ownership_boundary: ownershipBoundaryForMaintainedSurface()
|
|
829
|
-
};
|
|
830
|
-
})
|
|
831
|
-
.filter(Boolean);
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
export function readLocalMaintainedProofMetadata(graph) {
|
|
835
|
-
return readLocalMaintainedProofMetadataFromWorkspace(workspaceRootFromGraph(graph));
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
export function buildMaintainedBoundaryArtifact({
|
|
839
|
-
proofStories = [],
|
|
840
|
-
verificationTargets = null,
|
|
841
|
-
graph = null
|
|
842
|
-
} = {}) {
|
|
843
|
-
if (!proofStories.length) {
|
|
844
|
-
return null;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
const seams = buildMaintainedSeams(proofStories);
|
|
848
|
-
const outputs = buildMaintainedOutputs({
|
|
849
|
-
seams,
|
|
850
|
-
proofStories,
|
|
851
|
-
ownershipBoundary: ownershipBoundaryForMaintainedSurface(),
|
|
852
|
-
verificationTargets,
|
|
853
|
-
graph
|
|
854
|
-
});
|
|
855
|
-
const maintainedFiles = stableSortedStrings(proofStories.flatMap((item) => item.maintainedFiles || []));
|
|
856
|
-
const emittedDependencies = stableSortedStrings(proofStories.flatMap((item) => item.emittedDependencies || []));
|
|
857
|
-
const humanOwnedSeams = stableSortedStrings(proofStories.flatMap((item) => item.humanOwnedSeams || []));
|
|
858
|
-
|
|
859
|
-
return {
|
|
860
|
-
type: "maintained_boundary",
|
|
861
|
-
version: 2,
|
|
862
|
-
summary: {
|
|
863
|
-
focus: "Maintained-app files, emitted constraints, and explicit review boundaries",
|
|
864
|
-
maintained_file_count: maintainedFiles.length,
|
|
865
|
-
accepted_change_count: proofStories.filter((item) => item.classification === "accepted_change").length,
|
|
866
|
-
guarded_change_count: proofStories.filter((item) => item.classification === "guarded_manual_decision").length,
|
|
867
|
-
no_go_count: proofStories.filter((item) => item.classification === "no_go").length
|
|
868
|
-
},
|
|
869
|
-
maintained_files_in_scope: maintainedFiles,
|
|
870
|
-
emitted_artifact_dependencies: emittedDependencies,
|
|
871
|
-
human_owned_seams: humanOwnedSeams,
|
|
872
|
-
outputs,
|
|
873
|
-
seams,
|
|
874
|
-
proof_stories: proofStories.map((item) => ({
|
|
875
|
-
classification: item.classification,
|
|
876
|
-
relativePath: item.relativePath,
|
|
877
|
-
maintained_files: item.maintainedFiles || [],
|
|
878
|
-
emitted_dependencies: item.emittedDependencies || [],
|
|
879
|
-
human_owned_seams: item.humanOwnedSeams || [],
|
|
880
|
-
seam_family_id: item.seamFamilyId || null,
|
|
881
|
-
seam_family_label: item.seamFamilyLabel || null,
|
|
882
|
-
review_boundary: item.reviewBoundary,
|
|
883
|
-
ownership_boundary: item.ownership_boundary
|
|
884
|
-
})),
|
|
885
|
-
ownership_boundary: ownershipBoundaryForMaintainedSurface()
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
export function buildLocalMaintainedBoundaryArtifact(workspaceRoot, graph = null) {
|
|
890
|
-
const proofStories = readLocalMaintainedProofMetadataFromWorkspace(path.resolve(workspaceRoot));
|
|
891
|
-
if (!proofStories.length) {
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
const emittedDependencies = stableSortedStrings(proofStories.flatMap((item) => item.emittedDependencies || []));
|
|
896
|
-
const verificationTargets = graph
|
|
897
|
-
? recommendedVerificationTargets(graph, emittedDependencies, {
|
|
898
|
-
includeMaintainedApp: true,
|
|
899
|
-
rationale: "Local maintained proof stories should point agents at emitted dependency checks plus any maintained proof gates."
|
|
900
|
-
})
|
|
901
|
-
: null;
|
|
902
|
-
|
|
903
|
-
return buildMaintainedBoundaryArtifact({
|
|
904
|
-
proofStories,
|
|
905
|
-
verificationTargets,
|
|
906
|
-
graph
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
export function maintainedProofMetadata(graph) {
|
|
911
|
-
const repoRoot = repoRootFromGraph(graph);
|
|
912
|
-
const staticFiles = [
|
|
913
|
-
{
|
|
914
|
-
classification: "accepted_change",
|
|
915
|
-
path: "examples/maintained/proof-app/proof/issues-ownership-visibility-story.md",
|
|
916
|
-
maintainedFiles: ["examples/maintained/proof-app/src/issues.js"],
|
|
917
|
-
emittedDependencies: ["proj_web", "proj_api", "journey_issue_resolution_and_closure"],
|
|
918
|
-
humanOwnedSeams: ["maintained presenter structure", "detail/list rendering treatment"]
|
|
919
|
-
},
|
|
920
|
-
{
|
|
921
|
-
classification: "accepted_change",
|
|
922
|
-
path: "examples/maintained/proof-app/proof/issues-cross-surface-alignment-story.md",
|
|
923
|
-
maintainedFiles: ["examples/maintained/proof-app/src/issues.js"],
|
|
924
|
-
emittedDependencies: ["proj_web", "proj_api", "journey_issue_creation_and_assignment", "journey_issue_resolution_and_closure"],
|
|
925
|
-
humanOwnedSeams: [
|
|
926
|
-
"issues detail action state",
|
|
927
|
-
"issues list/card summary state",
|
|
928
|
-
"issues route and action metadata"
|
|
929
|
-
],
|
|
930
|
-
seamFamilyId: "issues_cross_surface_alignment",
|
|
931
|
-
seamFamilyLabel: "issues cross-surface ownership alignment"
|
|
932
|
-
},
|
|
933
|
-
{
|
|
934
|
-
classification: "guarded_manual_decision",
|
|
935
|
-
path: "examples/maintained/proof-app/proof/content-approval-workflow-decision-story.md",
|
|
936
|
-
maintainedFiles: ["examples/maintained/proof-app/src/content-approval-change-guards.js"],
|
|
937
|
-
emittedDependencies: ["cap_request_article_revision", "journey_editorial_review_and_revision"],
|
|
938
|
-
humanOwnedSeams: ["new workflow affordance treatment", "action placement and copy"]
|
|
939
|
-
},
|
|
940
|
-
{
|
|
941
|
-
classification: "no_go",
|
|
942
|
-
path: "examples/maintained/proof-app/proof/issues-ownership-visibility-drift-story.md",
|
|
943
|
-
maintainedFiles: ["examples/maintained/proof-app/src/issues.js"],
|
|
944
|
-
emittedDependencies: ["proj_web", "journey_issue_resolution_and_closure"],
|
|
945
|
-
humanOwnedSeams: ["owner visibility semantics must not drift"]
|
|
946
|
-
},
|
|
947
|
-
{
|
|
948
|
-
classification: "no_go",
|
|
949
|
-
path: "examples/maintained/proof-app/proof/content-approval-unsupported-change-story.md",
|
|
950
|
-
maintainedFiles: ["examples/maintained/proof-app/src/content-approval.js", "examples/maintained/proof-app/src/content-approval-change-guards.js"],
|
|
951
|
-
emittedDependencies: ["proj_web", "proj_api", "proj_db"],
|
|
952
|
-
humanOwnedSeams: ["unsupported relation and workflow meaning changes"]
|
|
953
|
-
},
|
|
954
|
-
{
|
|
955
|
-
classification: "no_go",
|
|
956
|
-
path: "examples/maintained/proof-app/proof/todo-project-owner-unsupported-change-story.md",
|
|
957
|
-
maintainedFiles: ["examples/maintained/proof-app/src/todo-change-guards.js"],
|
|
958
|
-
emittedDependencies: ["entity_project", "proj_web", "proj_api"],
|
|
959
|
-
humanOwnedSeams: ["ownership retargeting remains manual"]
|
|
960
|
-
},
|
|
961
|
-
{
|
|
962
|
-
classification: "independent_review",
|
|
963
|
-
path: "examples/maintained/proof-app/proof/maintained-contract-review.md",
|
|
964
|
-
maintainedFiles: [
|
|
965
|
-
"examples/maintained/proof-app/src/issues.js",
|
|
966
|
-
"examples/maintained/proof-app/src/content-approval-change-guards.js",
|
|
967
|
-
"examples/maintained/proof-app/src/todo-change-guards.js"
|
|
968
|
-
],
|
|
969
|
-
emittedDependencies: ["maintained-proof-package"],
|
|
970
|
-
humanOwnedSeams: ["human audit of emitted contracts vs maintained code"]
|
|
971
|
-
},
|
|
972
|
-
{
|
|
973
|
-
classification: "accepted_change",
|
|
974
|
-
path: "examples/generated/content-approval/implementation/proof/web-reference-seam-story.md",
|
|
975
|
-
maintainedFiles: ["examples/generated/content-approval/implementation/web/reference.js"],
|
|
976
|
-
emittedDependencies: ["proj_web", "journey_editorial_review_and_revision"],
|
|
977
|
-
humanOwnedSeams: ["example web reference composition"]
|
|
978
|
-
},
|
|
979
|
-
{
|
|
980
|
-
classification: "accepted_change",
|
|
981
|
-
path: "examples/generated/content-approval/implementation/proof/backend-reference-seam-story.md",
|
|
982
|
-
maintainedFiles: ["examples/generated/content-approval/implementation/backend/reference.js"],
|
|
983
|
-
emittedDependencies: ["proj_api", "proj_db"],
|
|
984
|
-
humanOwnedSeams: ["example backend reference integration"]
|
|
985
|
-
}
|
|
986
|
-
];
|
|
987
|
-
|
|
988
|
-
const staticProofs = staticFiles
|
|
989
|
-
.map((item) => {
|
|
990
|
-
const absolutePath = path.join(repoRoot, item.path);
|
|
991
|
-
return {
|
|
992
|
-
...item,
|
|
993
|
-
exists: fs.existsSync(absolutePath),
|
|
994
|
-
absolutePath,
|
|
995
|
-
relativePath: item.path,
|
|
996
|
-
reviewBoundary: reviewBoundaryForMaintainedClassification(item.classification),
|
|
997
|
-
ownership_boundary: ownershipBoundaryForMaintainedSurface()
|
|
998
|
-
};
|
|
999
|
-
})
|
|
1000
|
-
.filter((item) => item.exists);
|
|
1001
|
-
|
|
1002
|
-
return [
|
|
1003
|
-
...staticProofs,
|
|
1004
|
-
...readLocalMaintainedProofMetadata(graph)
|
|
1005
|
-
];
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
function maintainedSeamKind(label) {
|
|
1009
|
-
const normalized = String(label || "").toLowerCase();
|
|
1010
|
-
if (/audit|contract|review/.test(normalized)) {
|
|
1011
|
-
return "verification_harness";
|
|
1012
|
-
}
|
|
1013
|
-
if (/workflow|affordance|action|copy/.test(normalized)) {
|
|
1014
|
-
return "workflow_affordance";
|
|
1015
|
-
}
|
|
1016
|
-
if (/visibility|ownership|relation|policy/.test(normalized)) {
|
|
1017
|
-
return "policy_interpretation";
|
|
1018
|
-
}
|
|
1019
|
-
if (/route|navigation/.test(normalized)) {
|
|
1020
|
-
return "route_glue";
|
|
1021
|
-
}
|
|
1022
|
-
return "ui_presenter";
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
function maintainedSeamStatus(reviewBoundary) {
|
|
1026
|
-
const automationClass = reviewBoundary?.automation_class || "review_required";
|
|
1027
|
-
return automationClass === "safe" ? "aligned" : automationClass;
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
function maintainedSeamOwnershipClass(classification) {
|
|
1031
|
-
if (classification === "accepted_change") {
|
|
1032
|
-
return "contract_bound";
|
|
1033
|
-
}
|
|
1034
|
-
if (classification === "guarded_manual_decision" || classification === "independent_review") {
|
|
1035
|
-
return "advisory_only";
|
|
1036
|
-
}
|
|
1037
|
-
if (classification === "no_go") {
|
|
1038
|
-
return "out_of_bounds";
|
|
1039
|
-
}
|
|
1040
|
-
return "contract_bound";
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
function maintainedSeamAllowedChangeClasses(classification) {
|
|
1044
|
-
if (classification === "accepted_change") {
|
|
1045
|
-
return ["safe", "review_required"];
|
|
1046
|
-
}
|
|
1047
|
-
if (classification === "guarded_manual_decision") {
|
|
1048
|
-
return ["review_required", "manual_decision"];
|
|
1049
|
-
}
|
|
1050
|
-
if (classification === "independent_review") {
|
|
1051
|
-
return ["review_required"];
|
|
1052
|
-
}
|
|
1053
|
-
if (classification === "no_go") {
|
|
1054
|
-
return ["no_go"];
|
|
1055
|
-
}
|
|
1056
|
-
return ["review_required"];
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
function maintainedSeamDriftSignals(emittedDependencies = []) {
|
|
1060
|
-
const signals = new Set();
|
|
1061
|
-
for (const dependency of emittedDependencies || []) {
|
|
1062
|
-
if (dependency === "maintained-proof-package") {
|
|
1063
|
-
signals.add("verification_expectation_changed");
|
|
1064
|
-
continue;
|
|
1065
|
-
}
|
|
1066
|
-
if (dependency.startsWith("journey_") || dependency.startsWith("workflow_")) {
|
|
1067
|
-
signals.add("workflow_state_changed");
|
|
1068
|
-
continue;
|
|
1069
|
-
}
|
|
1070
|
-
if (dependency.startsWith("proj_ui") || dependency === "proj_web") {
|
|
1071
|
-
signals.add("emitted_contract_changed");
|
|
1072
|
-
signals.add("route_or_navigation_changed");
|
|
1073
|
-
continue;
|
|
1074
|
-
}
|
|
1075
|
-
if (
|
|
1076
|
-
dependency.startsWith("proj_") ||
|
|
1077
|
-
dependency.startsWith("cap_") ||
|
|
1078
|
-
dependency.startsWith("entity_") ||
|
|
1079
|
-
dependency.startsWith("shape_")
|
|
1080
|
-
) {
|
|
1081
|
-
signals.add("emitted_contract_changed");
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
return stableSortedStrings([...signals]);
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
function maintainedOutputDescriptor(filePaths = []) {
|
|
1088
|
-
const files = stableSortedStrings(filePaths);
|
|
1089
|
-
if (files.some((file) => String(file).startsWith("examples/maintained/proof-app/"))) {
|
|
1090
|
-
return {
|
|
1091
|
-
output_id: "maintained_app",
|
|
1092
|
-
label: "Maintained App",
|
|
1093
|
-
kind: "maintained_runtime",
|
|
1094
|
-
root_paths: ["examples/maintained/proof-app/**"]
|
|
1095
|
-
};
|
|
1096
|
-
}
|
|
1097
|
-
const exampleImplementationMatch = files
|
|
1098
|
-
.map((file) => String(file).match(/^examples\/(?:(generated)\/)?([^/]+)\/implementation\/(web|backend|runtime)\//))
|
|
1099
|
-
.find(Boolean);
|
|
1100
|
-
if (exampleImplementationMatch) {
|
|
1101
|
-
const [, category, slug, outputKind] = exampleImplementationMatch;
|
|
1102
|
-
const outputId = `output_${seamIdHint(`examples_${slug}_${outputKind}`)}`;
|
|
1103
|
-
const rootPrefix = category ? `examples/${category}/${slug}` : `examples/${slug}`;
|
|
1104
|
-
const root = `${rootPrefix}/implementation/${outputKind}`;
|
|
1105
|
-
return {
|
|
1106
|
-
output_id: outputId,
|
|
1107
|
-
label: `${titleCaseWords(slug)} ${titleCaseWords(outputKind)} Reference`,
|
|
1108
|
-
kind: outputKind === "web" ? "web_app" : outputKind === "backend" ? "backend_adapter" : "maintained_runtime",
|
|
1109
|
-
root_paths: [`${root}/**`]
|
|
1110
|
-
};
|
|
1111
|
-
}
|
|
1112
|
-
if (files.some((file) => String(file).startsWith("src/"))) {
|
|
1113
|
-
return {
|
|
1114
|
-
output_id: "output_src",
|
|
1115
|
-
label: "Source",
|
|
1116
|
-
kind: "backend_adapter",
|
|
1117
|
-
root_paths: ["src/**"]
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
const firstFile = files[0] || "";
|
|
1122
|
-
const segments = String(firstFile).split("/").filter(Boolean);
|
|
1123
|
-
const root = segments.length >= 2 ? segments.slice(0, 2).join("/") : (segments[0] || "maintained");
|
|
1124
|
-
const outputStem = seamIdHint(root);
|
|
1125
|
-
return {
|
|
1126
|
-
output_id: `output_${outputStem}`,
|
|
1127
|
-
label: titleCaseWords(root.replaceAll("/", "_")),
|
|
1128
|
-
kind: "maintained_runtime",
|
|
1129
|
-
root_paths: [`${root}/**`]
|
|
1130
|
-
};
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
function mergeMaintainedSeam(existing, next) {
|
|
1134
|
-
if (!existing) {
|
|
1135
|
-
return {
|
|
1136
|
-
...next,
|
|
1137
|
-
seam_family_id: next.seam_family_id || null,
|
|
1138
|
-
seam_family_label: next.seam_family_label || null,
|
|
1139
|
-
maintained_modules: stableSortedStrings(next.maintained_modules || []),
|
|
1140
|
-
emitted_dependencies: stableSortedStrings(next.emitted_dependencies || []),
|
|
1141
|
-
human_owned_aspects: stableSortedStrings(next.human_owned_aspects || []),
|
|
1142
|
-
allowed_change_classes: stableSortedStrings(next.allowed_change_classes || []),
|
|
1143
|
-
drift_signals: stableSortedStrings(next.drift_signals || []),
|
|
1144
|
-
proof_stories: [...(next.proof_stories || [])]
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
const statusPriority = ["aligned", "review_required", "manual_decision", "no_go"];
|
|
1149
|
-
const ownershipPriority = ["engine_owned", "contract_bound", "advisory_only", "out_of_bounds"];
|
|
1150
|
-
|
|
1151
|
-
const currentStatus = statusPriority.indexOf(existing.status);
|
|
1152
|
-
const nextStatus = statusPriority.indexOf(next.status);
|
|
1153
|
-
const currentOwnership = ownershipPriority.indexOf(existing.ownership_class);
|
|
1154
|
-
const nextOwnership = ownershipPriority.indexOf(next.ownership_class);
|
|
1155
|
-
|
|
1156
|
-
return {
|
|
1157
|
-
...existing,
|
|
1158
|
-
kind: existing.kind || next.kind,
|
|
1159
|
-
seam_family_id: existing.seam_family_id || next.seam_family_id || null,
|
|
1160
|
-
seam_family_label: existing.seam_family_label || next.seam_family_label || null,
|
|
1161
|
-
status: nextStatus > currentStatus ? next.status : existing.status,
|
|
1162
|
-
ownership_class: nextOwnership > currentOwnership ? next.ownership_class : existing.ownership_class,
|
|
1163
|
-
maintained_modules: stableSortedStrings([...(existing.maintained_modules || []), ...(next.maintained_modules || [])]),
|
|
1164
|
-
emitted_dependencies: stableSortedStrings([...(existing.emitted_dependencies || []), ...(next.emitted_dependencies || [])]),
|
|
1165
|
-
human_owned_aspects: stableSortedStrings([...(existing.human_owned_aspects || []), ...(next.human_owned_aspects || [])]),
|
|
1166
|
-
allowed_change_classes: stableSortedStrings([...(existing.allowed_change_classes || []), ...(next.allowed_change_classes || [])]),
|
|
1167
|
-
drift_signals: stableSortedStrings([...(existing.drift_signals || []), ...(next.drift_signals || [])]),
|
|
1168
|
-
proof_stories: stableSortedStrings([
|
|
1169
|
-
...(existing.proof_stories || []).map((item) => JSON.stringify(item)),
|
|
1170
|
-
...(next.proof_stories || []).map((item) => JSON.stringify(item))
|
|
1171
|
-
]).map((item) => JSON.parse(item))
|
|
1172
|
-
};
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
export function buildMaintainedSeams(proofStories = []) {
|
|
1176
|
-
const seams = new Map();
|
|
1177
|
-
|
|
1178
|
-
for (const story of proofStories || []) {
|
|
1179
|
-
for (const seamLabel of story.humanOwnedSeams || story.human_owned_seams || []) {
|
|
1180
|
-
const output = maintainedOutputDescriptor(story.maintainedFiles || story.maintained_files || []);
|
|
1181
|
-
const seam = {
|
|
1182
|
-
seam_id: `seam_${seamIdHint(seamLabel)}`,
|
|
1183
|
-
seam_family_id: story.seamFamilyId || story.seam_family_id || null,
|
|
1184
|
-
seam_family_label: story.seamFamilyLabel || story.seam_family_label || null,
|
|
1185
|
-
output_id: output.output_id,
|
|
1186
|
-
label: seamLabel,
|
|
1187
|
-
kind: maintainedSeamKind(seamLabel),
|
|
1188
|
-
ownership_class: maintainedSeamOwnershipClass(story.classification),
|
|
1189
|
-
status: maintainedSeamStatus(story.reviewBoundary || story.review_boundary),
|
|
1190
|
-
maintained_modules: story.maintainedFiles || story.maintained_files || [],
|
|
1191
|
-
emitted_dependencies: story.emittedDependencies || story.emitted_dependencies || [],
|
|
1192
|
-
human_owned_aspects: [seamLabel],
|
|
1193
|
-
allowed_change_classes: maintainedSeamAllowedChangeClasses(story.classification),
|
|
1194
|
-
drift_signals: maintainedSeamDriftSignals(story.emittedDependencies || story.emitted_dependencies || []),
|
|
1195
|
-
proof_stories: [
|
|
1196
|
-
{
|
|
1197
|
-
classification: story.classification || null,
|
|
1198
|
-
relativePath: story.relativePath || story.relative_path || null,
|
|
1199
|
-
review_boundary: story.reviewBoundary || story.review_boundary || null
|
|
1200
|
-
}
|
|
1201
|
-
]
|
|
1202
|
-
};
|
|
1203
|
-
seams.set(seam.seam_id, mergeMaintainedSeam(seams.get(seam.seam_id), seam));
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
return [...seams.values()].sort((a, b) => a.seam_id.localeCompare(b.seam_id));
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
export function buildMaintainedOutputs({
|
|
1211
|
-
seams = [],
|
|
1212
|
-
proofStories = [],
|
|
1213
|
-
ownershipBoundary = ownershipBoundaryForMaintainedSurface(),
|
|
1214
|
-
verificationTargets = null,
|
|
1215
|
-
graph = null
|
|
1216
|
-
} = {}) {
|
|
1217
|
-
const outputs = new Map();
|
|
1218
|
-
|
|
1219
|
-
for (const seam of seams || []) {
|
|
1220
|
-
const descriptor = maintainedOutputDescriptor(seam.maintained_modules || []);
|
|
1221
|
-
const outputId = seam.output_id || descriptor.output_id;
|
|
1222
|
-
const existing = outputs.get(outputId) || {
|
|
1223
|
-
output_id: outputId,
|
|
1224
|
-
label: descriptor.label,
|
|
1225
|
-
kind: descriptor.kind,
|
|
1226
|
-
root_paths: descriptor.root_paths,
|
|
1227
|
-
ownership_boundary: ownershipBoundary,
|
|
1228
|
-
verification_targets: verificationTargets || null,
|
|
1229
|
-
maintained_files_in_scope: [],
|
|
1230
|
-
human_owned_seams: [],
|
|
1231
|
-
seams: [],
|
|
1232
|
-
proof_stories: []
|
|
1233
|
-
};
|
|
1234
|
-
|
|
1235
|
-
existing.maintained_files_in_scope = stableSortedStrings([
|
|
1236
|
-
...existing.maintained_files_in_scope,
|
|
1237
|
-
...(seam.maintained_modules || [])
|
|
1238
|
-
]);
|
|
1239
|
-
existing.human_owned_seams = stableSortedStrings([
|
|
1240
|
-
...existing.human_owned_seams,
|
|
1241
|
-
seam.label
|
|
1242
|
-
]);
|
|
1243
|
-
existing.seams.push({
|
|
1244
|
-
...seam,
|
|
1245
|
-
output_id: outputId
|
|
1246
|
-
});
|
|
1247
|
-
outputs.set(outputId, existing);
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
for (const story of proofStories || []) {
|
|
1251
|
-
const descriptor = maintainedOutputDescriptor(story.maintainedFiles || story.maintained_files || []);
|
|
1252
|
-
const outputId = descriptor.output_id;
|
|
1253
|
-
const existing = outputs.get(outputId) || {
|
|
1254
|
-
output_id: outputId,
|
|
1255
|
-
label: descriptor.label,
|
|
1256
|
-
kind: descriptor.kind,
|
|
1257
|
-
root_paths: descriptor.root_paths,
|
|
1258
|
-
ownership_boundary: ownershipBoundary,
|
|
1259
|
-
verification_targets: verificationTargets || null,
|
|
1260
|
-
maintained_files_in_scope: [],
|
|
1261
|
-
human_owned_seams: [],
|
|
1262
|
-
seams: [],
|
|
1263
|
-
proof_stories: []
|
|
1264
|
-
};
|
|
1265
|
-
|
|
1266
|
-
existing.maintained_files_in_scope = stableSortedStrings([
|
|
1267
|
-
...existing.maintained_files_in_scope,
|
|
1268
|
-
...(story.maintainedFiles || story.maintained_files || [])
|
|
1269
|
-
]);
|
|
1270
|
-
existing.human_owned_seams = stableSortedStrings([
|
|
1271
|
-
...existing.human_owned_seams,
|
|
1272
|
-
...(story.humanOwnedSeams || story.human_owned_seams || [])
|
|
1273
|
-
]);
|
|
1274
|
-
existing.proof_stories.push(story);
|
|
1275
|
-
outputs.set(outputId, existing);
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
const verificationTargetsForOutput = (output) => {
|
|
1279
|
-
if (!graph) {
|
|
1280
|
-
return output.verification_targets || verificationTargets || null;
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
const emittedDependencies = stableSortedStrings([
|
|
1284
|
-
...output.seams.flatMap((seam) => seam.emitted_dependencies || []),
|
|
1285
|
-
...output.proof_stories.flatMap((story) => story.emittedDependencies || story.emitted_dependencies || [])
|
|
1286
|
-
]);
|
|
1287
|
-
const verificationIds = stableSortedStrings(
|
|
1288
|
-
emittedDependencies.filter((id) => String(id).startsWith("ver_"))
|
|
1289
|
-
);
|
|
1290
|
-
const generatedDependencyTargets = emittedDependencies.filter((id) => !String(id).startsWith("ver_"));
|
|
1291
|
-
const targetIds = stableSortedStrings([...verificationIds, ...generatedDependencyTargets]);
|
|
1292
|
-
const includeMaintainedApp = output.kind === "maintained_runtime" || output.kind === "web_app" || output.kind === "mobile_app";
|
|
1293
|
-
|
|
1294
|
-
const routedTargets = recommendedVerificationTargets(graph, targetIds, {
|
|
1295
|
-
includeMaintainedApp,
|
|
1296
|
-
rationale: `${output.label || output.output_id || "Maintained output"} should run the smallest verification set tied to its own emitted dependencies and maintained seams.`
|
|
1297
|
-
});
|
|
1298
|
-
|
|
1299
|
-
return {
|
|
1300
|
-
...routedTargets,
|
|
1301
|
-
verification_ids: stableSortedStrings([
|
|
1302
|
-
...(routedTargets.verification_ids || []),
|
|
1303
|
-
...(verificationTargets?.verification_ids || []).filter((id) => verificationIds.includes(id))
|
|
1304
|
-
]),
|
|
1305
|
-
generated_checks: stableSortedStrings([
|
|
1306
|
-
...(routedTargets.generated_checks || []),
|
|
1307
|
-
...(verificationTargets?.generated_checks || []).filter((check) => routedTargets.generated_checks?.includes(check))
|
|
1308
|
-
]),
|
|
1309
|
-
maintained_app_checks: includeMaintainedApp
|
|
1310
|
-
? stableSortedStrings([
|
|
1311
|
-
...(routedTargets.maintained_app_checks || []),
|
|
1312
|
-
...(verificationTargets?.maintained_app_checks || [])
|
|
1313
|
-
])
|
|
1314
|
-
: []
|
|
1315
|
-
};
|
|
1316
|
-
};
|
|
1317
|
-
|
|
1318
|
-
return [...outputs.values()]
|
|
1319
|
-
.map((output) => ({
|
|
1320
|
-
...output,
|
|
1321
|
-
verification_targets: verificationTargetsForOutput(output),
|
|
1322
|
-
write_scope: graph ? buildMaintainedWriteScope(graph, output.maintained_files_in_scope) : null,
|
|
1323
|
-
seams: [...output.seams].sort((a, b) => String(a.seam_id || "").localeCompare(String(b.seam_id || ""))),
|
|
1324
|
-
proof_stories: [...output.proof_stories]
|
|
1325
|
-
}))
|
|
1326
|
-
.sort((a, b) => a.output_id.localeCompare(b.output_id));
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
export function relativePathFromGraph(graph, targetPath) {
|
|
1330
|
-
return path.relative(repoRootFromGraph(graph), targetPath);
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
export function jsonByteSize(value) {
|
|
1334
|
-
return Buffer.byteLength(JSON.stringify(value));
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
export function jsonLineCount(value) {
|
|
1338
|
-
return JSON.stringify(value, null, 2).split("\n").length;
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
export function percentOf(part, whole) {
|
|
1342
|
-
if (!whole) {
|
|
1343
|
-
return 0;
|
|
1344
|
-
}
|
|
1345
|
-
return Number(((part / whole) * 100).toFixed(2));
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
export function buildDefaultWriteScope() {
|
|
1349
|
-
return {
|
|
1350
|
-
safe_to_edit: ["topogram/**", "candidates/**"],
|
|
1351
|
-
generator_owned: ["artifacts/**", "apps/**"],
|
|
1352
|
-
human_owned_review_required: ["examples/maintained/proof-app/**"],
|
|
1353
|
-
out_of_bounds: [".git/**", "node_modules/**"]
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
export function buildMaintainedWriteScope(graph, maintainedFiles = []) {
|
|
1358
|
-
return {
|
|
1359
|
-
safe_to_edit: stableSortedStrings(maintainedFiles),
|
|
1360
|
-
generator_owned: ["artifacts/**", "apps/**"],
|
|
1361
|
-
human_owned_review_required: stableSortedStrings([
|
|
1362
|
-
...maintainedFiles,
|
|
1363
|
-
"examples/maintained/proof-app/**"
|
|
1364
|
-
]),
|
|
1365
|
-
out_of_bounds: ["topogram/**"]
|
|
1366
|
-
};
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
export function recommendedVerificationTargets(graph, targetIds = [], options = {}) {
|
|
1370
|
-
const verificationIds = verificationIdsForTarget(graph, targetIds);
|
|
1371
|
-
const base = {
|
|
1372
|
-
verification_ids: verificationIds,
|
|
1373
|
-
generated_checks: verificationIds.length > 0 ? ["compile-check", "runtime-check"] : ["compile-check"],
|
|
1374
|
-
maintained_app_checks: [],
|
|
1375
|
-
rationale: options.rationale || null
|
|
1376
|
-
};
|
|
1377
|
-
|
|
1378
|
-
if (options.includeMaintainedApp) {
|
|
1379
|
-
base.maintained_app_checks = [
|
|
1380
|
-
"examples/maintained/proof-app/scripts/compile-check.mjs",
|
|
1381
|
-
"examples/maintained/proof-app/scripts/smoke.mjs",
|
|
1382
|
-
"examples/maintained/proof-app/scripts/runtime-check.mjs"
|
|
1383
|
-
];
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
return base;
|
|
1387
|
-
}
|
|
1
|
+
// @ts-check
|
|
1388
2
|
|
|
1389
3
|
export {
|
|
1390
4
|
docIds,
|
|
1391
5
|
refIds,
|
|
1392
|
-
stableSortedStrings
|
|
6
|
+
stableSortedStrings
|
|
7
|
+
} from "./shared/primitives.js";
|
|
8
|
+
export {
|
|
1393
9
|
summarizeProjection,
|
|
1394
10
|
summarizeRule,
|
|
1395
11
|
summarizeStatement,
|
|
1396
|
-
summarizeVerification
|
|
1397
|
-
|
|
12
|
+
summarizeVerification,
|
|
13
|
+
reviewBoundaryForCapability,
|
|
14
|
+
reviewBoundaryForProjection,
|
|
15
|
+
reviewBoundaryForEntity,
|
|
16
|
+
graphCounts
|
|
17
|
+
} from "./shared/summaries.js";
|
|
18
|
+
export {
|
|
19
|
+
summarizeDoc,
|
|
20
|
+
summarizeById,
|
|
21
|
+
summarizeStatementsByIds,
|
|
22
|
+
summarizeDocsByIds,
|
|
23
|
+
workspaceInventory
|
|
24
|
+
} from "./shared/relationships.js";
|
|
25
|
+
export {
|
|
26
|
+
relatedJourneysForCapability,
|
|
27
|
+
relatedWorkflowDocsForCapability,
|
|
28
|
+
relatedRulesForTarget,
|
|
29
|
+
relatedProjectionsForCapability,
|
|
30
|
+
relatedCapabilitiesForEntity,
|
|
31
|
+
relatedShapesForEntity,
|
|
32
|
+
relatedProjectionsForEntity,
|
|
33
|
+
relatedCapabilitiesForProjection,
|
|
34
|
+
relatedEntitiesForProjection,
|
|
35
|
+
relatedShapesForProjection,
|
|
36
|
+
relatedProjectionsForShape,
|
|
37
|
+
widgetById,
|
|
38
|
+
relatedWidgetsForProjection,
|
|
39
|
+
relatedShapesForWidget,
|
|
40
|
+
relatedProjectionsForWidget,
|
|
41
|
+
verificationIdsForTarget,
|
|
42
|
+
ensureContextSelection,
|
|
43
|
+
buildIndexes
|
|
44
|
+
} from "./shared/relationships.js";
|
|
45
|
+
export {
|
|
46
|
+
domainById,
|
|
47
|
+
summarizeDomain,
|
|
48
|
+
domainsByStatement,
|
|
49
|
+
relatedCapabilitiesForDomain,
|
|
50
|
+
relatedEntitiesForDomain,
|
|
51
|
+
relatedRulesForDomain,
|
|
52
|
+
relatedVerificationsForDomain,
|
|
53
|
+
relatedProjectionsForDomain,
|
|
54
|
+
pitchById,
|
|
55
|
+
requirementById,
|
|
56
|
+
acceptanceCriterionById,
|
|
57
|
+
taskById,
|
|
58
|
+
bugById,
|
|
59
|
+
documentById,
|
|
60
|
+
summarizePitch,
|
|
61
|
+
summarizeRequirement,
|
|
62
|
+
summarizeAcceptanceCriterion,
|
|
63
|
+
summarizeTask,
|
|
64
|
+
summarizeBug,
|
|
65
|
+
summarizeDocument,
|
|
66
|
+
getWorkflowDoc,
|
|
67
|
+
getJourneyDoc,
|
|
68
|
+
getStatement
|
|
69
|
+
} from "./shared/domain-sdlc.js";
|
|
70
|
+
export {
|
|
71
|
+
repoRootFromGraph,
|
|
72
|
+
readLocalMaintainedProofMetadata,
|
|
73
|
+
buildMaintainedBoundaryArtifact,
|
|
74
|
+
buildLocalMaintainedBoundaryArtifact,
|
|
75
|
+
maintainedProofMetadata,
|
|
76
|
+
buildMaintainedSeams,
|
|
77
|
+
buildMaintainedOutputs,
|
|
78
|
+
relativePathFromGraph
|
|
79
|
+
} from "./shared/maintained-boundary.js";
|
|
80
|
+
export {
|
|
81
|
+
jsonByteSize,
|
|
82
|
+
jsonLineCount,
|
|
83
|
+
percentOf,
|
|
84
|
+
buildDefaultWriteScope,
|
|
85
|
+
buildMaintainedWriteScope,
|
|
86
|
+
recommendedVerificationTargets
|
|
87
|
+
} from "./shared/metrics.js";
|