You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec: a page visibleWhen over the CEL engine's maxAstNodes (256) passes PageSchema at publish, then faults on every evaluation in the console and fails open, so the page gate it declares is never enforced #24953
Filing gate ①: class (c), declared ≠ enforced, measured. Filed by repo:cloud#1 (seat post #6026, session session_01FSg7JRUiTPo8GrgT38tAWP) from the objectstack-ai/cloud#3108 dev report (cloud comment 6297789614). ⛔ Not a claim.
Reader who acts: triage grades and routes it (expected domain:spec, with @objectstack/formula bounds and the page schema's predicate fields).
Dedupe: objectstack issues of both states (444 read) grepped for maxAstNodes, ast node, predicate size, bounds and fail open: 0 hits on point.
What happens (framework 9d13b5fc, objectui 616df659)
packages/formula/src/cel-engine.ts (objectstack main74fcec1e, :532-534) states the platform contract: 「A source over maxAstNodes / maxDepth / maxListElements does not parse here, because it does not parse anywhere else on the platform either」. DEFAULT_LIMITS.maxAstNodes is 256.
A cloud page declared a page:tabs item visibleWhen of 391 AST nodes (cloud commit cf2d31b7).
It passed PageSchema parse and the authoring-time gates: cloud's check:action-predicate-roots, 654 sources, green.
On a local stack with the pinned console, every evaluation faulted with [bounds] Exceeded maxAstNodes (256) for that item.
The renderer failed open, so the tab drew for a user the predicate meant to exclude.
A predicate field the page schema declares (visibleWhen and its siblings) is refused at publish with the same bounds verdict validateExpression gives. That is a loud VALIDATION_ERROR naming the field and the bound, the "declare = enforce" rule, instead of a runtime fault that fails open.
A test: a page whose visibleWhen exceeds maxAstNodes is refused at parse or publish.
Acceptance
The 391-node source above is refused when the page is registered or published, with the bound named.
Claim: PM loop round 21
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-24953-page-predicate-bounds
Worktree: objectstack-issue-24953
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/main `` or later; stop on a breach and explain it in the report):
the page schema's predicate fields (packages/spec/src/ui/page.zod.ts and the page:tabs item / component visibleWhen slots it declares), or the packages/lint expression pass that judges them;
the bounds verdict reused from @objectstack/formula (validateExpression / DEFAULT_LIMITS), not re-implemented;
tests, generated artifacts and .changeset/24953-*.md.
Container & model: M, mode:subagent, model: default (no path-derived mandate)
Clause-②: no
Responsibility: n/a — a declared predicate that fails open at runtime (declared ≠ enforced)
Thread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching page.zod.ts and the expression pass before opening its own.
Under 「甲」 (#60156292005854): refusing an over-bounds predicate that passes today is a narrowing no conversion can carry. So 18.x ships it as a WARNING at os validate / os build / the publish door, and the refusal is filed for 19.0, unless the dev measures otherwise and says so. Clause-② stays no either way.
Read on origin/main `` at 2026-10-20T20:24Z: packages/formula/src/cel-engine.ts declares that a source over `maxAstNodes` (256) "does not parse anywhere else on the platform either". `PageSchema` accepts a 391-node `page:tabs` item `visibleWhen` (objectstack-ai/cloud#3108).
Claim correction · domain:spec seat 3 · 2026-10-20T20:25Z · ⛔ Not a claim.
Claim 6300692037 prints a blank origin/main sha, because a git fetch failed with HTTP 502 at the act. The read and the worktree are on origin/mainf32d795ce5.
{
"issue": 24953,
"status": "done",
"branch": "claude/issue-24953-page-predicate-bounds",
"pr": "https://github.com/objectstack-ai/objectstack/pull/24999",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "Premise reproduced on origin/main f32d795ce5. A page:tabs item visibleWhen of 98 || terms (489 AST nodes; validateExpression answers cel-too-large, maxAstNodes, 256) passed PageSchema.safeParse and drew 0 findings at runAuthoringRules validate and build, and 0 errors and 0 advisories at the page publish door. The same source on the component NODE visibleWhen was already an ERROR (visibility-predicate-over-budget, at every door). So the bound is already enforced on the node slot, and the visibility pass misses every CEL slot inside the properties bag. Measured clean on main: object-form section visibleWhen, object-form inline field visibleWhen, record:alert visible. The new rule page-predicate-over-budget (packages/lint/src/validate-page-predicate-bounds.ts) parses each walked component's properties with its ComponentPropsMap row and judges every position where the parse produces a cel envelope, so it keeps no key list. The verdict is validateExpression's own cel-too-large, with its limit and limitValue. The finding names the key and the bound and does not echo the source. It does not descend composition slots, so nothing is reported twice. Per 甲 it is a WARNING (advisory tier) at os validate, os build, os lint and the page door advisories channel. A within-bounds source is unchanged. Four content/docs CLI transcripts move the author-time rule count from 49 to 50 (check:docs-transcript-drift). Changeset: @objectstack/lint minor, Clause-② no. PR body says Closes #24953. The 19.0 refusal text is in followup_19_0 for the seat to file.",
"tests": "Head cceddfcb61. Repro before the fix: a temporary probe file on base f32d795ce5, since deleted. It printed 'PageSchema ok? true', 'validate []', 'build []', 'door errors [] adv []', and the node-level control 'component [[visibility-predicate-over-budget,error,pages[0].regions[0].components[0]]]'. New suite: pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-page-predicate-bounds.test.ts gave 18 passed (VERDICT command-exit 0). Full lint suite: 152 files passed, 1 failed (the pinned page-door rule roster in runtime-gate.page-visibility-predicate-writes.test.ts). The roster was updated, and that file then passed 15/15. pnpm --filter @objectstack/lint typecheck gave VERDICT command-exit 0 (tsc --noEmit plus check:test-typecheck OK). Gates: dispatch-gates --commands derived 65 commands, and 29 more after the docs edit. Exit codes were captured with redirect-then-exit. Every command exited 0 except three. check:docs-transcript-drift went red (stale count 49), was fixed, and reran green ('4 declared transcript value(s) across 418 page(s) ... equal'). check:dual-build-cjs-loads gave exit 3, PREREQUISITE NOT MET (no full-repo dist): NOT MEASURED, declared to CI. check:lean-entry-closure gave exit 3, then MODULE_NOT_FOUND on metadata-core dist after a partial objectql build: NOT MEASURED, declared to CI. @objectstack/spec check:skill-examples gave exit 3, PREREQUISITE NOT MET (client dist): NOT MEASURED. pnpm --filter @objectstack/spec check:generated exited 0 (spec untouched). dispatch-gates --ran gave '94 derived famil(ies) accounted for'. No ablation was run: the red-before-green is the repro above, plus the node-level control and the within-bounds control in the suite. packages/cli integration tier: not touched, declared to CI.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay (objectstack-fleet[bot]): pr_create (POST /repos/objectstack-ai/objectstack/pulls draft, plus POST /issues/24999/assignees baozhoutao) and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/24953/comments). Plus git push (not REST). Zero label writes: the dispatch named no label and the diff carries a changeset.",
"open_questions": [],
"followup_19_0": "Title: lint: page-predicate-over-budget becomes an error at 19.0 (refuse a page component props CEL slot over the platform parse bounds). Body: In 18.x, page-predicate-over-budget (validatePagePredicateBounds, @objectstack/lint, landed by #24999 for #24953) reports a warning at os validate, os build, os lint and the page publish door. It fires on a CEL slot declared inside a page component's properties bag, such as a page:tabs item visibleWhen, object-form section and inline field visibleWhen / readonlyWhen / requiredWhen, record:alert visible, or action:* visible / disabled, whose source overruns DEFAULT_LIMITS (maxAstNodes 256, maxDepth, maxListElements). Such a source does not parse anywhere on the platform. It faults on every evaluation, and the console fails open. It is a warning only because of 甲 (#6015, record 6292005854): the refusal is a narrowing that no ADR-0087 conversion can carry. Wanted at 19.0: (1) the finding's severity becomes error, and the authoring-rules entry moves its tier from advisory to gating in the same edit, so a page carrying such a slot fails os build and is refused at the page door with 422 VALIDATION_ERROR on its next save. Stored pages keep loading, because the gate judges writes only. (2) The message drops 'A future major release refuses it.' (3) validate-page-predicate-bounds.test.ts flips its warning assertions to error and adds a door-refusal pin with code and status. (4) A changeset marks it BREAKING with FROM (warning, page saves) and TO (error, page refused), plus the one-line fix: shrink the predicate, or precompute it into a formula or roll-up field. Acceptance: the card's ~390-node tab-item visibleWhen is refused at os build and at the page door with the bound named. A within-bounds source is unchanged. Dedupe words: page-predicate-over-budget, maxAstNodes, page:tabs visibleWhen, 19.0 refusal.",
"out_of_scope_findings": [
"class: a (fails open, user-visible) · reach: objectui console renders a page:tabs item whose visibleWhen faults ([bounds] Exceeded maxAstNodes (256), the card's cloud repro): the tab draws for a user the predicate excludes · repo: objectui (the tab-item evaluator's fault fallback is visible=true) · dedupe words: tabs visibleWhen fail open, predicate fault fallback, evalFieldPredicate fallback",
"class: c · reach: os validate on base f32d795ce5 — a page:tabs item visibleWhen 'record.x === 1' (not CEL) parses through PageSchema and draws 0 findings at validate/build/page door; same for object-form section/field predicates and action:* visible inside the props bag (only bounds are judged by the new rule; the node-level visibility family's syntax/unknown-function verdicts are not borrowed because a tab item's environment differs: data = row, bare fields spread) · evidence: repro probe 'tab item syntax fault parse true []' · dedupe words: props-bag predicate syntax, tab item visibleWhen syntax, page:tabs predicate not judged",
"carrier: PR #24947 (authoring-rules.ts, different entry) · noted, not filed"
]
}
Measured: the component node's own visibleWhen was already refused over bounds (visibility-predicate-over-budget). The gap was every CEL slot inside a component's properties bag: page:tabs items, object-form sections and fields, record:alert, and action:*.
The fix: a new @objectstack/lint rule, page-predicate-over-budget. It parses each walked component's props with its ComponentPropsMap row and judges every CEL envelope with validateExpression's own cel-too-large verdict. Under 「甲」 it is a warning at os validate, os build, os lint and the page door. Clause-②: no. No contract review is owed, since only lint is touched.
Noted, not filed: props-bag predicates get no syntax or unknown-function verdict, only bounds. The node-level family is not borrowed because a tab item's evaluation environment differs.
Claim 6300692037 ends here; pm:dispatched is removed in this stroke.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 21
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24953-page-predicate-boundsWorktree:
objectstack-issue-24953Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/main`` or later; stop on a breach and explain it in the report):packages/spec/src/ui/page.zod.tsand thepage:tabsitem / componentvisibleWhenslots it declares), or thepackages/lintexpression pass that judges them;@objectstack/formula(validateExpression/DEFAULT_LIMITS), not re-implemented;.changeset/24953-*.md.Container & model:
M,mode:subagent,model: default (no path-derived mandate)Clause-②: no
Responsibility:
n/a — a declared predicate that fails open at runtime (declared ≠ enforced)Thread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching
page.zod.tsand the expression pass before opening its own.Under 「甲」 (#6015
6292005854): refusing an over-bounds predicate that passes today is a narrowing no conversion can carry. So 18.x ships it as a WARNING atos validate/os build/ the publish door, and the refusal is filed for 19.0, unless the dev measures otherwise and says so.Clause-②staysnoeither way.Read on
origin/main`` at 2026-10-20T20:24Z:packages/formula/src/cel-engine.tsdeclares that a source over `maxAstNodes` (256) "does not parse anywhere else on the platform either". `PageSchema` accepts a 391-node `page:tabs` item `visibleWhen` (objectstack-ai/cloud#3108).Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Claim correction ·
domain:specseat 3 · 2026-10-20T20:25Z · ⛔ Not a claim.Claim
6300692037prints a blankorigin/mainsha, because agit fetchfailed with HTTP 502 at the act. The read and the worktree are onorigin/mainf32d795ce5.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 24953, "status": "done", "branch": "claude/issue-24953-page-predicate-bounds", "pr": "https://github.com/objectstack-ai/objectstack/pull/24999", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "Premise reproduced on origin/main f32d795ce5. A page:tabs item visibleWhen of 98 || terms (489 AST nodes; validateExpression answers cel-too-large, maxAstNodes, 256) passed PageSchema.safeParse and drew 0 findings at runAuthoringRules validate and build, and 0 errors and 0 advisories at the page publish door. The same source on the component NODE visibleWhen was already an ERROR (visibility-predicate-over-budget, at every door). So the bound is already enforced on the node slot, and the visibility pass misses every CEL slot inside the properties bag. Measured clean on main: object-form section visibleWhen, object-form inline field visibleWhen, record:alert visible. The new rule page-predicate-over-budget (packages/lint/src/validate-page-predicate-bounds.ts) parses each walked component's properties with its ComponentPropsMap row and judges every position where the parse produces a cel envelope, so it keeps no key list. The verdict is validateExpression's own cel-too-large, with its limit and limitValue. The finding names the key and the bound and does not echo the source. It does not descend composition slots, so nothing is reported twice. Per 甲 it is a WARNING (advisory tier) at os validate, os build, os lint and the page door advisories channel. A within-bounds source is unchanged. Four content/docs CLI transcripts move the author-time rule count from 49 to 50 (check:docs-transcript-drift). Changeset: @objectstack/lint minor, Clause-② no. PR body says Closes #24953. The 19.0 refusal text is in followup_19_0 for the seat to file.", "tests": "Head cceddfcb61. Repro before the fix: a temporary probe file on base f32d795ce5, since deleted. It printed 'PageSchema ok? true', 'validate []', 'build []', 'door errors [] adv []', and the node-level control 'component [[visibility-predicate-over-budget,error,pages[0].regions[0].components[0]]]'. New suite: pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-page-predicate-bounds.test.ts gave 18 passed (VERDICT command-exit 0). Full lint suite: 152 files passed, 1 failed (the pinned page-door rule roster in runtime-gate.page-visibility-predicate-writes.test.ts). The roster was updated, and that file then passed 15/15. pnpm --filter @objectstack/lint typecheck gave VERDICT command-exit 0 (tsc --noEmit plus check:test-typecheck OK). Gates: dispatch-gates --commands derived 65 commands, and 29 more after the docs edit. Exit codes were captured with redirect-then-exit. Every command exited 0 except three. check:docs-transcript-drift went red (stale count 49), was fixed, and reran green ('4 declared transcript value(s) across 418 page(s) ... equal'). check:dual-build-cjs-loads gave exit 3, PREREQUISITE NOT MET (no full-repo dist): NOT MEASURED, declared to CI. check:lean-entry-closure gave exit 3, then MODULE_NOT_FOUND on metadata-core dist after a partial objectql build: NOT MEASURED, declared to CI. @objectstack/spec check:skill-examples gave exit 3, PREREQUISITE NOT MET (client dist): NOT MEASURED. pnpm --filter @objectstack/spec check:generated exited 0 (spec untouched). dispatch-gates --ran gave '94 derived famil(ies) accounted for'. No ablation was run: the red-before-green is the repro above, plus the node-level control and the within-bounds control in the suite. packages/cli integration tier: not touched, declared to CI.", "mcp_calls": "0", "api_writes": "2 — fleet-write relay (objectstack-fleet[bot]): pr_create (POST /repos/objectstack-ai/objectstack/pulls draft, plus POST /issues/24999/assignees baozhoutao) and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/24953/comments). Plus git push (not REST). Zero label writes: the dispatch named no label and the diff carries a changeset.", "open_questions": [], "followup_19_0": "Title: lint: page-predicate-over-budget becomes an error at 19.0 (refuse a page component props CEL slot over the platform parse bounds). Body: In 18.x, page-predicate-over-budget (validatePagePredicateBounds, @objectstack/lint, landed by #24999 for #24953) reports a warning at os validate, os build, os lint and the page publish door. It fires on a CEL slot declared inside a page component's properties bag, such as a page:tabs item visibleWhen, object-form section and inline field visibleWhen / readonlyWhen / requiredWhen, record:alert visible, or action:* visible / disabled, whose source overruns DEFAULT_LIMITS (maxAstNodes 256, maxDepth, maxListElements). Such a source does not parse anywhere on the platform. It faults on every evaluation, and the console fails open. It is a warning only because of 甲 (#6015, record 6292005854): the refusal is a narrowing that no ADR-0087 conversion can carry. Wanted at 19.0: (1) the finding's severity becomes error, and the authoring-rules entry moves its tier from advisory to gating in the same edit, so a page carrying such a slot fails os build and is refused at the page door with 422 VALIDATION_ERROR on its next save. Stored pages keep loading, because the gate judges writes only. (2) The message drops 'A future major release refuses it.' (3) validate-page-predicate-bounds.test.ts flips its warning assertions to error and adds a door-refusal pin with code and status. (4) A changeset marks it BREAKING with FROM (warning, page saves) and TO (error, page refused), plus the one-line fix: shrink the predicate, or precompute it into a formula or roll-up field. Acceptance: the card's ~390-node tab-item visibleWhen is refused at os build and at the page door with the bound named. A within-bounds source is unchanged. Dedupe words: page-predicate-over-budget, maxAstNodes, page:tabs visibleWhen, 19.0 refusal.", "out_of_scope_findings": [ "class: a (fails open, user-visible) · reach: objectui console renders a page:tabs item whose visibleWhen faults ([bounds] Exceeded maxAstNodes (256), the card's cloud repro): the tab draws for a user the predicate excludes · repo: objectui (the tab-item evaluator's fault fallback is visible=true) · dedupe words: tabs visibleWhen fail open, predicate fault fallback, evalFieldPredicate fallback", "class: c · reach: os validate on base f32d795ce5 — a page:tabs item visibleWhen 'record.x === 1' (not CEL) parses through PageSchema and draws 0 findings at validate/build/page door; same for object-form section/field predicates and action:* visible inside the props bag (only bounds are judged by the new rule; the node-level visibility family's syntax/unknown-function verdicts are not borrowed because a tab item's environment differs: data = row, bare fields spread) · evidence: repro probe 'tab item syntax fault parse true []' · dedupe words: props-bag predicate syntax, tab item visibleWhen syntax, page:tabs predicate not judged", "carrier: PR #24947 (authoring-rules.ts, different entry) · noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Landed ·
domain:specseat 3 ·baozhoutao· sessionsession_01D6F9axfoPzR7t8G1J7Ytzz· 2026-10-21T00:07Z0a3ce087ccthrough the merge queue. Verified onorigin/main: single parent, and thegit diff C^ Cpatch-id equals the reviewed headcceddfcb61's against its merge base (a50d2c4929).visibleWhenwas already refused over bounds (visibility-predicate-over-budget). The gap was every CEL slot inside a component'spropertiesbag:page:tabsitems, object-form sections and fields,record:alert, andaction:*.@objectstack/lintrule,page-predicate-over-budget. It parses each walked component's props with itsComponentPropsMaprow and judges every CEL envelope withvalidateExpression's owncel-too-largeverdict. Under 「甲」 it is a warning atos validate,os build,os lintand the page door.Clause-②: no. No contract review is owed, since only lint is touched.page-predicate-over-budgetbecomes an error, refusing a page component props CEL slot over the platform parse bounds (the refusal half of #24953) #25002. The console's fail-open on a faulting predicate is filed as console: a page component predicate that faults on evaluation (e.g. apage:tabsitemvisibleWhenover the CEL bounds) fails OPEN, so a tab draws for a user its predicate excludes objectui#13286.Noted, not filed: props-bag predicates get no syntax or unknown-function verdict, only bounds. The node-level family is not borrowed because a tab item's evaluation environment differs.
Claim
6300692037ends here;pm:dispatchedis removed in this stroke.Generated by Claude Code