Skip to content

Commit e3ca74e

Browse files
os-billclaude
andauthored
docs(spec): name the second publisher a duration-unit marker changes (#19016)
Fixes #18687 Clause-②: no ## What this is Option A of the card — a docblock paragraph on the two `.meta()` exemption-marker readers in `packages/spec/scripts/check-duration-unit-keys.ts`. Option B (a changeset-gate criterion) is deliberately NOT implemented here: the card itself says that one has to be measured first, so this PR carries **the measurement** instead of a rule. Option C is untouched. Comment-only. No declaration, schema, accept set or generator behaviour is touched — one file, 19 insertions, 1 deletion. ## What the file already said, and what it did not On the base tree the file already states, in assertion position, that a declared unit rides into the published JSON schema (`:183-184`, `:389-390`), and that the marker rides `z.toJSONSchema` verbatim so the reference page prints it (`:176-179`). All three are correct today and are left untouched; the new paragraph cross-references the channel rather than restating it. What is new — and it is the whole of this card — is the half none of them states: 1. `packages/spec/json-schema/` is published content: it is on this package's `files[]`. It also carries **zero tracked files** — it is a gitignored build artifact (`.gitignore:63`). Measured at `2767af8e83`: 0 tracked paths under `packages/spec/json-schema/`, against 17 under `packages/spec/api-surface/` by the same `git ls-tree`. 2. So the marker's arrival there is a change to **published package content that has no diff of its own**: there is no tracked byte of that directory for a review, a `git diff` or any diff-reading gate to see move. 3. So the first card that really marks a key owes its declaration to **two publishers**: the rendered reference page AND the published JSON Schema. The paragraph is hung on `DIMENSIONLESS_META_KEY`, whose docblock is already the one that speaks for both markers ("It sits beside `EXTERNAL_VOCABULARY_META_KEY` in this reader on purpose. Both are declarations ON THE SCHEMA…"), plus a one-line pointer to it from `EXTERNAL_VOCABULARY_META_KEY` so a reader arriving at the first marker is routed to it. ## One correction to the card's framing, measured The card says such a change produces "not one line of git diff". Measured on this tree that is too strong, so the note is written to the measured shape instead: - the marking **edit** is visible, and in `packages/spec` a marked `*.zod.ts` file is itself on `files[]` — so on a spec key that line is a published file in its own right; - `content/docs/references/**` is tracked (224 generated pages) and both markers render into it (`(unit per …)` / `(dimensionless — counts …)`), so that publisher moves visibly as well. The gap is the **artifact**, not the edit. Those two visible halves are precisely what makes the invisible third read as already accounted for — which is why the note is worth writing at all. ## Direct evidence for the claim After `pnpm --filter @objectstack/spec build` on this branch: - `packages/spec/json-schema/` materialises as 1532 generated JSON files, and `git status --ignored=matching` reports the directory as ignored — zero tracked. - The marker values are in that output verbatim, e.g. `"externalVocabulary": "HTTP Cache-Control \`max-age\` (RFC 9111 §5.2.2.1)"` — LIT control, the channel really does publish. - A fabricated marker name reads 0 hits in the same output — DARK control. ## Changeset: `skip-changeset`, measured rather than assumed The card's subject is exactly "the reason for `skip-changeset` still reads correct", so this one is measured file by file rather than asserted. Diff at `79e564be3a` vs merge base `2767af8e83` — one file: | file | on `packages/spec` `files[]`? | |---|---| | `packages/spec/scripts/check-duration-unit-keys.ts` | **NO** — matches none of the 11 entries (`dist`, `json-schema`, `liveness`, `prompts`, `llms.txt`, `README.md`, `src/**/*.zod.ts`, `CHANGELOG.md`, `api-surface`, `api-surface-declarations`, `spec-changes.json`); package is not private | Second, empirical leg against a real build: the sentence this PR adds appears **0** times across `dist/`, `json-schema/`, `api-surface/`, `liveness/` and `prompts/`; the positive control — a genuinely published string — appears 18 times in `dist/` and 8 times in `json-schema/`. Zero files on `files[]` moved, so `skip-changeset` holds, and it holds by measurement, not by the habit this card is about. ## The measurement option B owes (readings only — no rule is landed) Criterion measured: *a diff whose ADDED lines introduce a `.meta({ MARKER })` key position requires a non-`skip-changeset`*. A false positive is a commit the criterion fires on that touches no file on a `files[]`. Window, stated: **every non-merge commit reachable from `origin/main` at `2767af8e83` — 13175 commits**; hits span 2026-01-26 … 2026-09-17. (Wider than the brief's "last N commits touching `packages/spec`", and repo-wide rather than spec-only, since the criterion is repo-wide.) Candidates come from `git log --no-merges -G`; a candidate is kept only when an **added** line matches, which is what separates a marking from a removal. Broad reading — any `.meta({`: | reading | count | |---|---| | candidates from `-G` | 43 | | criterion FIRES (an added line, not just a removal) | 41 | | false positives, naive `files[]` membership | **10 of 41 = 24.4%** | | false positives, `src`-reaches-`dist` tarball reading | 8 of 41 = 19.5% | | fired and carried no `.changeset/*.md` | 11 | | DARK control — a fabricated marker name | **0** | **7 of the 10** naive false positives have their added `.meta({` under a `scripts/` path — the class the card predicts must exist. They include `8ca7aafc45`, which edits **this gate's own self-test fixtures**, and three commits editing `scripts/pm/check-widening-tells.mjs`. Narrow reading — an added line matching `.meta({ externalVocabulary` or `.meta({ dimensionless`. Six commits fire in all of history: | commit | fires on | verdict | |---|---|---| | `17965dfd7e` | `packages/spec/scripts/lib/schema-section.ts` and its test | false positive | | `8ca7aafc45` | this gate's own self-test fixtures | false positive | | `484484041a` | this gate's own self-test fixtures | false positive | | `7e6337007f` | `packages/spec/CHANGELOG.md` quoting a marker, in the release commit | fires, but nothing was marked | | `e9fcd6bbd4` | the commit that landed the two exemptions | true positive — carried a changeset | | `c049e74679` | two real markings under `src/` | true positive — carried a changeset | So the narrow criterion's false-positive rate is **3 of 6 (50%)** under the naive reading, or 4 of 6 if the release commit that marks nothing is counted; and **both** of its true positives already carried a changeset without any rule forcing them to. These are readings for the maintainer's decision on option B — no gate, `check-*.mjs` or CI criterion is changed by this PR. ## Verification - `check-duration-unit-keys --self-test` — green **before** (unmodified file at `2767af8e83`) and **after**: 104 cases across 13 batteries both times, every battery at or above its pinned floor. - `pnpm --filter @objectstack/spec build` :: exit 0 (under the shared verify lock, 127s). - `pnpm --filter @objectstack/spec check:docs` :: exit 0 — "224 generated files in sync with packages/spec", so **zero reference pages move**. - Derived gate sweep: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` yields 53 commands; all 53 were run with exit codes captured before any pipe. **51 exit 0.** Two exit 3 — `check:dual-build-cjs-loads` and `check:lean-entry-closure` — which is the code those gates use for PREREQUISITE NOT MET: both read built output of the whole package farm, which a spec-only build does not produce. Recorded as NOT MEASURED, not as green; a comment in `scripts/` reaches no `dist`, and CI builds the farm. `--ran` reconciliation: 53 derived, 51 run, 2 NOT-MEASURED derived from the recorded exit 3, **0 unrun**. - Repo-wide `pnpm lint` (`eslint . --no-inline-config`) at `79e564be3a`: **6858 files** in eslint's own surveyed population, 0 errors, 0 warnings, exit 0. Not narrowed — the whole union was run after the final commit. - `pnpm check:nul-bytes` :: exit 0, plus a direct control-character scan of the changed file: no hits. ## Acceptance notes - The card's "no git diff at all" framing is corrected above rather than repeated; the file now states the measured shape. Reported to the dispatching seat rather than filed. - `packages/spec/json-schema.manifest/` and `packages/spec/authorable-surface/` (14 tracked files each) are projections of `json-schema/` that record def keys and authorable keys, not `.meta()` markers — measured: zero occurrences of either marker name in both directories. So neither tracked projection gives the published JSON Schema a diff-visible shadow. Observation only, not filed. - Nothing else in scope was found to file under the three filing classes. --- _Generated by [Claude Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3597aeb commit e3ca74e

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

‎packages/spec/scripts/check-duration-unit-keys.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ const DURATION_ROOT_MODULE = 'src/shared/duration.zod.ts';
409409
* The `.meta()` key that declares exemption class (ii). A key carrying it
410410
* mirrors a name fixed by an external standard, so the RENAME is waived — never
411411
* the contradiction check, and never the requirement that the describe still
412-
* state the unit.
412+
* state the unit. What marking a key owes the PUBLISHED surfaces is stated once
413+
* for both markers, on {@link DIMENSIONLESS_META_KEY} below.
413414
*/
414415
const EXTERNAL_VOCABULARY_META_KEY = 'externalVocabulary';
415416

@@ -427,6 +428,23 @@ const EXTERNAL_VOCABULARY_META_KEY = 'externalVocabulary';
427428
* lying: a dimensionless key whose NAME carries a unit token still fails
428429
* `name-unit-contradicts-prose`, because "this number counts events" and "this
429430
* number is a span of milliseconds" cannot both be true of one key.
431+
*
432+
* ⚠️ MARKING A KEY EDITS A PUBLISHED ARTIFACT THAT HAS NO TRACKED BYTES, so a
433+
* marking declares itself to TWO publishers rather than one. Either marker
434+
* reaches `packages/spec/json-schema/` down the `z.toJSONSchema` channel
435+
* exemption class 2 names above, and this package's `files[]` ships that
436+
* directory — but it is a gitignored build artifact carrying ZERO tracked files
437+
* (measured on this repo at `2767af8e83`: 0 tracked paths under `json-schema/`,
438+
* against 17 under `api-surface/` by the same `git ls-tree`), so no diff can
439+
* show that it moved. The gap is the ARTIFACT, not the edit: the marking line
440+
* is visible, and this package's `files[]` ships its `.zod.ts` sources too, so
441+
* on a spec key that line is a published file in its own right; the rendered
442+
* note moves visibly as well, because `content/docs/references/**` is tracked.
443+
* ⛔ Those visible halves are the trap — they make the publishing story read as
444+
* fully told, while "nothing else published moved" is not a reading about
445+
* `json-schema/` at all, which cannot move in a diff. So the first card that
446+
* really marks a key declares BOTH publishers: the rendered reference page AND
447+
* the published JSON Schema (#18687).
430448
*/
431449
const DIMENSIONLESS_META_KEY = 'dimensionless';
432450

0 commit comments

Comments
 (0)