Repository navigation
fix(lint)!: refuse an app nav visible that does not parse, and page variables that are duplicated, unnamed or wrong-typed - #28723
Conversation
…riables that are duplicated, unnamed or wrong-typed Co-Authored-By: Claude <noreply@anthropic.com>
…usals at save, draft read and publish Co-Authored-By: Claude <noreply@anthropic.com>
…able refusals Co-Authored-By: Claude <noreply@anthropic.com>
…he page-variables rule Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 4 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 9c56ff111a777edb73bceb1f01bdc38a9791609a && git checkout 9c56ff111a777edb73bceb1f01bdc38a9791609a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d62d973734d1e0af3f183340a5674f320b7c0858 bb33ace7a2c8a9d1443d088873c8d9b9bbb60889 && git checkout -B drift-repro d62d973734d1e0af3f183340a5674f320b7c0858 && git merge --no-ff bb33ace7a2c8a9d1443d088873c8d9b9bbb60889
node scripts/docs-audit/affected-docs.mjs --json d62d973734d1e0af3f183340a5674f320b7c0858
|
|
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt Contract reviewServed-tier: Check-runs on the head at review time: 62 runs, 0 failed, 0 cancelled, 27 still in progress (Test Core 1-8, Test UI 1-16, Build Core, Build Docs, Live E2E UI, the five Type Check jobs, the six Lint jobs still running). Completed green: Check Changeset, PR-body guards, Governed Surface Queue Guard, Spec property liveness, Lint · PM dispatch-gates, Lint · scoped · tooling self-tests, Dogfood Regression Gate, Check PR Size, Check Documentation Links, Flag docs affected by code changes, Build UI Deps, Plan Test Core shards. The pending families are the queue guard's to wait on; nothing in this record re-runs or pre-judges them. ① Derived judgments
② Semver level
③ Boundary flags
Deviations, each answered:
Out-of-scope findings the dev reported, each escalated rather than fixed here: ④ Design judgmentThe narrowing, read against the published spec on Findings:
Implemented-by: VERDICT: PASS |
|
domain:server#5 · os-project-manager · session_01FEkQ5oc56xChD6Wrc4cGSt 席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」. 席位意见:与 diff 相符。导航
|
Requested by Leehom · project thread
Fixes #28663
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Skills-docs: none — no file under
skills/**teaches a navigation entry'svisiblegrammar or the pagevariableslist; the refusals carry their own fix andos explainentries.维护者速读
visible写成解析不了的 CEL(如'org_owner' in),现在和页面组件的visibleWhen一样被拒:保存、草稿诊断、发布、os validate四处同一条结论。页面variables新增一条规则:重名、空名、默认值类型和声明类型不符(number配"abc")都拒。visible、5 个页面变量,零命中。回滚即撤回@objectstack/lint的这次改动。packages/lint/src/validate-visibility-predicates.ts(新增的导航遍历和syntaxFinding);packages/lint/src/validate-page-variables.ts(新规则);packages/lint/src/authoring-rules.ts(家族加app、新规则注册)。pnpm --filter @objectstack/lint exec vitest run src/runtime-gate.app-nav-visible-predicate-writes.test.ts src/runtime-gate.page-variable-writes.test.ts,预期 31/31 通过。What changes
packages/lint/src/validate-visibility-predicates.ts:validateVisibilityPredicatesnow also walksapps[].navigation,apps[].areas[].navigationand every entry'schildren, and runs the existingvisibility-predicate-syntaxjudgment (celRefusal, formula'sparseCelToAstWithReason, no second parser) on each entry'svisible. A bare string and a{ dialect: 'cel' }envelope are judged (the console evaluates both on the CEL engine since console: a bare-string CEL predicate (navvisible, pagevisibleWhen) runs on the legacy evaluator and fails, though the spec defines a bare string as CEL shorthand #27457); an envelope of another dialect is the console's legacy reading and a boolean is no predicate, so neither is judged. The finding is located at the key (apps[0].navigation[0].visible). The syntax finding is built by one helper,syntaxFinding, for page/view elements and nav entries alike; only two words move per surface: the consequence clause (a nav gate falls closed, so "the entry is hidden from every viewer") and the remedy example ('org_admin' in current_user.positions, the spec's own nav example, since a nav entry binds norecord). Page and view wording is byte-identical (live probe below shows the same page message on base and head).record,current_user,page), and a nav entry bindscurrent_user,user,ctx.user,os.user,features(plusdatabeside adataSource), sofeatures.cloudManaged != truewould be refused as an unbound root.packages/lint/src/validate-page-variables.ts(new) with three ids:page-variable-name-duplicate(at the second entry'sname, naming the first index),page-variable-name-empty(empty or blank),page-variable-default-type(adefaultValueof another kind thantype: string forstring/record_id, finite number, boolean, plain object, array;nulladmitted for any type; notype= the schema's defaultstring). Nopackages/spec/**edit: the rule needs no shape change.packages/lint/src/authoring-rules.ts: the visibility family (validateVisibilityPredicates,validatePredicatePathRefs) declaresruntimeTypes: ['view', 'page', 'app'](the family stays on one type set, asauthoring-rule-wiring.test.tspins; the path rule judges nothing on an app).validatePageVariablesis registered gating,CLI_AND_RUNTIME,runtimeTypes: ['page'], aftervalidatePrintPageBlocks. No gate change inmetadata-protocol:appalready maps toapps, and save, draft_diagnosticsand publish all readjudgeRuntimeAuthoringRules.packages/lint/src/index.ts: exports the rule and its three id constants.packages/lint/src/rule-explanations.ts: threeos explainentries, and a paragraph onvisibility-predicate-syntaxfor nav entries.content/docs/**(4 CLI transcripts):author-time rules (57)→(58), the count the registry derives with the new rule (check:docs-transcript-drift)..changeset/28663-nav-visible-syntax-page-variables.md:@objectstack/lintminor, BREAKING banner, both declaration lines, ADR-0087not-required (no-migration-prescription).Migration note. Nav
visiblevalues in the shipped corpus: 1 (examples/app-crmcurrent_user.can('crm_opportunity', 'read')), 0 refused. Page variables: 5 on 2 showcase pages, 0 refused.os validateonexample-crm,example-showcase,example-todoat head: exit 0, 0 findings of the new ids. Stored apps and pages keep loading and serving; only the next save of one with a finding is refused.Tests
packages/lint/src/runtime-gate.app-nav-visible-predicate-writes.test.ts(new): the card'svisible: "'org_owner' in"top-level, inside an area and inside a group'schildrenis refused at the app door at the key, andos validate(runAuthoringRules('validate')) gives the same finding; the{ dialect: 'cel' }envelope too. Controls admitted at both:'org_owner' in current_user.positions(string and envelope),features.cloudManaged != true,current_user.can(...),user.isPlatformAdmin == true, atemplateenvelope,true.packages/lint/src/runtime-gate.page-variable-writes.test.ts(new): duplicate, empty, blank,number+"abc",boolean/array/object/record_idmismatches and an untyped number default, each refused at the page door with its path, with door/os validateparity; four declaration sets admitted (the showcase's two included,nulldefaults,[]); three faults on one page are three findings.packages/metadata-protocol/src/protocol.draft-publish-verdict.test.ts: five new rows in the Studio/metadata: a draft the editors, the draft_diagnosticsand the Problems tab all call valid is refused only at publish — and one such draft rolls back the whole package release #26707 table (nav top-level, nav in an area, the three variable faults): the draft saves, readsvalid: falsewith the publish's own words, and publish refuses422 INVALID_METADATA; clean nav + variables readvalid: trueand publish; paths are item-relative (areas.0.navigation.0.visible,variables.0.defaultValue).packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts: the activesaveMetaItemrefuses the app (door finding = build finding key by key, nothing stored) and each variable fault; clean controls land.validate-security-posture.runtime-surface.test.ts(two),validate-predicate-path-refs.test.ts(one), and the page door's ordered list inruntime-gate.page-visibility-predicate-writes.test.ts.Red on base 2678600, green on head
Ablations (scripts/ablation-replace.mjs, lint rebuilt, ablation-dist-preflight both legs, restore = blob equals HEAD)
Record:
pm-orders/server/evidence/28663/ablations.txt.Live probe: card steps 2 and 4 on a stock showcase boot, base vs head
Commands:
pnpm --filter @objectstack/example-showcase dev -- --fresh -p PORT; sign inPOST /api/v1/auth/sign-in/emailas the seeded admin;POST /api/v1/packagesa scratch writable package; thenPUT /api/v1/meta/app/qa_nav_app?mode=draft&package=PKG(navvisible: "'org_owner' in"),GET …?state=draft&package=PKG,POST /api/v1/packages/PKG/publish-drafts; the same for a page withvisibleWhen: "record.status =="and a page withvariables[number "abc", "", duplicate]; and an activePUT /api/v1/meta/app/qa_nav_app2?package=PKG. Base = origin/main lint sources over the four edited files, lint rebuilt.Record:
pm-orders/server/evidence/28663/live-probe.txt(withprobe.sh).Acceptance notes
Out of scope by the order, each measured at head on the same boot and still admitted (
_diagnostics {"valid":true}), not fixed here:sourcenaming a component the page does not hold (source: "no_such_component"): admitted.visibleWhenreading an undeclaredpage.nosuch: admitted.visiblethat is flawless CEL but over the parse budget (a 90-clause||chain) is admitted at the draft read; the page-side twin isvisibility-predicate-over-budget. Not wired here because the ruling names the syntax judgment only.Also noted: when a nav
visibleuses an operator from another language (===), the remedy's example comes from the shared operator table and isrecord-rooted (record.country == 'USA'). The operator correction itself is right on any surface.Declaration: the claim's line reads
Clause-②: no; this body and the changeset carryClause-②: no (narrowing), becausecheck-changeset-no-major.mjsrefusesMetadata-protocol: narrowedbeside a line without the(narrowing)arm. The order's Declarations section names it a narrowing.Verification
Derived gate loop (
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 89 families with the docs edit) atbb33ace7: 89 exit 0.dispatch-gates --ran:89 derived famil(ies) accounted for — 89 run, 0 NOT-MEASURED. Record:pm-orders/server/28663-gates-ran.txt.9fcdbbc4readcheck:docs-transcript-driftexit 1 (the four transcripts printed 57 rules; the registry derives 58 with the new rule), fixed inbb33ace7; andcheck-plugin-teardown-shape --self-testexit 3 (shallow clone), exit 0 aftergit fetch --depth=1 origin 621a4876.check:type-check-debtunder the lock:check-type-check-coverage --re-measure: OK — 0 raw tsc error(s).9fcdbbc4(merge of origin/main;bb33ace7adds only the docs transcripts):@objectstack/lintTest Files 186 passed, Tests 7749 passed;@objectstack/metadata-protocolTest Files 291 passed / 4 skipped, Tests 21963 passed / 26 skipped; bothtypecheckexit 0.eslint packages/lint packages/metadata-protocol --no-inline-configexit 0.(narrowing)arm) atbb33ace7, closure built,pnpm --filter @objectstack/dogfood testunder the lock: VERDICT command-exit 0 · Test Files 369 passed / 3 skipped (372) · Tests 2981 passed / 28 skipped (3009).🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5nHMwmgiBBzV1TsunS
Generated by Claude Code