Commit fbeb56e
Fixes #20126
Clause-②: no
Remainder (c) of the currency-mode class-closure card: the family's one
enumerating pin. Remainder (b) landed in PR #20217, the skills half
(#20196) in PR #20256, and the runtime member (#20091) in PR #20119, so
this test-only PR closes the card.
## What the pin is
One new test in spec's `repo` vitest project:
`packages/spec/src/data/currency-mode-family-closure.pin.test.ts`. The
maintainer's ruling on #20088 asked for one enumerating pin in the
owning package and ⛔ no new `check-*` gate. `packages/spec` owns
`CurrencyConfigSchema`, and its repo project already walks `skills/**`
and `content/**`. The pin enumerates the corpus, not the sites. A new
site anywhere in the radius reddens it, as well as a regression of an
old one.
- **Rule A.** Every `defaultCurrency` in `skills/**/*.md` and
`content/docs/**/*.mdx` sits in a unit that carries `fixed`, or that
says it is not the displayed currency (or not read) under `dynamic`.
- **Rule B.** The date record's number within five physical lines of
`currenc` (any case) counts 0. The matcher reads `ADR-0053`, `ADR 0053`
and the `adr/0053-` file link. The roots are `skills/**`,
`content/docs/**` and `packages/services/service-analytics/src/**`. Per
the family's appended sites 5-10 (ACCEPT `5853407641`, triage
`5853734589`), they also include `packages/spec/src/**`,
`packages/spec/liveness/**` and `examples/**`: non-code files anywhere,
plus `.ts` under each app's `src/`.
- **Runtime member.** It is #20091's own pin,
`packages/services/service-analytics/src/__tests__/currency-mode-relay.test.ts`,
on `main` (`git merge-base --is-ancestor 6780e34 HEAD` exit 0). The
closure pin only checks that this file still stands, and ⛔ does not
re-assert the resolver.
- **Site table.** Each family site (1-10, the three pages #20090 landed,
and 11-14) is mapped to the leg that guards it. The test asserts each
file's membership in each corpus, so if a site moves out of the radius,
the pin goes red.
## Outside the corpus, and why
- **Released entries.** This covers every `CHANGELOG.md` and
`content/docs/releases/**`. The seat ruled sites 11-14 (the released
17.0.0 entries) accepted history, since a released entry records what
shipped (claim `5866047669`). The two package CHANGELOGs sit outside
every root by construction. `examples/*/CHANGELOG.md` is inside a root
and is skipped by name. The test asserts both exclusions, with a live
control proving the by-name skip has something to skip.
- **The pin's own file.** It quotes both rules and their fabricated
controls.
## The three design facts (`5855122068`), each answered in the pin's
header
1. **Test titles.** Rule A reads published prose only (`.md` / `.mdx`),
so no test title is judged by it. The `field.test.ts` title stays
outside by corpus, not by exemption. Rule B does read test files inside
its roots.
2. **Negation versus citation.** Rule B does not try to tell them apart:
a negation within the window counts too. Currency text has no reason to
name the date record; the pin's message says to cite ADR-0104.
3. **Wrapped keys.** Both rules read logical text. A key hyphen-wrapped
at a line end (`default-` / `Currency`, `ADR-` / `0053`) rejoins after
the next line's comment prefix is stripped.
**Unit for rule A: not the line.** A strict line reading reds on 5
correct, accepted lines in
`skills/objectstack-data/rules/field-types.md` (ACCEPT `5853407641`'s
pin note). Instead, the unit is:
- in prose, the sentence across wrapped lines;
- in a table, the row;
- in a fenced comment, the sentence of its comment run;
- in fenced code, the innermost object literal holding the key, or the
sibling mapping in YAML.
So one `fixed` field in a fence never vouches for a neighbour's bare
`defaultCurrency`. There is one shape exemption: a parenthesised key
list that also names `currencyMode`, `(currencyMode, defaultCurrency)`.
It names keys and teaches no reading; this is `field-types.md:55`.
## Measured on this branch's base `dcd3bceaa` (assumption 1 holds)
- **Rule A:** 445 files in the corpus. 34 `defaultCurrency` occurrences
in 11 files; 0 failing, 1 of them the key-list exemption.
- **Rule B:** 2550 files in the corpus, 0 hits. 65 date-record lines
remain, all outside the window (date uses).
- **No live text site:** no text site was edited in this PR.
## Declared radius (AGENTS.md: a test that reads outside its package is
spelled so the gate can see it)
Rule B's example-code leg is new radius for
`@objectstack/spec#test:repo`. It is declared in two places:
- `scripts/cross-package-test-inputs.mjs` gets `examples/*/src/**/*.ts`;
- `turbo.json` gets the matching `$TURBO_ROOT$/...` input.
The glob is deliberately ⛔ not `examples/**/*.ts`. That glob covers the
CRM example's smoke test, which is the dispatch-gates self-test's
outside-packages specimen. The declaration comment states that the glob
reaches the two translation tests inside the todo app's `src/`. The
pin's site table quotes the showcase dataset's path, which holds the
glob on the roster. `check:cross-package-test-inputs` and
`check:ci-filter-parity` are both green.
## Verification
All readings are at head `7fc9f86b`, the branch's only commit; every
build and test ran through `scripts/pm/os-verify-lock.sh` (`VERDICT
command-exit 0` each).
- **The pin alone:** `pnpm --filter @objectstack/spec exec vitest run
--project repo --maxWorkers=2
src/data/currency-mode-family-closure.pin.test.ts` → `Test Files 1
passed (1)` / `Tests 6 passed (6)`.
- **Ablation, one leg per rule** (from the committed state,
`scripts/ablation-replace.mjs` in wrap mode, under the lock). The
expected direction was red, and both legs went red:
- Leg A drops ` (only under currencyMode: 'fixed')` from
`skills/objectstack-ui/rules/dashboards.md`, site 2's regression. Anchor
1 → 0, blob `570341f3` → `8e0c44f3`. Rule A goes red with exactly
`skills/objectstack-ui/rules/dashboards.md:307`: `Tests 1 failed / 5
passed`. Restored: blob equals HEAD `570341f3`, and `git diff HEAD` is
empty.
- Leg B inserts ` (ADR-0053)` after the key in
`examples/app-showcase/src/ui/datasets/chart-gallery.dataset.ts`, site
10's regression and the newly declared example-code radius. Anchor 1 →
0, blob `31348e15` → `1ca43894`. Rule B goes red with exactly
`examples/app-showcase/src/ui/datasets/chart-gallery.dataset.ts:47`:
`Tests 1 failed / 5 passed`. Restored: blob equals HEAD `31348e15`.
- The first leg-B attempt was a no-op and is not a reading: its
replacement embedded its own anchor, and the tool refused (anchor 1 → 1)
and restored before any test ran. It was re-run with an anchor the
replacement does not contain.
- Restored leg: `Tests 6 passed (6)`. `git diff HEAD` is 0 bytes and
`git status --porcelain` is empty.
- **spec, both projects:**
- `vitest run --project repo`: `Test Files 36 passed (36)` / `Tests 640
passed (640)`.
- `vitest run --project local`: `Test Files 561 passed (561)` / `Tests
16517 passed | 1 todo (16518)`.
- `pnpm --filter @objectstack/spec run typecheck` exits 0, and
`check:test-typecheck` is OK. `tsc -p tsconfig.test.json
--listFilesOnly` lists the new file, so the typecheck really reads it.
- **Builds:** `pnpm --filter @objectstack/spec build` exits 0. `turbo
run build --filter='./packages/*' --filter='./packages/*/*'
--concurrency=2` gives `Tasks: 71 successful, 71 total`.
- **Gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives 96 commands over the 4 changed
paths, and every one was run. `--ran` gives `96 derived, 96 run, 0
NOT-MEASURED, 0 UNRUN`. On the first pass, four gates exited 3 because
their prerequisite packages were not built. They exited 0 after the full
build: `check:doc-formula-expressions`, `check:dual-build-cjs-loads`,
`check:lean-entry-closure` and `check:type-check-debt`.
- **Readers of the edited declaration module:** each exits 0.
- `node scripts/pm/dispatch-gates.mjs --self-test`: 1976 cases,
including "no hint of this gate reaches a test file outside
packages/**".
- `node scripts/check-ci-filter-parity.mjs --self-test`.
- `node scripts/partition-test-shards.mjs --self-test`.
- `node scripts/check-published-list-mirrors.mjs`.
- `node scripts/check-examples-live-imports.mjs`.
- **Lint, narrowed** (CI owns `pnpm lint`):
- `eslint --no-inline-config --format json` on the two lintable changed
files gives 2 files / 0 errors / 0 warnings; `--print-config` gives them
4 and 2 active rules.
- `turbo.json` and `vitest.repo-tests.json` answer "File ignored because
no matching configuration", so they are outside eslint's population.
- `eslint.config.mjs` sets no `parserOptions.project`, so there is no
type-aware linting, and no untouched file's verdict can move.
- **Ships nothing:** spec's `files[]` is `dist`, `json-schema`,
`liveness`, `src/**/*.zod.ts` and so on. A grep of the published paths
for the pin finds 0 files; the control grep for `CurrencyConfigSchema`
in `dist` finds 30. So the diff takes `skip-changeset`.
- **Base:** the branch is one commit behind `origin/main` (`2c310705`).
That commit adds two `packages/spec/src/data` files with no date-record
token, so rule B cannot move on the merge. Not merged here.
## Acceptance notes (not filed)
- `.changeset/*.md` is outside the corpus. It is where released
CHANGELOG text originates, so a pending changeset citing the date record
for currency would not redden this pin before release. Carrier: none;
noted only.
- The `user selectable` wording that site 1 corrected is not a rule of
the card's pin definition, so it is not guarded here.
- Example tests (`examples/*/test/**`, `examples/*/e2e/**`) are outside
rule B's example-code leg, which follows the declared radius above.
- `node scripts/pm/measurement-claim-triage.mjs --self-test` (run as a
reader of the edited module) is red on the base, naming only
`scripts/check-dts-references.mjs:74` (UNTRIAGED), a file this PR does
not touch. No workflow or package script invokes it. Carrier: none.
- The objectui pointer in `5855122068` (objectui
`packages/i18n/src/currency.ts`, `CurrencyField.tsx`) is another
repository and is not read here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01ARcDurZ5j34RdqsGgc4jgH)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2304b16 commit fbeb56e
4 files changed
Lines changed: 447 additions & 1 deletion
File tree
- packages/spec
- src/data
- scripts
0 commit comments