Uh oh!
There was an error while loading. Please reload this page.
fix(lint): name the metadata-editing surface, not a *.form.ts filename - #8183
Conversation
…ame (#8042) Since #7815 the metadata layer is reachable at the runtime publish gate for a form view declaring `data: { provider: 'schema', schemaId }`. That door's audience is a Studio / REST `/meta` / MCP author who holds no `*.form.ts`, so `visibility-root-mislayered` and `visibility-bare-identifier` prescribed the right root and then justified it by naming a file the reader cannot open. Prose only — no rule id, severity, prescribed root or firing condition moves, and the actionable half of every message and hint is byte-stable. The mirror (runtime) arm named `*.view.ts` / `*.page.ts` the same way and is fixed with it. The `*.form.ts` mentions addressed to a file-aware CALLER (the `opts.layer` contract) are kept: there the filename is accurate and is the point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WocN37om5bw81JDoEEMA2e
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#8042
The metadata-layer arm of the visibility diagnostics explained the layer by naming
*.form.ts— a file a Studio / REST/meta/ MCP author of a schema-bound view does not have and cannot open. This names the surface instead: a metadata-editing form, the row under edit.Prose only. No rule id, severity, prescribed root or firing condition moves; the actionable half of every message and hint is byte-stable.
The premise, measured rather than assumed
Before touching anything, the publish-gate path was probed with the gate's own call shape —
validateVisibilityPredicates(stack), no options, which is exactly howauthoring-rules.tscalls it. A form view declaringdata: { provider: 'schema', schemaId }emitted both graded strings, each naming a file:Both reachable, both file-naming, prescriptions already correct. Premise holds.
What changed, and the discrimination behind each site
The rule file carried 8
*.form.tsoccurrences (counted, not eyeballed). The question applied per site was: is this string read by an author of the metadata, who may hold no source file — or is it explaining the caller contract to someone reading or maintaining the linter, where the filename is accurate and is the point?Rewritten — emitted prose an author reads (3):
MISLAYER_BY_LAYER.metadata.messagevisibility-bare-identifierhint, metadata armMISLAYER_BY_LAYER.runtime.messageBroadened — module and type docs that DEFINE the layer (3): the module note, the
VisibilityLayerdoc, and theCANONICAL_ROOT_BY_LAYERdoc each defined the metadata layer as*.form.tsfiles. Since #7815 that definition is incomplete rather than merely surface-specific: a schema-bound form view is on this layer with no file at all. Each now names both routes.Retained deliberately (2): the
opts.layeroption doc ("...which is what a file-aware caller linting a*.form.tsdoes") and thevalidateVisibilityPredicatesdoc ("passopts.layer = 'metadata'when linting a*.form.tsmetadata-editing form"). Both address a caller that is genuinely linting a file — the option exists precisely for that caller — so the filename is both correct and the useful word. A blanket find-and-replace would have deleted these, which is why one pin asserts they are still present.Net: 8 occurrences to 6, and zero remaining inside any emitted string. All 6 survivors are comments.
One judgment call beyond the graded scope, flagged for review
The graded targets are the two metadata-arm strings. I also rewrote the runtime arm, which explained its forbidden
data.root as "a*.form.tsrow under edit" and named the runtime surface as "a*.view.ts/*.page.tslive record".The reasoning: a view or page published through Studio has no
*.view.tseither, so the same finding applies, and the graded metadata message names*.view.ts/*.page.tsin the same sentence it names*.form.ts. Fixing only the graded half would have left one sentence half-pointing at files. Happy to narrow this back if review reads it as out of scope — it is isolated to one message string.Tests
Six pins in a new
#8042block, all on the no-options call (the gate's shape):messageorhintmatches a*.form.ts/*.view.ts/*.page.tsspelling, with a non-vacuity guard per row so a case that goes blind fails instead of passingReverse verification — direction predicted before running: revert the source, keep the tests, and the prose pins go red while the caller-contract pin stays green (origin/main still carries that wording). Measured exactly that: 4 failed, 113 passed, and the 4 are precisely the prose pins. That asymmetry is what separates "changed the right thing" from "changed everything".
Note on the suggested negative control: the emitted strings cannot be forked by caller path, because
MISLAYER_BY_LAYERis keyed by layer, not by how the layer was derived. So "the file-aware path still produces its retained wording" is not an available assertion — the file-aware caller reads the same prose. That is pinned as an equality instead, and the retained-wording control moved to the source-level pin.Verification
pnpm --filter @objectstack/lint test— 72 files, 1954 passed, 4 skipped.runtime-gate.test.tsuntouched and green.validate-visibility-predicates.test.ts— 117 passed (was 113 pass + 4 red under reverse verification).pnpm --filter @objectstack/lint typecheck— clean.eslinton both changed files — clean.check:nul-bytesOK (7428 files).check:spec-parsed-aliasOK.check:changeset-gate-self-tests,check:cross-package-test-inputs,check:objectui-changesetall green.check:objectui-pin-freshis red and pre-existing — it matched only because this PR adds a changeset, my diff touches no.objectui-sha, and it fails identically on a pristine tree (the pin has drifted behind upstream objectui sincea0151e9).Changeset added:
@objectstack/lintis published, so prose that changes what an author reads still ships as apatch.Generated by Claude Code