@cleocode/contracts 2026.5.78 → 2026.5.79
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/dist/exit-codes.d.ts +41 -0
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +52 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/operations/worktree.d.ts +251 -0
- package/dist/operations/worktree.d.ts.map +1 -1
- package/dist/release/plan.d.ts +533 -0
- package/dist/release/plan.d.ts.map +1 -0
- package/dist/release/plan.js +393 -0
- package/dist/release/plan.js.map +1 -0
- package/dist/release/plan.test.d.ts +17 -0
- package/dist/release/plan.test.d.ts.map +1 -0
- package/dist/release/plan.test.js +414 -0
- package/dist/release/plan.test.js.map +1 -0
- package/dist/tasks/archive.d.ts +3 -3
- package/package.json +2 -2
- package/src/exit-codes.ts +54 -0
- package/src/index.ts +79 -0
- package/src/operations/worktree.ts +274 -0
- package/src/release/plan.test.ts +501 -0
- package/src/release/plan.ts +493 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release Plan contracts — canonical Zod schema for `.cleo/release/<version>.plan.json`.
|
|
3
|
+
*
|
|
4
|
+
* The plan file is the source-of-truth state record for a release as it moves
|
|
5
|
+
* through the canonical FSM:
|
|
6
|
+
*
|
|
7
|
+
* planned → pr-opened → pr-merged → published → reconciled
|
|
8
|
+
*
|
|
9
|
+
* Off-ramp terminal states: `rolled_back`, `failed`, `cancelled`.
|
|
10
|
+
*
|
|
11
|
+
* This module defines the normative shape per SPEC-T9345 §6.1/§6.2. Consumers:
|
|
12
|
+
*
|
|
13
|
+
* - `cleo release plan` (T9525) — INSERTs status=planned
|
|
14
|
+
* - `cleo release open` (T9525) — UPDATEs status=pr-opened
|
|
15
|
+
* - `cleo release reconcile` (T9526) — re-validates and UPDATEs status=reconciled
|
|
16
|
+
*
|
|
17
|
+
* The schema is permissive on `evidenceAtoms` (length-zero arrays are
|
|
18
|
+
* structurally valid) — the non-empty invariant (R-301) is enforced by the
|
|
19
|
+
* verb implementations, not the contract, so backfill / migration tooling can
|
|
20
|
+
* load historical plans without contract-level rejection.
|
|
21
|
+
*
|
|
22
|
+
* @task T9527
|
|
23
|
+
* @epic T9492
|
|
24
|
+
* @adr ADR-T9345 (IVTR-release-overhaul)
|
|
25
|
+
* @spec .cleo/rcasd/T9345/research/SPEC-T9345-release-pipeline-v2.md §6
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
// ─── Schema version ──────────────────────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Semantic version of the Release Plan contract.
|
|
31
|
+
*
|
|
32
|
+
* Increment the MAJOR component on incompatible field renames or removals.
|
|
33
|
+
* Increment MINOR on additive optional-field changes. The plan JSON `$schema`
|
|
34
|
+
* URL is keyed off the MAJOR component (`/release-plan/v1.json` for `1.x.y`).
|
|
35
|
+
*/
|
|
36
|
+
export const RELEASE_PLAN_SCHEMA_VERSION = '1.0.0';
|
|
37
|
+
/**
|
|
38
|
+
* Canonical `$schema` URL embedded in plan files at write time. Consumers MAY
|
|
39
|
+
* use this string to identify the contract version when parsing legacy plans.
|
|
40
|
+
*/
|
|
41
|
+
export const RELEASE_PLAN_SCHEMA_URL = 'https://cleocode.io/schemas/release-plan/v1.json';
|
|
42
|
+
// ─── Enum literal tuples (exported for external introspection) ───────────────
|
|
43
|
+
/**
|
|
44
|
+
* Canonical npm dist-tag channels supported by the release pipeline.
|
|
45
|
+
*
|
|
46
|
+
* Includes `rc` in addition to the legacy `latest|beta|alpha` triple to allow
|
|
47
|
+
* release candidates without conflating with `beta` per SPEC §6.1.
|
|
48
|
+
*/
|
|
49
|
+
export const RELEASE_CHANNEL = ['latest', 'beta', 'alpha', 'rc'];
|
|
50
|
+
/**
|
|
51
|
+
* Version-scheme variants. `calver-suffix` is the hotfix grammar
|
|
52
|
+
* `vYYYY.M.DD.N` per SPEC R-402.
|
|
53
|
+
*/
|
|
54
|
+
export const RELEASE_SCHEME = ['calver', 'semver', 'calver-suffix'];
|
|
55
|
+
/**
|
|
56
|
+
* Release-kind classification. `hotfix` triggers the scope-strict completeness
|
|
57
|
+
* path per SPEC R-401; `prerelease` allows non-`latest` channels.
|
|
58
|
+
*/
|
|
59
|
+
export const RELEASE_KIND = ['regular', 'hotfix', 'prerelease'];
|
|
60
|
+
/**
|
|
61
|
+
* Lifecycle FSM states for a release plan. Ordered for documentation only —
|
|
62
|
+
* the runtime FSM enforces monotonic forward progress per SPEC R-302.
|
|
63
|
+
*/
|
|
64
|
+
export const RELEASE_STATUS = [
|
|
65
|
+
'planned',
|
|
66
|
+
'pr-opened',
|
|
67
|
+
'pr-merged',
|
|
68
|
+
'published',
|
|
69
|
+
'reconciled',
|
|
70
|
+
'rolled_back',
|
|
71
|
+
'failed',
|
|
72
|
+
'cancelled',
|
|
73
|
+
];
|
|
74
|
+
/**
|
|
75
|
+
* Gate verification status. `unresolved` indicates ADR-061's resolver could
|
|
76
|
+
* not produce a command for the project archetype (SPEC R-304).
|
|
77
|
+
*/
|
|
78
|
+
export const GATE_STATUS = ['passed', 'failed', 'skipped', 'unresolved'];
|
|
79
|
+
/**
|
|
80
|
+
* Canonical gate names recognized by the release pipeline. Mirrors the
|
|
81
|
+
* ADR-051 / ADR-061 evidence-atom canonical names (R-310).
|
|
82
|
+
*/
|
|
83
|
+
export const GATE_NAME = ['test', 'build', 'lint', 'typecheck', 'audit', 'security-scan'];
|
|
84
|
+
/**
|
|
85
|
+
* Platform tuples used by the release matrix per T1737 alignment (R-370).
|
|
86
|
+
*
|
|
87
|
+
* `any` collapses single platform-agnostic artifacts (R-371).
|
|
88
|
+
*/
|
|
89
|
+
export const PLATFORM_TUPLE = [
|
|
90
|
+
'linux-x64',
|
|
91
|
+
'linux-arm64',
|
|
92
|
+
'macos-x64',
|
|
93
|
+
'macos-arm64',
|
|
94
|
+
'windows-x64',
|
|
95
|
+
'any',
|
|
96
|
+
];
|
|
97
|
+
/**
|
|
98
|
+
* Supported publisher backends — the registries / distribution channels the
|
|
99
|
+
* release matrix may target.
|
|
100
|
+
*/
|
|
101
|
+
export const PUBLISHER = ['npm', 'cargo', 'docker', 'pypi', 'github-release', 'binary'];
|
|
102
|
+
/**
|
|
103
|
+
* Conventional-commit-aligned task classification used to slot tasks into the
|
|
104
|
+
* changelog `features` / `fixes` / `chores` / `breaking` buckets (§6.1).
|
|
105
|
+
*/
|
|
106
|
+
export const TASK_KIND = [
|
|
107
|
+
'feat',
|
|
108
|
+
'fix',
|
|
109
|
+
'chore',
|
|
110
|
+
'docs',
|
|
111
|
+
'refactor',
|
|
112
|
+
'test',
|
|
113
|
+
'perf',
|
|
114
|
+
'revert',
|
|
115
|
+
'breaking',
|
|
116
|
+
'hotfix',
|
|
117
|
+
];
|
|
118
|
+
/**
|
|
119
|
+
* SemVer-impact classification per task. The plan-time aggregate determines
|
|
120
|
+
* the release scheme bump when scheme=`semver` (informational under `calver`).
|
|
121
|
+
*/
|
|
122
|
+
export const IMPACT = ['major', 'minor', 'patch'];
|
|
123
|
+
/**
|
|
124
|
+
* Source attribution for resolved tool commands. Mirrors ADR-061 §1 surfaces.
|
|
125
|
+
*/
|
|
126
|
+
export const RESOLVED_SOURCE = ['project-context', 'language-default', 'legacy-alias'];
|
|
127
|
+
// ─── Enum schemas ────────────────────────────────────────────────────────────
|
|
128
|
+
/** Zod schema for {@link RELEASE_CHANNEL}. */
|
|
129
|
+
export const ReleaseChannelSchema = z.enum(RELEASE_CHANNEL);
|
|
130
|
+
/** Zod schema for {@link RELEASE_SCHEME}. */
|
|
131
|
+
export const ReleaseSchemeSchema = z.enum(RELEASE_SCHEME);
|
|
132
|
+
/** Zod schema for {@link RELEASE_KIND}. */
|
|
133
|
+
export const ReleaseKindSchema = z.enum(RELEASE_KIND);
|
|
134
|
+
/** Zod schema for {@link RELEASE_STATUS}. */
|
|
135
|
+
export const ReleaseStatusSchema = z.enum(RELEASE_STATUS);
|
|
136
|
+
/** Zod schema for {@link GATE_STATUS}. */
|
|
137
|
+
export const GateStatusSchema = z.enum(GATE_STATUS);
|
|
138
|
+
/** Zod schema for {@link GATE_NAME}. */
|
|
139
|
+
export const GateNameSchema = z.enum(GATE_NAME);
|
|
140
|
+
/** Zod schema for {@link PLATFORM_TUPLE}. */
|
|
141
|
+
export const PlatformTupleSchema = z.enum(PLATFORM_TUPLE);
|
|
142
|
+
/** Zod schema for {@link PUBLISHER}. */
|
|
143
|
+
export const PublisherSchema = z.enum(PUBLISHER);
|
|
144
|
+
/** Zod schema for {@link TASK_KIND}. */
|
|
145
|
+
export const TaskKindSchema = z.enum(TASK_KIND);
|
|
146
|
+
/** Zod schema for {@link IMPACT}. */
|
|
147
|
+
export const ImpactSchema = z.enum(IMPACT);
|
|
148
|
+
/** Zod schema for {@link RESOLVED_SOURCE}. */
|
|
149
|
+
export const ResolvedSourceSchema = z.enum(RESOLVED_SOURCE);
|
|
150
|
+
// ─── Field-level constraint helpers ──────────────────────────────────────────
|
|
151
|
+
/**
|
|
152
|
+
* ISO-8601 timestamp constraint. Accepts the subset Zod's `z.iso.datetime()`
|
|
153
|
+
* validates — RFC-3339 with optional fractional seconds and required offset.
|
|
154
|
+
*/
|
|
155
|
+
const Iso8601 = z.iso.datetime({ offset: true });
|
|
156
|
+
/**
|
|
157
|
+
* Non-empty trimmed string. Used for required text fields like task IDs and
|
|
158
|
+
* user-facing summaries to reject pure whitespace.
|
|
159
|
+
*/
|
|
160
|
+
const NonEmptyString = z.string().min(1);
|
|
161
|
+
// ─── Nested schemas ──────────────────────────────────────────────────────────
|
|
162
|
+
/**
|
|
163
|
+
* Zod schema for one task row in `plan.tasks[]`. Mirrors the SPEC §6.1 task
|
|
164
|
+
* shape exactly. `evidenceAtoms` is a permissive `string[]` — verbs enforce
|
|
165
|
+
* non-empty per R-301; the contract permits empty arrays so legacy plans
|
|
166
|
+
* remain parseable.
|
|
167
|
+
*
|
|
168
|
+
* `epicAncestor` is locked at plan time (R-303) and MUST NOT be re-derived
|
|
169
|
+
* by downstream consumers.
|
|
170
|
+
*
|
|
171
|
+
* `ivtrPhaseAtPlan` is informational only (R-316) — consumers MUST NOT
|
|
172
|
+
* gate decisions on its value.
|
|
173
|
+
*/
|
|
174
|
+
export const ReleasePlanTaskSchema = z.object({
|
|
175
|
+
/** Task ID (e.g. "T10001"). Format intentionally loose so historical IDs validate. */
|
|
176
|
+
id: NonEmptyString,
|
|
177
|
+
/** Conventional-commit-aligned task classification. */
|
|
178
|
+
kind: TaskKindSchema,
|
|
179
|
+
/** SemVer impact classification. */
|
|
180
|
+
impact: ImpactSchema,
|
|
181
|
+
/** Human-readable changelog line for this task. */
|
|
182
|
+
userFacingSummary: z.string(),
|
|
183
|
+
/**
|
|
184
|
+
* ADR-051 evidence atoms attesting the task's gate results. Format is
|
|
185
|
+
* `kind:value` (e.g. `commit:abc123`, `test-run:vitest.json`). The contract
|
|
186
|
+
* accepts empty arrays so legacy plans validate; `cleo release plan`
|
|
187
|
+
* enforces non-empty via R-301.
|
|
188
|
+
*/
|
|
189
|
+
evidenceAtoms: z.array(NonEmptyString),
|
|
190
|
+
/** IVTR phase at plan time — informational only per R-316. */
|
|
191
|
+
ivtrPhaseAtPlan: z.string().optional(),
|
|
192
|
+
/** Epic this task rolls up to, locked at plan time per R-303. */
|
|
193
|
+
epicAncestor: NonEmptyString,
|
|
194
|
+
});
|
|
195
|
+
/**
|
|
196
|
+
* Zod schema for one gate row in `plan.gates[]`. Each gate carries the
|
|
197
|
+
* resolved ADR-061 tool command + source attribution for forensic re-runs.
|
|
198
|
+
*/
|
|
199
|
+
export const ReleaseGateSchema = z.object({
|
|
200
|
+
/** Canonical gate name. */
|
|
201
|
+
name: GateNameSchema,
|
|
202
|
+
/** ADR-051 atom string identifying the resolved tool (e.g. `tool:test`). */
|
|
203
|
+
atom: NonEmptyString,
|
|
204
|
+
/** Gate execution status at plan time. */
|
|
205
|
+
status: GateStatusSchema,
|
|
206
|
+
/** ISO-8601 timestamp the gate was last verified. */
|
|
207
|
+
lastVerifiedAt: Iso8601,
|
|
208
|
+
/** Resolved shell command (e.g. `pnpm run test`). Optional for unresolved gates. */
|
|
209
|
+
resolvedCommand: z.string().optional(),
|
|
210
|
+
/** Provenance of the resolved command. Optional for unresolved gates. */
|
|
211
|
+
resolvedSource: ResolvedSourceSchema.optional(),
|
|
212
|
+
});
|
|
213
|
+
/**
|
|
214
|
+
* Zod schema for one row in `plan.platformMatrix[]`. Each entry encodes a
|
|
215
|
+
* (platform-tuple, publisher) pair the release will produce per R-370.
|
|
216
|
+
*
|
|
217
|
+
* `smoke` defaults to `true`; archetypes that produce platform-agnostic
|
|
218
|
+
* artifacts MAY set `false` to skip per-platform smoke tests (R-371).
|
|
219
|
+
*/
|
|
220
|
+
export const ReleasePlatformMatrixEntrySchema = z.object({
|
|
221
|
+
/** Target platform tuple. */
|
|
222
|
+
platform: PlatformTupleSchema,
|
|
223
|
+
/** Distribution backend. */
|
|
224
|
+
publisher: PublisherSchema,
|
|
225
|
+
/** Package identifier on the target backend (e.g. `@cleocode/cleo`). */
|
|
226
|
+
package: NonEmptyString,
|
|
227
|
+
/** Whether to run the GHA smoke job for this matrix entry. */
|
|
228
|
+
smoke: z.boolean().default(true).optional(),
|
|
229
|
+
});
|
|
230
|
+
/**
|
|
231
|
+
* Zod schema for `plan.preflightSummary`. Captures the four preflight checks
|
|
232
|
+
* runs by `cleo release plan` (R-024 / R-261).
|
|
233
|
+
*/
|
|
234
|
+
export const ReleasePreflightSummarySchema = z.object({
|
|
235
|
+
/** True if esbuild externals are out of sync with package.json. */
|
|
236
|
+
esbuildExternalsDrift: z.boolean(),
|
|
237
|
+
/** True if `pnpm-lock.yaml` diverges from the workspace manifest. */
|
|
238
|
+
lockfileDrift: z.boolean(),
|
|
239
|
+
/** True if all epic children are in terminal lifecycle states. */
|
|
240
|
+
epicCompletenessClean: z.boolean(),
|
|
241
|
+
/** True if no task appears in multiple in-flight release plans. */
|
|
242
|
+
doubleListingClean: z.boolean(),
|
|
243
|
+
/** Non-fatal preflight warnings (e.g. unresolved tools per R-024). */
|
|
244
|
+
preflightWarnings: z.array(z.string()).default([]).optional(),
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* Zod schema for `plan.changelog`. Tasks are bucketed by `kind` into the four
|
|
248
|
+
* canonical changelog sections; each section holds an array of task IDs
|
|
249
|
+
* preserving plan-time ordering.
|
|
250
|
+
*/
|
|
251
|
+
export const ReleasePlanChangelogSchema = z.object({
|
|
252
|
+
/** `kind=feat` tasks. */
|
|
253
|
+
features: z.array(NonEmptyString).default([]),
|
|
254
|
+
/** `kind=fix` or `kind=hotfix` tasks. */
|
|
255
|
+
fixes: z.array(NonEmptyString).default([]),
|
|
256
|
+
/** `kind=chore`, `docs`, `refactor`, `test`, `perf` tasks. */
|
|
257
|
+
chores: z.array(NonEmptyString).default([]),
|
|
258
|
+
/** `kind=breaking` or `kind=revert` tasks. */
|
|
259
|
+
breaking: z.array(NonEmptyString).default([]),
|
|
260
|
+
});
|
|
261
|
+
/**
|
|
262
|
+
* Zod schema for `plan.meta` — open-ended bag of informational fields.
|
|
263
|
+
*
|
|
264
|
+
* The catchall is `z.unknown()` (forward-compat: parsers MUST NOT reject
|
|
265
|
+
* fields the contract does not yet recognize) per ADR-039 envelope discipline.
|
|
266
|
+
*
|
|
267
|
+
* Documented keys:
|
|
268
|
+
*
|
|
269
|
+
* - `firstEverRelease` (R-023) — escape hatch for the first ever
|
|
270
|
+
* release where `previousVersion` is `null`.
|
|
271
|
+
* - `unresolvedTools` (R-024) — canonical tool names whose
|
|
272
|
+
* resolution failed during planning.
|
|
273
|
+
* - `archetype` (R-361) — detected project archetype string.
|
|
274
|
+
*/
|
|
275
|
+
export const ReleasePlanMetaSchema = z
|
|
276
|
+
.object({
|
|
277
|
+
/** True if this is the project's first ever release. */
|
|
278
|
+
firstEverRelease: z.boolean().optional(),
|
|
279
|
+
/** Canonical tool names that could not be resolved at plan time. */
|
|
280
|
+
unresolvedTools: z.array(z.string()).optional(),
|
|
281
|
+
/** Project archetype detected at plan time. */
|
|
282
|
+
archetype: z.string().optional(),
|
|
283
|
+
})
|
|
284
|
+
.catchall(z.unknown());
|
|
285
|
+
// ─── Top-level schema ────────────────────────────────────────────────────────
|
|
286
|
+
/**
|
|
287
|
+
* Canonical Zod schema for the entire `.cleo/release/<version>.plan.json`
|
|
288
|
+
* envelope. Mirrors SPEC-T9345 §6.1 1:1.
|
|
289
|
+
*
|
|
290
|
+
* Schema invariants enforced by this schema:
|
|
291
|
+
*
|
|
292
|
+
* - All enum fields reject unknown literal values (R-302 / R-304).
|
|
293
|
+
* - `tasks[]` MUST contain only fully-typed task rows (R-303 / R-316).
|
|
294
|
+
* - `gates[]` MUST contain only canonical gate names (R-310).
|
|
295
|
+
* - `platformMatrix[]` MUST be a homogeneous array of entry rows (R-370).
|
|
296
|
+
*
|
|
297
|
+
* Schema invariants enforced by VERBS (NOT this schema):
|
|
298
|
+
*
|
|
299
|
+
* - R-300: `previousVersion` non-null unless `meta.firstEverRelease=true`.
|
|
300
|
+
* - R-301: `tasks[*].evidenceAtoms` non-empty.
|
|
301
|
+
* - R-305: `platformMatrix[]` non-empty.
|
|
302
|
+
* - R-306: deterministic re-validation inside `open` and `reconcile`.
|
|
303
|
+
*/
|
|
304
|
+
export const ReleasePlanSchema = z.object({
|
|
305
|
+
/** Schema URL for this plan version. */
|
|
306
|
+
$schema: z.string().optional(),
|
|
307
|
+
/** Requested version string (e.g. "v2026.6.0"). Includes the leading `v`. */
|
|
308
|
+
version: NonEmptyString,
|
|
309
|
+
/** Resolved version string after suffix application (e.g. "v2026.6.0.2"). */
|
|
310
|
+
resolvedVersion: NonEmptyString,
|
|
311
|
+
/** True if a `calver-suffix` was applied to disambiguate a same-day hotfix. */
|
|
312
|
+
suffixApplied: z.boolean(),
|
|
313
|
+
/** Versioning scheme governing `version` / `resolvedVersion`. */
|
|
314
|
+
scheme: ReleaseSchemeSchema,
|
|
315
|
+
/** npm dist-tag channel for this release. */
|
|
316
|
+
channel: ReleaseChannelSchema,
|
|
317
|
+
/** Epic ID this release ships. */
|
|
318
|
+
epicId: NonEmptyString,
|
|
319
|
+
/** Release-kind classification. */
|
|
320
|
+
releaseKind: ReleaseKindSchema,
|
|
321
|
+
/** ISO-8601 timestamp the plan was written. */
|
|
322
|
+
createdAt: Iso8601,
|
|
323
|
+
/** Identifier of the actor that wrote the plan (agent name or operator). */
|
|
324
|
+
createdBy: NonEmptyString,
|
|
325
|
+
/**
|
|
326
|
+
* Version of the previous release on the same channel. MUST be `null` only
|
|
327
|
+
* for first-ever releases (R-300, enforced at the verb layer).
|
|
328
|
+
*/
|
|
329
|
+
previousVersion: z.string().nullable(),
|
|
330
|
+
/** Git tag of the previous release (typically `previousVersion` prefixed). */
|
|
331
|
+
previousTag: z.string().nullable(),
|
|
332
|
+
/** ISO-8601 timestamp the previous release was published. */
|
|
333
|
+
previousShippedAt: Iso8601.nullable(),
|
|
334
|
+
/** Tasks rolled into this release. */
|
|
335
|
+
tasks: z.array(ReleasePlanTaskSchema),
|
|
336
|
+
/** Bucketed changelog. */
|
|
337
|
+
changelog: ReleasePlanChangelogSchema,
|
|
338
|
+
/** Per-gate verification status. */
|
|
339
|
+
gates: z.array(ReleaseGateSchema),
|
|
340
|
+
/** Platform / publisher matrix. */
|
|
341
|
+
platformMatrix: z.array(ReleasePlatformMatrixEntrySchema),
|
|
342
|
+
/** Preflight summary from `cleo release plan`. */
|
|
343
|
+
preflightSummary: ReleasePreflightSummarySchema,
|
|
344
|
+
/** URL of the GHA workflow run (populated by `release-prepare.yml`). */
|
|
345
|
+
workflowRunUrl: z.string().nullable(),
|
|
346
|
+
/** URL of the bump PR (populated by `cleo release open`). */
|
|
347
|
+
prUrl: z.string().nullable(),
|
|
348
|
+
/** Merge commit SHA on `main` (populated by `release-publish.yml`). */
|
|
349
|
+
mergeCommitSha: z.string().nullable(),
|
|
350
|
+
/** Current FSM state per R-302. */
|
|
351
|
+
status: ReleaseStatusSchema,
|
|
352
|
+
/** Informational / forward-compat metadata. */
|
|
353
|
+
meta: ReleasePlanMetaSchema.optional(),
|
|
354
|
+
});
|
|
355
|
+
// ─── Parse helper ────────────────────────────────────────────────────────────
|
|
356
|
+
/**
|
|
357
|
+
* Parse and validate a raw JSON value as a {@link ReleasePlan}.
|
|
358
|
+
*
|
|
359
|
+
* Throws `ZodError` on any structural mismatch with detailed `.issues[]`
|
|
360
|
+
* pinpointing every offending field path. Callers SHOULD surface those issues
|
|
361
|
+
* via the LAFS `error.details` field for operator triage.
|
|
362
|
+
*
|
|
363
|
+
* Use {@link safeParseReleasePlan} if you prefer the non-throwing variant.
|
|
364
|
+
*
|
|
365
|
+
* @param input — Untyped value loaded from disk / wire / database.
|
|
366
|
+
* @returns The validated, fully-typed plan object.
|
|
367
|
+
* @throws ZodError when validation fails.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* import { readFileSync } from 'node:fs';
|
|
372
|
+
* import { parseReleasePlan } from '@cleocode/contracts';
|
|
373
|
+
*
|
|
374
|
+
* const raw = JSON.parse(readFileSync('.cleo/release/v2026.6.0.plan.json', 'utf8'));
|
|
375
|
+
* const plan = parseReleasePlan(raw);
|
|
376
|
+
* console.log(plan.status); // type-narrowed to ReleaseStatus
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
export function parseReleasePlan(input) {
|
|
380
|
+
return ReleasePlanSchema.parse(input);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Safe variant of {@link parseReleasePlan} that returns a discriminated-union
|
|
384
|
+
* result instead of throwing. Useful when validating user-supplied or
|
|
385
|
+
* persisted plans where structured error reporting is required.
|
|
386
|
+
*
|
|
387
|
+
* @param input — Untyped value to validate.
|
|
388
|
+
* @returns Zod safe-parse result.
|
|
389
|
+
*/
|
|
390
|
+
export function safeParseReleasePlan(input) {
|
|
391
|
+
return ReleasePlanSchema.safeParse(input);
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/release/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,OAAO,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,kDAAkD,CAAC;AAE1F,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAU,CAAC;AAE1E;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAU,CAAC;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAU,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,aAAa;IACb,QAAQ;IACR,WAAW;CACH,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAU,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,CAAU,CAAC;AAEnG;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW;IACX,aAAa;IACb,WAAW;IACX,aAAa;IACb,aAAa;IACb,KAAK;CACG,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,CAAU,CAAC;AAEjG;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,MAAM;IACN,KAAK;IACL,OAAO;IACP,MAAM;IACN,UAAU;IACV,MAAM;IACN,MAAM;IACN,QAAQ;IACR,UAAU;IACV,QAAQ;CACA,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,cAAc,CAAU,CAAC;AAEhG,gFAAgF;AAEhF,8CAA8C;AAC9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE5D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAE1D,2CAA2C;AAC3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AAEtD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAE1D,0CAA0C;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAEpD,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEhD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAE1D,wCAAwC;AACxC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEjD,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEhD,qCAAqC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAE3C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE5D,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAEjD;;;GAGG;AACH,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEzC,gFAAgF;AAEhF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,sFAAsF;IACtF,EAAE,EAAE,cAAc;IAClB,uDAAuD;IACvD,IAAI,EAAE,cAAc;IACpB,oCAAoC;IACpC,MAAM,EAAE,YAAY;IACpB,mDAAmD;IACnD,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IACtC,8DAA8D;IAC9D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,iEAAiE;IACjE,YAAY,EAAE,cAAc;CAC7B,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,2BAA2B;IAC3B,IAAI,EAAE,cAAc;IACpB,4EAA4E;IAC5E,IAAI,EAAE,cAAc;IACpB,0CAA0C;IAC1C,MAAM,EAAE,gBAAgB;IACxB,qDAAqD;IACrD,cAAc,EAAE,OAAO;IACvB,oFAAoF;IACpF,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,yEAAyE;IACzE,cAAc,EAAE,oBAAoB,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,6BAA6B;IAC7B,QAAQ,EAAE,mBAAmB;IAC7B,4BAA4B;IAC5B,SAAS,EAAE,eAAe;IAC1B,wEAAwE;IACxE,OAAO,EAAE,cAAc;IACvB,8DAA8D;IAC9D,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,mEAAmE;IACnE,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE;IAClC,qEAAqE;IACrE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE;IAC1B,kEAAkE;IAClE,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE;IAClC,mEAAmE;IACnE,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE;IAC/B,sEAAsE;IACtE,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC9D,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,yBAAyB;IACzB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,yCAAyC;IACzC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,8DAA8D;IAC9D,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3C,8CAA8C;IAC9C,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC9C,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,wDAAwD;IACxD,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACxC,oEAAoE;IACpE,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC/C,+CAA+C;IAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEzB,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,wCAAwC;IACxC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,6EAA6E;IAC7E,OAAO,EAAE,cAAc;IACvB,6EAA6E;IAC7E,eAAe,EAAE,cAAc;IAC/B,+EAA+E;IAC/E,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE;IAC1B,iEAAiE;IACjE,MAAM,EAAE,mBAAmB;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,oBAAoB;IAC7B,kCAAkC;IAClC,MAAM,EAAE,cAAc;IACtB,mCAAmC;IACnC,WAAW,EAAE,iBAAiB;IAC9B,+CAA+C;IAC/C,SAAS,EAAE,OAAO;IAClB,4EAA4E;IAC5E,SAAS,EAAE,cAAc;IACzB;;;OAGG;IACH,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,8EAA8E;IAC9E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,6DAA6D;IAC7D,iBAAiB,EAAE,OAAO,CAAC,QAAQ,EAAE;IACrC,sCAAsC;IACtC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC;IACrC,0BAA0B;IAC1B,SAAS,EAAE,0BAA0B;IACrC,oCAAoC;IACpC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACjC,mCAAmC;IACnC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,gCAAgC,CAAC;IACzD,kDAAkD;IAClD,gBAAgB,EAAE,6BAA6B;IAC/C,wEAAwE;IACxE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,6DAA6D;IAC7D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,uEAAuE;IACvE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,mCAAmC;IACnC,MAAM,EAAE,mBAAmB;IAC3B,+CAA+C;IAC/C,IAAI,EAAE,qBAAqB,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AA0DH,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAc;IAEd,OAAO,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schema tests for the Release Plan envelope (T9527).
|
|
3
|
+
*
|
|
4
|
+
* Validates the canonical SPEC-T9345 §6.1 shape against the Zod schema defined
|
|
5
|
+
* in {@link ./plan.ts}. Coverage targets:
|
|
6
|
+
*
|
|
7
|
+
* - Happy-path parse round-trip
|
|
8
|
+
* - Each enum field rejects unknown literal values
|
|
9
|
+
* - Required fields cannot be missing
|
|
10
|
+
* - `evidenceAtoms` stays permissive (verb-level enforcement, NOT contract)
|
|
11
|
+
* - All 8 `status` FSM values parse
|
|
12
|
+
* - `meta` is forward-compat (unknown keys pass through via `.catchall`)
|
|
13
|
+
*
|
|
14
|
+
* @task T9527
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=plan.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.test.d.ts","sourceRoot":"","sources":["../../src/release/plan.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|