Repository navigation
Description
domain:devx#1 · os-warren · session_01JQwxbXGDmSYVyFomEEAdU3
Filing gate: ① product defect with a named landing point and a reproduction (reach: POST /api/v1/packages/PKG/publish-drafts and the data door; reproduced on two boots, twice on the second, and once through Studio's Validations tab).
Business reason: an author writes a validation rule that compares a text field with a number, a common slip. Studio shows no verdict and autosaves; the publish succeeds and carries only a warning advisory saying the expression "silently evaluates to null". For a validation rule that is not what happens: rules fail closed, so from that moment every create and update on the object is refused with "could not be evaluated … write rejected". One typo takes the object's data entry down, and the gate's own message tells the author it is harmless.
Reader who acts: domain:server, the expression type judgment in packages/formula/src/validate.ts (the type-mismatch verdict at L349 is severity: 'warning' for every role) and the author-time gate that maps it for validations[].condition. The fail-closed evaluator is packages/objectql validation. The Studio half (no inline verdict) follows from the server's severity.
Dedupe (open and closed): "no such overload" 24 hits, "could not be evaluated" validation rule 25, "type mismatch" validation 24, expression-invalid warning validation rule write rejected 15. Nearest: #29026 (closed, the publish null-guard gate excluding flow conditions), #24720 (closed, a rule reading parent refuses every write), #24782 (closed, an unevaluable warning rule), #28944 (closed, date arithmetic passing the build gate). The nullable-number twin (record.qty > 1000 on a nullable field) IS refused at publish today; the open #27482 covers Studio not holding that one. None covers a type mismatch that publishes.
QA-source: #29893 · studio-authoring.validation-rules-authoring · observed beside the clauses
What happens
Measured at framework 589049b0 (main, 2026-11-03) on a stock showcase boot, as admin, in a runtime package P.
PUT /api/v1/meta/object/orch_v4?mode=draft&package=P{"name":"orch_v4","label":"V4","sharingModel":"public_read_write","fields":{"name":{"type":"text","label":"Name","required":true}},"validations":[{"name":"name_gt","type":"script","condition":"record.name > 5","message":"bad","severity":"error"}]}→ 200.POST /api/v1/packages/P/publish-drafts{}→ 200outcome: published, with one advisory,rule: expression-invalid,severity: warning, atobjects.orch_v4.validations[0].condition, whose message reads: "type mismatchstring > int—record.nameholds text but is used with>against a number. This faults at runtime, so the expression silently evaluates to null (unless the value happens to be numeric). …"POST /api/v1/data/orch_v4{"name":"abc"}→ 400VALIDATION_FAILED: "Validation rule 'name_gt' could not be evaluated (runtime: no such overload: dyn > int) — write rejected." Every write is refused this way.
Through Studio (Validations → New → Reject the save when… → Expression → record.name > 5): no verdict at the input, two autosaves 200, no held line, and the same publish and write answers.
Expected: for a validation rule condition (a fail-closed role) the type mismatch is an error that refuses at save or at publish, as the nullable-comparison twin already is. If the warning stays for formula fields, where "evaluates to null" is true, its text should not be served for a role where it is false.
Control: the same field required: false gets the nullable-comparison verdict instead, and the publish is refused (expression-invalid, error).
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p1 ·
domain:server·pm:queue· 2026-11-03T11:02Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5
Claim: PM loop round 1
Session:
session_01WGufzhUVCv2vcJJepWyHQQ(dev: os-dev card thread; seatsession_01WGufzibcN9oHa8kDbTTnL5)Account:
os-support-aiBranch:
claude/project-thread-ytyozv(harness-pinned thread branch; platform exception toclaude/issue-<n>-<slug>)Worktree: the dev thread's own container checkout
Domain:
domain:serverSeat:
domain:server#6File surface:
packages/formula/src/validate.ts(thetype-mismatchverdict) and the author-time gate that maps verdicts per expression role; publish-door pins; one changeset;skills/**/ docs only if they teach the comparison (stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate; seat judgment for a design-bearing narrowing),effort: highClause-②: no
Metadata-protocol: narrowed
Responsibility:
the platform's own publish gate (formula validate's type-mismatch verdict is a warning in every role) | none — the nullable-comparison twin is refused, this class is not | every author who writes a text-vs-number comparison in a validation rule; the object's writes are then all refusedThread-read: 6602066434
Premise: holds (triage 6602066434; card measured at
589049b0, reproduced on two boots and through Studio)Serial constraints cleared: none (no in-flight claim or open PR on
packages/formula/src/validate.ts; the dev re-checks at PR time)Stamp: 2026-11-03T11:14Z
Clause-②: nowith a(narrowing)arm on the PR body and changeset: publish refuses a type mismatch in a fail-closed role (precedent: the nullable-comparison twin already refuses). Stays in this lane perexecution-duties.md(a narrowing card does not move); owes aCONTRACT_REVIEW_TIERreview on the narrowing face before the queue./mnt/project-files/server-orders/29904.md(project files). Routed to this seat by triage (Notify: release-blocker, mailbox pm:mailbox — domain:server#6 · os-support-ai #29907).objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzhUVCv2vcJJepWyHQQ
os-dev-report
Stamp: 2026-11-03T12:57Z
{ "issue": 29904, "status": "done", "branch": "claude/project-thread-ytyozv", "pr": "https://github.com/objectstack-ai/objectstack/pull/29923", "session": "session_01WGufzhUVCv2vcJJepWyHQQ", "premise_still_valid": true, "summary": "type-mismatch (text or boolean ordered/arithmetic'd against a number) is now an error at the fail-closed predicate sites: validation rule condition/when and nested rules, field requiredWhen/readonlyWhen, option visibleWhen, hook condition. formula takes ExprSchemaHint.faultOutcome ('fail-closed') and words the error for a refused write (fix: size() for length, double() with its own fault named); lint decides the sites in one FAIL_CLOSED constant with the site ledger; mcp validate_expression site 'validation' agrees. Formula fields, flow conditions and display predicates keep the warning. ADR-0087: registered semantic entry validation-type-mismatch-refused (a FROM-TO line contradicts not-required, precedent #28944). Head 1dfad411f.", "tests": "formula 64/1629, lint 192/7949, mcp 55/660, spec 808/24115 (+1 todo), spec test:repo 89/1524, objectql new door file 3/3; typecheck formula/lint/mcp/spec/objectql exit 0. Ablation: fail-closed severity put back to warning (ablation-replace anchor 1 to 0, dist preflight marker in 2 files) -> lint 2 pins red (expected severity error), objectql door red (expected published to be refused), formula and mcp pins red; twin control stayed green; restore blob = HEAD, preflight --absent clean, all green again. Real boot (showcase --fresh, full build): publish-drafts outcome=refused, expression-invalid error at objects.tmm_lead.validations[0].condition; size() rewrite publishes, abc 201 / abcdefg 400 rule_violation; formula publishes with warning; nullable twin refused unchanged; draft save 200 for both (as before).", "gates": "dispatch-gates --commands: 106 families at 1dfad411f, all exit 0; --ran: 106 derived, 106 run, 0 NOT-MEASURED. Round 1 at d5b798c0f had check:objectql-double-limit exit 1 (new test double limit-blind), fixed, full list rerun. pnpm lint exit 0. check-adr-0087-registration exit 0. CI check-runs: in_progress at report time.", "dogfood_battery": "1dfad411f · VERDICT command-exit 0 · Test Files 410 passed | 3 skipped (413) · Tests 3379 passed | 28 skipped (3407) · no failures", "mcp_calls": "3 — issue_read get #29904, issue_read get_comments #29904 x2 (reads only)", "api_writes": "2 — relay pr_create (PR 29923, read back identical, no assignees), os-dev-report comment via post-stamped.mjs; plus git push (not REST)", "open_questions": [ { "question": "Flow start/edge/decision conditions on a record-triggered flow: the nullable twin refuses there with outcome run-fails (#29026), and the type-mismatch warning text there ('evaluates to null') is false (the run fails, the write lands). Grade it an error too?", "options": [ "A: leave as warning in this PR (current), file a follow-up card to add a run-fails outcome", "B: add a run-fails outcome and grade it error here (widens the narrowing beyond write-refusing roles)" ], "recommendation": "A, because the order scopes this narrowing to roles that refuse the write, and a flow outcome needs its own wording and pins" } ], "security_findings": "withheld", "out_of_scope_findings": [ "carrier: none · noted, not filed: validation rules of severity warning/info do not refuse on a fault (logged), yet both this verdict and the nullable twin refuse them at publish; parity kept, noted in PR Acceptance notes" ], "deviations": [ "Harness step 'add assignee and request review' skipped per os-dev rule 2.", "PR body opened without the signed trailer (os-dev forbids dev-written HTML comments); the seat appends it via issue_patch.", "Dispatch said FROM-TO line plus disposition: the gate refuses not-required with a FROM-TO label, so the disposition is registered (spec semantic entry) and @objectstack/spec moves (minor)." ] }Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5
PR #29923: contract review PASS 6604729050 (
CONTRACT_REVIEW_TIER, narrowing face) and ACCEPT at1dfad411. Out-of-scope follow-up filed as #29926 (flow-conditionrun-failswording, advisory-severity rules, refusal-code template contract). Landing on all-green.objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5
Landed · 2026-11-03T13:49Z · PR #29923 merged through the queue as
4c2cd29a(ACCEPT → PR #29923; contract review PASS 6604729050 atCONTRACT_REVIEW_TIER).pm:dispatchedremoved with the close. Follow-up: #29926 (flow-conditionrun-failswording, advisory-severity rules, refusal-code template contract), awaiting triage.