@ontrails/trails 1.0.0-beta.17 → 1.0.0-beta.19
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 +139 -0
- package/README.md +7 -10
- package/package.json +13 -12
- package/src/app.ts +14 -4
- package/src/cli.ts +16 -0
- package/src/lifecycle-source-io.ts +33 -0
- package/src/project-writes.ts +62 -5
- package/src/retired-topo-command.ts +36 -0
- package/src/run-adapter-check.ts +76 -0
- package/src/run-collision.ts +1 -0
- package/src/trails/adapter-check.ts +244 -0
- package/src/trails/add-surface.ts +18 -18
- package/src/trails/add-trail.ts +3 -2
- package/src/trails/add-verify.ts +30 -6
- package/src/trails/{topo-compile.ts → compile.ts} +16 -8
- package/src/trails/completions-complete.ts +1 -1
- package/src/trails/create-adapter.ts +1084 -0
- package/src/trails/create-scaffold.ts +243 -29
- package/src/trails/create.ts +118 -17
- package/src/trails/deprecate.ts +59 -0
- package/src/trails/dev-clean.ts +2 -2
- package/src/trails/dev-reset.ts +2 -2
- package/src/trails/dev-stats.ts +1 -1
- package/src/trails/doctor.ts +56 -0
- package/src/trails/draft-promote.ts +1 -0
- package/src/trails/guide.ts +2 -2
- package/src/trails/revise.ts +53 -0
- package/src/trails/run-example.ts +12 -7
- package/src/trails/run-examples.ts +3 -3
- package/src/trails/run.ts +7 -4
- package/src/trails/survey.ts +332 -25
- package/src/trails/topo-history.ts +1 -1
- package/src/trails/topo-output-schemas.ts +30 -1
- package/src/trails/topo-pin.ts +3 -2
- package/src/trails/topo-read-support.ts +49 -8
- package/src/trails/topo-reports.ts +39 -22
- package/src/trails/topo-store-support.ts +62 -16
- package/src/trails/topo-support.ts +1 -1
- package/src/trails/topo-unpin.ts +2 -2
- package/src/trails/topo.ts +2 -2
- package/src/trails/{topo-verify.ts → validate.ts} +7 -7
- package/src/trails/version-lifecycle-support.ts +945 -0
- package/src/trails/warden-guide.ts +8 -0
- package/src/trails/warden.ts +18 -2
- package/src/versions.ts +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,144 @@
|
|
|
1
1
|
# trails
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.19
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 1eb5bdc: Rename first-class trail composition from the `cross` API family to the `compose` family across core contracts, testing helpers, topo projections, Warden rules, CLI scaffolds, and docs. `composes`, `ctx.compose`, `composeInput`, and `Compose*` type names are now the public authoring vocabulary; topo persistence migrates legacy composition rows and graph keys forward.
|
|
8
|
+
- 120caf5: Promote topo artifact commands to `trails compile` and `trails validate`.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- e41c382: Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
|
|
13
|
+
- 14714b8: Add a beta.15 to beta.19 downstream migration guide (`docs/releases/beta15-to-beta19.md`) that ties together package install, CLI/MCP/HTTP surface decisions, public output schemas, contract testing, resource mocks / `unmockable`, error taxonomy, observability, Topographer artifact workflow, layer evolution, the `cross`→`compose` composition rename, trail-versioning runtime adoption, and adapter authoring. Linked from `docs/index.md` Release Notes and cross-references the focused migration guides under `docs/migration/`.
|
|
14
|
+
- 91328d3: Make `trails create` reruns reconcile existing scaffold files instead of overwriting present files and then failing on existing surfaces.
|
|
15
|
+
- 6471b73: Preserve the original `create.scaffold` Result boundary when `trails create` cannot scaffold a project.
|
|
16
|
+
- 51aac45: Add `entity.list` and `entity.delete` trails to the generated entity starter so fresh scaffolds model complete CRUD coverage.
|
|
17
|
+
- 5efa32c: Generate project-level `AGENTS.md` and `CLAUDE.md` guidance so new Trails apps
|
|
18
|
+
start with canonical agent instructions.
|
|
19
|
+
- 88c0316: Generate a contextual `README.md` for new Trails projects with first-run
|
|
20
|
+
commands, selected surfaces, starter notes, and agent guidance pointers.
|
|
21
|
+
- 99154d4: Generate `tsconfig.tests.json` in new Trails projects so root test files are
|
|
22
|
+
covered by editor TypeScript tooling without changing build output.
|
|
23
|
+
- 492f71c: Move CLI, MCP, HTTP, established-surface, and surface-parity helpers behind explicit subpaths so root contract testing imports no longer require optional surface peers. The Trails CLI scaffolder now emits `import { testAllEstablished } from '@ontrails/testing/established'` for generated verification.
|
|
24
|
+
- 4bc8a99: Clarify the Topographer artifact workflow around top-level `trails compile`, `trails validate`, and `trails diff` commands, including explicit diagnostics for retired `trails topo compile`, `trails topo verify`, and `trails topo check` attempts.
|
|
25
|
+
- 16cb740: Run examples and contract checks across live trail version entries, and project version-entry example coverage into topo and survey reports.
|
|
26
|
+
- 92e709b: Declare explicit permit scopes on mutating built-in CLI trails and scaffolded entity starter trails.
|
|
27
|
+
|
|
28
|
+
Preserve the resolved CLI permit on result callbacks so run-collision recovery can re-execute protected trails without losing authorization context.
|
|
29
|
+
|
|
30
|
+
- 1f48342: Preserve original Result error boundaries in CLI trails by returning existing Result failures directly instead of re-wrapping their errors.
|
|
31
|
+
- c14aa3a: Report structured entry and graph force audit details from `trails doctor`.
|
|
32
|
+
- 2df73cc: Configure scaffolded Trails projects to allow `TODO :::` fieldwork markers while keeping standard `TODO:` warning comments blocked.
|
|
33
|
+
- 7f50fe2: Add version lifecycle CLI trails for revising, deprecating, archiving, and diagnosing trail version entries.
|
|
34
|
+
- 653d1fc: Add a top-level `trails diff` command and extend TopoGraph diffs with version, marker, lifecycle status, support set, and force-event audit details.
|
|
35
|
+
- 2e76288: Add graph-only force event projection for forced compile break acceptance and block unforced breaking topo changes.
|
|
36
|
+
- 52e4e8f: Add the `@ontrails/trails` CLI package and core framework command scripts to newly scaffolded projects.
|
|
37
|
+
- 58be821: Generated projects now pin `@ontrails/*` packages to the exact scaffolded
|
|
38
|
+
package version instead of emitting caret prerelease ranges.
|
|
39
|
+
- da7cbcb: Generated projects now include a minimal `.trails/scaffold.json` provenance
|
|
40
|
+
breadcrumb recording the scaffold schema version, package version, starter
|
|
41
|
+
template, and generation timestamp.
|
|
42
|
+
- fc00aeb: Add adapter target conformance metadata and scaffold extracted HTTP adapters through `trails create adapter`.
|
|
43
|
+
- 1c975c3: Define the Warden fix-metadata contract (`WardenFix`, `WardenFixCapability`, `WardenFixClass`, `WardenFixSafety`, `WardenFixEdit`) with optional `fix` metadata on diagnostics and rule metadata, projected through the guide, manifest, markdown, and agent guidance. Export `wardenFixClasses`/`wardenFixSafeties` value arrays and surface the rule `fix` capability in the `warden.guide` trail output schema. Dormant until a rule declares it.
|
|
44
|
+
- d5d518e: Add `warden --fix` to apply safe source fixes. The executor applies only `safety: 'safe'` edits last-to-first, re-reading and rewriting affected files, while review-required, edit-less, and topo diagnostics stay reported but unapplied. The report surfaces applied, changed-file, and skipped counts.
|
|
45
|
+
|
|
46
|
+
Expose `fix` through the Trails app wrapper and mark the `warden` trail as write intent with explicit public access because `fix: true` mutates source files while the local governance command remains directly runnable.
|
|
47
|
+
|
|
48
|
+
- 678cb1c: Expose the shared adapter readiness engine through Warden's opt-in
|
|
49
|
+
`--adapter-check` diagnostics and the local `trails adapter check` authoring
|
|
50
|
+
workflow.
|
|
51
|
+
- 619cb15: Add a Warden rule (`no-destructured-compose`) that coaches trail blazes to call `ctx.compose(...)` directly instead of destructuring `compose` from the context.
|
|
52
|
+
|
|
53
|
+
Keep the generated `create` trail on the direct `ctx.compose(...)` shape so framework-authored trails follow the same composition guidance.
|
|
54
|
+
|
|
55
|
+
- Updated dependencies [bb81ffe]
|
|
56
|
+
- Updated dependencies [e41c382]
|
|
57
|
+
- Updated dependencies [ed5926b]
|
|
58
|
+
- Updated dependencies [a2f1825]
|
|
59
|
+
- Updated dependencies [a2f1825]
|
|
60
|
+
- Updated dependencies [1eb5bdc]
|
|
61
|
+
- Updated dependencies [f8d80b9]
|
|
62
|
+
- Updated dependencies [94a8380]
|
|
63
|
+
- Updated dependencies [94a8380]
|
|
64
|
+
- Updated dependencies [846a597]
|
|
65
|
+
- Updated dependencies [8638dae]
|
|
66
|
+
- Updated dependencies [8638dae]
|
|
67
|
+
- Updated dependencies [8638dae]
|
|
68
|
+
- Updated dependencies [f0f7e2f]
|
|
69
|
+
- Updated dependencies [223aaad]
|
|
70
|
+
- Updated dependencies [3125f4d]
|
|
71
|
+
- Updated dependencies [2494dc6]
|
|
72
|
+
- Updated dependencies [4bc8a99]
|
|
73
|
+
- Updated dependencies [120caf5]
|
|
74
|
+
- Updated dependencies [2d53717]
|
|
75
|
+
- Updated dependencies [16cb740]
|
|
76
|
+
- Updated dependencies [8894ecb]
|
|
77
|
+
- Updated dependencies [fdf7ec9]
|
|
78
|
+
- Updated dependencies [92e709b]
|
|
79
|
+
- Updated dependencies [d76be13]
|
|
80
|
+
- Updated dependencies [84f56a5]
|
|
81
|
+
- Updated dependencies [64fb15a]
|
|
82
|
+
- Updated dependencies [653d1fc]
|
|
83
|
+
- Updated dependencies [431b04c]
|
|
84
|
+
- Updated dependencies [2e76288]
|
|
85
|
+
- Updated dependencies [5d88104]
|
|
86
|
+
- Updated dependencies [f04a9ef]
|
|
87
|
+
- Updated dependencies [fc00aeb]
|
|
88
|
+
- Updated dependencies [1c975c3]
|
|
89
|
+
- Updated dependencies [48d5ff4]
|
|
90
|
+
- Updated dependencies [d5d518e]
|
|
91
|
+
- Updated dependencies [216bf10]
|
|
92
|
+
- Updated dependencies [ab1c77c]
|
|
93
|
+
- Updated dependencies [8ca5b85]
|
|
94
|
+
- Updated dependencies [4f43874]
|
|
95
|
+
- Updated dependencies [678cb1c]
|
|
96
|
+
- Updated dependencies [5874fd6]
|
|
97
|
+
- Updated dependencies [619cb15]
|
|
98
|
+
- Updated dependencies [4642268]
|
|
99
|
+
- Updated dependencies [9bab0cf]
|
|
100
|
+
- Updated dependencies [3ceeba8]
|
|
101
|
+
- Updated dependencies [beafd03]
|
|
102
|
+
- Updated dependencies [7b173e0]
|
|
103
|
+
- Updated dependencies [6e50e7b]
|
|
104
|
+
- Updated dependencies [48edf8d]
|
|
105
|
+
- Updated dependencies [12ffa3b]
|
|
106
|
+
- Updated dependencies [2f262f7]
|
|
107
|
+
- Updated dependencies [58b01f2]
|
|
108
|
+
- @ontrails/adapter-kit@1.0.0-beta.19
|
|
109
|
+
- @ontrails/core@1.0.0-beta.19
|
|
110
|
+
- @ontrails/cli@1.0.0-beta.19
|
|
111
|
+
- @ontrails/commander@1.0.0-beta.19
|
|
112
|
+
- @ontrails/http@1.0.0-beta.19
|
|
113
|
+
- @ontrails/mcp@1.0.0-beta.19
|
|
114
|
+
- @ontrails/topographer@1.0.0-beta.19
|
|
115
|
+
- @ontrails/warden@1.0.0-beta.19
|
|
116
|
+
- @ontrails/observe@1.0.0-beta.19
|
|
117
|
+
- @ontrails/tracing@1.0.0-beta.19
|
|
118
|
+
- @ontrails/permits@1.0.0-beta.19
|
|
119
|
+
|
|
120
|
+
## 1.0.0-beta.18
|
|
121
|
+
|
|
122
|
+
### Patch Changes
|
|
123
|
+
|
|
124
|
+
- Updated dependencies [c0b2948]
|
|
125
|
+
- Updated dependencies [fc3219c]
|
|
126
|
+
- Updated dependencies [bc2d327]
|
|
127
|
+
- Updated dependencies [bf44972]
|
|
128
|
+
- Updated dependencies [57c8672]
|
|
129
|
+
- Updated dependencies [510ea50]
|
|
130
|
+
- Updated dependencies [e0ae995]
|
|
131
|
+
- @ontrails/http@1.0.0-beta.18
|
|
132
|
+
- @ontrails/observe@1.0.0-beta.18
|
|
133
|
+
- @ontrails/tracing@1.0.0-beta.18
|
|
134
|
+
- @ontrails/commander@1.0.0-beta.18
|
|
135
|
+
- @ontrails/cli@1.0.0-beta.18
|
|
136
|
+
- @ontrails/core@1.0.0-beta.18
|
|
137
|
+
- @ontrails/mcp@1.0.0-beta.18
|
|
138
|
+
- @ontrails/permits@1.0.0-beta.18
|
|
139
|
+
- @ontrails/topographer@1.0.0-beta.18
|
|
140
|
+
- @ontrails/warden@1.0.0-beta.18
|
|
141
|
+
|
|
3
142
|
## 1.0.0-beta.17
|
|
4
143
|
|
|
5
144
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Command-line tools for working with Trails projects.
|
|
4
4
|
|
|
5
|
-
Use the CLI to scaffold a Trails app, add surfaces, inspect the current topo, run
|
|
6
|
-
warden checks, manage draft state, and keep local Trails project state tidy.
|
|
5
|
+
Use the CLI to scaffold a Trails app, add surfaces, inspect the current topo, run warden checks, manage draft state, and keep local Trails project state tidy.
|
|
7
6
|
|
|
8
7
|
```bash
|
|
9
8
|
bunx @ontrails/trails create
|
|
@@ -11,17 +10,15 @@ bunx @ontrails/trails create
|
|
|
11
10
|
|
|
12
11
|
Common workflows:
|
|
13
12
|
|
|
14
|
-
- `trails create` starts a new Trails project with generated trail, topo, surface,
|
|
15
|
-
and verification files.
|
|
13
|
+
- `trails create` starts a new Trails project with generated trail, topo, surface, and verification files.
|
|
16
14
|
- `trails add surface` adds another surface entrypoint to an existing project.
|
|
17
|
-
- `trails topo` inspects
|
|
18
|
-
- `trails
|
|
19
|
-
|
|
15
|
+
- `trails topo` inspects topo state and manages pins/history.
|
|
16
|
+
- `trails compile` writes committed topo artifacts.
|
|
17
|
+
- `trails validate` checks committed topo artifacts for drift.
|
|
18
|
+
- `trails warden` runs Trails governance checks for contract and architecture drift.
|
|
20
19
|
- `trails guide` shows available trails and examples from a project.
|
|
21
20
|
|
|
22
|
-
Trails is contract-first: define trails once with typed input, Result output,
|
|
23
|
-
examples, and meta; the framework derives CLI, MCP, HTTP, and future surfaces from
|
|
24
|
-
the same contracts.
|
|
21
|
+
Trails is contract-first: define trails once with typed input, Result output, examples, and meta; the framework derives CLI, MCP, HTTP, and future surfaces from the same contracts.
|
|
25
22
|
|
|
26
23
|
See the main Trails documentation for the full framework guide:
|
|
27
24
|
<https://github.com/outfitter-dev/trails>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/trails",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.19",
|
|
4
4
|
"bin": {
|
|
5
5
|
"trails": "./bin/trails.ts"
|
|
6
6
|
},
|
|
@@ -23,20 +23,21 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@clack/prompts": "^1.1.0",
|
|
26
|
-
"@ontrails/
|
|
27
|
-
"@ontrails/
|
|
28
|
-
"@ontrails/
|
|
29
|
-
"@ontrails/
|
|
30
|
-
"@ontrails/
|
|
31
|
-
"@ontrails/
|
|
32
|
-
"@ontrails/
|
|
33
|
-
"@ontrails/
|
|
34
|
-
"@ontrails/
|
|
35
|
-
"@ontrails/
|
|
26
|
+
"@ontrails/adapter-kit": "^1.0.0-beta.19",
|
|
27
|
+
"@ontrails/cli": "^1.0.0-beta.19",
|
|
28
|
+
"@ontrails/commander": "^1.0.0-beta.19",
|
|
29
|
+
"@ontrails/core": "^1.0.0-beta.19",
|
|
30
|
+
"@ontrails/http": "^1.0.0-beta.19",
|
|
31
|
+
"@ontrails/mcp": "^1.0.0-beta.19",
|
|
32
|
+
"@ontrails/observe": "^1.0.0-beta.19",
|
|
33
|
+
"@ontrails/permits": "^1.0.0-beta.19",
|
|
34
|
+
"@ontrails/topographer": "^1.0.0-beta.19",
|
|
35
|
+
"@ontrails/tracing": "^1.0.0-beta.19",
|
|
36
|
+
"@ontrails/warden": "^1.0.0-beta.19",
|
|
36
37
|
"commander": "^14.0.3",
|
|
37
38
|
"zod": "^4.3.5"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
41
|
+
"@ontrails/testing": "^1.0.0-beta.19"
|
|
41
42
|
}
|
|
42
43
|
}
|
package/src/app.ts
CHANGED
|
@@ -3,25 +3,30 @@ import { topo } from '@ontrails/core';
|
|
|
3
3
|
import * as addSurface from './trails/add-surface.js';
|
|
4
4
|
import * as addTrail from './trails/add-trail.js';
|
|
5
5
|
import * as addVerify from './trails/add-verify.js';
|
|
6
|
+
import * as adapterCheck from './trails/adapter-check.js';
|
|
7
|
+
import * as compile from './trails/compile.js';
|
|
6
8
|
import * as completions from './trails/completions.js';
|
|
7
9
|
import * as completionsComplete from './trails/completions-complete.js';
|
|
8
10
|
import * as create from './trails/create.js';
|
|
11
|
+
import * as createAdapter from './trails/create-adapter.js';
|
|
9
12
|
import * as createScaffold from './trails/create-scaffold.js';
|
|
13
|
+
import * as deprecate from './trails/deprecate.js';
|
|
10
14
|
import * as devClean from './trails/dev-clean.js';
|
|
11
15
|
import * as devReset from './trails/dev-reset.js';
|
|
12
16
|
import * as devStats from './trails/dev-stats.js';
|
|
17
|
+
import * as doctor from './trails/doctor.js';
|
|
13
18
|
import * as draftPromote from './trails/draft-promote.js';
|
|
14
19
|
import * as guide from './trails/guide.js';
|
|
20
|
+
import * as revise from './trails/revise.js';
|
|
15
21
|
import * as run from './trails/run.js';
|
|
16
22
|
import * as runExample from './trails/run-example.js';
|
|
17
23
|
import * as runExamples from './trails/run-examples.js';
|
|
18
24
|
import * as survey from './trails/survey.js';
|
|
19
|
-
import * as topoCompile from './trails/topo-compile.js';
|
|
20
25
|
import * as topoHistory from './trails/topo-history.js';
|
|
21
26
|
import * as topoPin from './trails/topo-pin.js';
|
|
22
27
|
import * as topoCommand from './trails/topo.js';
|
|
23
28
|
import * as topoUnpin from './trails/topo-unpin.js';
|
|
24
|
-
import * as
|
|
29
|
+
import * as validate from './trails/validate.js';
|
|
25
30
|
import * as warden from './trails/warden.js';
|
|
26
31
|
import * as wardenGuide from './trails/warden-guide.js';
|
|
27
32
|
|
|
@@ -32,19 +37,24 @@ export const app = topo(
|
|
|
32
37
|
runExample,
|
|
33
38
|
survey,
|
|
34
39
|
topoCommand,
|
|
35
|
-
|
|
40
|
+
compile,
|
|
36
41
|
topoHistory,
|
|
37
42
|
topoPin,
|
|
38
43
|
topoUnpin,
|
|
39
|
-
|
|
44
|
+
validate,
|
|
45
|
+
revise,
|
|
46
|
+
deprecate,
|
|
47
|
+
doctor,
|
|
40
48
|
devStats,
|
|
41
49
|
devClean,
|
|
42
50
|
devReset,
|
|
43
51
|
guide,
|
|
44
52
|
draftPromote,
|
|
53
|
+
adapterCheck,
|
|
45
54
|
warden,
|
|
46
55
|
wardenGuide,
|
|
47
56
|
create,
|
|
57
|
+
createAdapter,
|
|
48
58
|
createScaffold,
|
|
49
59
|
addSurface,
|
|
50
60
|
addVerify,
|
package/src/cli.ts
CHANGED
|
@@ -21,7 +21,12 @@ import { deriveTopoGraph } from '@ontrails/topographer';
|
|
|
21
21
|
|
|
22
22
|
import { app } from './app.js';
|
|
23
23
|
import { resolveInputWithClack } from './clack.js';
|
|
24
|
+
import { getRetiredTopoCommandDiagnostic } from './retired-topo-command.js';
|
|
24
25
|
import { attachCompletionsInstallCommand } from './run-completions-install.js';
|
|
26
|
+
import {
|
|
27
|
+
applyAdapterCheckExitCode,
|
|
28
|
+
tryAdapterCheckOutput,
|
|
29
|
+
} from './run-adapter-check.js';
|
|
25
30
|
import { tryRecoverFromRunCollision } from './run-collision.js';
|
|
26
31
|
import { tryExampleRunOutput } from './run-example.js';
|
|
27
32
|
import { tryExamplesRunOutput } from './run-examples.js';
|
|
@@ -64,6 +69,7 @@ const buildOnResult =
|
|
|
64
69
|
// envelope on stdout that includes the captured records under
|
|
65
70
|
// `tracing`. Hand that case off before the regular chain so the
|
|
66
71
|
// existing handlers do not also write to stdout.
|
|
72
|
+
applyAdapterCheckExitCode(resolvedCtx);
|
|
67
73
|
if (session !== undefined && tryTraceJsonOutput(resolvedCtx, session)) {
|
|
68
74
|
return;
|
|
69
75
|
}
|
|
@@ -80,6 +86,9 @@ const buildOnResult =
|
|
|
80
86
|
if (tryWardenOutput(resolvedCtx)) {
|
|
81
87
|
return;
|
|
82
88
|
}
|
|
89
|
+
if (tryAdapterCheckOutput(resolvedCtx)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
83
92
|
await defaultOnResult(resolvedCtx);
|
|
84
93
|
};
|
|
85
94
|
|
|
@@ -267,6 +276,13 @@ const normalizeWardenArgv = (argv: readonly string[]): string[] => {
|
|
|
267
276
|
* process-lifetime sink.
|
|
268
277
|
*/
|
|
269
278
|
const runSurfaceOnce = async (): Promise<void> => {
|
|
279
|
+
const retiredTopoCommand = getRetiredTopoCommandDiagnostic(process.argv);
|
|
280
|
+
if (retiredTopoCommand !== null) {
|
|
281
|
+
process.stderr.write(`${retiredTopoCommand.message}\n`);
|
|
282
|
+
process.exitCode = 1;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
270
286
|
const session = maybeInstallTraceSession();
|
|
271
287
|
try {
|
|
272
288
|
const program = createProgram(app, {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
import { InternalError, Result } from '@ontrails/core';
|
|
4
|
+
|
|
5
|
+
export const readLifecycleSourceFile = (
|
|
6
|
+
filePath: string
|
|
7
|
+
): Result<string, Error> => {
|
|
8
|
+
try {
|
|
9
|
+
return Result.ok(readFileSync(filePath, 'utf8'));
|
|
10
|
+
} catch (error: unknown) {
|
|
11
|
+
return Result.err(
|
|
12
|
+
error instanceof Error
|
|
13
|
+
? error
|
|
14
|
+
: new InternalError(`Unable to read lifecycle source file ${filePath}`)
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const writeLifecycleSourceFile = (
|
|
20
|
+
filePath: string,
|
|
21
|
+
source: string
|
|
22
|
+
): Result<void, Error> => {
|
|
23
|
+
try {
|
|
24
|
+
writeFileSync(filePath, source);
|
|
25
|
+
return Result.ok();
|
|
26
|
+
} catch (error: unknown) {
|
|
27
|
+
return Result.err(
|
|
28
|
+
error instanceof Error
|
|
29
|
+
? error
|
|
30
|
+
: new InternalError(`Unable to write lifecycle source file ${filePath}`)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
};
|
package/src/project-writes.ts
CHANGED
|
@@ -36,6 +36,10 @@ export type ProjectWriteOperation =
|
|
|
36
36
|
readonly path: string;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
interface ProjectOperationOptions {
|
|
40
|
+
readonly existing?: 'overwrite' | 'preserve';
|
|
41
|
+
}
|
|
42
|
+
|
|
39
43
|
export const validateProjectName = (
|
|
40
44
|
name: string
|
|
41
45
|
): TrailsResult<string, ValidationError> =>
|
|
@@ -222,12 +226,59 @@ export const planProjectOperation = (
|
|
|
222
226
|
}
|
|
223
227
|
};
|
|
224
228
|
|
|
229
|
+
const shouldApplyProjectOperation = (
|
|
230
|
+
projectDir: string,
|
|
231
|
+
operation: ProjectWriteOperation,
|
|
232
|
+
options: ProjectOperationOptions
|
|
233
|
+
): TrailsResult<boolean, Error> => {
|
|
234
|
+
if (options.existing !== 'preserve' || operation.kind === 'rename') {
|
|
235
|
+
return Result.ok(true);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const { path } = operation;
|
|
239
|
+
const target = resolveProjectPath(projectDir, path);
|
|
240
|
+
if (target.isErr()) {
|
|
241
|
+
return Result.err(target.error);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return Result.ok(!existsSync(target.value));
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const selectProjectOperations = (
|
|
248
|
+
projectDir: string,
|
|
249
|
+
operations: readonly ProjectWriteOperation[],
|
|
250
|
+
options: ProjectOperationOptions
|
|
251
|
+
): TrailsResult<ProjectWriteOperation[], Error> => {
|
|
252
|
+
const selected: ProjectWriteOperation[] = [];
|
|
253
|
+
for (const operation of operations) {
|
|
254
|
+
const shouldApply = shouldApplyProjectOperation(
|
|
255
|
+
projectDir,
|
|
256
|
+
operation,
|
|
257
|
+
options
|
|
258
|
+
);
|
|
259
|
+
if (shouldApply.isErr()) {
|
|
260
|
+
return Result.err(shouldApply.error);
|
|
261
|
+
}
|
|
262
|
+
if (shouldApply.value) {
|
|
263
|
+
selected.push(operation);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return Result.ok(selected);
|
|
268
|
+
};
|
|
269
|
+
|
|
225
270
|
export const planProjectOperations = (
|
|
226
271
|
projectDir: string,
|
|
227
|
-
operations: readonly ProjectWriteOperation[]
|
|
272
|
+
operations: readonly ProjectWriteOperation[],
|
|
273
|
+
options: ProjectOperationOptions = {}
|
|
228
274
|
): TrailsResult<PlannedProjectOperation[], Error> => {
|
|
275
|
+
const selected = selectProjectOperations(projectDir, operations, options);
|
|
276
|
+
if (selected.isErr()) {
|
|
277
|
+
return Result.err(selected.error);
|
|
278
|
+
}
|
|
279
|
+
|
|
229
280
|
const planned: PlannedProjectOperation[] = [];
|
|
230
|
-
for (const operation of
|
|
281
|
+
for (const operation of selected.value) {
|
|
231
282
|
const result = planProjectOperation(projectDir, operation);
|
|
232
283
|
if (result.isErr()) {
|
|
233
284
|
return Result.err(result.error);
|
|
@@ -302,14 +353,20 @@ const applyProjectOperation = async (
|
|
|
302
353
|
|
|
303
354
|
export const applyProjectOperations = async (
|
|
304
355
|
projectDir: string,
|
|
305
|
-
operations: readonly ProjectWriteOperation[]
|
|
356
|
+
operations: readonly ProjectWriteOperation[],
|
|
357
|
+
options: ProjectOperationOptions = {}
|
|
306
358
|
): Promise<TrailsResult<PlannedProjectOperation[], Error>> => {
|
|
307
|
-
const
|
|
359
|
+
const selected = selectProjectOperations(projectDir, operations, options);
|
|
360
|
+
if (selected.isErr()) {
|
|
361
|
+
return Result.err(selected.error);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const planned = planProjectOperations(projectDir, selected.value);
|
|
308
365
|
if (planned.isErr()) {
|
|
309
366
|
return Result.err(planned.error);
|
|
310
367
|
}
|
|
311
368
|
|
|
312
|
-
for (const operation of
|
|
369
|
+
for (const operation of selected.value) {
|
|
313
370
|
const applied = await applyProjectOperation(projectDir, operation);
|
|
314
371
|
if (applied.isErr()) {
|
|
315
372
|
return Result.err(applied.error);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const retiredTopoCommandReplacements = {
|
|
2
|
+
check: 'trails validate',
|
|
3
|
+
compile: 'trails compile',
|
|
4
|
+
verify: 'trails validate',
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
export type RetiredTopoCommand = keyof typeof retiredTopoCommandReplacements;
|
|
8
|
+
|
|
9
|
+
export interface RetiredTopoCommandDiagnostic {
|
|
10
|
+
readonly attempted: `trails topo ${RetiredTopoCommand}`;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly replacement: (typeof retiredTopoCommandReplacements)[RetiredTopoCommand];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const isRetiredTopoCommand = (
|
|
16
|
+
command: string | undefined
|
|
17
|
+
): command is RetiredTopoCommand =>
|
|
18
|
+
command !== undefined && command in retiredTopoCommandReplacements;
|
|
19
|
+
|
|
20
|
+
export const getRetiredTopoCommandDiagnostic = (
|
|
21
|
+
argv: readonly string[]
|
|
22
|
+
): RetiredTopoCommandDiagnostic | null => {
|
|
23
|
+
const [command, subcommand] = argv.slice(2);
|
|
24
|
+
if (command !== 'topo' || !isRetiredTopoCommand(subcommand)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const replacement = retiredTopoCommandReplacements[subcommand];
|
|
29
|
+
const attempted = `trails topo ${subcommand}` as const;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
attempted,
|
|
33
|
+
message: `"${attempted}" was retired. Use "${replacement}" instead.\nTopographer artifact commands now live at the top level: "trails compile", "trails validate", and "trails diff". "trails topo" is for topo-store history, pin, and unpin.`,
|
|
34
|
+
replacement,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ActionResultContext } from '@ontrails/cli';
|
|
2
|
+
import { deriveOutputMode } from '@ontrails/cli';
|
|
3
|
+
|
|
4
|
+
interface AdapterCheckResultValue {
|
|
5
|
+
readonly formatted: string;
|
|
6
|
+
readonly passed: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const isAdapterCheckResultValue = (
|
|
10
|
+
value: unknown
|
|
11
|
+
): value is AdapterCheckResultValue => {
|
|
12
|
+
if (typeof value !== 'object' || value === null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const candidate = value as Record<string, unknown>;
|
|
16
|
+
return (
|
|
17
|
+
typeof candidate['formatted'] === 'string' &&
|
|
18
|
+
typeof candidate['passed'] === 'boolean'
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const wantsStructuredOutput = (ctx: ActionResultContext): boolean =>
|
|
23
|
+
deriveOutputMode(ctx.flags, ctx.topoName).mode !== 'text';
|
|
24
|
+
|
|
25
|
+
const isAdapterCheckTrail = (ctx: ActionResultContext): boolean =>
|
|
26
|
+
ctx.trail.id === 'adapter.check';
|
|
27
|
+
|
|
28
|
+
const readAdapterCheckResultValue = (
|
|
29
|
+
ctx: ActionResultContext
|
|
30
|
+
): AdapterCheckResultValue | undefined => {
|
|
31
|
+
if (!isAdapterCheckTrail(ctx) || ctx.result.isErr()) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return isAdapterCheckResultValue(ctx.result.value)
|
|
36
|
+
? ctx.result.value
|
|
37
|
+
: undefined;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const applyAdapterCheckExitCode = (
|
|
41
|
+
ctx: ActionResultContext
|
|
42
|
+
): boolean => {
|
|
43
|
+
if (!isAdapterCheckTrail(ctx)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (ctx.result.isErr()) {
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const value = readAdapterCheckResultValue(ctx);
|
|
53
|
+
if (!value) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
process.exitCode = value.passed ? 0 : 1;
|
|
58
|
+
return true;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const tryAdapterCheckOutput = (ctx: ActionResultContext): boolean => {
|
|
62
|
+
const value = readAdapterCheckResultValue(ctx);
|
|
63
|
+
if (!value) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
applyAdapterCheckExitCode(ctx);
|
|
68
|
+
if (wantsStructuredOutput(ctx)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (value.formatted.length > 0) {
|
|
73
|
+
process.stdout.write(`${value.formatted}\n`);
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
};
|
package/src/run-collision.ts
CHANGED