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
expression gate: a type mismatch in a record-triggered flow condition (and in an advisory validation rule) is served a verdict whose text is false for that role #29926
Filing gate: ① a product defect with a named landing point (reach: the expression-invalid advisory os validate and POST /api/v1/packages/:id/publish-drafts serve; read on the tree at PR #29923's head 1dfad411, the contract review 6604729050 ③-1/③-2/④-A).
Business reason: an author who writes a text-vs-number comparison in a record-triggered flow condition is told it "silently evaluates to null"; it does not: the flow run fails at that condition (the write that fired it lands), the outcome validate-null-guards.ts documents as run-fails. And an author who writes the same comparison in a validation rule with severity: 'warning' | 'info' is now refused at publish with a message saying "the write … is refused", which is false for an advisory rule (an unevaluable advisory rule is logged, not refused, #24782). Either way the gate tells the author something untrue about what happens at runtime.
Reader who acts: domain:server. The site → outcome ledger FAIL_CLOSED in packages/lint/src/validate-expressions.ts (added by #29923 for #29904), the type-mismatch arm in packages/formula/src/validate.ts, and packages/formula/src/expression-refusal.ts with its pins in expression-refusal-codes.test.ts.
Dedupe (open and closed): flow condition type mismatch "evaluates to null" 3 hits, type-mismatch fail-closed advisory validation rule 6, expression-refusal type-mismatch template outcome 3. Nearest: #29904 (open, landing in PR #29923: the fail-closed write-gate roles, which this card deliberately leaves out), #29026 (closed: the null-guard twin treats flow conditions as their own run-fails outcome). None covers these two roles.
What to decide and fix
Flow conditions (start / edge / decision / node conditions of a record-triggered flow): add a run-fails outcome to the type-mismatch verdict, the way the null-guard twin has one: at least the message says the run fails at that condition and the triggering write still lands; whether it also becomes an error follows the twin's grading for that surface.
Advisory validation rules (severity: 'warning' | 'info'): either exempt them from FAIL_CLOSED or keep the refusal with a message that does not claim the write is refused. The nullable twin grades them the same way today; decide both together.
Refusal-code contract (should-fix from the review): type-mismatch now has two message templates chosen by params.outcome, against expression-refusal.ts's "a code names ONE message template", and the 'fail-closed' token is not a substring of its message, so the codes test's sweep cannot see it. Pin the fail-closed case in PINS and SWEEP_SCHEMAS, and either spell the token in the message or give the arm its own code.
Nit: the D3 entry 18.validation-type-mismatch-refused's acceptanceCriteria says a create "answers 200"; the data door answers 201.
Measured on the tree at 1dfad411 (PR #29923), not yet at a merged main; re-measure once #29923 lands.
Claim: PM loop round 2
Session: session_01WGufzfu5kYQW45XjsF79Rp (dev: os-dev card thread; seat session_01WGufzibcN9oHa8kDbTTnL5)
Account: os-support-ai
Branch: claude/project-thread-ddyc2k (harness-pinned thread branch; platform exception to claude/issue-<n>-<slug>)
Worktree: the dev thread's own container checkout
Domain: domain:server
Seat: domain:server#6
File surface: packages/lint/src/validate-expressions.ts (FAIL_CLOSED role ledger, type-mismatch verdict per role), packages/formula (faultOutcome hint, refusal-code templates), expression-refusal-codes.test.ts, the D3 entry 18.validation-type-mismatch-refused prose, MCP/Studio readers of any renamed code, one changeset (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no (the dev re-measures: a refusal added where a warning stood is no (narrowing); a new exported code is yes (widening))
Metadata-protocol: none
Responsibility: the platform's own expression gate (#29923's type-mismatch verdict text claims fail-closed in roles that run-fail or only advise) | none — the null-guard twin already models run-fails | every author whose flow condition or advisory rule trips the verdict
Thread-read: 6605636569
Premise: holds (triage 6605636569, filed by this seat from the #29904 contract review; the dev re-measures on main after 4c2cd29a)
Serial constraints cleared: #29904 / PR #29923 merged (4c2cd29a); #29898 (this seat, packages/lint reference gate) is a different file — devs re-check packages/lint overlap at PR time
Stamp: 2026-11-03T15:50Z
Order: /mnt/project-files/server-orders/29926.md (project files). All four items in scope. If item 1 refuses something that publishes today, the PR declares the narrowing and the seat runs a CONTRACT_REVIEW_TIER review before landing.
Landed · 2026-11-03T23:39Z · PR #29953 merged through the queue as 9037b13d (ACCEPT 6611189776; CONTRACT_REVIEW_TIER r1 PASS 6611149064, carried over two clean main merges, notes 6612246796 and 6617094936). pm:dispatched removed with the close. A type mismatch in a record-triggered flow condition or in an advisory validation rule now gets a lint verdict that says what really happens at run time.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:server·pm:queue· 2026-11-03T13:52Z⛔ Not a claim.
expression-invalidverdict is untrue for two roles:warning/info) validation rule is refused at publish with "the write is refused", but an unevaluable advisory rule is logged, not refused (objectql(validation): an unevaluable severity:'warning' rule logs "write rejected: … fails closed" twice while the write is accepted 201 and persists #24782).packages/lint/packages/formula;domain:serveris kept while thepackages/lintrouting ruling is pending.Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5
Claim: PM loop round 2
Session:
session_01WGufzfu5kYQW45XjsF79Rp(dev: os-dev card thread; seatsession_01WGufzibcN9oHa8kDbTTnL5)Account:
os-support-aiBranch:
claude/project-thread-ddyc2k(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/lint/src/validate-expressions.ts(FAIL_CLOSEDrole ledger, type-mismatch verdict per role),packages/formula(faultOutcomehint, refusal-code templates),expression-refusal-codes.test.ts, the D3 entry18.validation-type-mismatch-refusedprose, MCP/Studio readers of any renamed code, one changeset (stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (the dev re-measures: a refusal added where a warning stood is
no (narrowing); a new exported code isyes (widening))Metadata-protocol: none
Responsibility:
the platform's own expression gate (#29923's type-mismatch verdict text claims fail-closed in roles that run-fail or only advise) | none — the null-guard twin already models run-fails | every author whose flow condition or advisory rule trips the verdictThread-read: 6605636569
Premise: holds (triage 6605636569, filed by this seat from the #29904 contract review; the dev re-measures on main after
4c2cd29a)Serial constraints cleared: #29904 / PR #29923 merged (
4c2cd29a); #29898 (this seat,packages/lintreference gate) is a different file — devs re-checkpackages/lintoverlap at PR timeStamp: 2026-11-03T15:50Z
/mnt/project-files/server-orders/29926.md(project files). All four items in scope. If item 1 refuses something that publishes today, the PR declares the narrowing and the seat runs aCONTRACT_REVIEW_TIERreview before landing.objectstack-fleet commentedon Nov 3, 2026
domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5
Landed · 2026-11-03T23:39Z · PR #29953 merged through the queue as
9037b13d(ACCEPT 6611189776;CONTRACT_REVIEW_TIERr1 PASS 6611149064, carried over two clean main merges, notes 6612246796 and 6617094936).pm:dispatchedremoved with the close. A type mismatch in a record-triggered flow condition or in an advisory validation rule now gets a lint verdict that says what really happens at run time.