Skip to content

Commit c120dbd

Browse files
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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
`packages/spec/src/api/odata.zod.ts` — the module docblock's `@example Programmatic Use` block is now type-checked by `check:skill-examples`: it carries an `os:check` marker and the `ODataQuery` import it needs to compile standalone (#19065).
6+
7+
Clause-②: no
8+
9+
That block ships twice — inside the tarball as `src/api/odata.zod.ts` (this package's `files[]` lists `src/**/*.zod.ts`; measured with `npm pack --dry-run`) and on the generated reference page `content/docs/references/api/odata.mdx` — and nothing compiled it. An example whose keys contradict the schema declared in the same file could therefore stay green indefinitely, which is the defect #19028 found and #19058 corrected in text only.
10+
11+
- **The reference page moves by exactly one line.** The marker is machinery and `build-docs.ts` drops it before rendering, so the only visible change on the page is the `import type { ODataQuery } from '@objectstack/spec/api';` line the block needs in order to stand alone.
12+
- **No schema, no accept set and no behaviour moves.** `ODataQuerySchema` is byte-identical. Whether it should refuse undeclared keys instead of stripping them is a separate question about a published accept set and is deliberately untouched here.
13+
- **The sibling `@example OData Query` block stays unmarked, and that is a measurement rather than an omission.** It is an HTTP request under a bare fence, not TypeScript, and the gate recognises only ts/tsx/typescript fences — a marker above it is reported as an orphan, so it would fail the gate rather than check the block.

‎content/docs/references/api/odata.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ GET /api/odata/customers?
5656

5757
**Programmatic Use**
5858
```typescript
59+
import type { ODataQuery } from '@objectstack/spec/api';
60+
5961
const query: ODataQuery = {
6062
$select: ['name', 'email'],
6163
$filter: "country eq 'US' and revenue gt 100000",

‎packages/spec/src/api/odata.zod.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ import { z } from 'zod';
5252
* ```
5353
*
5454
* @example Programmatic Use
55+
* <!-- os:check -->
5556
* ```typescript
57+
* import type { ODataQuery } from '@objectstack/spec/api';
58+
*
5659
* const query: ODataQuery = {
5760
* $select: ['name', 'email'],
5861
* $filter: "country eq 'US' and revenue gt 100000",

0 commit comments

Comments
 (0)