@mannyc1/ts-release 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/ARCHITECTURE.md +13 -8
  2. package/README.md +226 -448
  3. package/SPEC.md +48 -43
  4. package/dist/artifacts/adapter.d.ts +39 -0
  5. package/dist/artifacts/adapter.d.ts.map +1 -0
  6. package/dist/artifacts/adapter.js +23 -0
  7. package/dist/artifacts/adapter.js.map +1 -0
  8. package/dist/artifacts/registry.d.ts +21 -0
  9. package/dist/artifacts/registry.d.ts.map +1 -0
  10. package/dist/artifacts/registry.js +21 -0
  11. package/dist/artifacts/registry.js.map +1 -0
  12. package/dist/config/schema.js +1 -1
  13. package/dist/config/schema.js.map +1 -1
  14. package/dist/domain/artifact.d.ts +85 -3
  15. package/dist/domain/artifact.d.ts.map +1 -1
  16. package/dist/domain/artifact.js +171 -3
  17. package/dist/domain/artifact.js.map +1 -1
  18. package/dist/domain/evidence.d.ts +16 -65
  19. package/dist/domain/evidence.d.ts.map +1 -1
  20. package/dist/domain/evidence.js +15 -60
  21. package/dist/domain/evidence.js.map +1 -1
  22. package/dist/domain/operation.d.ts +7 -17
  23. package/dist/domain/operation.d.ts.map +1 -1
  24. package/dist/domain/operation.js +22 -144
  25. package/dist/domain/operation.js.map +1 -1
  26. package/dist/domain/release.d.ts +1 -49
  27. package/dist/domain/release.d.ts.map +1 -1
  28. package/dist/domain/release.js +2 -47
  29. package/dist/domain/release.js.map +1 -1
  30. package/dist/domain/remote-state.d.ts +0 -27
  31. package/dist/domain/remote-state.d.ts.map +1 -1
  32. package/dist/domain/remote-state.js +1 -23
  33. package/dist/domain/remote-state.js.map +1 -1
  34. package/dist/domain/target.d.ts +14 -1
  35. package/dist/domain/target.d.ts.map +1 -1
  36. package/dist/domain/target.js +17 -3
  37. package/dist/domain/target.js.map +1 -1
  38. package/dist/planner/artifact-inventory.d.ts.map +1 -1
  39. package/dist/planner/artifact-inventory.js +3 -1
  40. package/dist/planner/artifact-inventory.js.map +1 -1
  41. package/dist/planner/errors.d.ts +2 -16
  42. package/dist/planner/errors.d.ts.map +1 -1
  43. package/dist/planner/errors.js +2 -14
  44. package/dist/planner/errors.js.map +1 -1
  45. package/dist/planner/evidence-recorder.d.ts +8 -6
  46. package/dist/planner/evidence-recorder.d.ts.map +1 -1
  47. package/dist/planner/evidence-recorder.js +50 -18
  48. package/dist/planner/evidence-recorder.js.map +1 -1
  49. package/dist/planner/executor.d.ts +12 -12
  50. package/dist/planner/executor.d.ts.map +1 -1
  51. package/dist/planner/executor.js +43 -55
  52. package/dist/planner/executor.js.map +1 -1
  53. package/dist/planner/normalize-release.d.ts +3 -0
  54. package/dist/planner/normalize-release.d.ts.map +1 -1
  55. package/dist/planner/normalize-release.js +128 -4
  56. package/dist/planner/normalize-release.js.map +1 -1
  57. package/dist/planner/reconcile.d.ts.map +1 -1
  58. package/dist/planner/reconcile.js +2 -4
  59. package/dist/planner/reconcile.js.map +1 -1
  60. package/dist/planner/render-plan.d.ts.map +1 -1
  61. package/dist/planner/render-plan.js +12 -19
  62. package/dist/planner/render-plan.js.map +1 -1
  63. package/dist/targets/adapter-helpers.d.ts +20 -5
  64. package/dist/targets/adapter-helpers.d.ts.map +1 -1
  65. package/dist/targets/adapter-helpers.js +77 -7
  66. package/dist/targets/adapter-helpers.js.map +1 -1
  67. package/dist/targets/github.d.ts.map +1 -1
  68. package/dist/targets/github.js +1 -9
  69. package/dist/targets/github.js.map +1 -1
  70. package/dist/targets/homebrew.d.ts.map +1 -1
  71. package/dist/targets/homebrew.js +131 -18
  72. package/dist/targets/homebrew.js.map +1 -1
  73. package/dist/targets/npm.d.ts.map +1 -1
  74. package/dist/targets/npm.js +1 -7
  75. package/dist/targets/npm.js.map +1 -1
  76. package/dist/targets/pypi.d.ts.map +1 -1
  77. package/dist/targets/pypi.js +50 -12
  78. package/dist/targets/pypi.js.map +1 -1
  79. package/dist/targets/scoop.d.ts.map +1 -1
  80. package/dist/targets/scoop.js +18 -8
  81. package/dist/targets/scoop.js.map +1 -1
  82. package/dist/workflows/config.d.ts +69 -119
  83. package/dist/workflows/config.d.ts.map +1 -1
  84. package/dist/workflows/config.js +80 -125
  85. package/dist/workflows/config.js.map +1 -1
  86. package/dist/workflows/diagnostics.d.ts.map +1 -1
  87. package/dist/workflows/diagnostics.js +6 -3
  88. package/dist/workflows/diagnostics.js.map +1 -1
  89. package/dist/workflows/distribution.d.ts +25 -0
  90. package/dist/workflows/distribution.d.ts.map +1 -0
  91. package/dist/workflows/distribution.js +24 -0
  92. package/dist/workflows/distribution.js.map +1 -0
  93. package/dist/workflows/evidence.d.ts +4 -13
  94. package/dist/workflows/evidence.d.ts.map +1 -1
  95. package/dist/workflows/evidence.js +15 -27
  96. package/dist/workflows/evidence.js.map +1 -1
  97. package/dist/workflows/index.d.ts +1 -0
  98. package/dist/workflows/index.d.ts.map +1 -1
  99. package/dist/workflows/index.js +1 -0
  100. package/dist/workflows/index.js.map +1 -1
  101. package/dist/workflows/init.d.ts +3 -3
  102. package/dist/workflows/init.d.ts.map +1 -1
  103. package/dist/workflows/init.js +46 -0
  104. package/dist/workflows/init.js.map +1 -1
  105. package/examples/README.md +4 -4
  106. package/package.json +18 -15
  107. package/templates/README.md +15 -2
  108. package/templates/bun-cli-github/README.md +14 -0
  109. package/templates/bun-cli-github/release.config.json +89 -0
  110. package/dist/domain/status.d.ts +0 -43
  111. package/dist/domain/status.d.ts.map +0 -1
  112. package/dist/domain/status.js +0 -51
  113. package/dist/domain/status.js.map +0 -1
  114. package/dist/internal/workflow-phases.d.ts +0 -3
  115. package/dist/internal/workflow-phases.d.ts.map +0 -1
  116. package/dist/internal/workflow-phases.js +0 -2
  117. package/dist/internal/workflow-phases.js.map +0 -1
  118. package/dist/planner/release-eligibility.d.ts +0 -39
  119. package/dist/planner/release-eligibility.d.ts.map +0 -1
  120. package/dist/planner/release-eligibility.js +0 -578
  121. package/dist/planner/release-eligibility.js.map +0 -1
  122. package/dist/planner/status.d.ts +0 -40
  123. package/dist/planner/status.d.ts.map +0 -1
  124. package/dist/planner/status.js +0 -313
  125. package/dist/planner/status.js.map +0 -1
package/README.md CHANGED
@@ -1,193 +1,144 @@
1
- # release
1
+ # @mannyc1/ts-release
2
2
 
3
- `@mannyc1/ts-release` turns release intent into explicit, inspectable, repeatable publishing operations.
3
+ Portable artifact and package-manager distribution planning for TypeScript projects.
4
4
 
5
- The root package is the reusable TypeScript release library. The official Bun
6
- CLI app lives in `apps/release-ts`, and the root `cli` script delegates to that
7
- private first-party app.
5
+ `@mannyc1/ts-release` helps you declare the thing you want to distribute, stage
6
+ platform-specific artifacts when needed, and feed those artifacts into
7
+ target-specific package managers, catalogs, release hosts, and install surfaces.
8
+ Publish operations still stay reviewable and approval-gated, but the product
9
+ center is portable distribution data.
8
10
 
9
- The default workflow is plan-first:
11
+ Use it when you need to answer:
10
12
 
11
- ```sh
12
- bun run cli validate-config --config release.config.json
13
- bun run cli plan --config release.config.json --format text
14
- bun run cli run --config release.config.json --execute --approve-irreversible
15
- ```
13
+ - Which binaries, archives, packages, or generated files make up this release?
14
+ - Which package managers or install channels consume each artifact variant?
15
+ - What target-specific files or commands will be generated?
16
+ - Which operations are only rendering data, and which ones publish externally?
17
+ - What evidence proves what was staged, rendered, validated, or executed?
16
18
 
17
- On GitHub Actions, the primary CI integration is the JavaScript action:
19
+ The root package is the reusable TypeScript library. This repo also contains the
20
+ first-party Bun CLI app in `apps/release-ts` and the bundled GitHub Action in
21
+ `apps/ts-release-action`.
18
22
 
19
- ```yaml
20
- - uses: mannyc2/ts-release-action@v1
21
- with:
22
- command: plan
23
- config: release.config.json
24
- format: markdown
23
+ ## What It Does
24
+
25
+ `ts-release` models distribution as data:
26
+
27
+ ```text
28
+ release config
29
+ -> normalized release identity
30
+ -> artifact recipes and inventory
31
+ -> installable artifact variants
32
+ -> target-specific distribution operations
33
+ -> generated package-manager files
34
+ -> explicit execution evidence
35
+ -> verification or reconciliation
25
36
  ```
26
37
 
27
- The action calls the TypeScript workflow APIs directly and keeps target-native
28
- operations visible in the plan. It defaults to `runtime: bundled`; workspace
29
- runtime mode is deferred until a same-module-graph Node platform setup can be
30
- required without surprising users. The source currently lives in
31
- `apps/ts-release-action`.
38
+ The library currently plans, stages, and validates these distribution surfaces:
39
+
40
+ | Surface | What ts-release models |
41
+ |---|---|
42
+ | npm | package publish, native dry-run validation, provenance, trusted publishing |
43
+ | GitHub Releases | release creation, asset uploads, REST API verification, draft reconciliation |
44
+ | Homebrew taps | generated formula files, macOS artifact variants, and approved tap pushes |
45
+ | PyPI | already-built distributions and platform CLI wrapper wheels published through Twine |
46
+ | Scoop buckets | generated manifest files, Windows binary shims, and approved bucket pushes |
47
+ | Bun executables | optional binary artifact recipe staging before target planning |
32
48
 
33
- The action supports the review commands `plan`, `validate-config`, `status`,
34
- `eligibility`, `check-intent`, `doctor`, `check-auth`, and `check-ci`, plus the approved workflow commands
35
- `validate`, `run`, `resume`, and `reconcile`. Use `upload-evidence: true` when
36
- an action job should publish collected `.release/evidence` JSON files even after
37
- a command fails.
49
+ It is not a fake universal package manager and does not hide each ecosystem's
50
+ manifest rules. It can stage declared artifacts through adapters, but it does
51
+ not replace full build pipelines, compilers, signing, or installer toolchains.
52
+ The job is to keep shared artifact inventory and target-specific distribution
53
+ data in one typed plan.
38
54
 
39
- The `run` command is the recommended release path: it renders generated files,
40
- validates every preflight, executes approved publish operations, and verifies
41
- remote state in order. The primitive commands remain available for review and
42
- debug flows:
55
+ ## Quick Start
56
+
57
+ Inside this repository, the CLI script runs the first-party Bun app:
43
58
 
44
59
  ```sh
45
- bun run cli schema --out release-config.schema.json
46
- bun run cli init --template npm-github --package @scope/pkg --repo owner/repo
47
- bun run cli validate-config --config release.config.json --format text
60
+ bun run cli init --template bun-cli-github --package @scope/pkg --repo owner/repo --github-actions --write
61
+ bun run cli validate-config --config release.config.json
62
+ bun run cli stage-artifacts --config release.config.json --format text
48
63
  bun run cli plan --config release.config.json --format text
49
- bun run cli plan --config release.config.json --format summary
50
- bun run cli explain npm:npm-publish --config release.config.json
51
- bun run cli doctor --config release.config.json --format text
52
- bun run cli check-auth --config release.config.json --target npm --format text
53
- bun run cli check-ci --config release.config.json --workflow .github/workflows/release.yml --format markdown
54
- bun run cli check-intent --config release.config.json --format text
55
- bun run cli render --config release.config.json --execute
56
- bun run cli validate --config release.config.json
57
- bun run cli print --config release.config.json
58
- bun run cli execute --config release.config.json --execute --approve-irreversible
59
- bun run cli verify --config release.config.json
60
- bun run cli eligibility --config release.config.json --format text
61
- bun run cli reconcile --config release.config.json --execute
64
+ bun run cli render --config release.config.json
62
65
  ```
63
66
 
64
- Rendering writes generated target files locally and records `render.json` evidence. `execute` is a lower-level primitive that runs publish operations only. Publishing is blocked unless execution is explicitly approved. Irreversible operations require a second approval flag.
67
+ The first useful path is artifact-first: write or scaffold a config, stage any
68
+ declared artifact recipes, plan the target distribution work, then render
69
+ package-manager files or release metadata. These commands do not publish
70
+ anything unless an execution command receives explicit approval.
65
71
 
66
- Status and resume commands use existing `.release/evidence` files to report progress and continue conservative unfinished work:
72
+ To publish through the full ordered workflow, pass both execution approvals:
67
73
 
68
74
  ```sh
69
- bun run cli status --config release.config.json --format text
70
- bun run cli resume --config release.config.json --execute --approve-irreversible
75
+ bun run cli run --config release.config.json --execute --approve-irreversible
71
76
  ```
72
77
 
73
- Resume skips operations with successful matching evidence, reruns safe read-only failures, and blocks failed publish operations until remote state is reconciled manually.
74
- `eligibility` resolves the configured release decision strategy and checks npm and GitHub remote state when a release is intended.
75
- `check-intent` is a read-only CI gate for the explicit intent-file strategy, and the GitHub Action exposes the same command for intent-file workflows.
76
- `reconcile` is separate from resume: it inspects GitHub release state through the API and can publish a matching draft release with explicit `--execute` without republishing immutable npm versions.
77
-
78
- The executable is an argv and console adapter over TypeScript workflows. Release workflows are modeled as typed functions first, then exposed through the CLI for terminal and CI usage.
78
+ `run` renders generated files, validates preflights, executes approved publish
79
+ operations, and verifies remote state. The lower-level commands are available
80
+ when you want a manual pause between phases:
79
81
 
80
- ## Imports
81
-
82
- The package root export is intentionally empty. For onboarding and application workflow code, import the opt-in workflow facade from `@mannyc1/ts-release/workflows`; for maximum tree-shaking or target-author control, import the exact module you need from an explicit subpath.
83
-
84
- ```ts
85
- import * as Effect from "effect/Effect"
86
- import { type ReleaseIntent } from "@mannyc1/ts-release/domain/release"
87
- import { createReleasePlan } from "@mannyc1/ts-release/planner/create-release-plan"
88
- import { validatePlan } from "@mannyc1/ts-release/planner/executor"
89
-
90
- export const planAndValidate = Effect.fn("docs.planAndValidate")(function*(intent: ReleaseIntent) {
91
- const plan = yield* createReleasePlan(intent)
92
- const evidence = yield* validatePlan(plan)
93
- return { plan, evidence }
94
- })
82
+ ```sh
83
+ bun run cli render --config release.config.json --execute
84
+ bun run cli validate --config release.config.json
85
+ bun run cli print --config release.config.json
86
+ bun run cli execute --config release.config.json --execute --approve-irreversible
87
+ bun run cli verify --config release.config.json
95
88
  ```
96
89
 
97
- `createReleasePlan` needs a `TargetRegistry` layer. Command execution needs a `ReleaseCommandRunner` layer, while artifact checks and checksum generation use Effect Platform `FileSystem`, `Path`, and `Crypto` services directly. High-level config-file workflows, render writes, and evidence writes also need Effect Platform `FileSystem` and `Path` services. Workflows that verify HTTP evidence, such as `verifyPlan`, `runApprovedReleaseWorkflow`, or direct `VerifyHttpOperation` execution, also need a `ReleaseHttp` layer. Applications can compose `@mannyc1/ts-release/workflows` and their platform services at the edge, or use exact lower-level imports from `@mannyc1/ts-release/workflows/live`, `@mannyc1/ts-release/host/platform`, and `@mannyc1/ts-release/host/http`. Tests can import `makeTestReleaseHttpLayer` from `@mannyc1/ts-release/host/http`. Internal Effect imports use deep module paths such as `effect/Effect` and `effect/Layer` to keep bundlers from depending on broad root-package analysis. See `ARCHITECTURE.md` for the module taxonomy.
98
-
99
- Reusable operations in docs and examples should use `Effect.fn`; workflow bodies use `Effect.gen`. Durable data, options, tagged target variants, and typed errors use `Schema.Class`, `Schema.TaggedClass`, and `Schema.TaggedErrorClass`, with `.make(...)` for construction. Runtime layers are provided once at CLI, action, script, application, or test boundaries.
90
+ ## GitHub Actions
100
91
 
101
- ## TypeScript Workflows
92
+ The bundled action is the intended CI adapter:
102
93
 
103
- Applications can call high-level release workflows without argv arrays or CLI command names:
104
-
105
- ```ts
106
- import * as BunHttpClient from "@effect/platform-bun/BunHttpClient"
107
- import * as BunServices from "@effect/platform-bun/BunServices"
108
- import * as Effect from "effect/Effect"
109
- import * as Layer from "effect/Layer"
110
- import { Config, Live } from "@mannyc1/ts-release/workflows"
111
-
112
- const root = "/path/to/release-workspace"
113
- const RuntimeLayer = Live.makeLayer({ root }).pipe(
114
- Layer.provideMerge(BunServices.layer),
115
- Layer.provideMerge(BunHttpClient.layer)
116
- )
117
-
118
- const textPlan = await Effect.runPromise(
119
- Config.renderPlan({ root, configPath: "release.config.json", format: "text" }).pipe(
120
- Effect.provide(RuntimeLayer)
121
- )
122
- )
94
+ ```yaml
95
+ - uses: mannyc2/ts-release-action@v1
96
+ with:
97
+ command: plan
98
+ config: release.config.json
99
+ format: markdown
100
+ upload-evidence: true
101
+ ```
123
102
 
124
- const plan = await Effect.runPromise(
125
- Config.plan({ root, configPath: "release.config.json" }).pipe(
126
- Effect.provide(RuntimeLayer)
127
- )
128
- )
103
+ Supported action commands are `plan`, `validate-config`, `doctor`, `check-auth`,
104
+ `check-ci`, `validate`, `run`, and `reconcile`. Artifact recipe staging remains
105
+ owned by the Bun CLI/runtime because the bundled action runs on Node.
129
106
 
130
- const evidence = await Effect.runPromise(
131
- Config.run({
132
- root,
133
- configPath: "release.config.json",
134
- execute: true,
135
- approveIrreversible: true
136
- }).pipe(
137
- Effect.provide(RuntimeLayer)
138
- )
139
- )
140
-
141
- const status = await Effect.runPromise(
142
- Config.status({ root, configPath: "release.config.json", format: "json" }).pipe(
143
- Effect.provide(RuntimeLayer)
144
- )
145
- )
107
+ Publishing still needs explicit approval:
146
108
 
147
- const resumedEvidence = await Effect.runPromise(
148
- Config.resume({
149
- root,
150
- configPath: "release.config.json",
151
- execute: true,
152
- approveIrreversible: true
153
- }).pipe(
154
- Effect.provide(RuntimeLayer)
155
- )
156
- )
109
+ ```yaml
110
+ - uses: mannyc2/ts-release-action@v1
111
+ with:
112
+ command: run
113
+ config: release.config.json
114
+ execute: "true"
115
+ approve-irreversible: "true"
116
+ upload-evidence: true
117
+ ```
157
118
 
158
- const eligibility = await Effect.runPromise(
159
- Config.checkEligibility({
160
- root,
161
- configPath: "release.config.json"
162
- }).pipe(
163
- Effect.provide(RuntimeLayer)
164
- )
165
- )
119
+ For npm trusted publishing, configure npmjs for the GitHub repository and
120
+ workflow, grant `id-token: write`, and keep `trustedPublishing` in the npm
121
+ target. Trusted publishing uses OIDC during `npm publish`; it does not use
122
+ `NPM_TOKEN`.
166
123
 
167
- const reconciliationEvidence = await Effect.runPromise(
168
- Config.reconcile({
169
- root,
170
- configPath: "release.config.json",
171
- execute: true
172
- }).pipe(
173
- Effect.provide(RuntimeLayer)
174
- )
175
- )
176
- ```
124
+ For PyPI trusted publishing, configure a pending or existing PyPI Trusted
125
+ Publisher for the GitHub repository, workflow, and release environment, then
126
+ keep `trustedPublishing` in the PyPI target. Twine uses OIDC during
127
+ `twine upload`; it does not require `TWINE_USERNAME` or `TWINE_PASSWORD` in CI.
177
128
 
178
- Use `@mannyc1/ts-release/workflows` for the curated `Config`, `Init`, `Diagnostics`, `Evidence`, and `Live` namespaces. Exact leaf imports such as `@mannyc1/ts-release/workflows/config`, `@mannyc1/ts-release/workflows/init`, `@mannyc1/ts-release/workflows/diagnostics`, `@mannyc1/ts-release/workflows/evidence`, and `@mannyc1/ts-release/workflows/live` remain stable and are preferred when an application needs maximum tree-shaking or direct access to option classes. Applications provide platform services at the edge, such as `FileSystem`, `Path`, `HttpClient`, and command execution. Use explicit lower-level planner, config, target, host, and domain subpaths when an application needs finer control over planning, execution, or test layers.
129
+ ## Config
179
130
 
180
- ## Example Config
131
+ A release config declares identity, artifacts, target policy, and evidence
132
+ location.
181
133
 
182
134
  ```json
183
135
  {
184
136
  "$schema": "https://mannyc2.github.io/ts-release/schema/release-config.schema.json",
185
137
  "identity": {
186
- "name": "@mannyc1/ts-release",
187
- "version": "0.1.0",
188
- "commit": "abc123",
189
- "tag": "v0.1.0",
190
- "notes": "Release notes"
138
+ "_tag": "PackageManifestReleaseIdentitySource",
139
+ "packagePath": "package.json",
140
+ "commit": "HEAD",
141
+ "tagTemplate": "v{version}"
191
142
  },
192
143
  "artifacts": [
193
144
  {
@@ -195,12 +146,6 @@ Use `@mannyc1/ts-release/workflows` for the curated `Config`, `Init`, `Diagnosti
195
146
  "path": ".",
196
147
  "format": "directory",
197
148
  "consumers": ["npm"]
198
- },
199
- {
200
- "id": "github-asset",
201
- "path": "artifacts/mannyc1-ts-release-0.1.0.tgz",
202
- "format": "tarball",
203
- "consumers": ["github"]
204
149
  }
205
150
  ],
206
151
  "targets": [
@@ -208,7 +153,7 @@ Use `@mannyc1/ts-release/workflows` for the curated `Config`, `Init`, `Diagnosti
208
153
  "_tag": "NpmRegistryTarget",
209
154
  "id": "npm",
210
155
  "registry": "https://registry.npmjs.org",
211
- "packageName": "@mannyc1/ts-release",
156
+ "packageName": "@scope/pkg",
212
157
  "packagePath": ".",
213
158
  "trustedPublishing": {
214
159
  "provider": "github-actions",
@@ -221,16 +166,6 @@ Use `@mannyc1/ts-release/workflows` for the curated `Config`, `Init`, `Diagnosti
221
166
  "dryRunSupport": "native",
222
167
  "mutability": "immutable",
223
168
  "recovery": "publish-new-version"
224
- },
225
- {
226
- "_tag": "GitHubReleaseTarget",
227
- "id": "github",
228
- "repository": "owner/repo",
229
- "tokenEnv": "GH_TOKEN",
230
- "draft": true,
231
- "dryRunSupport": "simulated",
232
- "mutability": "mutable-release",
233
- "recovery": "delete-and-recreate"
234
169
  }
235
170
  ],
236
171
  "strict": true,
@@ -238,223 +173,133 @@ Use `@mannyc1/ts-release/workflows` for the curated `Config`, `Init`, `Diagnosti
238
173
  }
239
174
  ```
240
175
 
241
- The optional `$schema` key powers editor completion and does not change release behavior. Print the derived schema with `bun run cli schema`, and use `bun run cli validate-config` to check JSON syntax and release config shape without running target validators.
242
-
243
- Paths are release-workspace relative and may not be absolute or contain parent traversal. `evidenceDirectory` may include the literal `{version}` placeholder, which is resolved during planning so each release version can use its own evidence directory.
244
- Artifact paths may use `{version}`, `{name}`, and `{normalizedName}`. `normalizedName` removes a leading npm scope marker and replaces `/` with `-`, matching generated self-release artifact names such as `mannyc1-ts-release-0.1.0.tgz`.
245
-
246
- ## Release Strategies
247
-
248
- Release identity and release decisions are strategy-backed data. Target adapters still receive a concrete release identity and still produce reviewable, approval-gated operations.
249
-
250
- | Strategy | Good for | Source of truth |
251
- |---|---|---|
252
- | Static config | audited/manual release identity | release config |
253
- | Package manifest | npm/package releases with one version source | `package.json` |
254
- | Git tag | tag-triggered release workflows | current Git tag |
255
- | Conventional commits | automated SemVer from commit messages | commits since the latest matching tag |
256
- | Intent files | reviewed release intent in PRs | `.release/intents/*.json` |
257
-
258
- Static identity remains supported:
259
-
260
- ```json
261
- {
262
- "identity": {
263
- "name": "@scope/pkg",
264
- "version": "0.1.0",
265
- "commit": "abc123",
266
- "tag": "v0.1.0"
267
- }
268
- }
269
- ```
270
-
271
- For npm-style packages, prefer manifest-derived identity to avoid repeating versions in release config:
176
+ Useful config commands:
272
177
 
273
- ```json
274
- {
275
- "identity": {
276
- "_tag": "PackageManifestReleaseIdentitySource",
277
- "packagePath": "package.json",
278
- "commit": "HEAD",
279
- "tagTemplate": "v{version}"
280
- }
281
- }
178
+ ```sh
179
+ bun run cli schema --out release-config.schema.json
180
+ bun run cli validate-config --config release.config.json --format text
181
+ bun run cli plan --config release.config.json --format summary
182
+ bun run cli explain npm:npm-publish --config release.config.json
282
183
  ```
283
184
 
284
- Decision strategies are opt-in through `releaseDecision`. The default `RemoteStateReleaseDecision` uses the resolved identity, then checks npm and GitHub state. Git tag and conventional commit strategies can return `skipped` without error when no release input is present. Intent files are small JSON documents in `.release/intents`:
185
+ Paths are release-workspace relative. Artifact paths can interpolate
186
+ `{version}`, `{name}`, and `{normalizedName}`. Evidence directories can
187
+ interpolate `{version}`.
285
188
 
286
- ```json
287
- {
288
- "$schema": "https://mannyc2.github.io/ts-release/schema/release-intent.schema.json",
289
- "package": "@scope/pkg",
290
- "release": "patch",
291
- "summary": "Explain the user-visible change.",
292
- "empty": false
293
- }
294
- ```
295
-
296
- This is a first-party intent-file format, not full Changesets compatibility. Publish operations remain plan data until explicit execution approval, regardless of which strategy chose the intended version.
189
+ ## Artifact Variants
297
190
 
298
- Homebrew tap targets model catalog updates as generated files plus an approval-gated push:
191
+ Artifact recipes can produce installable variants for different operating
192
+ systems and architectures. Bun executable recipes derive variant metadata from
193
+ their compile target, so the release plan can carry facts such as `linux`/`x64`
194
+ or `windows`/`x64` before any package-manager adapter consumes the artifact.
299
195
 
300
196
  ```json
301
197
  {
302
- "_tag": "HomebrewTapTarget",
303
- "id": "homebrew",
304
- "repository": "owner/homebrew-tap",
305
- "formulaName": "release",
306
- "formulaPath": ".release/generated/release.rb",
307
- "artifactId": "github-asset",
308
- "url": "https://github.com/owner/repo/releases/download/v0.1.0/mannyc1-ts-release-0.1.0.tgz",
309
- "installPath": "bin/release",
310
- "dryRunSupport": "simulated",
311
- "mutability": "mutable-index",
312
- "recovery": "manual"
198
+ "id": "cli-linux-x64",
199
+ "target": "bun-linux-x64-baseline",
200
+ "path": "artifacts/pkg-{version}-linux-x64",
201
+ "consumers": ["github"]
313
202
  }
314
203
  ```
315
204
 
316
- PyPI registry targets coordinate already-built Python distributions through Twine. They do not build wheels or sdists:
205
+ The planned artifact inventory for that output includes an executable artifact
206
+ with a variant like:
317
207
 
318
208
  ```json
319
209
  {
320
- "_tag": "PyPiRegistryTarget",
321
- "id": "pypi",
322
- "repositoryUrl": "https://test.pypi.org/legacy/",
323
- "usernameEnv": "TWINE_USERNAME",
324
- "passwordEnv": "TWINE_PASSWORD",
325
- "dryRunSupport": "native",
326
- "mutability": "immutable",
327
- "recovery": "publish-new-version"
210
+ "os": "linux",
211
+ "arch": "x64",
212
+ "libc": "glibc",
213
+ "targetTriple": "bun-linux-x64-baseline"
328
214
  }
329
215
  ```
330
216
 
331
- Use `TWINE_USERNAME` and `TWINE_PASSWORD` for token-based local publishing so secrets stay in environment variables rather than command arguments. PyPI Trusted Publishing belongs at the CI/auth layer; this adapter records Twine commands and their auth requirements. TestPyPI is a real registry publish target, not a dry-run.
217
+ Direct artifact declarations can also include `variant` when an artifact was
218
+ built outside `ts-release`. Homebrew formulas can consume macOS `darwin` x64
219
+ and arm64 variants from one target, and Scoop manifests can derive a stable shim
220
+ from a Windows executable variant. Future package-manager adapters should follow
221
+ that pattern instead of guessing platform support from filenames.
332
222
 
333
- Scoop bucket targets model Windows installer catalog updates as generated JSON manifests plus an approval-gated push:
334
-
335
- ```json
336
- {
337
- "_tag": "ScoopBucketTarget",
338
- "id": "scoop",
339
- "repository": "owner/scoop-bucket",
340
- "manifestName": "release",
341
- "manifestPath": ".release/generated/release.json",
342
- "artifactId": "github-asset",
343
- "url": "https://github.com/owner/repo/releases/download/v0.1.0/mannyc1-ts-release-0.1.0.zip",
344
- "bin": "release.exe",
345
- "dryRunSupport": "simulated",
346
- "mutability": "mutable-index",
347
- "recovery": "manual"
348
- }
349
- ```
223
+ ## Diagnostics
350
224
 
351
- Tap and bucket pushes use the Git credentials configured for the local checkout; `tokenEnv` is not supported for these catalog targets yet.
352
-
353
- Use `run --execute --approve-irreversible` for the ordered release workflow, or use `plan`, `render --execute`, `validate`, `print`, `execute --execute`, and `verify` separately when generated catalog files need a manual review pause before any tap or bucket update is pushed.
354
-
355
- ## Plan Review
356
-
357
- Text plans include the release identity, evidence directory, artifact inventory, target capabilities, operation commands, HTTP verification requests, validation notes, and execution gates. Command operations include a human command summary plus an `argv:` JSON array that preserves exact argument boundaries for review.
358
-
359
- ```text
360
- @mannyc1/ts-release@0.1.0
361
- commit: abc123
362
- evidence: .release/evidence/0.1.0
363
- artifacts: 2
364
- targets: 2
365
- operations: 9
366
-
367
- targets:
368
- - github [GitHubReleaseTarget] auth=env-token dry-run=simulated strategy=simulated-plan mutability=mutable-release recovery=delete-and-recreate
369
- - npm [NpmRegistryTarget] auth=trusted-publishing runs-in=ci provider=github-actions workflow=release.yml required-permission=id-token:write package-prerequisite=exists dry-run=native strategy=native-command mutability=immutable recovery=publish-new-version
370
- ```
371
-
372
- Summary plans provide a compact human first pass over risk, execution gates, target auth setup, and gated operation IDs:
225
+ Static diagnostics help catch missing auth and unsafe workflow setup before an
226
+ approved run:
373
227
 
374
228
  ```sh
375
- bun run cli plan --config release.config.json --format summary
229
+ bun run cli doctor --config release.config.json --format text
230
+ bun run cli check-auth --config release.config.json --target npm --format text
231
+ bun run cli check-ci --config release.config.json --workflow .github/workflows/release.yml --format markdown
376
232
  ```
377
233
 
378
- Markdown plans are intended for CI artifacts and PR review:
234
+ Diagnostics report confidence levels instead of pretending local checks can
235
+ prove provider-side setup. For example, npm trusted publishing can only be fully
236
+ confirmed inside the configured GitHub Actions environment.
379
237
 
380
- ```sh
381
- bun run cli plan --config release.config.json --format markdown > release-plan.md
382
- ```
238
+ ## Programmatic API
383
239
 
384
- Use `explain` when one operation needs a focused review without executing anything:
240
+ Install the library and provide platform services at your application boundary:
385
241
 
386
242
  ```sh
387
- bun run cli explain npm:npm-publish --config release.config.json
243
+ bun add @mannyc1/ts-release effect@beta @effect/platform-bun@beta
388
244
  ```
389
245
 
390
- JSON plans include the same data in a stable, CI-artifact-friendly shape, including `targetCapabilities`.
391
-
392
- GitHub release verification uses the GitHub REST API to check the release tag, title, draft flag, prerelease flag, and each uploaded artifact name.
246
+ High-level workflows are available from the opt-in workflow facade:
393
247
 
394
- ## Status and Resume
395
-
396
- `status` reads local phase evidence and reports each current operation as pending, passed, failed, blocked, or complete without executing anything. The JSON format is schema-backed for CI or dashboards; the text format is intended for terminal review.
397
-
398
- `resume` is intentionally conservative. It skips successful matching evidence, can rerun missing work and failed read-only validation or verification operations, and never reruns a failed publish operation. A failed publish command can still have changed the outside world, so resume blocks until a maintainer reconciles npm, GitHub, or any other remote state manually.
399
-
400
- `reconcile` is the narrow remote repair path for GitHub Releases. It reads the GitHub release by tag, blocks on mismatched metadata or assets, skips an already matching published release, and can run `gh release edit <tag> --draft=false` for a matching draft when the target expects a public release. It does not run `npm publish`.
401
-
402
- ## Public API
403
-
404
- The intentional public API is the explicit subpath list in `package.json`. The root package export remains empty. Programmatic callers can use the opt-in `@mannyc1/ts-release/workflows` facade for happy-path workflow APIs, or exact leaf subpaths such as `@mannyc1/ts-release/workflows/config`, `@mannyc1/ts-release/workflows/init`, and `@mannyc1/ts-release/workflows/diagnostics` for maximum tree-shaking and direct option-class access. Lower-level planner/config/target/status subpaths remain available for finer control. The official CLI command adapter lives in the private `apps/release-ts` app rather than the reusable root package API.
405
-
406
- The package export checker fails if a new export is added without being added to the intentional API list.
407
-
408
- ## Templates
248
+ ```ts
249
+ import * as BunHttpClient from "@effect/platform-bun/BunHttpClient"
250
+ import * as BunServices from "@effect/platform-bun/BunServices"
251
+ import * as Effect from "effect/Effect"
252
+ import * as Layer from "effect/Layer"
253
+ import { Distribution, Live } from "@mannyc1/ts-release/workflows"
409
254
 
410
- Copyable starter configs live in `templates/`. They are authoring starting
411
- points with placeholder package, repository, tap, and bucket names. Runnable
412
- fixtures live in `examples/`.
255
+ const root = "/path/to/release-workspace"
256
+ const RuntimeLayer = Live.makeLayer({ root }).pipe(
257
+ Layer.provideMerge(BunServices.layer),
258
+ Layer.provideMerge(BunHttpClient.layer)
259
+ )
413
260
 
414
- Config templates are intentionally narrow:
261
+ const textPlan = await Effect.runPromise(
262
+ Distribution.renderPlan({ root, configPath: "release.config.json", format: "text" }).pipe(
263
+ Effect.provide(RuntimeLayer)
264
+ )
265
+ )
415
266
 
416
- - `npm-only` for an existing npm package using GitHub Actions trusted publishing.
417
- - `npm-github` for npm plus GitHub Releases.
418
- - `multi-target-homebrew` for npm, GitHub Releases, and a Homebrew tap.
419
- - `multi-target-scoop` for npm, GitHub Releases, and a Scoop bucket.
267
+ const evidence = await Effect.runPromise(
268
+ Distribution.run({
269
+ root,
270
+ configPath: "release.config.json",
271
+ execute: true,
272
+ approveIrreversible: true
273
+ }).pipe(Effect.provide(RuntimeLayer))
274
+ )
420
275
 
421
- ```sh
422
- bun run cli init --template npm-github --package @scope/pkg --repo owner/repo
423
- bun run cli init --template npm-github --package @scope/pkg --repo owner/repo --write
424
- bun run cli init --template npm-github --package @scope/pkg --repo owner/repo --github-actions --package-manager npm --write
425
- bun run cli plan --config release.config.json --format text
276
+ console.log(textPlan)
277
+ console.log(evidence.schemaVersion)
426
278
  ```
427
279
 
428
- The npm templates enable provenance and set `verifyPackageExists: true`, which
429
- adds a read-only `npm view <package>` validation before trusted publishing.
430
- Add `--github-actions` to include the action-first trusted-publishing workflow
431
- template in the preview or write set. Workflow scaffolding supports
432
- `--package-manager bun|npm|pnpm|yarn`, plus single-line `--install-command` and
433
- `--build-command` overrides. Those commands are CI setup steps, not release
434
- target policy; publish operations still come from the `ts-release` plan.
435
- Existing files are not overwritten unless `--overwrite` is also passed.
280
+ Use `@mannyc1/ts-release/workflows` for the curated `Distribution`, `Config`,
281
+ `Init`, `Diagnostics`, `Evidence`, and `Live` namespaces. The `Distribution`
282
+ namespace is the artifact-first facade; `Config` keeps the lower-level
283
+ config-file workflow names. Use exact subpaths such as
284
+ `@mannyc1/ts-release/workflows/distribution` or lower-level `domain/`,
285
+ `planner/`, `targets/`, and `host/` modules when you need tighter control or
286
+ maximum tree-shaking.
436
287
 
437
- Action-first GitHub templates live under `templates/github-actions/`. The
438
- checked-in templates use npm setup by default, while this repository's own
439
- self-release workflow uses the Bun preset.
288
+ The package root export is intentionally empty. Public API is the explicit
289
+ subpath list in `package.json`.
440
290
 
441
- Use `doctor`, `check-auth`, and `check-ci` after writing a template to inspect
442
- static readiness before any publish operation is approved.
291
+ ## Templates And Examples
443
292
 
444
- ## Examples
293
+ Config templates live in `templates/`:
445
294
 
446
- Runnable example configs live in `examples/`:
295
+ - `npm-only`
296
+ - `npm-github`
297
+ - `bun-cli-github`
298
+ - `multi-target-homebrew`
299
+ - `multi-target-scoop`
447
300
 
448
- - `examples/multi-target`
449
- - `examples/npm-only`
450
- - `examples/npm-first-publish`
451
- - `examples/github-release`
452
- - `examples/homebrew-tap`
453
- - `examples/pypi-registry`
454
- - `examples/scoop-bucket`
455
- - `examples/non-strict-skips`
456
-
457
- `examples/multi-target` demonstrates one release coordinated across GitHub Releases, npm, and a Homebrew tap. The focused fixtures cover PyPI, Scoop, npm-only trusted publishing, token-based first npm publish, GitHub-only releases, and non-strict skipped validators. Build the package first, then plan an example from its directory:
301
+ Runnable fixtures live in `examples/` and are checked through the same workflow
302
+ path as user configs.
458
303
 
459
304
  ```sh
460
305
  bun run build
@@ -462,13 +307,18 @@ cd examples/multi-target
462
307
  bun ../../apps/release-ts/src/cli/main.ts plan --config release.config.json --format text
463
308
  ```
464
309
 
465
- Trusted-publishing npm examples use provenance and `verifyPackageExists`. The
466
- `npm-first-publish` example intentionally stays token-based because npm trusted
467
- publishing can only be configured after the package already exists.
310
+ Templates with `artifactRecipes` need an explicit staging step before target
311
+ planning expects the generated files to exist:
312
+
313
+ ```sh
314
+ bun run cli stage-artifacts --config release.config.json --format text
315
+ ```
468
316
 
469
317
  ## Evidence
470
318
 
471
- Render, validation, execution, and verification evidence is written as JSON bundles. Failed commands still preserve partial evidence before the command failure is returned. Use `evidenceDirectory` such as `.release/evidence/{version}` when older local evidence should not collide with the current release version.
319
+ Validation, rendering, execution, reconciliation, and verification write JSON
320
+ evidence bundles. Primitive commands write named files such as
321
+ `validation.json`; the full `run` workflow writes `evidence.json`.
472
322
 
473
323
  ```json
474
324
  {
@@ -479,126 +329,54 @@ Render, validation, execution, and verification evidence is written as JSON bund
479
329
  {
480
330
  "id": "npm:npm-pack-dry-run:command",
481
331
  "operationId": "npm:npm-pack-dry-run",
482
- "operationFingerprint": "{\"_tag\":\"ValidateCommandOperation\",\"id\":\"npm:npm-pack-dry-run\",\"targetId\":\"npm\",\"approval\":{\"requiresExecute\":false,\"requiresIrreversibleApproval\":false},\"command\":{\"executable\":\"npm\",\"args\":[\"pack\",\"--dry-run\",\"--json\"],\"requiredEnv\":[],\"redactedEnv\":[]}}",
332
+ "phase": "validation",
333
+ "targetId": "npm",
334
+ "risk": "read-only",
483
335
  "status": "passed",
484
336
  "severity": "info",
337
+ "message": "npm pack dry run passed.",
338
+ "startedAt": "2026-01-01T00:00:00.000Z",
339
+ "endedAt": "2026-01-01T00:00:00.100Z",
340
+ "durationMillis": 100,
341
+ "command": "npm pack --dry-run --json",
485
342
  "exitCode": 0
486
343
  }
487
344
  ]
488
345
  }
489
346
  ```
490
347
 
491
- Non-strict mode records missing validators as visible skipped evidence instead of silently dropping them.
492
-
493
- ## Readiness
494
-
495
- Normal verification stays deterministic and does not require live external services:
496
-
497
- ```sh
498
- bun run check:release
499
- ```
500
-
501
- CI runs the portable package checks on Linux, macOS, and Windows. The release
502
- gate runs the self-release config guard, the static self-release CI diagnostic,
503
- and then the portable checks.
504
-
505
- Real-tool integration checks are opt-in:
506
-
507
- ```sh
508
- bun run test:integration:tools
509
- RELEASE_INTEGRATION_GITHUB=1 bun run test:integration:tools
510
- ```
511
-
512
- The first command validates npm adapter operations against the real `npm` CLI. The second also validates GitHub adapter readiness checks against the real `gh` CLI and requires `gh auth status` to succeed. GitHub release creation itself has no native dry-run; release validation is simulated from the deterministic plan before publish and verified against GitHub only after publish.
348
+ Failed commands preserve partial evidence when possible. Non-strict mode records
349
+ missing validators as visible skipped evidence instead of silently dropping them.
513
350
 
514
- Example configs and templates are checked through the TypeScript workflow path:
351
+ ## Reconciliation
515
352
 
516
- ```sh
517
- bun run check:examples
518
- ```
353
+ `reconcile` is a narrow repair path for GitHub Releases. It reads the release by
354
+ tag, blocks on mismatched metadata or assets, skips an already matching
355
+ published release, and can publish a matching draft with `--execute`.
519
356
 
520
- This repository also includes a self-release config at `apps/release-ts/release.config.json` that targets both npm and GitHub for the scoped `@mannyc1/ts-release` package. The app-owned self-release scripts live under `apps/release-ts/scripts`, with root package scripts delegating to them. The self-release config must pass `bun run check:self-release-config`, and the workflow must pass `bun run check:self-release-ci`, before portable release checks proceed. It derives name and version from the root `package.json`, uses `{version}` artifact templates, and keeps `identity.commit` as `HEAD` for stored-config convenience. Generated plans resolve `HEAD` to the current short commit, and the self-release guard requires a committed Git checkout with clean tracked files.
357
+ It does not replay immutable registry publishes:
521
358
 
522
359
  ```sh
523
- bun run check:self-release-config
524
- bun run check:self-release-ci
360
+ bun run cli reconcile --config release.config.json --execute
525
361
  ```
526
362
 
527
- ### Self Release
363
+ ## Repository Checks
528
364
 
529
- The local non-publish gates for this package are:
365
+ Use Bun for package management, scripts, and tests:
530
366
 
531
367
  ```sh
532
368
  bun run check:release
533
- bun run release:artifacts
534
- bun run cli plan --config apps/release-ts/release.config.json --format text
535
- bun run --cwd apps/release-ts cli plan --root ../.. --config apps/release-ts/release.config.json --format text
536
- ```
537
-
538
- `release:artifacts` delegates to `apps/release-ts/scripts/build-release-artifacts.ts` and writes ignored files under `.release/artifacts`: the npm package tarball and standalone CLI executables for Linux, macOS, and Windows. GitHub Actions runs on protected `main` and checks release eligibility before the full release gate. When `should_release` is true, the plan job runs `check:release`, builds artifacts, records a Markdown release plan, uploads evidence, and does not execute release operations. The protected `execute` job uses the reviewed `.release/artifacts` download, grants `contents: write` and `id-token: write`, and runs approved execution with npm trusted publishing OIDC instead of an npm token.
539
-
540
- ### Local Release Auth
541
-
542
- Use `.env.example` as the local credential contract. Export `GH_TOKEN`, or copy
543
- `.env.example` to `.env` and fill in token values locally. `.env` and `.npmrc`
544
- are ignored intentionally; keep token values out of commits. `.npmrc.example`
545
- shows npm's `${NPM_TOKEN}` interpolation form for token-based npm targets.
546
- `TWINE_USERNAME` and `TWINE_PASSWORD` are only needed for PyPI/Twine examples.
547
-
548
- For npmjs releases from GitHub Actions, prefer structured `trustedPublishing` on
549
- the npm target:
550
-
551
- ```json
552
- {
553
- "packageName": "@mannyc1/ts-release",
554
- "trustedPublishing": {
555
- "provider": "github-actions",
556
- "workflow": "release.yml",
557
- "packageExists": true,
558
- "verifyPackageExists": true
559
- },
560
- "access": "public",
561
- "provenance": true
562
- }
369
+ bun run check:examples
370
+ bun run check:readme
563
371
  ```
564
372
 
565
- Trusted publishing authenticates during `npm publish` with CI OIDC, so
566
- `ts-release` records that mode in validation evidence instead of running
567
- `npm whoami`, which does not validate OIDC publishing. Configure npmjs trusted
568
- publishing for an existing package and use a GitHub-hosted runner with
569
- `id-token: write`, Node 22.14+ and npm 11.5.1+. The `packageExists` field must be
570
- `true` as a precondition acknowledgement, not first-publish support. Setting
571
- `verifyPackageExists` to `true` adds a read-only `npm view <package>` validation
572
- check. Trusted publishing does not use `NPM_TOKEN` for `npm publish`; token-based
573
- npm targets may still use `.npmrc.example` and `NPM_TOKEN`.
574
-
575
- Diagnostics stay static by default and report confidence instead of pretending
576
- local checks prove provider setup:
373
+ Real-tool integration checks are opt-in:
577
374
 
578
375
  ```sh
579
- bun run cli check-auth --config release.config.json --format text
580
- bun run cli check-ci --config release.config.json --workflow .github/workflows/release.yml --format markdown
581
- bun run cli doctor --config release.config.json --format json
376
+ bun run test:integration:tools
377
+ RELEASE_INTEGRATION_GITHUB=1 bun run test:integration:tools
582
378
  ```
583
379
 
584
- The reusable GitHub Actions trusted-publishing workflow template lives at
585
- `templates/github-actions/trusted-publishing.yml`. It uses
586
- `mannyc2/ts-release-action@v1` to record a Markdown plan, uploads review
587
- artifacts, and requires a protected `release` environment before running
588
- approved execution. npm trusted publishing uses OIDC, not `NPM_TOKEN`;
589
- `GH_TOKEN` is for GitHub Releases and API verification.
590
-
591
- ### First npm Publish Bootstrap
592
-
593
- Trusted publishing is the preferred steady state for GitHub Actions, but npm
594
- requires the package to exist before trusted publishing can be configured. For a
595
- new package, use a temporary token-based npm target with `tokenEnv: "NPM_TOKEN"`
596
- and no `trustedPublishing` object. After the first version exists on npm,
597
- configure npm trusted publishing for owner `mannyc2`, repository `ts-release`,
598
- and workflow filename `release.yml`, then switch the target to
599
- `trustedPublishing`.
600
-
601
- Do not commit token values. Keep `.env.example` and `.npmrc.example` as
602
- placeholder contracts only.
603
-
604
- The first-release GitHub target uses `GH_TOKEN` for both `gh` command authentication and read-only REST API verification. The release workflow sets up a current Node/npm toolchain for trusted publishing and enables npm provenance for CI-based publishes where the registry can generate provenance.
380
+ See `ARCHITECTURE.md` for module boundaries, `SPEC.md` for the design contract,
381
+ `templates/README.md` for starter configs, and `examples/README.md` for runnable
382
+ fixtures.