From 89a49d0923236385f5bfb0d4c3c8862a5df8b968 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 18:22:31 +0000 Subject: [PATCH] chore(cli): retire SCAFFOLD_TSX_RANGE, a conditional statement nothing satisfies The `os create example` template was the only emission that ever declared a `tsx` range; once it was retired the constant reached no scaffold at all. Its docblock -- "The `tsx` range a scaffolded project declares when its scripts need it" -- is not a false statement but a conditional whose antecedent nothing on the tree satisfies. Vacuously true, so a review hunting false statements never catches it; what it misleads is the reader's default assumption that some scaffold satisfies the antecedent. The constant and its docblock are removed together. No surviving emission should declare `tsx`: all four (`os init -t app` / `-t plugin` / `-t empty`, `os create plugin`) plus the bundled `create-objectstack` blank template run every script they emit through `objectstack`, `tsc` or `vitest`, none of which executes a `.ts` entrypoint directly. `@objectstack/cli`, which each of them declares, already carries `tsx` as its own dependency. No assertion is added for the retired range. The comment in `test/scaffold-emission-policy.e2e.test.ts` is updated to describe the retirement rather than the intermediate state, keeping its rule intact: a row is owed by a range some emission really declares, and by nothing else. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015QE8qk46e5CHJxyQEUjbf8 --- .changeset/scaffold-tsx-range-retired.md | 38 +++++++++++++++++++ packages/cli/src/commands/init.ts | 3 -- .../test/scaffold-emission-policy.e2e.test.ts | 12 ++++-- 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 .changeset/scaffold-tsx-range-retired.md diff --git a/.changeset/scaffold-tsx-range-retired.md b/.changeset/scaffold-tsx-range-retired.md new file mode 100644 index 0000000000..d406b5a931 --- /dev/null +++ b/.changeset/scaffold-tsx-range-retired.md @@ -0,0 +1,38 @@ +--- +'@objectstack/cli': patch +--- + +chore(cli): retire `SCAFFOLD_TSX_RANGE`, a conditional statement nothing satisfies + +`SCAFFOLD_TSX_RANGE` and its docblock are removed from `src/commands/init.ts`. The +`os create example` template was the only emission that ever declared a `tsx` range, +and its retirement left the constant reaching no scaffold at all. + +**The docblock is the reason, and it is not a false statement.** It read *"The `tsx` +range a scaffolded project declares **when its scripts need it**"* — a conditional +whose antecedent no longer holds anywhere on the tree. Vacuously true, so no review +looking for false statements catches it; what it misleads is a reader's default +assumption that some scaffold satisfies the antecedent. + +**No surviving scaffold should declare `tsx`, measured rather than assumed.** All four +surviving emissions (`os init -t app` / `-t plugin` / `-t empty`, `os create plugin`) +plus the bundled `create-objectstack` blank template run every script they emit through +`objectstack`, `tsc` or `vitest`; none executes a `.ts` entrypoint directly, which is +the only thing `tsx` is for. The capability is not missing either: `@objectstack/cli` +— which every one of those emissions declares — carries `tsx` as its own dependency. +Declaring it a second time in a scaffold would have announced a lower floor +(`^4.21.0`) for a tool the project never names. + +**Nothing importable is withdrawn.** This package's `exports` map is `.` / `./console` +/ `./hook-body` / `./package.json`, with no subpath pattern, and `src/index.ts` +re-exports only the oclif command classes — so no consumer could ever import this +symbol. It is a `patch` and not a breaking change for that reason, but it is not +`skip-changeset` either: the CLI builds with plain `tsc`, so the constant really did +ship. Measured across a before/after build of `packages/cli`, four files inside the +published `files[]` move — `dist/commands/init.js`, `dist/commands/init.d.ts` and both +`.map` siblings — and the other 496 are byte-identical. + +No assertion is added for the retired range. `test/scaffold-emission-policy.e2e.test.ts` +already records why: a row in that table is owed by a range some emission really +declares, and by nothing else. Its comment is updated to describe the retirement rather +than the intermediate state it used to describe. diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 504f2858e4..bdc57a5b8c 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -317,9 +317,6 @@ export const SCAFFOLD_VITEST_RANGE = '^4.0.0'; /** The `@types/node` range a scaffolded project declares. */ export const SCAFFOLD_TYPES_NODE_RANGE = '^22.0.0'; -/** The `tsx` range a scaffolded project declares when its scripts need it. */ -export const SCAFFOLD_TSX_RANGE = '^4.21.0'; - /** The zod range a scaffolded project declares when it authors schemas. */ export const SCAFFOLD_ZOD_RANGE = '^4.3.6'; diff --git a/packages/cli/test/scaffold-emission-policy.e2e.test.ts b/packages/cli/test/scaffold-emission-policy.e2e.test.ts index 52a17a3adc..9c2201fa1b 100644 --- a/packages/cli/test/scaffold-emission-policy.e2e.test.ts +++ b/packages/cli/test/scaffold-emission-policy.e2e.test.ts @@ -204,10 +204,14 @@ describe('scaffold emission policy — one definition, four emissions', () => { it('emits the exported constant rather than a literal, for every policy range', () => { const ranges = declaredRanges(); // ⚠️ `tsx` left this table with #16483: the retired `os create example` - // template was the only emission that declared it, so `SCAFFOLD_TSX_RANGE` - // now reaches no scaffold at all. Asserting it here anyway would compare an - // empty harvest against the constant and go red on a correct tree; a row is - // owed by a range some emission really declares, and by nothing else. + // template was the only emission that declared it. `SCAFFOLD_TSX_RANGE` + // has now been retired with it — every surviving emission runs its scripts + // through `objectstack`, `tsc` or `vitest`, none of which is invoked as + // `tsx`, so no emission declares that range. Asserting it here anyway + // would compare an empty harvest against a constant and go red on a + // correct tree; a row is owed by a range some emission really declares, + // and by nothing else — so this table grows a `tsx` row only after some + // emission declares one, never to keep a constant company. const expected: Array<[string, string]> = [ ['typescript', SCAFFOLD_TYPESCRIPT_RANGE], ['vitest', SCAFFOLD_VITEST_RANGE],