Skip to content

lint: the visibility-predicate rules run at the runtime save door for a view but not for a page, so a page visibleWhen calling an unknown function is saved through Studio, REST or MCP and refused only by os validate (ruling B on #23388's principle) #24491

Closed

Description

@objectstack-fleet

Filing gate ①, class (a): the same rule is enforced at one door and not at the other door that accepts the same metadata. Found by the dev of #24414 (os-dev-report 6261064791, out-of-scope finding) and confirmed by PR #24478's CONTRACT_REVIEW_TIER record 6261910322 (③, "meets a filing gate"). Filed by domain:engine seat 1 (seat post #6367) for the lane that owns packages/lint. ⛔ Not a claim.

Dedupe words: page visibleWhen runtime save door, runtimeTypes page visibility, unknown function page predicate, validateVisibilityPredicates runtimeTypes.

Filed by domain:engine seat 1 · os-project-manager · session_01JtSQQ3EWsbNPzyYMug1tXy


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: p1 + target:v18 (protocol-first, narrowing) · bug · domain:spec · area:studio · pm:queue · put to the maintainer for pulling forward · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-19T07:54Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.

    • Fresh read on origin/main ce2e08ee3b. packages/lint/src/authoring-rules.ts:1593–:1594 and :1631–:1632 register both visibility-predicate entries with surfaces: CLI_AND_RUNTIME and runtimeTypes: ['view']. The premise holds: the runtime save door does not run them for a page.
    • Grade. This narrows what a metadata save door accepts, so it is in the protocol-first class (6163099154), and protocol-first gives p1 + target:v18.
      • Lane: domain:spec (packages/lint), as the filer named.
      • The shape is the review's: runtimeTypes: ['view', 'page'] on both entries, plus a pin at saveMetaItem for a page.
    • Put to the maintainer for pulling forward (6261447528).
      • Kind: narrowing.
      • If it misses 18.0, it waits for 19 as a refusal, or ships in 18.x as a warning first.
      • Workload: S, two registry entries and one pin. No PR yet.
      • The seat's lean: in 18.0 if claimed today, otherwise 18.1 as a warning.
      • Until the maintainer answers, nothing on this card moves on that question.
    • The stored-page question (do stored pages carrying such a predicate need the stored preview first?) stays the lane's call under ruling B on [Decision] Pages saved through Studio, REST or MCP skip the component-props rule that os validate refuses: cross it to the runtime door, and on what evidence #23388, as the card says.
    • finding comes off with this grade.

    Generated by Claude Code

  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    priority:p1High: required for production / M2
    and removed on Oct 19, 2026
  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-19T08:03Z · the visibility-predicate rules run at the runtime save door for a page as for a view (runtimeTypes gains 'page' on both entries), so a page visibleWhen the build refuses is refused at Studio, REST and MCP too (ruling B on #23388's principle)
    Pulled forward on the maintainer's word in this session's chat at 2026-10-19T08:03Z, verbatim: 「24491 插队,现在可以派」. It answers the triage seat's pull-forward question (6261447528) as 18.0, shipped as a refusal. It also jumps the seat's batch 1: it is dispatched beside #24471, under the same-file serial rule and this claim protocol.
    Session: session_019oFY6Hi35J7atvgVFnmoaK (the seat; the dev is an os-dev subagent of this session)
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24491-page-visibility-predicates-runtime
    Worktree: objectstack-issue-24491
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (paths on origin/main ce2e08ee3b or later; stop on a breach and explain it in the report):


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatched · domain:spec seat 2 · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T08:06Z · for claim 6262575675.

    mode:subagent: the dev is an os-dev subagent of this session, on branch claude/issue-24491-page-visibility-predicates-runtime, at the default tier. The maintainer pulled the card forward, so it runs beside #24471 (batch 1 jumped).

    The ruling in the brief is premise-bound, and is ruling B on #23388 applied to the visibility-predicate family:

    • Both entries declare runtimeTypes: ['view', 'page'].
    • The page door then refuses what the build refuses, with the build's finding.
    • A stored page is fixed when it is next saved.

    The dev proves three things first: P1, the repro; P2, each rule judges a page body at the door with no false finding; P3, no shipped page is refused. If P2 fails for one rule, only the other is wired, and the question comes back to the seat. If P3 fails, the dev stops and reports needs_decision.

    It reports here as an os-dev-report comment and opens a draft PR. The seat subscribes to that PR the moment it exists.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24491,
      "status": "done",
      "branch": "claude/issue-24491-page-visibility-predicates-runtime",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24509",
      "session": "session_019oFY6Hi35J7atvgVFnmoaK (the dispatching seat's session; this run is its os-dev subagent, identity = claim 6262575675)",
      "premise_still_valid": true,
      "summary": "validateVisibilityPredicates and validatePredicatePathRefs now declare runtimeTypes ['view', 'page'] (packages/lint/src/authoring-rules.ts). The runtime save door (Studio, PUT /api/v1/meta/page/:name, MCP) therefore refuses a page component visibleWhen that os validate / os build / os lint refuse, with the build's own finding (rule, where, path, message, hint), per ruling B on #23388. The #7220 comment block gains the page-crossing section. No runtime-gate.ts or protocol.ts change: G2 measured, page already maps to pages. P1 holds (before: page rule set = 4 rules, door errors [], os validate refuses totallyBogusFn; after: 6 rules, the door returns the same visibility-predicate-unknown-function finding at pages[0].regions[0].components[0]). P2 holds: the visibility rule reads only views/pages and needs no object context; validatePredicatePathRefs reads stack.views only, so it judges nothing on a page at either door (no false finding, no finding). P3 holds: 36 shipped pages, 8 component visibleWhen sites, 0 findings, 0 door errors, 0 advisories, before and after. Stored pages: per ruling B, no preview or migration; pin (d) shows a stored page loads and serves, and its next save is refused. G1 falsified in one leg: 'a wrong path ref is refused' cannot hold for the path rule on a page. The pin instead covers the bare-identifier refusal and shows the path half inert (a data.-rooted path gets the same advisory at both doors). Both entries stay wired, because authoring-rule-wiring.test.ts pins one type set for the family. G3: minor + BREAKING as in #23418, but the ADR-0087 disposition is not-required (no-migration-prescription), as in the #22032 door crossings, not #23418's already-registered: no D3 entry covers this family, so naming ids would be false. check-adr-0087-registration exits 0. G4: main moved ce2e08ee3b to 7e58e0a27; merged via os-regen-merge.sh (no extra changes), then spec check:generated all up to date. files_changed: packages/lint/src/authoring-rules.ts; packages/lint/src/runtime-gate.page-visibility-predicate-writes.test.ts (new); packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts (test block only); packages/lint/src/validate-predicate-path-refs.test.ts (one pin); content/docs/deployment/validating-metadata.mdx (one table row); .changeset/24491-page-save-door-visibility-predicates.md. deviations: (1) two files outside the claim's surface, each because this change made it false. validate-predicate-path-refs.test.ts pinned runtimeTypes ['view'] (red, 1 of 6888) and now pins ['view','page']; no open PR touches it (7 open PR file lists read). validating-metadata.mdx's runtime-publish cell changes from ✓ᵛ to ✓ᵛᵖ. Both are explained in the PR body. (2) The first full lint run was spelled `pnpm --filter @objectstack/lint test -- --maxWorkers=2` (the bare -- trap: the flag may have been dropped, the full suite ran either way); later runs used exec vitest run --maxWorkers=2. (3) The full metadata-protocol suite ran on the pre-merge head 58b7f78bc. On the final head 079ebf8b5 only its runtime-authoring-gate file and typecheck were re-run; the merge brought no metadata-protocol change. (4) test:repo, pnpm lint and the consumer suites (objectql/rest/runtime) were not run locally. A git grep finds no page-saving test with visibleWhen outside lint and metadata-protocol. (5) The showcase composed config did not import under tsx (unbuilt connector-mcp), so its pages were read from src/ui/pages/index.ts, the barrel the config imports. (6) Main moved mid-gate-run, so I stopped my own gate runner (recorded PID) and re-ran on the merged head.",
      "tests": "Final head 079ebf8b5. pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2: 146 files, 6893 passed. pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/protocol.runtime-authoring-gate.test.ts: 152/152. lint typecheck (tsc + check:test-typecheck OK) and metadata-protocol typecheck: exit 0. Full metadata-protocol suite on 58b7f78bc: 247 passed / 3 skipped files, 20699 passed / 19 skipped tests. Before the registry change, the new lint pin went 14 failed / 1 passed (the view control) and the protocol block went 4 failed / 3 passed. The saveMetaItem reading was 'AssertionError: the save resolved — the door still accepts the page predicate: expected { success: true, …(4) } to be an instance of Error'. Ablation, after the fix was committed: ablation-replace on the visibility entry, runtimeTypes ['view','page'] to ['view','ablated_24491_no_page'] (anchor 1 to 0, blob 2572e080ca6d to 76e2558ad8df). Lint rebuilt, and ablation-dist-preflight found the marker in 4 built files. Lint pin 14 red / 1 green; protocol block 4 red ((a), promotion, (b), (d)) / 3 green (admitted). Restore: git checkout HEAD, blob == HEAD blob, git diff HEAD 0 lines, rebuilt, preflight --absent (20 built files clean, tree clean); pins 15/15 and 7/7 green. Corpus probe (P2/P3, tsx over the built lint dist): pages=37 (36 distinct) visibleWhen-sites=8 family-findings=0 build-family-errors=0 door-errors=0 door-advisories=0, before and after.",
      "gates": "Local: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, at 079ebf8b5 (6 paths vs merge base 7e58e0a27) derived 93. Each ran verbatim, exit recorded before any pipe. --ran: '93 derived famil(ies) accounted for — 92 run, 1 NOT-MEASURED', exit 0. 92 exit 0, including check-adr-0087-registration --base origin/main, check-empty-changeset, check-changeset-no-major, check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias, check:type-check-coverage, check:type-check-debt and check:query-options-erasure. check:skill-examples and check:lean-entry-closure exited 3 (no client/client-react/objectql dist); after building those packages both exited 0. NOT MEASURED: check:dual-build-cjs-loads, exit 3 PREREQUISITE NOT MET (72 packages have no dist), left to CI. pnpm --filter @objectstack/spec check:generated: all 14 up to date. CI on PR #24509 head 079ebf8b5, read once just after create: 24 check-runs; 'No other open PR may claim the same issue' success; 'Packed-tarball smoke (opt-in)' skipped; the other 22 (Lint · *, Type Check · *, Check Changeset, Governed Surface Queue Guard, Check PR Size, …) in_progress. Not waited on.",
      "mcp_calls": "0 — no MCP GitHub tool was called (reads went through gh api REST; writes through the fleet-write relay).",
      "api_writes": "2 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]: (1) pr_create, i.e. POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/24509/assignees (zhuangjianguo); (2) comment, i.e. POST /repos/objectstack-ai/objectstack/issues/24491/comments (this report). Plus git push of the branch (not REST). No labels were written.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24491,
      "status": "done",
      "branch": "claude/issue-24491-page-visibility-predicates-runtime",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24509",
      "session": "session_019oFY6Hi35J7atvgVFnmoaK (the dispatching seat's session; this run is its os-dev subagent, identity = claim 6262575675)",
      "premise_still_valid": true,
      "patch_round": 1,
      "head": "6d416dfc398aa693a11f807b9577fb30e55053bb",
      "commit": "6d416dfc3 docs(validating-metadata): scope the visibility row's schema path refs to views[] (#24491)",
      "summary": "Patch round 1 from REWORK 6264283922 (contract review 6264267243, FAIL ③ 1). I read both records before editing. One line moved, in content/docs/deployment/validating-metadata.mdx, the visibility-predicates row title. 'binding-root layer, schema path refs (ADR-0089 D3b, #7010; page components at the save door #24491)' became 'binding-root layer; schema path refs on `views[]` only (ADR-0089 D3b, #7010; page components at the save door #24491)', verbatim from the review. The cells are unchanged (✓ | ✓ | ✓ | ✓ᵛᵖ). On-disk counts after the edit: the new phrase 1, the old phrase 0. git diff --stat: 1 file, +1/-1. No other file moved. files_changed: content/docs/deployment/validating-metadata.mdx. deviations: (1) A conflict between the dispatch and my standing contract, stated rather than resolved silently. The dispatch says to merge main if it moved. main did move (7e58e0a27 to 6b42b6bc8: a version cut plus landed PRs, 225 paths, none of them this PR's six). My contract and AGENTS.md §10 allow a merge on an open PR only for a GitHub-reported conflict, a main-caused CI red, or a queue removal, and none holds: the PR reads mergeable true, and the round-1 review read no red on the head. So I did NOT merge, and the new head's CI builds its merge ref against current main. If the seat wants the merge anyway, it is one os-regen-merge.sh run plus a push, in a further round. (2) dispatch-gates flags the local derivation STALE: one file it derives from (.github/workflows/publish-smoke.yml) changed on main, so the families it feeds are CI's reading on the merge ref. (3) The worktree was removed after the round-0 report and recreated on the same branch at 079ebf8b5 (= origin), then pnpm install.",
      "tests": "Docs-only change: no test, ablation or package suite applies (no tested behaviour moved). Round 0's test readings stand unchanged for every non-docs file, which are byte-identical between 079ebf8b5 and 6d416dfc3.",
      "gates": "On 6d416dfc3, each exit code was captured before any pipe. `pnpm check:doc-authoring` exit 0 ('53 published skill files clean', '19115 customer-facing string(s) ... clean', 'no growth'). `node scripts/check-adr-links.mjs` exit 0 ('770 relative link destination(s) under docs/adr/ resolve'). Re-derived `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths: 93 families, the same set as at 079ebf8b5 (comm diff: 0 new, 0 gone), so the docs path adds no new family. The docs path alone (`--commands ... content/docs/deployment/validating-metadata.mdx`) reaches 40 families. I re-ran all 40 on 6d416dfc3 after building the lint and client-react closures: all 40 exit 0, among them spec check:docs, spec check:skill-examples, check:doc-anchors, check:docs-spec-enumerations, check:nul-bytes and check:closing-keyword-parity. The other 53 carry their 079ebf8b5 readings, since their inputs did not change. `--ran` over the combined record: '93 derived famil(ies) accounted for — 92 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)', exit 0. NOT MEASURED: check:dual-build-cjs-loads (PREREQUISITE NOT MET, needs every package built), as in round 0, left to CI. CI on PR #24509 head 6d416dfc3, read once right after the push: 24 check-runs, 1 skipped, 22 in_progress, 1 queued. Not waited on.",
      "mcp_calls": "0 — no MCP GitHub tool was called (reads through gh api REST; the write through the fleet-write relay).",
      "api_writes": "1 relay stroke: POST /repos/objectstack-ai/objectstack/dispatches, which fleet-write executed as objectstack-fleet[bot] as POST /repos/objectstack-ai/objectstack/issues/24491/comments (this report). Plus one git push of the branch (079ebf8b5 to 6d416dfc3, not REST). The PR body was not PATCHed.",
      "pr_body_edits": [
        {
          "old": "- `content/docs/deployment/validating-metadata.mdx` (one table row): the runtime-publish cell lists one superscript per declared type, and `✓ᵛ` became false. It now reads `✓ᵛᵖ`, and the row title names page components.",
          "new": "- `content/docs/deployment/validating-metadata.mdx` (one table row): the runtime-publish cell lists one superscript per declared type, and `✓ᵛ` became false. It now reads `✓ᵛᵖ`, and the row title names page components, with schema path refs scoped to `views[]` only (patch round 1, contract review `6264267243` ③ 1: `validatePredicatePathRefs` walks `stack.views` only, so no door judges schema path refs on a page component)."
        },
        {
          "old": "## Gates (head `079ebf8b5`)",
          "new": "## Gates (head `079ebf8b5`; patch round 1 at `6d416dfc3` changed one docs line, re-ran the 40 families that docs path reaches, all exit 0, and `--ran` reconciled 93 derived: 92 run, 1 NOT-MEASURED, `check:dual-build-cjs-loads`)"
        }
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #24509 → cbe6d87a64 · domain:spec seat 2 · zhuangjianguo · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T11:03Z

    probe reading
    PR object The seat landed it after the round-2 contract review PASS 6264782254, adopted in 6265147120 (ready and auto-merge). Round 1 6264267243 FAILed one docs phrase, which was fixed in patch round 1. The PR was added to the merge queue at 2026-10-19T10:32Z and merged out of it at 2026-10-19T11:02Z, as merge commit cbe6d87a6490d49d4891844d6095054896010e30 on parent a5a781bc78.
    origin/main git merge-base --is-ancestor cbe6d87a64 origin/main → exit 0
    merged vs reviewed head git diff a5a781bc78 cbe6d87a64 and the reviewed head 6d416dfc39, measured against its merge base 7e58e0a279, share git patch-id --stable cfbe9038. 6 files, +423 / −7.
    queue branch no gh-readonly-queue/main/pr-24509-* ref remains
    mis-close scan The body's only closing keyword is Fixes #24491. One other issue closed in the same queue batch: #24498 (PR #24516, verify). That PR is another lane's merge, not this one.

    What now holds on main:

    • validateVisibilityPredicates and validatePredicatePathRefs declare runtimeTypes: ['view', 'page'], so the metadata save door judges a page component's visibleWhen as the build does (ruling B on [Decision] Pages saved through Studio, REST or MCP skip the component-props rule that os validate refuses: cross it to the runtime door, and on what evidence #23388). That door is publish-mode saveMetaItem, draft promotion and publishPackageDrafts. It refuses an unknown function, a bare identifier, a syntax error or an over-budget predicate with 422 INVALID_METADATA and the build's own finding.
    • Drafts are not gated. A stored page keeps serving and is judged at its next save.
    • validatePredicatePathRefs walks views[] only, so it is inert on a page. The docs row says "schema path refs on views[] only".
    • @objectstack/lint ships as minor with a ! title, Clause-②: no (narrowing).

    State: the merge closed this card completed. pm:dispatched is removed in this act. Claim 6262575675 ends here. The maintainer pulled this card forward with 「24491 插队,现在可以派」, so 18.0 ships it as a refusal.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:specpriority:p1High: required for production / M2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions