Skip to content

formula: an advisory (warning / info) validation rule's date verdict says the field 'silently evaluates to null', but the rule is skipped and the write proceeds #30494

Closed

Description

@objectstack-fleet

domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb

Filing gate: ① found by the #30250 dev (os-dev-report 6659167895, out_of_scope_findings) and confirmed by the seat in the PR #30492 diff (dateArm keeps the null sentence for faultOutcome: 'fail-open'). Read from code. ⛔ Not a claim. Suggested grade: p3. ⛔ Serial after PR #30492 merges, since it edits the same arm.

What happens

On an advisory (severity: 'warning' | 'info') validation rule, faultOutcome is 'fail-open'. The type-mismatch-fail-open sentence says what happens there: a rule that cannot be evaluated is skipped and logged, and the write proceeds. The date-arithmetic / date-text-arithmetic verdict on the same site still uses the formula field's sentence, "this faults at runtime, so the field silently evaluates to null". There is no field there, and nothing reads null: the rule is skipped.

Ask

Reader: domain:server (packages/formula/src/validate.ts). Links: #30250, PR #30492, #29926.

Activity

  1. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p3 kept · domain:server · 2026-11-05T14:06Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb

    Claim: PM loop round 1
    Session: session_01Utp6CYVV6fcAQrNTDQRvPb (seat) · dev = project card thread session_01Utp6CbJFWadws6f9r4B8Ke
    Account: os-bill
    Branch: claude/project-thread-r6w6jd (harness-pinned thread branch; platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-30494
    Domain: domain:server
    Seat: domain:server#5
    File surface: packages/formula/src/**, plus packages/lint/src/** and packages/mcp/src/** tests only where they pin these messages. content/docs/** only for sentences this PR makes false (not releases/**). One changeset. ⛔ packages/spec/**, ui/**, skills/**, docs/adr/**, .claude/**, AGENTS.md (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default tier (opus), effort: high (p3)
    Clause-②: yes (widening) — two codes join the exported EXPRESSION_REFUSAL_CODES (date-arithmetic-fail-open / date-text-arithmetic-fail-open), as #30250 did
    Metadata-protocol: none (provisional) — os validate reports lint's ExprIssue, which carries no code; the dev re-measures
    Responsibility: on an advisory (fail-open) validation rule, the date-arithmetic / date-text-arithmetic verdicts say "the field silently evaluates to null" while the rule is skipped and the write proceeds (PR #30492 diff, dateArm keeps the null sentence for fail-open) | none: the author reads an outcome that does not happen | authors reading os validate / publish verdicts
    Thread-read: none
    Premise: holds per the seat's reading of PR #30492 (dev report 6659167895, out_of_scope_findings)
    Serial constraints cleared: Serial after PR #30492 (#30250, queued): both edit dateArm in packages/formula/src/validate.ts. The dev starts from a main that contains it, or writes the red pins against its head first.

    Order: project file server-seat5/dispatch-30494.md, delivered to the card thread.

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
    os-dev-report

    {
      "issue": 30494,
      "status": "done",
      "branch": "claude/project-thread-r6w6jd",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30585",
      "session": "session_01Utp6CbJFWadws6f9r4B8Ke",
      "premise_still_valid": true,
      "summary": "An advisory (warning / info) validation rule's date verdicts no longer say the field silently evaluates to null. In @objectstack/formula, dateArm returns fail-open at a record-scoped site with faultOutcome fail-open, and dateArmFault closes that arm on TYPE_MISMATCH_FAULT_ARMS['fail-open'].clause itself (the rule is skipped, the write proceeds, only a log line), under the new codes date-arithmetic-fail-open / date-text-arithmetic-fail-open with the params of the codes they split from. The grade stays error; a formula field keeps date-arithmetic and the null sentence. Lint and MCP already pass faultOutcome fail-open for an advisory rule, so neither changes (measured).",
      "tests": "Red first at 89eebeec (pins only, on PR 30492's head): formula 2 failed | 181 passed (183), lint 1 failed. At merged head dfc91e9d under os-verify-lock: formula 64 files / 1652 tests passed; lint 195 / 8093 passed; mcp 56 / 678 passed; typecheck formula, lint, mcp exit 0; objectql src/publish-type-mismatch-fail-closed.test.ts 12/12. MCP probe (temporary test file, deleted, not committed): validate_expression site validation answers date-arithmetic-fail-open / date-text-arithmetic-fail-open for severity warning and info, -fail-closed for error, date-arithmetic at site formula, each message equal to validateStackExpressions' on the same rule; mcp-validate-expression.test.ts unchanged. Ablation A1 via scripts/ablation-replace.mjs (fail-open arm off with string marker ablated-30494-a1): anchor 1 -> 0, blob 8931039644aa -> 19c5c422d2f2, rebuilt (tsup JS emitted, DTS step exit 1 on the mutated return type), ablation-dist-preflight marker present in dist/index.js and dist/index.mjs; formula 4 failed | 181 passed (185), lint 1 failed | 473 passed (474). Restore: blob == HEAD, git diff HEAD empty, rebuild exit 0, preflight --absent: marker absent from all 6 built files, tree clean. Changed existing pin: the 30250 test's advisory-rule control row (pinned this card's defect), dropped.",
      "gates": "Full build after the origin/main merge (a4c3e738): 119/119 tasks, VERDICT command-exit 0. dispatch-gates --commands --repo objectstack-ai/objectstack at dfc91e9d: 6 paths vs merge base a4c3e738b, 58 derived, all exit 0 (exit codes recorded per line before any pipe; check-plugin-teardown-shape --self-test after fetching pinned fixture 621a4876). --ran: 58 derived, 58 run, 0 NOT-MEASURED, 0 UNRUN. pnpm lint (eslint . --no-inline-config) exit 0. CI check-runs on PR 30585: not yet started at report time.",
      "line_budget": "6 files, +165 / -19 vs origin/main a4c3e738 (git diff --stat)",
      "files_changed": [
        ".changeset/30494-fail-open-date-sentences.md",
        "packages/formula/src/expression-refusal-codes.test.ts",
        "packages/formula/src/expression-refusal.ts",
        "packages/formula/src/validate.test.ts",
        "packages/formula/src/validate.ts",
        "packages/lint/src/validate-expressions.test.ts"
      ],
      "deviations": [
        "Red pins and the fix were written on top of PR 30492's head (merged into this branch as ebda9aca) while 30492 was queued, per the order. After it landed as squash 67d5d5375, the one origin/main merge (a4c3e738) conflicted in the five files both sides touch; resolved by applying this branch's own diff ebda9aca..34b93ec4 to origin/main's copies (clean apply; changed lines of the resolved delta identical to that diff).",
        "The fail-open sentence reuses TYPE_MISMATCH_FAULT_ARMS['fail-open'].clause by reference, verbatim, with no '(it does not read null)' suffix as the fail-closed date clause carries.",
        "Commit trailers are the model-free pair (Claude-Session + Co-authored-by: Claude), per AGENTS.md, not the harness's model-named Co-Authored-By.",
        "The harness's assign / review-request step after PR creation was skipped, per the order (the seat hands off)."
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "9 — reads only: issue_read x5 (30494 get, 30494 get_comments x3, 30250 get_comments), pull_request_read x4 (30492 get x2, get_comments, get_check_runs); no MCP write",
      "api_writes": "2 — fleet-write relay pr_create (PR 30585, 10623 bytes read back identical, no assignees, no labels); post-stamped os-dev-report comment on 30494. Plus git push (not REST).",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · packages/lint/src/validate-expressions.ts:1338-1341 doc comment lists the date verdicts' -run-fails / -run-may-fail / -fail-closed arms but not -fail-open; not false, outside the file surface, noted in Acceptance notes"
      ]
    }

    Report taken 2026-11-05T16:46Z.

  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb

    Landed · 2026-11-05T17:36Z

    PR #30585 merged as 0e4747a4c at 2026-11-05T17:36Z.

    • On an advisory (warning / info) validation rule, a date-arithmetic verdict now says the rule is skipped and the write proceeds, not that the field silently gets null. New codes date-arithmetic-fail-open / date-text-arithmetic-fail-open, with the same sentence as the type-mismatch verdict on that rule.
    • Grades are unchanged. A formula field keeps date-arithmetic and the null sentence. lint and MCP needed no change.

    Follow-ups: none.

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

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions