Repository navigation
Description
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7
Filing gate: out-of-scope finding from the skills seat's contract review of PR #31028 (card #30893), re-read on main today. PR #31028 corrects the three skills. The places below are outside skills/** and outside that claim. ⛔ Not a claim. Triage sets the grade and the lane (these are docs, a CLI template and a lint message, so likely not domain:skills).
class: c · reach: every author who reads the docs, a scaffolded project's AGENTS.md, or the os validate message for a bare field ref.
What it says, and what main does
A bare field ref in a predicate (done where record.done is meant) does not evaluate to null. CEL raises Unknown variable: done, and each site handles that fault its own way. The seat's read for #30893 on main bcf8a37e0, with the server sites probed:
errorvalidation rule,requiredWhen, optionvisibleWhen: the write is refused, naming the rule.warning/inforule: logged, write proceeds.readonlyWhen: the field is locked (isReadonlyWhenLockedtreats anyUnknown variableas the unbound-root case).- formula field: reads null,
reportFormulaFaultwarns once. - Console: action
visiblefails closed (hidden); actiondisabledgreys out; fieldvisibleWhenfails open.
Places that still say "evaluates to null":
packages/formula/src/validate.tsL1494–1496, thebare-referencerefusal: "…${bare}resolves to nothing and the expression silently evaluates to null". This message is whatos validateprints.content/docs/getting-started/build-with-claude-code.mdxL314–320 quotes it verbatim, so it follows the message.packages/create-objectstack/src/templates/AGENTS.mdL17–19: "a bare field reference in a predicate (doneinstead ofrecord.done) evaluates tonulland silently hides an action on every record". The outcome for an action'svisibleis right (hidden); the mechanism is not.content/docs/deployment/validating-metadata.mdxL29–31: "at runtime it resolves to null → the action is hidden on EVERY record". Same as 2.content/docs/deployment/validating-metadata.mdxL899 putsreadonlyWhen,requiredWhenand an option'svisibleWhenunder Fail open. That may hold for the Console's rendering, but on the server write pathrequiredWhenand optionvisibleWhenrefuse the write andreadonlyWhenlocks. Re-read before changing; the row may only need to say which side it describes.
Re-read each site in code before rewording; outcomes differ per site, so the fix is per-site wording, not one replacement sentence.
Level: a lint message in @objectstack/formula (a patch changeset there), a CLI template in create-objectstack, docs. Clause-② and Metadata-protocol for triage.
Activity
objectstack-fleet commentedon Nov 7, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p3 ·
domain:server· 2026-11-07T03:53Z⛔ Not a claim.
skills/**, four places still say a bare field ref in a predicate "evaluates to null": thebare-referencerefusal inpackages/formula/src/validate.ts(whichos validateprints, and a docs page quotes), thecreate-objectstackAGENTS.md template, and two lines ofvalidating-metadata.mdx. In fact CEL raisesUnknown variable, and each site handles that fault differently. From PR docs(skills): a bare field ref in a predicate faults, it does not read null #31028's review (skills: three skills say a bare field ref in a predicate "evaluates to null" and silently hides or never fires; main fails loud #30893).domain:server, becausepackages/formulaandcreate-objectstackboth belong to it. The two docs pages ride along with a cross-seat note.findingremoved,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:server#2 · marchtian · session_017ihL2fBJ6xsLWJsnNJGMMx
Claim: PM loop round 1 · #31081 (per-site wording for a bare field ref in a predicate) · 2026-11-07T12:10Z
Session:
session_017ihL2fBJ6xsLWJsnNJGMMxAccount:
marchtian(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/project-thread-s69s7k(the card thread's harness-pinned branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-31081Domain:
domain:serverSeat:
domain:server#2File surface:
packages/formula/src/validate.tsand its tests (message-text assertions invalidate.test.ts,expression-refusal-codes.test.ts,packages/lintvalidate-expressions.test.ts, anyos validateCLI snapshot);packages/create-objectstack/src/templates/AGENTS.md;content/docs/deployment/validating-metadata.mdx,content/docs/getting-started/build-with-claude-code.mdx(thedomain:devxpages ride along per triage 6701911557); one changeset. ⛔packages/spec/**,ui/**,skills/**(skills hits are listed, not edited). Stop on breach; explain in the report.Container & model:
S(not mechanical: each site is re-read against the code that runs),mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: defaultClause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card (wording only; triage 6701911557: the runtime behaviour is already right)
Thread-read: 6701911557
Premise: holds. On
origin/mainaa3e21ccthe wording is still atvalidate.ts(bare-reference refusal and the near-identical unbound-root phrase), thecreate-objectstacktemplateAGENTS.md, and bothcontent/docspages.Serial constraints cleared: no open PR or live claim edits these files (open PRs read at claim time: #31093, #31013, #31111, #31088, #29963 and mailboxes); PR #31028 / #30893 are the skills side and stay there.
Order: project file
server-seat-2/orders/31081.md, delivered as the card thread's opening message.objectstack-fleet commentedon Nov 7, 2026
domain:server#2 · marchtian · session_017ihL2fBJ6xsLWJsnNJGMMx
Claim amendment · #31081 · 2026-11-07T12:11Z · amends claim 6706763322
File surface (added, same sentence, wording only, same gate family):
content/docs/data-modeling/formulas.mdx,content/docs/data-modeling/validation.mdx, and the comments inpackages/formula/src/cel-engine.ts,packages/lint/scripts/check-doc-formula-expressions.mjs,packages/cli/test/authoring-rule-command-parity.test.ts. Comment and prose edits only in the three code files; no logic change.Still out:
ui/packages/app-shell/src/views/metadata-admin/celAuthoring.ts(ui/**, listed inout_of_scope_findings),skills/**.Everything else in claim 6706763322 stands.
objectstack-fleet commentedon Nov 7, 2026
domain:server#2 · marchtian · session_017ihL2cdAGuFRofhFrM4z5k
os-dev-report
{ "issue": 31081, "status": "done", "branch": "claude/project-thread-s69s7k", "pr": "https://github.com/objectstack-ai/objectstack/pull/31117", "session": "session_017ihL2cdAGuFRofhFrM4z5k", "premise_still_valid": true, "summary": "Reworded every place that said a bare field ref (or a mistyped root) in a record-scoped expression evaluates to null: the bare-reference and unbound-root refusals in @objectstack/formula validate.ts (now: unknown variable, the expression faults with Unknown variable: NAME, and the site's fault rule decides the outcome), their doc comments and cel-engine.ts docblock, the create-objectstack AGENTS.md template, validating-metadata.mdx (code comment, Fail open row scoped to the Console's rendering, submit paragraph gains option visibleWhen and the readonlyWhen lock exception), build-with-claude-code.mdx (comment and quoted transcript), formulas.mdx and validation.mdx (claim amendment 6706775171), and two comments in lint/cli. Codes and params unchanged; one patch changeset for @objectstack/formula and create-objectstack.", "sites": [ { "path": "packages/formula/src/validate.ts (bare-reference refusal)", "old": "resolves to nothing and the expression silently evaluates to null", "new": "is an unknown variable and the expression faults with Unknown variable: NAME instead of reading the field. The site's fault rule decides the outcome (a formula field reads null, an error validation rule refuses the write, an action's visible hides the action).", "runtime_behaviour_read": "one template for every record-scoped site (a code names one template); formula fault reads null via reportFormulaFault; error validation rule fail-closed in rule-validator.ts; Console action visible fails closed (DeclaredActionsBar.tsx)" }, { "path": "packages/formula/src/validate.ts (unbound-root refusal)", "old": "resolves to nothing and the expression silently evaluates to null", "new": "NAME.… is an unknown variable, so the expression faults with Unknown variable: NAME instead of reading it", "runtime_behaviour_read": "same cel-js Unknown variable fault that firstUndeclaredReference keys on" }, { "path": "packages/formula/src/validate.ts doc comments (fieldTypes, scope) and cel-engine.ts firstUndeclaredReference docblock", "old": "silently evaluates to null / never fires", "new": "faults; a formula reads null, a predicate is refused, locked, hidden or skipped by its site", "runtime_behaviour_read": "faultOutcome docblock in validate.ts" }, { "path": "packages/create-objectstack/src/templates/AGENTS.md", "old": "evaluates to null and silently hides an action on every record", "new": "is an unknown variable, so the predicate cannot be evaluated on any record: an action whose visible reads it is hidden on every record, and an error validation rule that reads it refuses every write", "runtime_behaviour_read": "Console visible fail-closed; validation error rule fail-closed; template ships via tsup copy to dist/templates" }, { "path": "content/docs/deployment/validating-metadata.mdx code comment", "old": "resolves to null → the action is hidden on EVERY record", "new": "unknown variable, predicate faults on every record, the Console hides an action whose visible faults", "runtime_behaviour_read": "as above" }, { "path": "content/docs/deployment/validating-metadata.mdx Fail open row + submit paragraph", "old": "Fail open (unqualified); A broken requiredWhen or readonlyWhen is refused by the server", "new": "Fail open in the Console's rendering, server judges requiredWhen/readonlyWhen/option visibleWhen again on the write; option visibleWhen refused too; readonlyWhen reading an unbound name holds the lock (field change dropped, rest lands)", "runtime_behaviour_read": "requiredWhen refuses (ADR-0137 D2), option gate refuses (unevaluableOptionGateError), isReadonlyWhenLocked returns true on unknownVariableOf and stripReadonlyWhenFields drops the field" }, { "path": "content/docs/getting-started/build-with-claude-code.mdx comment and os-validate transcript", "old": "resolves to null; old message verbatim", "new": "unknown variable / Console hides; new message verbatim (hand-wrapped)", "runtime_behaviour_read": "transcript follows the refusal text" }, { "path": "content/docs/data-modeling/formulas.mdx build-time check row", "old": "a bare amount resolves to nothing and evaluates to null", "new": "unknown variable, faults; a formula reads null, a predicate takes its site's fault outcome", "runtime_behaviour_read": "as for the refusal" }, { "path": "content/docs/data-modeling/validation.mdx callout", "old": "resolves to nothing and the rule silently never fires", "new": "unknown variable; an error rule refuses every write it judges, a warning/info rule is skipped with a log line", "runtime_behaviour_read": "error fail-closed, advisory fail-open (TYPE_MISMATCH_FAULT_ARMS fail-open wording)" }, { "path": "packages/lint/scripts/check-doc-formula-expressions.mjs header; packages/cli/test/authoring-rule-command-parity.test.ts comment", "old": "does not throw ... silently evaluates to null; silently evaluates to null", "new": "never reads the field, faults, a formula reads null; the rule (error by default) refuses every write it judges", "runtime_behaviour_read": "comments only; ValidationRule severity defaults to error" } ], "tests": "head 064a4d46f. pnpm --filter @objectstack/formula test :: exit 0 (Test Files 65/65, Tests 1703/1703); formula typecheck :: exit 0; lint vitest on 7 files asserting these refusals :: exit 0 (7/7 files, 610/610); pnpm --filter create-objectstack test :: exit 0 (25/25, 374/374); eslint --no-inline-config on the 5 changed code files :: exit 0. Moved pins: expression-refusal-codes.test.ts bare-reference and unbound-root messages. No ablation: wording only, no tested behaviour changed.", "gates": "dispatch-gates --commands: 97 derived; 96 run exit 0 (3 first exit 3 on prerequisites, re-run green after fetching the teardown fixture commit and building the client-react and objectql closures); NOT MEASURED: pnpm check:dual-build-cjs-loads, reason: needs every package dist (full build), left to CI Lint & Repo Gates. dispatch-gates --ran :: exit 0, 97 accounted, 96 run, 1 NOT-MEASURED. PR check-runs: in_progress at report time. Order's pnpm lint: not run repo-wide (os-dev.md: repo-wide lint is CI-owned; conflict noted), eslint on changed files instead.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write pr_create, run 42374495151, PR #31117, read-back identical); this report comment via post-stamped. git push is not a REST write.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none (ui/** outside claim) · ui/packages/app-shell/src/views/metadata-admin/celAuthoring.ts L60 and L645 comments still say a bare field ref silently evaluates to null at runtime · comment-only, not filed · dedupe words: celAuthoring bare field evaluates null", "carrier: none · skills/** carries zero hits for the phrase on 5f0037449 (git grep -i 'evaluates to null|resolves to nothing' filtered to bare/record. lines), so nothing to hand to the skills side" ] }