Repository navigation
Commit c120dbd
docs(spec): bring the odata module's Programmatic Use example under check:skill-examples (#19745)
Part of #19065
Clause-②: no
The module docblock of `packages/spec/src/api/odata.zod.ts` carries two
file-level `@example` blocks. Both ship twice — inside the tarball as
`src/api/odata.zod.ts` (this package's `files[]` lists
`src/**/*.zod.ts`) and on the generated reference page
`content/docs/references/api/odata.mdx` — and neither was inside
`check:skill-examples`' reach. This brings the TypeScript one under the
gate.
## The diff
- an `os:check` marker line (the HTML-comment spelling the gate declares
for this surface) on the line directly above the `@example Programmatic
Use` fence;
- the one import that block needs to compile standalone, `import type {
ODataQuery } from '@objectstack/spec/api';`, plus its blank line;
- the regenerated `content/docs/references/api/odata.mdx`, and a `patch`
changeset.
That is 3 added lines in the source file and 2 on the generated page. No
other file under `packages/spec/src/**` is touched, no prose is tidied
and no citation is repointed — #17242 holds a broad claim over comment
prose in that tree and this stays one hunk for it to merge past.
## The card asked for TWO markers. Only one of the two blocks can carry
one — measured, not argued
`@example OData Query` is an HTTP request under a **bare** fence, not
TypeScript. The gate's fence-language predicate is `FENCE_OPEN_RE` in
`packages/spec/scripts/check-skill-examples.ts`, which recognises `ts` /
`tsx` / `typescript` and nothing else; a marker above any other fence is
an **orphan**, which the gate treats as an error rather than a no-op.
Probed on this branch with `scripts/ablation-replace.mjs` (mutation and
restore both proven on disk):
```
GATE_EXIT[orphan]=1
✗ Found an os:check marker not directly above a ts / tsx / typescript fence
- packages/spec/src/api/odata.zod.ts:43
```
(the gate's own line spells those three with their fences; they are
written bare here so this body stays one flat code block)
So marking that block does not check it — it fails the gate. Making it
checkable would mean rewriting an HTTP URL example as TypeScript, or
teaching the gate a fourth fence language: both are decisions, neither
is this card. Hence `Part of` rather than a closing keyword — the seat
decides whether the HTTP half is closeable at all.
## Acceptance — both halves, exit codes captured before any pipe
The card's test: strip the `$` from one key in the `@example
Programmatic Use` block, the gate must go RED; put it back, GREEN.
**RED** — `scripts/ablation-replace.mjs --file
packages/spec/src/api/odata.zod.ts --anchor ' * $select: ['
--replacement ' * select: [' --expect 1`, then rebuild `packages/spec`
and run `pnpm --filter @objectstack/spec check:skill-examples`:
```
ON-DISK[red] blob=1e0293a959aeae2ee00bfd7452a1097378b59a5c
BUILD_EXIT[red]=0
GATE_EXIT[red]=1
✗ [spec source TSDoc (@objectstack/spec)] examples do not compile:
packages/spec/src/api/odata.zod.ts:60:3
error TS2561: Object literal may only specify known properties, but 'select'
does not exist in type '{ $select?: …; $filter?: …; … }'. Did you mean to write '$select'?
```
**GREEN** — restore, rebuild, re-run:
```
ON-DISK[green] blob=9157561783280ae6118140edcdd58a3f011e3952
BUILD_EXIT[green]=0
GATE_EXIT[green]=0
✅ 259 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them
```
The tree was restored from the committed state and proven: `blob == HEAD
(9157561)` and `git diff HEAD` empty, on both ablations. The
rebuild in each leg is a **prerequisite** of the gate (its
dist-freshness guard refuses a `dist` older than `src`), not the carrier
of the mutation: the mutated text is a TSDoc comment the gate reads from
`src`, and `dist` only supplies the declarations the block is checked
against.
Before / after on the gate's own counts: **258 blocks / 10 on the
spec-source surface → 259 / 11**.
## What moved on the reference page
Exactly one line. The marker is machinery and `renderFileDescription`
drops it before classification
(`packages/spec/scripts/lib/file-description.ts`,
`SKILL_EXAMPLE_MARKER`), which is also why it cannot break the MDX
build:
under the page's `**Programmatic Use**` heading and its typescript
fence, two lines are added at the top of the block — `import type {
ODataQuery } from '@objectstack/spec/api';` and the blank line under it
— and nothing else on the page changes.
Sibling entries under `content/docs/references/**` survive the
regeneration — 225 files on both sides, exactly one differing
(`api/odata.mdx`), and three quoted-exact `git grep -F` probes taken
from the three most recent reference-page commits on `main` read
identical counts on `origin/main` and on this branch (1 / 1, 1 / 1, 4 /
4), against a dark control reading 0. `scripts/pm/os-regen-merge.sh` was
run before the push and refused with "origin/main was already contained
in this branch — this refusal IS the whole outcome": `origin/main` has
not moved since this branch's base, so there was no merge to make.
## Local verification
- `pnpm --filter @objectstack/spec typecheck` → exit 0
- `pnpm --filter @objectstack/spec test` → exit 0, 515 files / 15043
tests passed
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` derived **102** families from this worktree; all 102 were
run and reconciled with `--ran`: **101 exit 0, 1 NOT MEASURED**. The one
is `pnpm check:dual-build-cjs-loads`, exit 3 — it needs a
**whole-workspace** build (33 packages have no `dist` here,
`@objectstack/account`, `@objectstack/setup`, `@objectstack/studio`, …
), which a docs-only diff does not buy; `Build Core` covers it in CI.
- `pnpm lint` was **narrowed** rather than skipped, with the three
readings that make a narrowing a measurement: ① the population is read
from `eslint.config.mjs`'s own `files` globs, every one of them a
`{ts,tsx,mts,cts,js,jsx,mjs,cjs}` extension, so of the three changed
paths only the `.ts` one is in it (the `.mdx` and the changeset each
came back `errorCount 0 / warningCount 1` — the *ignored-file* warning);
② `--format json` reports **1** file linted, 0 errors, 0 warnings; ③ the
config never enables type-aware linting for any file (no
`parserOptions.project`, no typed `@typescript-eslint` rules — stated
and measured in its own header), so a comment-only edit in one file
cannot move the verdict on a file it did not touch. Readings taken at
`4a54706`.
## Acceptance notes
- **The `@example OData Query` block stays structurally unverifiable.**
Not a defect and not filed: the gate is a TypeScript compiler, and that
block is an HTTP request. Noted here rather than carried further.
- **Coverage on this surface is still 7 files of the 134 that write
`@example` under `packages/spec/src`** (the card's own reading, at
`221dabb72a`). This PR moves it by one file; the rest is the card's
explicit non-scope.
- ⛔ **Not touched, deliberately:** whether `ODataQuerySchema` should
refuse undeclared keys instead of stripping them. That changes the
accept set of a published schema with consequences on the wire, and the
example blocks here are written so they do not imply it either way.
---
_Generated by [Claude
Code](https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 16d090e commit c120dbd
3 files changed
Lines changed: 18 additions & 0 deletions
File tree
- .changeset
- content/docs/references/api
- packages/spec/src/api
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
| 59 | + | |
| 60 | + | |
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| 55 | + | |
55 | 56 | | |
| 57 | + | |
| 58 | + | |
56 | 59 | | |
57 | 60 | | |
58 | 61 | | |
| |||
0 commit comments