test(spec): the currency-mode family's enumerating closure pin (#20126) - #20415
Merged
objectstack-fleet[bot] merged 1 commit intoSep 28, 2026
Merged
Conversation
One test in spec's repo project walks the family's corpus and holds two text rules at zero: every `defaultCurrency` unit in the published skills and docs carries the `fixed` condition, and the date record is never named within five lines of currency text. The spec package's declared radius gains each example app's `src/**/*.ts`, which rule B reads. Claude-Session: https://claude.ai/code/session_01ARcDurZ5j34RdqsGgc4jgH Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift Check
What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contributor
Author
|
This was referenced Sep 28, 2026
objectstack-fleet
Bot
deleted the
claude/issue-20126-currency-family-closure-pin
branch
September 28, 2026 15:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
repovitest 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 newcheck-*gate.packages/specownsCurrencyConfigSchema, and its repo project already walksskills/**andcontent/**. 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.defaultCurrencyinskills/**/*.mdandcontent/docs/**/*.mdxsits in a unit that carriesfixed, or that says it is not the displayed currency (or not read) underdynamic.currenc(any case) counts 0. The matcher readsADR-0053,ADR 0053and theadr/0053-file link. The roots areskills/**,content/docs/**andpackages/services/service-analytics/src/**. Per the family's appended sites 5-10 (ACCEPT5853407641, triage5853734589), they also includepackages/spec/src/**,packages/spec/liveness/**andexamples/**: non-code files anywhere, plus.tsunder each app'ssrc/.currencyMode, so adynamicfield'sdefaultCurrencyshows on analytics faces while field faces show the tenant currency #20091's own pin,packages/services/service-analytics/src/__tests__/currency-mode-relay.test.ts, onmain(git merge-base --is-ancestor 6780e34a HEADexit 0). The closure pin only checks that this file still stands, and ⛔ does not re-assert the resolver.field-types.mdandfield-types.mdxcontradicts the spec:dynamicis taught as a per-record{ value, currency }, and the resolution order has no mode #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
CHANGELOG.mdandcontent/docs/releases/**. The seat ruled sites 11-14 (the released 17.0.0 entries) accepted history, since a released entry records what shipped (claim5866047669). The two package CHANGELOGs sit outside every root by construction.examples/*/CHANGELOG.mdis 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 three design facts (
5855122068), each answered in the pin's header.md/.mdx), so no test title is judged by it. Thefield.test.tstitle stays outside by corpus, not by exemption. Rule B does read test files inside its roots.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(ACCEPT5853407641's pin note). Instead, the unit is:So one
fixedfield in a fence never vouches for a neighbour's baredefaultCurrency. There is one shape exemption: a parenthesised key list that also namescurrencyMode,(currencyMode, defaultCurrency). It names keys and teaches no reading; this isfield-types.md:55.Measured on this branch's base
dcd3bceaa(assumption 1 holds)defaultCurrencyoccurrences in 11 files; 0 failing, 1 of them the key-list exemption.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.mjsgetsexamples/*/src/**/*.ts;turbo.jsongets 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'ssrc/. The pin's site table quotes the showcase dataset's path, which holds the glob on the roster.check:cross-package-test-inputsandcheck:ci-filter-parityare both green.Verification
All readings are at head
7fc9f86b, the branch's only commit; every build and test ran throughscripts/pm/os-verify-lock.sh(VERDICT command-exit 0each).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).scripts/ablation-replace.mjsin wrap mode, under the lock). The expected direction was red, and both legs went red:(only under currencyMode: 'fixed')fromskills/objectstack-ui/rules/dashboards.md, site 2's regression. Anchor 1 → 0, blob570341f3→8e0c44f3. Rule A goes red with exactlyskills/objectstack-ui/rules/dashboards.md:307:Tests 1 failed / 5 passed. Restored: blob equals HEAD570341f3, andgit diff HEADis empty.(ADR-0053)after the key inexamples/app-showcase/src/ui/datasets/chart-gallery.dataset.ts, site 10's regression and the newly declared example-code radius. Anchor 1 → 0, blob31348e15→1ca43894. Rule B goes red with exactlyexamples/app-showcase/src/ui/datasets/chart-gallery.dataset.ts:47:Tests 1 failed / 5 passed. Restored: blob equals HEAD31348e15.Tests 6 passed (6).git diff HEADis 0 bytes andgit status --porcelainis empty.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 typecheckexits 0, andcheck:test-typecheckis OK.tsc -p tsconfig.test.json --listFilesOnlylists the new file, so the typecheck really reads it.pnpm --filter @objectstack/spec buildexits 0.turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2givesTasks: 71 successful, 71 total.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderives 96 commands over the 4 changed paths, and every one was run.--rangives96 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-closureandcheck:type-check-debt.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.pnpm lint):eslint --no-inline-config --format jsonon the two lintable changed files gives 2 files / 0 errors / 0 warnings;--print-configgives them 4 and 2 active rules.turbo.jsonandvitest.repo-tests.jsonanswer "File ignored because no matching configuration", so they are outside eslint's population.eslint.config.mjssets noparserOptions.project, so there is no type-aware linting, and no untouched file's verdict can move.files[]isdist,json-schema,liveness,src/**/*.zod.tsand so on. A grep of the published paths for the pin finds 0 files; the control grep forCurrencyConfigSchemaindistfinds 30. So the diff takesskip-changeset.origin/main(2c310705). That commit adds twopackages/spec/src/datafiles with no date-record token, so rule B cannot move on the merge. Not merged here.Acceptance notes (not filed)
.changeset/*.mdis 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.user selectablewording that site 1 corrected is not a rule of the card's pin definition, so it is not guarded here.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 onlyscripts/check-dts-references.mjs:74(UNTRIAGED), a file this PR does not touch. No workflow or package script invokes it. Carrier: none.5855122068(objectuipackages/i18n/src/currency.ts,CurrencyField.tsx) is another repository and is not read here.Generated by Claude Code