@ontrails/warden 1.0.0-beta.4 → 1.0.0-beta.42
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/CHANGELOG.md +837 -13
- package/README.md +133 -26
- package/bin/warden.ts +51 -0
- package/package.json +27 -6
- package/src/adapter-check.ts +136 -0
- package/src/cli.ts +1570 -105
- package/src/command.ts +986 -0
- package/src/config.ts +193 -0
- package/src/draft.ts +22 -0
- package/src/drift.ts +233 -23
- package/src/fix.ts +126 -0
- package/src/formatters.ts +78 -13
- package/src/guide.ts +245 -0
- package/src/index.ts +247 -15
- package/src/project-context.ts +446 -0
- package/src/project-rules.ts +290 -0
- package/src/resolve.ts +531 -0
- package/src/rules/activation-orphan.ts +97 -0
- package/src/rules/captured-kernel.ts +375 -0
- package/src/rules/circular-refs.ts +150 -0
- package/src/rules/cli-command-route-coherence.ts +177 -0
- package/src/rules/composes-declarations.ts +839 -0
- package/src/rules/context-no-surface-types.ts +79 -15
- package/src/rules/dead-internal-trail.ts +161 -0
- package/src/rules/dead-public-trail.ts +258 -0
- package/src/rules/draft-file-marking.ts +155 -0
- package/src/rules/draft-visible-debt.ts +82 -0
- package/src/rules/duplicate-exported-symbol.ts +211 -0
- package/src/rules/duplicate-public-contract.ts +137 -0
- package/src/rules/entity-exists.ts +254 -0
- package/src/rules/entity-ids.ts +15 -0
- package/src/rules/error-mapping-completeness.ts +290 -0
- package/src/rules/example-valid.ts +395 -0
- package/src/rules/fires-declarations.ts +740 -0
- package/src/rules/governed-symbol-residue.ts +438 -0
- package/src/rules/implementation-returns-result.ts +1409 -166
- package/src/rules/incomplete-accessor-for-standard-op.ts +272 -0
- package/src/rules/incomplete-crud.ts +583 -0
- package/src/rules/index.ts +277 -10
- package/src/rules/intent-propagation.ts +125 -0
- package/src/rules/layer-field-name-drift.ts +102 -0
- package/src/rules/library-projection-coherence.ts +100 -0
- package/src/rules/metadata.ts +871 -0
- package/src/rules/missing-reconcile.ts +97 -0
- package/src/rules/missing-visibility.ts +111 -0
- package/src/rules/no-destructured-compose.ts +196 -0
- package/src/rules/no-dev-permit-in-source.ts +99 -0
- package/src/rules/no-direct-implementation-call.ts +12 -7
- package/src/rules/no-legacy-cli-alias-export.ts +247 -0
- package/src/rules/no-legacy-layer-imports.ts +211 -0
- package/src/rules/no-native-error-result.ts +118 -0
- package/src/rules/no-redundant-result-error-wrap.ts +384 -0
- package/src/rules/no-retired-cross-vocabulary.ts +204 -0
- package/src/rules/no-sync-result-assumption.ts +1141 -98
- package/src/rules/no-throw-in-detour-recover.ts +225 -0
- package/src/rules/no-throw-in-implementation.ts +15 -8
- package/src/rules/no-top-level-surface.ts +371 -0
- package/src/rules/on-references-exist.ts +194 -0
- package/src/rules/orphaned-signal.ts +149 -0
- package/src/rules/owner-projection-parity.ts +143 -0
- package/src/rules/permit-governance.ts +25 -0
- package/src/rules/public-export-example-coverage.ts +573 -0
- package/src/rules/public-internal-deep-imports.ts +456 -0
- package/src/rules/public-output-schema.ts +29 -0
- package/src/rules/public-union-output-discriminants.ts +150 -0
- package/src/rules/read-intent-fires.ts +188 -0
- package/src/rules/reference-exists.ts +97 -0
- package/src/rules/registry-names.ts +167 -0
- package/src/rules/resolved-import-boundary.ts +146 -0
- package/src/rules/resource-declarations.ts +697 -0
- package/src/rules/resource-exists.ts +181 -0
- package/src/rules/resource-id-grammar.ts +65 -0
- package/src/rules/resource-mock-coverage.ts +115 -0
- package/src/rules/retired-vocabulary.ts +633 -0
- package/src/rules/scan.ts +38 -25
- package/src/rules/scheduled-destroy-intent.ts +44 -0
- package/src/rules/signal-graph-coaching.ts +220 -0
- package/src/rules/source/composition.ts +165 -0
- package/src/rules/source/drafts.ts +164 -0
- package/src/rules/source/entities.ts +618 -0
- package/src/rules/source/pragmas.ts +45 -0
- package/src/rules/source/resources.ts +64 -0
- package/src/rules/source/signals.ts +397 -0
- package/src/rules/source/stores.ts +310 -0
- package/src/rules/specs.ts +9 -5
- package/src/rules/static-resource-accessor-preference.ts +653 -0
- package/src/rules/surface-overlay-coherence.ts +262 -0
- package/src/rules/surface-trailhead-coherence.ts +366 -0
- package/src/rules/trail-fork-coaching.ts +625 -0
- package/src/rules/trail-versioning-source.ts +1076 -0
- package/src/rules/trail-versioning-topo.ts +172 -0
- package/src/rules/trailhead-override-divergence.ts +356 -0
- package/src/rules/types.ts +354 -8
- package/src/rules/unmaterialized-activation-source.ts +85 -0
- package/src/rules/unreachable-detour-shadowing.ts +339 -0
- package/src/rules/valid-describe-refs.ts +162 -32
- package/src/rules/valid-detour-contract.ts +78 -0
- package/src/rules/warden-export-symmetry.ts +540 -0
- package/src/rules/warden-rules-use-ast.ts +1109 -0
- package/src/rules/webhook-route-collision.ts +306 -0
- package/src/trails/activation-orphan.trail.ts +84 -0
- package/src/trails/captured-kernel.trail.ts +108 -0
- package/src/trails/circular-refs.trail.ts +29 -0
- package/src/trails/cli-command-route-coherence.trail.ts +47 -0
- package/src/trails/composes-declarations.trail.ts +22 -0
- package/src/trails/context-no-surface-types.trail.ts +21 -0
- package/src/trails/dead-internal-trail.trail.ts +26 -0
- package/src/trails/dead-public-trail.trail.ts +31 -0
- package/src/trails/deprecation-without-guidance.trail.ts +21 -0
- package/src/trails/draft-file-marking.trail.ts +16 -0
- package/src/trails/draft-visible-debt.trail.ts +16 -0
- package/src/trails/duplicate-exported-symbol.trail.ts +48 -0
- package/src/trails/duplicate-public-contract.trail.ts +47 -0
- package/src/trails/entity-exists.trail.ts +21 -0
- package/src/trails/error-mapping-completeness.trail.ts +30 -0
- package/src/trails/example-valid.trail.ts +25 -0
- package/src/trails/fires-declarations.trail.ts +23 -0
- package/src/trails/fork-without-preserved-implementation.trail.ts +31 -0
- package/src/trails/governed-symbol-residue.trail.ts +24 -0
- package/src/trails/implementation-returns-result.trail.ts +20 -0
- package/src/trails/incomplete-accessor-for-standard-op.trail.ts +76 -0
- package/src/trails/incomplete-crud.trail.ts +39 -0
- package/src/trails/index.ts +89 -0
- package/src/trails/intent-propagation.trail.ts +30 -0
- package/src/trails/layer-field-name-drift.trail.ts +39 -0
- package/src/trails/library-projection-coherence.trail.ts +43 -0
- package/src/trails/marker-schema-unsupported.trail.ts +23 -0
- package/src/trails/missing-reconcile.trail.ts +33 -0
- package/src/trails/missing-visibility.trail.ts +22 -0
- package/src/trails/no-destructured-compose.trail.ts +44 -0
- package/src/trails/no-dev-permit-in-source.trail.ts +16 -0
- package/src/trails/no-direct-implementation-call.trail.ts +16 -0
- package/src/trails/no-legacy-cli-alias-export.trail.ts +41 -0
- package/src/trails/no-legacy-layer-imports.trail.ts +41 -0
- package/src/trails/no-native-error-result.trail.ts +18 -0
- package/src/trails/no-redundant-result-error-wrap.trail.ts +55 -0
- package/src/trails/no-retired-cross-vocabulary.trail.ts +42 -0
- package/src/trails/no-sync-result-assumption.trail.ts +19 -0
- package/src/trails/no-throw-in-detour-recover.trail.ts +24 -0
- package/src/trails/no-throw-in-implementation.trail.ts +20 -0
- package/src/trails/no-top-level-surface.trail.ts +43 -0
- package/src/trails/on-references-exist.trail.ts +21 -0
- package/src/trails/orphaned-signal.trail.ts +36 -0
- package/src/trails/owner-projection-parity.trail.ts +26 -0
- package/src/trails/pending-force.trail.ts +21 -0
- package/src/trails/permit-governance.trail.ts +51 -0
- package/src/trails/prefer-schema-inference.trail.ts +21 -0
- package/src/trails/public-export-example-coverage.trail.ts +16 -0
- package/src/trails/public-internal-deep-imports.trail.ts +94 -0
- package/src/trails/public-output-schema.trail.ts +55 -0
- package/src/trails/public-union-output-discriminants.trail.ts +33 -0
- package/src/trails/read-intent-fires.trail.ts +20 -0
- package/src/trails/reference-exists.trail.ts +25 -0
- package/src/trails/resolved-import-boundary.trail.ts +109 -0
- package/src/trails/resource-declarations.trail.ts +25 -0
- package/src/trails/resource-exists.trail.ts +27 -0
- package/src/trails/resource-id-grammar.trail.ts +39 -0
- package/src/trails/resource-mock-coverage.trail.ts +40 -0
- package/src/trails/run.ts +160 -0
- package/src/trails/scheduled-destroy-intent.trail.ts +56 -0
- package/src/trails/schema.ts +237 -0
- package/src/trails/signal-graph-coaching.trail.ts +77 -0
- package/src/trails/static-resource-accessor-preference.trail.ts +25 -0
- package/src/trails/surface-overlay-coherence.trail.ts +24 -0
- package/src/trails/surface-trailhead-coherence.trail.ts +25 -0
- package/src/trails/topo.ts +6 -0
- package/src/trails/trail-fork-coaching.trail.ts +42 -0
- package/src/trails/trailhead-override-divergence.trail.ts +47 -0
- package/src/trails/unmaterialized-activation-source.trail.ts +72 -0
- package/src/trails/unreachable-detour-shadowing.trail.ts +45 -0
- package/src/trails/valid-describe-refs.trail.ts +18 -0
- package/src/trails/valid-detour-contract.trail.ts +71 -0
- package/src/trails/version-gap.trail.ts +35 -0
- package/src/trails/version-pinned-compose.trail.ts +23 -0
- package/src/trails/version-without-examples.trail.ts +38 -0
- package/src/trails/warden-export-symmetry.trail.ts +16 -0
- package/src/trails/warden-rules-use-ast.trail.ts +64 -0
- package/src/trails/webhook-route-collision.trail.ts +50 -0
- package/src/trails/wrap-rule.ts +224 -0
- package/src/workspaces.ts +199 -0
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/dist/cli.d.ts +0 -46
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -218
- package/dist/cli.js.map +0 -1
- package/dist/drift.d.ts +0 -26
- package/dist/drift.d.ts.map +0 -1
- package/dist/drift.js +0 -27
- package/dist/drift.js.map +0 -1
- package/dist/formatters.d.ts +0 -29
- package/dist/formatters.d.ts.map +0 -1
- package/dist/formatters.js +0 -87
- package/dist/formatters.js.map +0 -1
- package/dist/index.d.ts +0 -26
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -26
- package/dist/index.js.map +0 -1
- package/dist/rules/ast.d.ts +0 -41
- package/dist/rules/ast.d.ts.map +0 -1
- package/dist/rules/ast.js +0 -161
- package/dist/rules/ast.js.map +0 -1
- package/dist/rules/context-no-surface-types.d.ts +0 -12
- package/dist/rules/context-no-surface-types.d.ts.map +0 -1
- package/dist/rules/context-no-surface-types.js +0 -96
- package/dist/rules/context-no-surface-types.js.map +0 -1
- package/dist/rules/implementation-returns-result.d.ts +0 -13
- package/dist/rules/implementation-returns-result.d.ts.map +0 -1
- package/dist/rules/implementation-returns-result.js +0 -277
- package/dist/rules/implementation-returns-result.js.map +0 -1
- package/dist/rules/index.d.ts +0 -15
- package/dist/rules/index.d.ts.map +0 -1
- package/dist/rules/index.js +0 -34
- package/dist/rules/index.js.map +0 -1
- package/dist/rules/no-direct-impl-in-route.d.ts +0 -12
- package/dist/rules/no-direct-impl-in-route.d.ts.map +0 -1
- package/dist/rules/no-direct-impl-in-route.js +0 -47
- package/dist/rules/no-direct-impl-in-route.js.map +0 -1
- package/dist/rules/no-direct-implementation-call.d.ts +0 -12
- package/dist/rules/no-direct-implementation-call.d.ts.map +0 -1
- package/dist/rules/no-direct-implementation-call.js +0 -39
- package/dist/rules/no-direct-implementation-call.js.map +0 -1
- package/dist/rules/no-sync-result-assumption.d.ts +0 -6
- package/dist/rules/no-sync-result-assumption.d.ts.map +0 -1
- package/dist/rules/no-sync-result-assumption.js +0 -98
- package/dist/rules/no-sync-result-assumption.js.map +0 -1
- package/dist/rules/no-throw-in-detour-target.d.ts +0 -12
- package/dist/rules/no-throw-in-detour-target.d.ts.map +0 -1
- package/dist/rules/no-throw-in-detour-target.js +0 -87
- package/dist/rules/no-throw-in-detour-target.js.map +0 -1
- package/dist/rules/no-throw-in-implementation.d.ts +0 -9
- package/dist/rules/no-throw-in-implementation.d.ts.map +0 -1
- package/dist/rules/no-throw-in-implementation.js +0 -34
- package/dist/rules/no-throw-in-implementation.js.map +0 -1
- package/dist/rules/prefer-schema-inference.d.ts +0 -7
- package/dist/rules/prefer-schema-inference.d.ts.map +0 -1
- package/dist/rules/prefer-schema-inference.js +0 -86
- package/dist/rules/prefer-schema-inference.js.map +0 -1
- package/dist/rules/scan.d.ts +0 -8
- package/dist/rules/scan.d.ts.map +0 -1
- package/dist/rules/scan.js +0 -32
- package/dist/rules/scan.js.map +0 -1
- package/dist/rules/specs.d.ts +0 -29
- package/dist/rules/specs.d.ts.map +0 -1
- package/dist/rules/specs.js +0 -192
- package/dist/rules/specs.js.map +0 -1
- package/dist/rules/structure.d.ts +0 -13
- package/dist/rules/structure.d.ts.map +0 -1
- package/dist/rules/structure.js +0 -142
- package/dist/rules/structure.js.map +0 -1
- package/dist/rules/types.d.ts +0 -52
- package/dist/rules/types.d.ts.map +0 -1
- package/dist/rules/types.js +0 -2
- package/dist/rules/types.js.map +0 -1
- package/dist/rules/valid-describe-refs.d.ts +0 -7
- package/dist/rules/valid-describe-refs.d.ts.map +0 -1
- package/dist/rules/valid-describe-refs.js +0 -51
- package/dist/rules/valid-describe-refs.js.map +0 -1
- package/dist/rules/valid-detour-refs.d.ts +0 -6
- package/dist/rules/valid-detour-refs.d.ts.map +0 -1
- package/dist/rules/valid-detour-refs.js +0 -116
- package/dist/rules/valid-detour-refs.js.map +0 -1
- package/src/__tests__/cli.test.ts +0 -198
- package/src/__tests__/drift.test.ts +0 -74
- package/src/__tests__/formatters.test.ts +0 -157
- package/src/__tests__/implementation-returns-result.test.ts +0 -129
- package/src/__tests__/no-direct-implementation-call.test.ts +0 -83
- package/src/__tests__/no-sync-result-assumption.test.ts +0 -85
- package/src/__tests__/no-throw-in-detour-target.test.ts +0 -78
- package/src/__tests__/prefer-schema-inference.test.ts +0 -84
- package/src/__tests__/rules.test.ts +0 -227
- package/src/__tests__/valid-describe-refs.test.ts +0 -60
- package/src/rules/ast.ts +0 -213
- package/src/rules/no-direct-impl-in-route.ts +0 -81
- package/src/rules/no-throw-in-detour-target.ts +0 -150
- package/src/rules/valid-detour-refs.ts +0 -187
- package/tsconfig.json +0 -9
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const governedVocabularyTransitionStatuses = [
|
|
4
|
+
'planned',
|
|
5
|
+
'active',
|
|
6
|
+
'complete',
|
|
7
|
+
] as const;
|
|
8
|
+
|
|
9
|
+
const governedVocabularySingleTargetSchema = z.object({
|
|
10
|
+
kind: z.literal('single'),
|
|
11
|
+
to: z.string().min(1),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const governedVocabularyClassifiedTargetSchema = z.object({
|
|
15
|
+
guidance: z.string().min(1),
|
|
16
|
+
kind: z.literal('classified'),
|
|
17
|
+
options: z
|
|
18
|
+
.array(
|
|
19
|
+
z.object({
|
|
20
|
+
to: z.string().min(1),
|
|
21
|
+
when: z.string().min(1),
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
.min(1),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const governedVocabularyTargetSchema = z.discriminatedUnion('kind', [
|
|
28
|
+
governedVocabularySingleTargetSchema,
|
|
29
|
+
governedVocabularyClassifiedTargetSchema,
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
export const governedVocabularyPreserveRuleSchema = z.object({
|
|
33
|
+
paths: z.array(z.string().min(1)).optional(),
|
|
34
|
+
pattern: z.string().min(1),
|
|
35
|
+
reason: z.string().min(1),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const governedVocabularyScopeSchema = z.object({
|
|
39
|
+
exclude: z.array(z.string().min(1)).optional(),
|
|
40
|
+
extensions: z.array(z.string().min(1)).optional(),
|
|
41
|
+
ignoredDirectories: z.array(z.string().min(1)).optional(),
|
|
42
|
+
include: z.array(z.string().min(1)).optional(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const governedVocabularySymbolRenameMatchModes = [
|
|
46
|
+
'exact',
|
|
47
|
+
'identifier-segment',
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
50
|
+
export const governedVocabularySymbolRenameSchema = z.object({
|
|
51
|
+
from: z.string().min(1),
|
|
52
|
+
match: z.enum(governedVocabularySymbolRenameMatchModes).default('exact'),
|
|
53
|
+
reviewDeclarationTypes: z.array(z.string().min(1)).default([]),
|
|
54
|
+
to: z.string().min(1),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const governedVocabularyLiteralRenameSchema = z.object({
|
|
58
|
+
from: z.string().min(1),
|
|
59
|
+
match: z.enum(['exact', 'property-key', 'review']).optional(),
|
|
60
|
+
moduleSpecifier: z
|
|
61
|
+
.object({
|
|
62
|
+
targetPackage: z.string().min(1),
|
|
63
|
+
})
|
|
64
|
+
.optional(),
|
|
65
|
+
to: z.string().min(1),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const governedVocabularyTransitionSchema = z.object({
|
|
69
|
+
codeIdentifiers: z.array(z.string().min(1)).default([]),
|
|
70
|
+
docs: z.object({
|
|
71
|
+
guidance: z.array(z.string().min(1)).default([]),
|
|
72
|
+
summary: z.string().min(1),
|
|
73
|
+
}),
|
|
74
|
+
from: z.string().min(1),
|
|
75
|
+
id: z.string().min(1),
|
|
76
|
+
intent: z.string().min(1),
|
|
77
|
+
kind: z.literal('vocabulary'),
|
|
78
|
+
oldForms: z.array(z.string().min(1)).min(1),
|
|
79
|
+
overrides: z.record(z.string().min(1), z.string().min(1)).default({}),
|
|
80
|
+
preserve: z.array(governedVocabularyPreserveRuleSchema).default([]),
|
|
81
|
+
reviewForms: z.array(z.string().min(1)).default([]),
|
|
82
|
+
safeRewriteForms: z.record(z.string().min(1), z.string().min(1)).default({}),
|
|
83
|
+
scope: governedVocabularyScopeSchema.optional(),
|
|
84
|
+
status: z.enum(governedVocabularyTransitionStatuses),
|
|
85
|
+
stringLiteralRenames: z
|
|
86
|
+
.array(governedVocabularyLiteralRenameSchema)
|
|
87
|
+
.default([]),
|
|
88
|
+
symbolRenames: z.array(governedVocabularySymbolRenameSchema).default([]),
|
|
89
|
+
target: governedVocabularyTargetSchema,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const governedVocabularyRegistrySchema = z
|
|
93
|
+
.array(governedVocabularyTransitionSchema)
|
|
94
|
+
.superRefine((transitions, ctx) => {
|
|
95
|
+
const seenIds = new Set<string>();
|
|
96
|
+
const seenFrom = new Set<string>();
|
|
97
|
+
|
|
98
|
+
for (const [index, transition] of transitions.entries()) {
|
|
99
|
+
if (seenIds.has(transition.id)) {
|
|
100
|
+
ctx.addIssue({
|
|
101
|
+
code: 'custom',
|
|
102
|
+
message: `Duplicate governed vocabulary transition id "${transition.id}".`,
|
|
103
|
+
path: [index, 'id'],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
seenIds.add(transition.id);
|
|
107
|
+
|
|
108
|
+
if (seenFrom.has(transition.from)) {
|
|
109
|
+
ctx.addIssue({
|
|
110
|
+
code: 'custom',
|
|
111
|
+
message: `Duplicate governed vocabulary source "${transition.from}".`,
|
|
112
|
+
path: [index, 'from'],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
seenFrom.add(transition.from);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export type GovernedVocabularyPreserveRule = z.output<
|
|
120
|
+
typeof governedVocabularyPreserveRuleSchema
|
|
121
|
+
>;
|
|
122
|
+
export type GovernedVocabularyScope = z.output<
|
|
123
|
+
typeof governedVocabularyScopeSchema
|
|
124
|
+
>;
|
|
125
|
+
export type GovernedVocabularyTarget = z.output<
|
|
126
|
+
typeof governedVocabularyTargetSchema
|
|
127
|
+
>;
|
|
128
|
+
export type GovernedVocabularySymbolRename = z.output<
|
|
129
|
+
typeof governedVocabularySymbolRenameSchema
|
|
130
|
+
>;
|
|
131
|
+
export type GovernedVocabularyLiteralRename = z.output<
|
|
132
|
+
typeof governedVocabularyLiteralRenameSchema
|
|
133
|
+
>;
|
|
134
|
+
export type GovernedVocabularyTransition = z.output<
|
|
135
|
+
typeof governedVocabularyTransitionSchema
|
|
136
|
+
>;
|
|
137
|
+
export type GovernedVocabularyTransitionInput = z.input<
|
|
138
|
+
typeof governedVocabularyTransitionSchema
|
|
139
|
+
>;
|
|
140
|
+
|
|
141
|
+
const defineTransition = (
|
|
142
|
+
input: GovernedVocabularyTransitionInput
|
|
143
|
+
): GovernedVocabularyTransition =>
|
|
144
|
+
governedVocabularyTransitionSchema.parse(input);
|
|
145
|
+
|
|
146
|
+
const reviewFunctionParamDeclarations = {
|
|
147
|
+
reviewDeclarationTypes: ['FunctionParam'],
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const v1VocabularyHistoricalExcludes = [
|
|
151
|
+
'.agents/goals/**',
|
|
152
|
+
'**/.agents/goals/**',
|
|
153
|
+
'.agents/memory/**',
|
|
154
|
+
'**/.agents/memory/**',
|
|
155
|
+
'.agents/notes/**',
|
|
156
|
+
'**/.agents/notes/**',
|
|
157
|
+
'.claude/agent-memory/**',
|
|
158
|
+
'**/.claude/agent-memory/**',
|
|
159
|
+
'.agents/plans/archive/**',
|
|
160
|
+
'**/.agents/plans/archive/**',
|
|
161
|
+
'.changeset/**',
|
|
162
|
+
'**/.changeset/**',
|
|
163
|
+
'.scratch/**',
|
|
164
|
+
'**/.scratch/**',
|
|
165
|
+
'.trails/regrade/history/**',
|
|
166
|
+
'**/.trails/regrade/history/**',
|
|
167
|
+
'**/CHANGELOG.md',
|
|
168
|
+
'**/.tmp-tests/**',
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
const v1VocabularyHistoricalPreservePaths = [
|
|
172
|
+
'.agents/plans/**',
|
|
173
|
+
'**/.agents/plans/**',
|
|
174
|
+
'docs/adr/0*.md',
|
|
175
|
+
'docs/adr/decision-map.json',
|
|
176
|
+
'docs/migration/**',
|
|
177
|
+
'docs/releases/beta*.md',
|
|
178
|
+
'docs/releases/v1-vocabulary-reset.md',
|
|
179
|
+
'docs/releases/v1-vocabulary-transition-workflow.md',
|
|
180
|
+
'scripts/vocab-cutover-*.ts',
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
const v1VocabularySelfExcludes = [
|
|
184
|
+
'packages/warden/src/__tests__/retired-vocabulary.test.ts',
|
|
185
|
+
'packages/warden/src/rules/retired-vocabulary.ts',
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
const unique = (values: readonly string[]): string[] => [...new Set(values)];
|
|
189
|
+
|
|
190
|
+
const escapeRegExp = (value: string): string =>
|
|
191
|
+
value.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
192
|
+
|
|
193
|
+
const formsPattern = (forms: readonly string[]): string =>
|
|
194
|
+
`(?:${forms.map(escapeRegExp).join('|')})`;
|
|
195
|
+
|
|
196
|
+
const defineV1Transition = (
|
|
197
|
+
input: GovernedVocabularyTransitionInput
|
|
198
|
+
): GovernedVocabularyTransition =>
|
|
199
|
+
defineTransition({
|
|
200
|
+
...input,
|
|
201
|
+
preserve: [
|
|
202
|
+
{
|
|
203
|
+
paths: v1VocabularyHistoricalPreservePaths,
|
|
204
|
+
pattern: formsPattern(
|
|
205
|
+
unique([...(input.oldForms ?? []), ...(input.reviewForms ?? [])])
|
|
206
|
+
),
|
|
207
|
+
reason:
|
|
208
|
+
'Preserve authored migration plans and historical decision/release evidence while keeping occurrences visible to the run ledger.',
|
|
209
|
+
},
|
|
210
|
+
...(input.preserve ?? []),
|
|
211
|
+
],
|
|
212
|
+
scope: {
|
|
213
|
+
...input.scope,
|
|
214
|
+
exclude: unique([
|
|
215
|
+
...v1VocabularyHistoricalExcludes,
|
|
216
|
+
...v1VocabularySelfExcludes,
|
|
217
|
+
...(input.scope?.exclude ?? []),
|
|
218
|
+
]),
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
export const governedVocabularyTransitions =
|
|
223
|
+
governedVocabularyRegistrySchema.parse([
|
|
224
|
+
defineTransition({
|
|
225
|
+
codeIdentifiers: ['ctx.cross', 'crossInput', 'crosses'],
|
|
226
|
+
docs: {
|
|
227
|
+
guidance: [
|
|
228
|
+
'Exact ctx.cross, crossInput, and crosses forms are mechanically rewritten.',
|
|
229
|
+
'Broader cross or Cross forms route to review because a text rule cannot prove the intended symbol boundary.',
|
|
230
|
+
],
|
|
231
|
+
summary:
|
|
232
|
+
'Beta.19 retired cross composition vocabulary in favor of compose.',
|
|
233
|
+
},
|
|
234
|
+
from: 'cross',
|
|
235
|
+
id: 'cross-compose',
|
|
236
|
+
intent:
|
|
237
|
+
'Retire beta.19 cross composition vocabulary in favor of compose.',
|
|
238
|
+
kind: 'vocabulary',
|
|
239
|
+
oldForms: ['cross', 'Cross', 'crosses', 'crossInput', 'ctx.cross'],
|
|
240
|
+
reviewForms: ['Cross', 'cross'],
|
|
241
|
+
safeRewriteForms: {
|
|
242
|
+
crossInput: 'composeInput',
|
|
243
|
+
crosses: 'composes',
|
|
244
|
+
'ctx.cross': 'ctx.compose',
|
|
245
|
+
},
|
|
246
|
+
status: 'complete',
|
|
247
|
+
symbolRenames: [
|
|
248
|
+
{ ...reviewFunctionParamDeclarations, from: 'cross', to: 'compose' },
|
|
249
|
+
{
|
|
250
|
+
...reviewFunctionParamDeclarations,
|
|
251
|
+
from: 'crossInput',
|
|
252
|
+
to: 'composeInput',
|
|
253
|
+
},
|
|
254
|
+
{ ...reviewFunctionParamDeclarations, from: 'crosses', to: 'composes' },
|
|
255
|
+
],
|
|
256
|
+
target: { kind: 'single', to: 'compose' },
|
|
257
|
+
}),
|
|
258
|
+
defineV1Transition({
|
|
259
|
+
codeIdentifiers: ['blaze', 'blazes'],
|
|
260
|
+
docs: {
|
|
261
|
+
guidance: [
|
|
262
|
+
'Treat code/API identifiers as governed symbols, not prose-only vocabulary.',
|
|
263
|
+
'Review inflected forms such as blazed or blazing instead of forcing a mechanical rewrite.',
|
|
264
|
+
],
|
|
265
|
+
summary:
|
|
266
|
+
'The authored trail behavior field is moving from blaze to implementation.',
|
|
267
|
+
},
|
|
268
|
+
from: 'blaze',
|
|
269
|
+
id: 'v1-blaze-implementation',
|
|
270
|
+
intent:
|
|
271
|
+
'Move the authored trail behavior field from blaze to implementation for v1.',
|
|
272
|
+
kind: 'vocabulary',
|
|
273
|
+
oldForms: ['blaze', 'blazes', 'Blaze'],
|
|
274
|
+
reviewForms: ['Blaze', 'blazing', 'blazed', 'trailblaze'],
|
|
275
|
+
safeRewriteForms: {
|
|
276
|
+
blaze: 'implementation',
|
|
277
|
+
blazes: 'implementations',
|
|
278
|
+
},
|
|
279
|
+
status: 'complete',
|
|
280
|
+
stringLiteralRenames: [
|
|
281
|
+
{ from: 'blaze', match: 'property-key', to: 'implementation' },
|
|
282
|
+
],
|
|
283
|
+
symbolRenames: [
|
|
284
|
+
{
|
|
285
|
+
...reviewFunctionParamDeclarations,
|
|
286
|
+
from: 'blaze',
|
|
287
|
+
match: 'identifier-segment',
|
|
288
|
+
to: 'implementation',
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
...reviewFunctionParamDeclarations,
|
|
292
|
+
from: 'blazes',
|
|
293
|
+
to: 'implementations',
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
target: { kind: 'single', to: 'implementation' },
|
|
297
|
+
}),
|
|
298
|
+
defineV1Transition({
|
|
299
|
+
codeIdentifiers: ['contour', 'contours', 'wayfind.contours'],
|
|
300
|
+
docs: {
|
|
301
|
+
guidance: [
|
|
302
|
+
'Keep domain-object semantics distinct from entities in app data until the occurrence is classified.',
|
|
303
|
+
'Treat contour code/API identifiers as governed symbols, with FunctionParam shadows routed to review.',
|
|
304
|
+
'Rewrite exact framework string literals only; prose, substrings, and inflections stay outside mechanical apply.',
|
|
305
|
+
],
|
|
306
|
+
summary:
|
|
307
|
+
'The domain object declaration term is moving from contour to entity.',
|
|
308
|
+
},
|
|
309
|
+
from: 'contour',
|
|
310
|
+
id: 'v1-contour-entity',
|
|
311
|
+
intent:
|
|
312
|
+
'Move the domain object declaration vocabulary from contour to entity for v1.',
|
|
313
|
+
kind: 'vocabulary',
|
|
314
|
+
oldForms: ['contour', 'contours', 'Contour'],
|
|
315
|
+
reviewForms: ['Contour', 'Contours', 'contoured', 'contouring'],
|
|
316
|
+
safeRewriteForms: {
|
|
317
|
+
contour: 'entity',
|
|
318
|
+
contours: 'entities',
|
|
319
|
+
},
|
|
320
|
+
status: 'complete',
|
|
321
|
+
stringLiteralRenames: [
|
|
322
|
+
{ from: 'contour', match: 'review', to: 'entity' },
|
|
323
|
+
{ from: 'contours', match: 'review', to: 'entities' },
|
|
324
|
+
{ from: 'wayfind.contours', to: 'wayfind.entities' },
|
|
325
|
+
],
|
|
326
|
+
symbolRenames: [
|
|
327
|
+
{
|
|
328
|
+
...reviewFunctionParamDeclarations,
|
|
329
|
+
from: 'contour',
|
|
330
|
+
match: 'identifier-segment',
|
|
331
|
+
to: 'entity',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
...reviewFunctionParamDeclarations,
|
|
335
|
+
from: 'contours',
|
|
336
|
+
match: 'identifier-segment',
|
|
337
|
+
to: 'entities',
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
target: { kind: 'single', to: 'entity' },
|
|
341
|
+
}),
|
|
342
|
+
defineV1Transition({
|
|
343
|
+
codeIdentifiers: [
|
|
344
|
+
'@ontrails/topographer',
|
|
345
|
+
'@ontrails/topographer/backend-support',
|
|
346
|
+
'0042-core-topographer-boundary-doctrine',
|
|
347
|
+
'core-topographer-boundary-doctrine',
|
|
348
|
+
'Topographer-owned',
|
|
349
|
+
'packages/topographer',
|
|
350
|
+
'topographer',
|
|
351
|
+
'topographers',
|
|
352
|
+
],
|
|
353
|
+
docs: {
|
|
354
|
+
guidance: [
|
|
355
|
+
'Treat topographer code/API identifiers as governed symbols, with case and compound forms handled by identifier-segment matching.',
|
|
356
|
+
'Rewrite only exact package route/module-specifier occurrences; near routes and larger route strings stay untouched.',
|
|
357
|
+
],
|
|
358
|
+
summary:
|
|
359
|
+
'The graph artifact package and vocabulary moved from topographer to topography.',
|
|
360
|
+
},
|
|
361
|
+
from: 'topographer',
|
|
362
|
+
id: 'v1-topographer-topography',
|
|
363
|
+
intent:
|
|
364
|
+
'Move graph artifact package routes and code vocabulary from topographer to topography for v1.',
|
|
365
|
+
kind: 'vocabulary',
|
|
366
|
+
oldForms: [
|
|
367
|
+
'@ontrails/topographer',
|
|
368
|
+
'@ontrails/topographer/backend-support',
|
|
369
|
+
'0042-core-topographer-boundary-doctrine',
|
|
370
|
+
'core-topographer-boundary-doctrine',
|
|
371
|
+
'Topographer-owned',
|
|
372
|
+
'packages/topographer',
|
|
373
|
+
'topographer',
|
|
374
|
+
'topographers',
|
|
375
|
+
'Topographer',
|
|
376
|
+
],
|
|
377
|
+
reviewForms: ['Topographer'],
|
|
378
|
+
safeRewriteForms: {
|
|
379
|
+
'0042-core-topographer-boundary-doctrine':
|
|
380
|
+
'0042-core-topography-boundary-doctrine',
|
|
381
|
+
'@ontrails/topographer': '@ontrails/topography',
|
|
382
|
+
'@ontrails/topographer/backend-support':
|
|
383
|
+
'@ontrails/topography/backend-support',
|
|
384
|
+
'Topographer-owned': 'Topography-owned',
|
|
385
|
+
'core-topographer-boundary-doctrine':
|
|
386
|
+
'core-topography-boundary-doctrine',
|
|
387
|
+
'packages/topographer': 'packages/topography',
|
|
388
|
+
topographer: 'topography',
|
|
389
|
+
topographers: 'topographies',
|
|
390
|
+
},
|
|
391
|
+
status: 'complete',
|
|
392
|
+
stringLiteralRenames: [
|
|
393
|
+
{
|
|
394
|
+
from: '@ontrails/topographer',
|
|
395
|
+
moduleSpecifier: { targetPackage: '@ontrails/topography' },
|
|
396
|
+
to: '@ontrails/topography',
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
from: '@ontrails/topographer/backend-support',
|
|
400
|
+
moduleSpecifier: { targetPackage: '@ontrails/topography' },
|
|
401
|
+
to: '@ontrails/topography/backend-support',
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
from: '0042-core-topographer-boundary-doctrine',
|
|
405
|
+
to: '0042-core-topography-boundary-doctrine',
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
from: 'core-topographer-boundary-doctrine',
|
|
409
|
+
to: 'core-topography-boundary-doctrine',
|
|
410
|
+
},
|
|
411
|
+
{ from: 'Topographer-owned', to: 'Topography-owned' },
|
|
412
|
+
{ from: 'packages/topographer', to: 'packages/topography' },
|
|
413
|
+
],
|
|
414
|
+
symbolRenames: [
|
|
415
|
+
{
|
|
416
|
+
...reviewFunctionParamDeclarations,
|
|
417
|
+
from: 'topographer',
|
|
418
|
+
match: 'identifier-segment',
|
|
419
|
+
to: 'topography',
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
...reviewFunctionParamDeclarations,
|
|
423
|
+
from: 'topographers',
|
|
424
|
+
match: 'identifier-segment',
|
|
425
|
+
to: 'topographies',
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
target: { kind: 'single', to: 'topography' },
|
|
429
|
+
}),
|
|
430
|
+
defineV1Transition({
|
|
431
|
+
codeIdentifiers: [
|
|
432
|
+
'facets',
|
|
433
|
+
'facetId',
|
|
434
|
+
'McpSurfaceFacetMap',
|
|
435
|
+
'surface-facet-coherence',
|
|
436
|
+
'wayfind.facets',
|
|
437
|
+
],
|
|
438
|
+
docs: {
|
|
439
|
+
guidance: [
|
|
440
|
+
'A trailhead is one grouped surface entry fronting several trails while preserving member identity.',
|
|
441
|
+
'Code/API identifiers remain governed symbols and need structured preservation before broad application.',
|
|
442
|
+
],
|
|
443
|
+
summary:
|
|
444
|
+
'The grouped surface entry term is moving from facet to trailhead.',
|
|
445
|
+
},
|
|
446
|
+
from: 'facet',
|
|
447
|
+
id: 'v1-facet-trailhead',
|
|
448
|
+
intent:
|
|
449
|
+
'Move grouped surface entry vocabulary from facet to trailhead for v1.',
|
|
450
|
+
kind: 'vocabulary',
|
|
451
|
+
oldForms: ['facet', 'facets', 'Facet'],
|
|
452
|
+
reviewForms: ['Facet'],
|
|
453
|
+
safeRewriteForms: {
|
|
454
|
+
facet: 'trailhead',
|
|
455
|
+
facets: 'trailheads',
|
|
456
|
+
},
|
|
457
|
+
status: 'complete',
|
|
458
|
+
stringLiteralRenames: [
|
|
459
|
+
{ from: 'surface-facet-coherence', to: 'surface-trailhead-coherence' },
|
|
460
|
+
{ from: 'wayfind.facets', to: 'wayfind.trailheads' },
|
|
461
|
+
],
|
|
462
|
+
symbolRenames: [
|
|
463
|
+
{ ...reviewFunctionParamDeclarations, from: 'facet', to: 'trailhead' },
|
|
464
|
+
{
|
|
465
|
+
...reviewFunctionParamDeclarations,
|
|
466
|
+
from: 'facets',
|
|
467
|
+
to: 'trailheads',
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
...reviewFunctionParamDeclarations,
|
|
471
|
+
from: 'facetId',
|
|
472
|
+
to: 'trailheadId',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
...reviewFunctionParamDeclarations,
|
|
476
|
+
from: 'McpSurfaceFacetMap',
|
|
477
|
+
to: 'McpSurfaceTrailheadMap',
|
|
478
|
+
},
|
|
479
|
+
],
|
|
480
|
+
target: { kind: 'single', to: 'trailhead' },
|
|
481
|
+
}),
|
|
482
|
+
defineV1Transition({
|
|
483
|
+
codeIdentifiers: ['@ontrails/warden/ast'],
|
|
484
|
+
docs: {
|
|
485
|
+
guidance: [
|
|
486
|
+
'Treat the package route as an exact code string and module specifier, not as vocabulary prose or an identifier segment.',
|
|
487
|
+
'Rewrite only exact string literal/module-specifier occurrences; near routes and larger strings stay untouched.',
|
|
488
|
+
],
|
|
489
|
+
summary:
|
|
490
|
+
'The reusable AST helper route moved from @ontrails/warden/ast to @ontrails/source.',
|
|
491
|
+
},
|
|
492
|
+
from: '@ontrails/warden/ast',
|
|
493
|
+
id: 'v1-warden-ast-source',
|
|
494
|
+
intent:
|
|
495
|
+
'Move reusable AST helper imports from @ontrails/warden/ast to @ontrails/source for v1.',
|
|
496
|
+
kind: 'vocabulary',
|
|
497
|
+
oldForms: ['@ontrails/warden/ast'],
|
|
498
|
+
preserve: [
|
|
499
|
+
{
|
|
500
|
+
paths: [
|
|
501
|
+
'adapters/commander/src/__tests__/to-commander.test.ts',
|
|
502
|
+
'apps/trails/src/__tests__/mcp.test.ts',
|
|
503
|
+
'apps/trails/src/__tests__/regrade.test.ts',
|
|
504
|
+
'packages/regrade/src/downstream/__tests__/ast-rewrite.test.ts',
|
|
505
|
+
'packages/regrade/src/downstream/__tests__/vocabulary.test.ts',
|
|
506
|
+
'packages/warden/src/__tests__/retired-vocabulary.test.ts',
|
|
507
|
+
'scripts/verify-oxc-resolver-published.ts',
|
|
508
|
+
],
|
|
509
|
+
pattern: '^@ontrails/warden/ast$',
|
|
510
|
+
reason:
|
|
511
|
+
'Preserve transition regression fixtures and the intentional negative resolver assertion after the public route is retired.',
|
|
512
|
+
},
|
|
513
|
+
],
|
|
514
|
+
reviewForms: [],
|
|
515
|
+
safeRewriteForms: {
|
|
516
|
+
'@ontrails/warden/ast': '@ontrails/source',
|
|
517
|
+
},
|
|
518
|
+
status: 'complete',
|
|
519
|
+
stringLiteralRenames: [
|
|
520
|
+
{
|
|
521
|
+
from: '@ontrails/warden/ast',
|
|
522
|
+
moduleSpecifier: { targetPackage: '@ontrails/source' },
|
|
523
|
+
to: '@ontrails/source',
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
target: { kind: 'single', to: '@ontrails/source' },
|
|
527
|
+
}),
|
|
528
|
+
defineV1Transition({
|
|
529
|
+
codeIdentifiers: ['@ontrails/wayfinder'],
|
|
530
|
+
docs: {
|
|
531
|
+
guidance: [
|
|
532
|
+
'Treat the package route as an exact code string and module specifier, not as Wayfind product vocabulary.',
|
|
533
|
+
'Rewrite only the exact package route; subpaths, near routes, and larger strings stay untouched for review.',
|
|
534
|
+
],
|
|
535
|
+
summary:
|
|
536
|
+
'The Wayfinder package API moved into @ontrails/topography while Wayfind remains the operator-facing product name.',
|
|
537
|
+
},
|
|
538
|
+
from: '@ontrails/wayfinder',
|
|
539
|
+
id: 'v1-wayfinder-topography',
|
|
540
|
+
intent:
|
|
541
|
+
'Move programmatic Wayfinder imports into @ontrails/topography while preserving Wayfind surface vocabulary.',
|
|
542
|
+
kind: 'vocabulary',
|
|
543
|
+
oldForms: ['@ontrails/wayfinder'],
|
|
544
|
+
reviewForms: [],
|
|
545
|
+
safeRewriteForms: {
|
|
546
|
+
'@ontrails/wayfinder': '@ontrails/topography',
|
|
547
|
+
},
|
|
548
|
+
status: 'complete',
|
|
549
|
+
stringLiteralRenames: [
|
|
550
|
+
{
|
|
551
|
+
from: '@ontrails/wayfinder',
|
|
552
|
+
moduleSpecifier: { targetPackage: '@ontrails/topography' },
|
|
553
|
+
to: '@ontrails/topography',
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
target: { kind: 'single', to: '@ontrails/topography' },
|
|
557
|
+
}),
|
|
558
|
+
defineV1Transition({
|
|
559
|
+
codeIdentifiers: [],
|
|
560
|
+
docs: {
|
|
561
|
+
guidance: [
|
|
562
|
+
'Use derive for contract-owned fact production.',
|
|
563
|
+
'Use render for surface- or operator-facing presentation.',
|
|
564
|
+
'Route every occurrence to review until the stage is classified.',
|
|
565
|
+
],
|
|
566
|
+
summary: 'Projection vocabulary splits by stage into derive or render.',
|
|
567
|
+
},
|
|
568
|
+
from: 'projection',
|
|
569
|
+
id: 'v1-projection-derive-render',
|
|
570
|
+
intent:
|
|
571
|
+
'Split projection vocabulary into derive/render by lifecycle stage for v1.',
|
|
572
|
+
kind: 'vocabulary',
|
|
573
|
+
oldForms: ['projection', 'projections', 'project', 'projected'],
|
|
574
|
+
reviewForms: ['projection', 'projections', 'project', 'projected'],
|
|
575
|
+
safeRewriteForms: {},
|
|
576
|
+
status: 'planned',
|
|
577
|
+
target: {
|
|
578
|
+
guidance:
|
|
579
|
+
'No single replacement is safe. Classify by whether the occurrence produces contract facts or presents derived facts.',
|
|
580
|
+
kind: 'classified',
|
|
581
|
+
options: [
|
|
582
|
+
{
|
|
583
|
+
to: 'derive',
|
|
584
|
+
when: 'The occurrence describes producing contract-owned facts or inferred data from authored inputs.',
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
to: 'render',
|
|
588
|
+
when: 'The occurrence describes presenting derived facts through a surface, report, guide, or operator output.',
|
|
589
|
+
},
|
|
590
|
+
],
|
|
591
|
+
},
|
|
592
|
+
}),
|
|
593
|
+
]);
|
|
594
|
+
|
|
595
|
+
export const listGovernedVocabularyTransitions =
|
|
596
|
+
(): readonly GovernedVocabularyTransition[] => governedVocabularyTransitions;
|
|
597
|
+
|
|
598
|
+
export const getGovernedVocabularyTransition = (
|
|
599
|
+
id: string
|
|
600
|
+
): GovernedVocabularyTransition | undefined =>
|
|
601
|
+
governedVocabularyTransitions.find((transition) => transition.id === id);
|
|
602
|
+
|
|
603
|
+
export const requireGovernedVocabularyTransition = (
|
|
604
|
+
id: string
|
|
605
|
+
): GovernedVocabularyTransition => {
|
|
606
|
+
const transition = getGovernedVocabularyTransition(id);
|
|
607
|
+
if (transition === undefined) {
|
|
608
|
+
throw new Error(`Unknown governed vocabulary transition "${id}".`);
|
|
609
|
+
}
|
|
610
|
+
return transition;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
export const formatGovernedVocabularyTransitionGuide = (
|
|
614
|
+
transitions: readonly GovernedVocabularyTransition[] = governedVocabularyTransitions
|
|
615
|
+
): string =>
|
|
616
|
+
transitions
|
|
617
|
+
.map((transition) => {
|
|
618
|
+
const target =
|
|
619
|
+
transition.target.kind === 'single'
|
|
620
|
+
? transition.target.to
|
|
621
|
+
: transition.target.options
|
|
622
|
+
.map((option) => `${option.to} (${option.when})`)
|
|
623
|
+
.join(' or ');
|
|
624
|
+
const lines = [
|
|
625
|
+
`- ${transition.id}: ${transition.from} -> ${target}`,
|
|
626
|
+
` - Status: ${transition.status}`,
|
|
627
|
+
` - Intent: ${transition.intent}`,
|
|
628
|
+
` - Safe rewrites: ${Object.keys(transition.safeRewriteForms).length}`,
|
|
629
|
+
` - Review forms: ${transition.reviewForms.join(', ') || 'none'}`,
|
|
630
|
+
];
|
|
631
|
+
return lines.join('\n');
|
|
632
|
+
})
|
|
633
|
+
.join('\n');
|