Repository navigation
Commit 034f5a3
test(spec): pin the OpenAPI WRITE-refusal test on the generator's diagnostic (#18790)
Fixes #18591
Clause-②: no
`refuses to WRITE the artifact when the document is inconsistent`
(`packages/spec/scripts/openapi-self-consistency.test.ts`) asserted only
a non-zero exit
status and a missing artifact. **A subprocess that never starts
satisfies both**, so the
case stayed green in exactly the scenario where the gate it exists to
pin never ran once.
The fix is the shape its three sibling spawn tests already carry: assert
the generator's
own diagnostic text as well. Test file only, 8 lines added, nothing else
touched.
## Which text to assert — measured, not assumed
The claim comment could not say what the generator actually prints for
the injected
`ApiErrorTypo` ref. The mutated generator was run once and read:
```text
Error: OpenAPI document is not self-consistent: 1 unresolvable $ref(s).
- #/components/schemas/ApiErrorTypo (referenced at components.schemas.Broken)
defined components.schemas: [CreateRequest, UpdateRequest, SingleRecordResponse,
ListRecordResponse, DeleteResponse, ApiError, BulkRequest, BulkResponse, BaseResponse, Broken]
```
So the sibling's pair does apply verbatim, and both halves are now
asserted:
`toMatch(/unresolvable \$ref/)` and
`toContain('#/components/schemas/ApiErrorTypo')`.
## Acceptance controls
Probe: park `node_modules/.pnpm/tsx@4.23.12` aside, so `npx tsx`
resolves the pnpm shim
and the shim's target is gone — the generator subprocess never starts.
Proven in effect
before any result was read (`npx tsx --version` exit 1, `Cannot find
module …/tsx/dist/cli.mjs`),
restored under a `trap … EXIT INT TERM` with absolute paths and proven
byte-identical after
each leg (same inode 689295, same tar-stream sha256 `e8d303f8…67e6`).
### LIT — the red leg
Same command both times: `pnpm --filter @objectstack/spec exec vitest
run --project local --maxWorkers=2
scripts/openapi-self-consistency.test.ts`
| tsx parked | file counts | `refuses to WRITE …` |
|:---|:---|:---|
| **before** (`2085be2b2d`) | `Tests 8 failed \| 13 passed (21)` |
**PASSED** — the vacuous pass |
| **after** (`cd4904d361`) | `Tests 9 failed \| 12 passed (21)` |
**FAILED** |
The new failure, in full:
```text
FAIL |local| scripts/openapi-self-consistency.test.ts > build-openapi.ts end to end >
refuses to WRITE the artifact when the document is inconsistent
AssertionError: expected 'node:internal/modules/cjs/loader:1386…' to match /unresolvable \$ref/
```
All nine spawn tests in the file now go red under the probe; before this
change, eight did.
### DARK — normal tree
| tsx in place | result |
|:---|:---|
| **before** (`2085be2b2d`) | `Test Files 1 passed (1)` · `Tests 21
passed (21)` |
| **after** (`cd4904d361`) | `Test Files 1 passed (1)` · `Tests 21
passed (21)` |
Nothing reddened. Whole package at `cd4904d361`: `pnpm --filter
@objectstack/spec test` →
`Test Files 485 passed | 1 skipped (486)` · `Tests 14015 passed | 1
skipped (14016)`, exit 0.
`pnpm --filter @objectstack/spec typecheck` → exit 0 (`tsc --noEmit`,
`check:scripts-typecheck`,
`check:test-typecheck`; the test-typecheck debt ledger did not move).
## Changeset — measured
`npm pack --dry-run --json` in `packages/spec` at `cd4904d361`: **275**
published entries,
**0** of them under `scripts/`, so the changed file is not in this
package's `files[]`.
Positive control on the same reading: `src/**/*.zod.ts` is present
(`src/ai/agent.zod.ts`, …),
so the instrument is live. Nothing published moves ⇒ no changeset is
owed; `skip-changeset`
applies and is declared, not omitted.
## Gates
`node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--ran …` at `cd4904d361`:
56 derived families — **51 run exit 0**, **5 NOT MEASURED** (recorded
exit 3, `PREREQUISITE NOT MET`:
`check:dts-closure`, `check:dual-build-cjs-loads`,
`check:lean-entry-closure`,
`check:sourcemap-no-sources-content`, `check:type-check-debt`). All five
read a built `dist/`
across the workspace and refuse without one; this diff emits nothing to
any `dist/`, so they are
CI's closure-build run, not a red. Dependency-closure build (`--filter
'@objectstack/spec^...'`)
is an empty run: `packages/spec` has no workspace dependencies.
`eslint --no-inline-config --format json` on the changed file: 1 file, 0
errors, 0 warnings.
The repo-wide `pnpm lint` sweep is CI's run. Invariance leg, quoted from
`eslint.config.mjs`'s
own header: "this repo runs one `eslint.config.mjs`, which never enables
type-aware linting
(no `parserOptions.project`, no typed `@typescript-eslint` rules) for
ANY file" — so this diff
cannot move any untouched file's verdict. The universe count was not
measured, so this is a
targeted run, not a proven narrowing.
## Acceptance notes
- Swept the repo for the same vacuous shape: `git grep
"status).not.toBe(0)" -- '*.test.ts'`
returns 9 hits across 4 files; the 5 outside this file each carry an
output assertion on the
adjacent line, so no second instance of this defect class exists in that
spelling. Observation,
not a card.
- `runGenerator()` could immunise the whole spawn family structurally by
refusing a launch
failure once, instead of each case re-deriving it from diagnostic text.
Out of scope here —
the card prescribes the siblings' shape and forbids inventing one — and
moot for this file
now that all nine spawn cases assert output. Noted, not filed.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 00b38d7 commit 034f5a3
1 file changed
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
375 | 375 | | |
376 | 376 | | |
377 | 377 | | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
378 | 386 | | |
379 | 387 | | |
380 | 388 | | |
| |||
0 commit comments