Skip to content

A list inside a nested-relation condition in a dataset or measure filter ({ account: { region: ['a'] } }) passes the save-time schema door and is refused only when the chart runs #20080

Description

@objectstack-fleet

Filing gate: ① a product defect with a named landing site (the publish-clean, fail-later class). It was measured by the #19889 dev (os-dev-report 5823840715, out_of_scope_findings[0], class c). The at-tier review 5824029954 on PR #20047 confirmed it real. The domain:spec seat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d) re-read it at origin/main 7f1de2eb66, after PR #20047 landed as 6aa3188a39. Filed unassigned and unlabelled: routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling: the remedy needs one (below).
Hand that acts: the lane triage routes this to.
Dedupe (including closed): the semantic query nested relation list dataset filter publishes but refused at chart time analytics equality array returns 5 hits. The nearest are #20035 and #20010 (the object-form analytics where skipping other arms of the shared comparand face). Neither covers a list under a nested relation. No match on DatasetSchema filter nested region array accepted assertNoListInEqualitySlot.

The defect (at origin/main 7f1de2eb66)

  • The save-time schema door does not judge it. PR fix(spec)!: refuse an array in the equality slot at the schema door, in the comparand face's own words (#19889) #20047 made FilterConditionSchema refuse an array in the equality slot, but only at depth === 0 of each pass (packages/spec/src/data/filter.zod.ts:1676, :1698). A no-$ spec, i.e. a nested-relation condition, recurses at depth + 1 (:1690) and is not judged. That is deliberate: the shared compile face assertListComparandShapes does not descend a no-$ spec either. The engine accepts a deep-equality comparand there, and ruling A (5805248669) mirrors the face.
  • The analytics door does judge it. packages/services/service-analytics/src/strategies/filter-normalizer.ts forEachWhereFieldEntry (:1569) recurses into a no-$ spec (:1588-1590) and flattens the nested relation to a dotted member. assertNoListInEqualitySlot (:1655) then hands each equality-slot list to the shared face, which refuses it with INVALID_FILTER / 400.
  • So, as measured by the dev at 46e1c81727: DatasetSchema.safeParse({ …, filter: { account: { region: ['a'] } } }) returns success: true, while the analytics door answers INVALID_FILTER / 400 ("The implicit-equality comparand on field "region" …"). The dataset saves clean, and every chart built on it fails.
  • The pending changesets say so. .changeset/19889-filter-schema-door-array-equality.md and the corrected .changeset/19888-analytics-implicit-array.md state the exception: a list inside a nested relation still publishes and is refused when it is charted.

Producer: a stored dataset or measure filter. In-repo census (the dev's): 0 shipped instances. Deployed metadata: NOT MEASURED.

Remedy shape (needs a decision; not ruled here)

  • (A) Carrier-specific refinement. The analytics carriers (DatasetSchema.filter, DatasetMeasureSchema.filter) get a refinement that descends a nested relation the way the analytics door does and refuses the list at save. The shared FilterConditionSchema stays as ruled, because the engine path accepts a deep-equality comparand.
  • (B) The analytics door stops descending into a no-$ spec and treats it as the engine does (a deep-equality comparand). The two doors then agree and nothing is refused late, but a nested list's meaning changes.

Seam: spec DatasetSchema.filter / DatasetMeasureSchema.filter → runtime service-analytics filter-normalizer.ts assertNoListInEqualitySlot.

Dedupe words: nested relation list dataset filter publishes · analytics where nested relation equality array · DatasetSchema filter nested region array accepted


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    分诊首次定级:priority:p3 · bug · domain:spec · pm:queue —— 数据集或度量的筛选里,嵌套关联下的列表({ account: { region: ['a'] } })在保存时通过校验,到图表运行时才被拒绝

    Path: 分析的两个载体 DatasetSchema.filter / DatasetMeasureSchema.filter(packages/spec)· 对照 packages/spec/src/data/filter.zod.ts(第 1676 行起,只在 depth === 0 时判列表)与 packages/services/service-analytics/src/strategies/filter-normalizer.ts(第 1569 行 forEachWhereFieldEntry 会下探嵌套关联,第 1655 行 assertNoListInEqualitySlot 拒绝列表)

    Triage: lands in packages/spec (the analytics carriers) ⇒ domain:spec, bug, priority:p3, pm:queue; rationale: the save door judges an equality-slot list only at depth 0 (deliberately, mirroring the shared face and ruling A 5805248669, because the engine accepts a deep-equality comparand there) while the analytics door descends a nested relation and refuses the list, so a dataset saves clean and every chart on it fails with INVALID_FILTER / 400 (measured by the #19889 dev); 0 shipped instances, loud at chart time, hence p3; triage's routing is remedy A — a refinement on the two analytics carriers that refuses at save what the analytics door refuses at run — which moves the refusal earlier without changing any ruled meaning; remedy B (the analytics door stops descending) changes what a nested list means and would need a ruling, so it is not taken.

    分诊席 #6015,2026-09-25T02:26Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectstack origin/main 7f1de2eb66 上核对。#20081 是本卡的一字不差的重复(晚 50 秒建成),本席已把它交给维护者,建议作为重复关闭。

    本席核对

    • filter.zod.ts 第 1676 行:if (depth === 0) { 才判列表。
    • filter-normalizer.ts 第 1569 行是 forEachWhereFieldEntry,第 1655 行是 assertNoListInEqualitySlot。
    • 两份待发更新说明都还在 .changeset/:19889-filter-schema-door-array-equality.md 第 24 行写明了这个例外(「A field spec with no $ key, such as the nested-relation condition …, is not judged … The analytics where door does refuse that shape when a dataset or measure filter is charted」);另一份是 19888-analytics-implicit-array.md。
    • PR fix(spec)!: refuse an array in the equality slot at the schema door, in the comparand face's own words (#19889) #20047 已合并为 6aa3188a39。

    为什么选 A,而且不找维护者

    • A:只在两个分析载体上加校验,保存时就拒绝分析那一面本来就会拒绝的东西。已有的含义都不变,只是把拒绝提前了。
    • B:让分析那一面不再下探,这会改变嵌套列表的含义,需要裁决。
    • 所以本席按 A 路由。如果执行席位认为 B 更好,再交维护者。

    执行要点

    1. 在两个分析载体上加校验:像分析那一面一样下探嵌套关联,对等值位置上的列表用同一句话拒绝。共用的 FilterConditionSchema 保持现状,不动。
    2. ⚠️ 待发更新说明:如果本卡在下一次 changeset version 之前落地,上面两份待发更新说明里写「例外」的句子就会变成假话,必须在同一个 PR 里一起改掉(待发更新说明里的假话属于 p1 一类)。
    3. 收窄的登记:按 ADR-0087 登记,更新说明写明旧数据集的改法。
    4. 钉子:DatasetSchema.safeParse 对嵌套列表返回失败,报错与分析那一面一致;顶层列表照旧拒绝;嵌套关联下的非列表值照常通过。

    Generated by Claude Code

  2. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01QcAS3qiYYZNezaxZxaUdMV
    Account: os-project-manager (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-20080-dataset-filter-nested-list-refused
    Worktree: objectstack-issue-20080
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface: packages/spec/src/ui/dataset.zod.ts (a refinement on the two analytics carriers DatasetSchema.filter / DatasetMeasureSchema.filter only) and its tests; the exception sentences of the two PENDING changesets .changeset/19889-filter-schema-door-array-equality.md and .changeset/19888-analytics-implicit-array.md (triage item 2: they turn false when this lands; a deliberate correction, confirmed by the at-tier record); packages/spec/src/migrations/ (one ADR-0087 entry plus its regenerated region); .changeset/. ⛔ Not packages/spec/src/data/filter.zod.ts or filter-comparand-shape.ts (held by #19886 stage 2b), import-only reuse. ⛔ Not service-analytics (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default judgment tier (dispatch-gates.mjs --tier at 2bbebf5: 「no path-derived mandate … floor · default · ceiling」; a door refinement mirroring another face)
    Clause-②: no
    Thread-read: 5825670610
    Serial constraints cleared: read at 2026-09-27T06:52Z — Open-PR census (10 open PRs besides the release PR): none touches packages/spec/src/ui/dataset.zod.ts or the two pending changesets; PR #20180 (#20003) edits a service-analytics test only. In-flight claims: #19886 stage 2b (os-zhuang) names filter.zod.ts and filter-comparand-shape.ts, off this surface (import-only). Sibling #20116 (same class, the shared checkFilterConditionComparands in filter.zod.ts) is NOT folded: fold gate ① fails (different fix sites, shared door vs carrier refinement) ⇒ it stays queued, serial behind #19886.


    Scope, restated from the dev contract: 「范围 = 这张 issue,别无其它。」 Remedy A only, as triage routed it (5825670610); ⛔ remedy B (the analytics door stops descending) needs a ruling and is not this card.

  3. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 20080,
    "status": "done",
    "branch": "claude/issue-20080-dataset-filter-nested-list-refused",
    "pr": "#20207",
    "session": "session_01QcAS3qiYYZNezaxZxaUdMV (mode:subagent, the PM session id)",
    "premise_still_valid": true,
    "summary": "Remedy A as triage routed it (record 5825670610). DatasetSchema.filter and DatasetMeasureSchema.filter now refuse on save an array in the equality slot of a field inside a nested-relation condition (implicit form and $eq, empty included, any relation depth, under $and / $or / $not). The walk mirrors the analytics door (its mapWhereFieldEntries traversal and isNestedRelationSpec test), reports only inside a nested relation, and prints the face's sentence from the shared builder arrayEqualityComparandMessage; the shared FilterConditionSchema is untouched (ruling A). The premise re-measured at base 9e7824a: DatasetSchema.safeParse answered success:true for both shapes, and the analytics door refuses both (INVALID_FILTER/400). The narrowing is registered as ADR-0087 entry dataset-filter-nested-relation-equality-array-refused-at-save; the exception sentences of the two pending changesets (19888, 19889) and one sentence each in two unreleased sibling major-18 entries are corrected; the 11 new dropped-refinement sites are declared.",
    "tests": "All at head 3ed391a unless named; exit codes captured before any pipe; heavy runs through os-verify-lock.sh. New pins packages/spec/src/ui/dataset-filter-nested-relation-list.test.ts: 68 passed (§1 12 nested shapes refused at the list path on DatasetSchema.filter, measure filter via DatasetSchema, DatasetMeasureSchema alone, plus one-document-all-refusals; §2 carrier message EQUALS the analytics door refusal rebuilt from its one-entry hand-over to the face, minus the location clause, envelope INVALID_FILTER/400 asserted; §3 top-level lists reported exactly once; §4 13 controls accepted and kept on both carriers, and FilterConditionSchema still accepts both nested shapes). Ablation 1 (scripts/ablation-replace.mjs, anchor 1 to 0, blob 781a5b6df01f to 5411f8763031): refinement removed -> 50 failed | 18 passed (§1+§2 red, §3+§4 green); restore proven blob == HEAD 781a5b6df01f, git diff HEAD empty. Ablation 2: outside-relation guard removed -> exactly the 4 §3 rows red (4 failed | 64 passed); restore proven. Subject resolves by relative import to src, so no dist leg applies. Cross-door conformance (one-off, not committed): 3000 seeded random filters through the real analytics door (normalizeAnalyticsFilterTree, service-analytics source) and the rebuilt DatasetSchema: door refused 2240 with the equality sentence, 1304 of them where the shared schema alone misses; carrier agreed on 3000/3000, 0 mismatches. pnpm --filter @objectstack/spec test at 43df140: 1 failed | 15902 passed | 2 todo (the ledger header total, fixed in 3ed391a); scripts/dropped-refinements.test.ts + new pins rerun at 3ed391a: 95 passed. pnpm --filter @objectstack/spec typecheck: exit 0 (check:test-typecheck OK, 53 files / 255 errors held in ledger); tsc -p tsconfig.test.json --listFiles lists the new test once; 0 of the 255 errors in any touched file. pnpm --filter @objectstack/spec build && check:generated at 43df140: all 15 artifacts up to date; gen:schema rerun at 3ed391a: exit 0, 585 sites across 207 schemas all declared, tree clean. Base vs head ui/Dataset.json and ui/DatasetMeasure.json bodies byte-identical with x-dropped-refinements removed (compare worktree at 9e7824a). Consumers (upstream-prefix filter @objectstack/service-analytics^... built its 14-package closure): service-analytics test 128 files / 3017 passed (all 128 tracked test files, incl. the read-only control where-equality-slot-list-refusal.test.ts); metadata typescript-serializer-annotation.test.ts 7 passed; platform-objects report-form-echo-decisions.test.ts 35 passed; rest (3 files) and cli (1 file) declared to CI (closures 25 / 57 packages) with a static sweep: none of the 80 consumer test files referencing DatasetSchema passes a nested-relation list through it. Lint (declared narrowing): eslint --no-inline-config --format json on the 6 touched TS files -> 6 files reported, 0 errors, 0 warnings, none ignored; eslint.config.mjs never enables type-aware linting (its note near line 326) and no touched module export changed, so no untouched file verdict can move. Repo-wide pnpm lint is CI.",
    "gates": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 3ed391a (identical to the derivation at 43df140): 87 families. --ran reconciliation with recorded exit codes: 87 derived, 85 run, 2 NOT-MEASURED, 0 UNRUN. 84 exit 0. check-empty-changeset --base origin/main exit 1 BY DESIGN (DELIBERATE CORRECTION of the two pending changesets, declared under its own PR heading, no skip-changeset). NOT MEASURED: check:type-check-debt and check:dual-build-cjs-loads, both exit 3 PREREQUISITE NOT MET (whole-repo build, CI). check:doc-formula-expressions first exit 3 (lint/formula unbuilt), rerun exit 0 after the closure build. CI not awaited (in_progress at report time).",
    "line_budget": "n/a (no skills/** or governed ledger touched)",
    "files_changed": [
    "packages/spec/src/ui/dataset.zod.ts",
    "packages/spec/src/ui/dataset-filter-nested-relation-list.test.ts (new)",
    "packages/spec/src/migrations/entries/semantic/18.dataset-filter-nested-relation-equality-array-refused-at-save.ts (new)",
    "packages/spec/src/migrations/entries/semantic/18.filter-equality-array-comparand-refused-at-save.ts",
    "packages/spec/src/migrations/entries/semantic/18.filter-equality-array-comparand-refused.ts",
    "packages/spec/src/migrations/registry.ts (regenerated region)",
    "packages/spec/dropped-refinements.baseline.json",
    ".changeset/20080-dataset-filter-nested-relation-list.md (new)",
    ".changeset/19888-analytics-implicit-array.md",
    ".changeset/19889-filter-schema-door-array-equality.md"
    ],
    "deviations": [
    "packages/spec/dropped-refinements.baseline.json is outside the claim File surface: build-schemas.ts refuses a new refinement until its sites are declared (11 sites across 6 existing entries, exactly as printed; header droppedRefinementSites 574 -> 585).",
    "Two unreleased sibling ADR-0087 entries were edited (one sentence each plus one acceptance-criteria sentence): inside the claimed packages/spec/src/migrations/ directory but beyond its parenthetical (one entry plus its region). Each sentence said the nested-relation list refuses only at chart time, which this change makes false; same principle as triage item 2.",
    "H1 refined: the shared sentence lives in packages/spec/src/data/filter-comparand-refusal-text.ts (the builder both doors import), imported read-only; filter.zod.ts and filter-comparand-shape.ts are not edited (the test imports assertListComparandShapes only to rebuild the door refusal).",
    "H1 design note: a first cut refined FilterConditionSchema directly, which cloned the recursive schema and changed the published ui/Dataset.json (a second inlined copy beside the $ref); replaced by a check on each carrier optional wrapper, measured byte-identical.",
    "PR body carries the claim line Clause-②: no verbatim; the PR changeset carries Clause-②: no (narrowing), the spelling check:adr-0087-registration reads.",
    "A foreground wait via pgrep -f matched the asking shell (as AGENTS.md warns) and timed out harmlessly; every later wait was on a PID recorded at launch."
    ],
    "mcp_calls": "0",
    "api_writes": "3 REST writes, each one repository_dispatch to POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write relay as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (PR 20207, draft forced), run 36308599466; (2) label-write --assign os-project-manager -> POST /repos//issues/20207/assignees, run 36308637463, read back MATCHES; (3) this os-dev-report comment -> POST /repos//issues/20080/comments. git push (not REST): 6 pushes of the branch. Reads (GET) not counted.",
    "open_questions": [
    {
    "question": "Confirm the deliberate correction of the two pending changesets (.changeset/19888-analytics-implicit-array.md, .changeset/19889-filter-schema-door-array-equality.md); check-empty-changeset stays red until a person confirms it.",
    "options": [
    "A: confirm on PR 20207 as written",
    "B: request different wording for either note"
    ],
    "recommendation": "A: each edit replaces only the exception sentence this change makes false, and restoring either from base republishes a false sentence (the gate text names this class DELIBERATE CORRECTION)."
    }
    ],
    "out_of_scope_findings": [
    "class: a · reach: DatasetSchema.safeParse, the save door behind defineStack / os validate / the metadata protocol save, answers success:true where the shared face and the analytics door answer INVALID_FILTER/400 · evidence: probe at 3ed391a with a control dataset that parses: { amount: { $gt: null } }, { stage: { $in: 'won' } }, { acct: { stage: { $in: ['won', null] } } }, { amount: { $between: [null, 5] } } and their { acct: ... } nested forms all accepted; the face refuses each; same save-door family as #19889 / #20116 -> fold into that family collector card, not filed singly · dedupe words: dataset filter $gt null accepted at save · FilterConditionSchema other comparand arms not judged at save · $in non-list dataset filter saves clean",
    "carrier: 承接者:无 · noted, not filed: whether a stored dashboard widget filter or report runtimeFilter reaches the analytics door carrying a nested-relation list is decided on the objectui side, NOT MEASURED; a caller where and a dataset selection runtimeFilter do reach it and are refused at request time (loud)",
    "carrier: 承接者:无 · noted, not filed: dropped-refinements.baseline.json measured.refinementSitesThatDidProject reads 369 while build-schemas.ts prints 409 at base 9e7824a and at head; no test reads the field"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #20207 at head 3ed391abf9f717f1be723d9064d8bb19ba9c1c74 · domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-27T09:16Z

    This is the seat's review, read against GitHub rather than the report.

    • Shape: draft, base main, first line Fixes #20080. It is the only closing keyword. Clause-②: no is line-leading, and it is right for a narrowing. The PR assignee is os-project-manager.
    • Remedy A (triage 5825670610):
      • DatasetSchema.filter and DatasetMeasureSchema.filter refuse an equality-slot list inside a nested relation, at any depth and under $and / $or / $not.
      • The sentence comes from the shared builder in filter-comparand-refusal-text.ts, imported read-only.
      • ⛔ The shared FilterConditionSchema is untouched (ruling A 5805248669). The published ui/Dataset.json / ui/DatasetMeasure.json bodies are measured byte-identical apart from the declared dropped-refinement sites.
      • Evidence: two ablations with proven restores, and 3000/3000 carrier-versus-door agreement.
    • File-surface amendment to claim 5853543833 (recorded here, ⛔ not a second claim):
      • packages/spec/dropped-refinements.baseline.json gains 11 sites, because build-schemas.ts refuses an undeclared refinement.
      • One sentence each in the two unreleased major-18 entries 18.filter-equality-array-comparand-refused-at-save and 18.filter-equality-array-comparand-refused. Both said a nested-relation list is refused only at chart time, which this change makes false; that is a must-fix under the dev contract.
    • Check Changeset red: this is check-empty-changeset's DELIBERATE CORRECTION class, triage item 2 (the exception sentences of pending 19888 and 19889). The dev's open question, answered: A, keep both corrections. Under landing-operations.md the confirmation is a same-head at-tier PASS record that names each corrected note and judges each rewritten sentence. ⛔ No skip-changeset.
    • Clause-② gate: the path limb fires (packages/spec/src/**). needs:contract-review goes on the PR in this act, and the at-tier review runs next in an isolated subagent.
    • CI on this head at review time: 12 success, 3 skipped, 16 in progress, 1 red (Check Changeset, above).

    Out-of-scope findings (the dev's three):

  5. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 20080,
    "status": "done",
    "branch": "claude/issue-20080-dataset-filter-nested-list-refused",
    "pr": "#20207",
    "session": "session_01QcAS3qiYYZNezaxZxaUdMV (mode:subagent, the PM session id)",
    "premise_still_valid": true,
    "summary": "Merge-only round after the queue dequeued PR 20207 with MERGE_CONFLICT. Re-fetched origin/main (af32cf9, which contains e7344f0 #20204) and merged it once with scripts/pm/os-regen-merge.sh, in its order: merge, commit, rerun, regenerate. The only conflict (driver-free bare-clone probe: exit 1, one path) was packages/spec/dropped-refinements.baseline.json. The merge commit e70d591 takes main's side, byte-equal to main's blob. The regeneration commit a053bfc re-derives this branch's 11 sites from the schema build's printed corrected entries, with none removed, and sets the header to the build's own measurement: 588 sites across 207 schemas, which is main's 577 plus 11. registry.ts auto-merged and is exactly what gen:migration-registry writes. Pushed as a fast-forward: 3ed391a to a053bfc. No change to the PR's own content, no rebase, amend or force-push, no ready, auto-merge or label action.",
    "tests": "At new head a053bfc, heavy runs through os-verify-lock.sh, exit codes captured before any pipe. pnpm --filter @objectstack/spec build: exit 0 (gen:schema: 588 refinement sites across 207 schemas, all declared; 1536 schemas generated; tree clean afterwards). pnpm --filter @objectstack/spec check:generated: exit 0, all 15 generated artifacts up to date (check:migration-registry, check:authorable-surface, check:api-surface, check:spec-changes, check:upgrade-guide, check:docs among them). vitest scripts/dropped-refinements.test.ts + src/ui/dataset-filter-nested-relation-list.test.ts: 2 files, 95 passed (27 ledger tests including the header-totals test, plus the 68 pins). Standalone: check:migration-registry exit 0 (256 semantic, 210 retired-key, 196 retired-def), and this PR's entry id appears exactly once as an id. check:authorable-surface exit 0. node scripts/check-adr-0087-registration.mjs --base af32cf9 (the merged main): exit 0, 1 declared-breaking changeset carrying registered dataset-filter-nested-relation-equality-array-refused-at-save. check-empty-changeset --base af32cf9: exit 1 on exactly the two DELIBERATE CORRECTION notes (19888, 19889). Unchanged and by design. Old-head to new-head split (3ed391a to a053bfc, 152 paths, +9374/-2660): 150 byte-equal to main's blob. Regenerated: 2. dropped-refinements.baseline.json is main's side plus the build-printed 11 sites plus the measured header. registry.ts: gen:migration-registry rewrites it byte-identical (blob db141c3889), and its prose outside the 6 generated regions equals main's (control: the old head's prose equals base's, so the branch never touched prose). Anything else: 0. Survival (script step 4.3): all 255 of main's semantic ids are present at head, and the only extra id is this PR's. The entries directory differs from main only by this PR's entry file. #20204's packages/spec/src/data/filter.zod.ts is byte-equal to main. GitHub after the push: PR 20207 head a053bfc, mergeable true, mergeable_state blocked (checks or review pending), base af32cf9. origin/main was still af32cf9 at that read, so it did not move and no second merge arose.",
    "gates": "Ran the gates the dispatch named for this round (above). No full re-derivation this round: the diff only brings in main's files and regenerates two generated files. check-empty-changeset stays red by design (DELIBERATE CORRECTION, unchanged). CI on a053bfc was not awaited.",
    "line_budget": "n/a",
    "files_changed": [
    "merge commit e70d591: origin/main af32cf9 brought in; packages/spec/dropped-refinements.baseline.json resolved to main's side",
    "a053bfcc2a: packages/spec/dropped-refinements.baseline.json (+11 build-printed sites, droppedRefinementSites 577 -> 588)"
    ],
    "deviations": [
    "Dispatch premise corrected by measurement: dropped-refinements.baseline.json is NOT written by build-schemas.ts or gen:schema. It is a hand-edited ledger (its own description), git check-attr merge answers unspecified, and it is not in NOT_DRIVER_MANAGED. build-schemas.ts only verifies it and PRINTS the corrected entries. So "regenerate" was done as: take main's side in the merge commit, then apply the build's printed corrected entries mechanically (a script that refused any removal or any site outside the 11 expected), then set the header from the build's measured total. No count was hand-merged.",
    "os-regen-merge.sh labels this path class 1 ("resolve by hand"). The dispatch's route (main's side, then re-derive after the merge commit) was followed instead; both land on the same bytes, and this one keeps the merge commit free of hand-merged content."
    ],
    "mcp_calls": "0",
    "api_writes": "1 REST write: this os-dev-report comment, POST /repos//issues/20080/comments, sent through the fleet-write relay as objectstack-fleet[bot]. git push (not REST): 1 fast-forward push, 3ed391a to a053bfc. Reads (GET) not counted.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed. #20204 (merged in this round) now refuses a list under $ne at the shared face and at FieldOperatorsSchema.$ne. Measured at a053bfc against a control dataset that parses: DatasetSchema.safeParse accepts { stage: { $ne: ['a'] } } and { acct: { stage: { $ne: ['a'] } } }, while the face on the analytics hand-over refuses both with INVALID_FILTER/400. That is the save-door family already reported last round (the other arms, #19889 / #20116). One consequence for this PR's own text: the dataset.zod.ts docblock phrase "$ne carrying a list (no ruling decides it)" and the §4 test label "$ne carrying a list — no ruling decides it" are now stale. Behaviour and pins are unaffected (the carrier does not judge $ne, and the pins still pass). Not edited, because this round forbids content changes. The fix is a one-line wording change for whoever picks up the $ne save-door gap."
    ]
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 20080,
    "status": "done",
    "branch": "claude/issue-20080-dataset-filter-nested-list-refused",
    "pr": "#20207",
    "session": "session_01QcAS3qiYYZNezaxZxaUdMV (mode:subagent, the PM session id)",
    "premise_still_valid": true,
    "summary": "Patch round: the two phrases this PR carried that became false once #20204 landed now state what is true. Commit 9425cae is a fast-forward from a053bfc, wording only, 2 files, +6/-2. The dataset.zod.ts docblock now says a $ne list is refused at the shared comparand face and at FieldOperatorsSchema.$ne under ruling A on #19886 (record 5805254639), and on the analytics door's hand-over of a nested entry, but not yet at this save door or FilterConditionSchema's. That stored-filter arm is #20116's: release record 5854888976 on #19886 moved it there, so it is no longer #19886's remainder. The §4 test label says the same in short. No behaviour change: the carrier still does not judge $ne.",
    "tests": "Behaviour measured from source at a053bfc before wording, with a control dataset that parses. $ne: [a], top level and nested under account: DatasetSchema.filter, the measure filter and FilterConditionSchema all answer success true. The shared face (assertListComparandShapes): refuses the top-level form with INVALID_FILTER/400 ("Operator \"$ne\" on field \"stage\" requires a single comparable value"). It also refuses the analytics door's one-entry hand-over of the nested entry (holder where.account), and accepts the whole nested condition, which it does not descend. FieldOperatorsSchema.$ne [a]: refused at path $ne. Control $ne scalar: accepted. At head 9425cae: vitest src/ui/dataset-filter-nested-relation-list.test.ts gave 1 file, 68 passed, including the relabelled §4 row (through os-verify-lock.sh, command-exit 0). git grep "no ruling decides" over the files this PR changes against main: 0 hits. Diff 9425cae vs a053bfc: exactly 2 hunks, in dataset.zod.ts (docblock) and the test file (one label). No other file. Gates exit 0 on the edited text: node scripts/check-spec-docblock-symbol-anchors.mjs, pnpm check:issue-citations, pnpm check:doc-authoring, pnpm check:nul-bytes. The edited docblock sits on the module-private refuseNestedRelationEqualityLists, so no exported TSDoc or generated artifact reads it.",
    "gates": "Ran the proofs the order named, plus the four text gates above. No re-derivation: the diff is two comment/label hunks. check-empty-changeset stays red by design (DELIBERATE CORRECTION, unchanged). CI on 9425cae was not awaited.",
    "line_budget": "n/a",
    "files_changed": [
    "packages/spec/src/ui/dataset.zod.ts (docblock only, the $ne clause)",
    "packages/spec/src/ui/dataset-filter-nested-relation-list.test.ts (one §4 test label)"
    ],
    "deviations": [
    "The order suggested citing "the carrier-save arm that #19886 records as its remainder". Measured on #19886: release record 5854888976 moved that stored-filter arm to #20116 and says it is no longer #19886's remainder. So the text cites #20116 for the arm, and names that record."
    ],
    "mcp_calls": "0",
    "api_writes": "1 REST write: this os-dev-report comment, POST /repos//issues/20080/comments, sent through the fleet-write relay as objectstack-fleet[bot]. git push (not REST): 1 fast-forward push, a053bfc to 9425cae. Reads (GET) not counted.",
    "merge_state": "origin/main moved to 7e7fab7 (#20211, #20190, #20208) after the last merge. The PR is NOT dirty: a driver-free bare-clone merge-tree of 9425cae against 7e7fab7 exits 0 with no conflicted path, and GitHub reads mergeable true, mergeable_state blocked (checks and review pending), draft false, auto_merge null. No merge was made this round.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: #20116 · noted, not filed, edited nothing: after #20204, more unreleased text still calls a $ne list unjudged (the list in record 5854888976 on #19886, measured here). Two of them sit in files this PR also touches. (1) .changeset/19888-analytics-implicit-array.md line 30: "$ne with a list is not part of the ruling and is not judged here". That note is one of the two this PR deliberately corrects, and the sentence is now false: the analytics door's shape pass hands each entry to the face, and the face refuses a $ne list (measured: INVALID_FILTER/400 on the door's hand-over). The same-head review of the DELIBERATE CORRECTION may want it in that correction. (2) Entry 18.filter-equality-array-comparand-refused.ts lines 68-69: "$ne carrying an array ... is deliberately left to its own ruling", which is stale now that ruling A has landed; this PR edited a different sentence of that entry. The others are changesets 19757, 19974, 19975, 20010, 20035 and 20099. All were left untouched, because this round is limited to the two phrases."
    ]
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record — PR #20207 merged through the merge queue at 2026-09-27T11:24Z as e8fcf5554e · domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-27T11:25Z

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions