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
The FILTER-axis formula refusal (#8296) shipped without the ADR-0087 semantic entry its SORT-axis twin (#7095) carries — the upgrade guide will not mention it #8370
Filed from PR #8369 (#8296). Unassigned; the fix lands in packages/spec, which that card's dispatch deliberately fenced off ("if implementation requires a change — not just a read — to packages/spec, stop and route that slice to the spec seat").
PR #8369 gives the FILTER axis its unmaterializable verdict at both doors: a where on a formula field is now 400 INVALID_FIELD instead of 200-with-zero-rows, at the REST ingress and at the engine seam that saved reports / flows / dashboards reach directly.
Its SORT-axis twin, #7095, made exactly the same kind of change — an engine-boundary refusal for a formula field that used to answer 200 — and paired it with an ADR-0087 semantic migration entry:
registered in packages/spec/src/migrations/registry.ts
surfaced through spec-changes.json and the generated docs/protocol-upgrade-guide.md
The FILTER refusal has no such entry. Its entry would be id: engine-find-formula-filter-refused (or similar) with the same three fields the sort entry carries — surface (a where naming a formula field, at both doors), replacement (denormalise onto a stored field, written when the source changes, and filter that; summary / autonumber need no action), and acceptanceCriteria (grep saved reports, flows, dashboards and view filters for a filtered field whose object declares it as a formula).
Why it matters
That entry is the only notification channel for this class. The sort entry says so in as many words: this is a code-path API with no sys_metadata row for the D2 chain to rewrite, so the ledger IS the notification. objectstack migrate meta, spec-changes.json and the upgrade guide all read the registries, so an unregistered behaviour change is a silent gap on the upgrade path — the #6148 shape.
It matters slightly MORE here than on the sort axis: a refused sort returns the same rows in a different order, while a refused filter changes the row SET, and the surfaces that break are author-written (sys_saved_report.query.filter, flow node filters, dashboard widget filters), not code.
Not an oversight and not a judgement that it is unnecessary — the dispatch fenced packages/spec changes to the spec seat, and adding an entry means touching entries/semantic/, registry.ts and two regenerated artifacts. The changeset there is therefore minor for both packages with no **BREAKING** declaration (the launch-window convention, and what #6994 — the same refusal class at ingress — shipped as), so the ADR-0087 changeset gate is not triggered and nothing currently asks the question.
Not for this issue to decide
Whether the entry is genuinely required, or whether not-required (no-migration-prescription) is the honest disposition, is a real question: no key, symbol or stored value moves, and no mechanical rewrite exists in either direction (the platform cannot invent the stored column, and it must not filter post-hoc — driver.find has already applied limit / offset, so a post-hoc predicate would filter an arbitrary PAGE). The sort axis answered "register it anyway" for the identical shape, which is the strongest available precedent.
Related: #8299 (the disposition catalog has no category for published runtime surfaces with no metadata surface) is the general form of the same question.
Triage: lands in packages/spec (migrations/entries/semantic/, registry.ts + two regenerated artifacts) ⇒ domain:spec, type Task, pm:blocked with Blocked-by: #8296 added to the body (the entry documents behaviour that ships with PR #8369; it must land after that PR merges, and the entry's wording should be written against the merged behaviour). Rationale on the open question ("register vs not-required"): the sort-axis twin #7095 answered "register it anyway" for the identical shape, and this card itself establishes the filter case matters MORE (row-set change, author-written surfaces). Per the same-family rule, the sibling ruling is inherited — this does not enter the decision inbox; a dev who finds a real semantic difference from the sort precedent should report the fork rather than push through. The general disposition-catalog gap stays #8299.
Unlock scan: Blocked-by: #8296 cleared — #8296 closed (PR #8369 merged; both doors now refuse). Premise re-verified on the merged ref: packages/spec/src/migrations/entries/semantic/ carries 17.engine-find-formula-order-by-refused.ts and no FILTER-axis sibling, so the asymmetry stands. Back to pm:queue.
Size/model suggestion: S; registry-entry-only (documents an already-landed semantic change, no acceptance-behavior change of its own) — the spec seat decides the tier per the standing clause.
Claim: PM loop round 1
Session: session_01E5tUwGM3LQoqErTfkvRW7W
Branch: claude/issue-8370-filter-refusal-adr0087-entry
Worktree: objectstack-issue-8370
Domain: domain:spec
File surface: packages/spec/src/migrations/entries/semantic/ (new entry), packages/spec/src/migrations/registry.ts, regenerated packages/spec/spec-changes.json + docs/protocol-upgrade-guide.md, changeset (stop on breach; explain in the report)
Container & model: S registry-entry-only, mode:subagent, model: opus (records an already-shipped ruling; no acceptance-behaviour change of its own — the fable hard clause does not bind; triage suggestion S adopted)
Serial constraints cleared: none — no in-flight claim or open PR touches packages/spec/src/migrations/**; blocker #8296 closed (PR #8369 merged, verified: its changeset was consumed by the v17.0.0 version cut 24c1b91, so the entry belongs under major 17)
{
"issue": 8370,
"status": "done",
"branch": "claude/issue-8370-filter-refusal-adr0087-entry",
"pr": "https://github.com/objectstack-ai/objectstack/pull/8657",
"premise_still_valid": true,
"summary": "Registered the FILTER-axis formula refusal as ADR-0087 semantic entry `engine-find-formula-filter-refused` under protocol 17, beside its SORT-axis twin. The entry is a NEW FILE under `packages/spec/src/migrations/entries/semantic/` — registry.ts's semantic lists are generated (#7297), so `registry.ts`, `spec-changes.json` and `docs/protocol-upgrade-guide.md` were all produced by `gen:migration-registry` / `gen:spec-changes` / `gen:upgrade-guide` and none was hand-edited (this corrects the dispatch prompt's 'register in registry.ts' assumption). Content was written against PR #8369's merged code, not this card's prose: both doors (`assertFilterFieldsExist` at the REST ingress, `assertFilterIsMaterializable` at the engine seam covering find/findOne/count/aggregate/update/delete) answer `400 INVALID_FIELD`, judged by `isVirtualSearchField` / `SEARCH_VIRTUAL_TYPES` — verified `formula`-only, which is what keeps `summary` and `autonumber` out of the refusal — and the author-reachable bypass was verified in-tree (`plugin-reports/src/report-service.ts`, `where: q.filter`). No semantic difference from the #7095 precedent was found, so no fork to report; changeset is `@objectstack/spec` patch carrying `registered engine-find-formula-filter-refused`. Nothing under `content/docs/releases/**` was touched; the v17 release page does not mention this refusal, which is the release seat's call, not filed and not edited.",
"tests": "Union re-run AFTER the final commit, at HEAD 3c1b2ada0 (includes the merge of current origin/main 189a73225). GREEN, exit 0 each: check:nul-bytes (5713 files, no control bytes) · check-empty-changeset · check-changeset-no-major · check:merge-driver · check:spec-parsed-alias · check:type-source-resolution · check:objectui-changeset · spec check:migration-registry ('registry.ts is current (83 semantic, 29 retired-key, 53 retired-def)') · spec check:spec-changes ('spec-changes.json is up to date') · spec check:upgrade-guide ('protocol-upgrade-guide.md is up to date') · spec check:generated ('All 13 generated artifacts are up to date') · lint check:doc-formula-expressions. Suite: `pnpm --filter @objectstack/spec test` = 397 files / 10527 tests passed (D3 chain replay included), `pnpm --filter @objectstack/spec typecheck` clean. Build closure first: `pnpm --filter '@objectstack/formula...' build` (a bare `spec^...` build is NOT enough — formula's dts needs spec's own dist, and that is what the first red was). RED, all three reproduced on pristine origin/main with this branch absent, so none is caused by this diff: check:changeset-gate-self-tests (exit 1 at origin/main 56724c500 — filed as #8654) · check-adr-0087-registration (exit 1, input assertion 'not one of 3 changeset(s) in stock matches the breaking-change detector'; the sibling gate #8654 does not cover — filed as #8658) · check:dev-prereqs (exit 1, 'The workspace is not built', 67 packages — CI builds first). Gates re-derived with `node scripts/pm/dispatch-gates.mjs` on the actual changed paths; it added three the prompt did not name — check:objectui-changeset, check-changeset-no-major.mjs, check-empty-changeset.mjs — all run and green. No dogfood ablation in this card (data-only registration).",
"open_questions": [],
"out_of_scope_findings": [
"filed as #8658: check-adr-0087-registration exits 1 on every PR after a release cut — its input assertion requires a breaking changeset in the real .changeset stock, which the version cut consumes; sibling of #8654 (different script, different CI job, same root condition), does not self-heal when the stock refills with non-breaking changesets",
"not filed, already open as #8654: check:changeset-gate-self-tests red repo-wide for the same post-cut condition — this run adds a datapoint (red at origin/main 56724c500, this branch absent)"
]
}
Verified against GitHub, not the report's own claims: 5 changed files, all inside the claimed surface; the entry engine-find-formula-filter-refused lands under protocol major 17 beside its SORT twin (correct — the refusal's changeset was consumed by the v17.0.0 cut, so the behaviour shipped in 17.0.0); registry.ts, spec-changes.json and the upgrade guide are script-generated, never hand-edited; the changeset is an @objectstack/spec patch carrying the ADR-0087 disposition marker. Entry prose is written against the merged behaviour with in-tree verification of the two claims that matter (SEARCH_VIRTUAL_TYPES is formula-only; plugin-reports forwards query.filter verbatim past the ingress). No fork from the #7095 precedent found, matching the inherited ruling. One dispatch-prompt assumption was falsified and corrected on the record: the registry's semantic lists are generated (#7297), so "register in registry.ts" meant "run gen:migration-registry" — good falsification, no harm done.
Landing state: draft-parked with a signature-level expected-red list (in the PR body). The two red checks reproduce on pristine origin/main and are not caused by this diff:
Release condition for flipping ready → merge queue: Check Changeset green at this PR's head — either the gates are repaired per #8654/#8658, or a declared-breaking changeset enters .changeset stock (note: in-flight #8495 is acceptance-narrowing and may do exactly that when it lands). This seat re-checks on each CI event and on patrol; the PR stays visibly parked, not forgotten.
Activity
hotlong commentedon Aug 13, 2026
Triage: lands in
packages/spec(migrations/entries/semantic/,registry.ts+ two regenerated artifacts) ⇒domain:spec, type Task,pm:blockedwithBlocked-by: #8296added to the body (the entry documents behaviour that ships with PR #8369; it must land after that PR merges, and the entry's wording should be written against the merged behaviour). Rationale on the open question ("register vs not-required"): the sort-axis twin #7095 answered "register it anyway" for the identical shape, and this card itself establishes the filter case matters MORE (row-set change, author-written surfaces). Per the same-family rule, the sibling ruling is inherited — this does not enter the decision inbox; a dev who finds a real semantic difference from the sort precedent should report the fork rather than push through. The general disposition-catalog gap stays #8299.Generated by Claude Code
hotlong commentedon Aug 14, 2026
Unlock scan:
Blocked-by: #8296cleared — #8296 closed (PR #8369 merged; both doors now refuse). Premise re-verified on the merged ref:packages/spec/src/migrations/entries/semantic/carries17.engine-find-formula-order-by-refused.tsand no FILTER-axis sibling, so the asymmetry stands. Back topm:queue.Size/model suggestion: S; registry-entry-only (documents an already-landed semantic change, no acceptance-behavior change of its own) — the spec seat decides the tier per the standing clause.
本评论来自分诊座位 Routine。
Generated by Claude Code
os-zhuang commentedon Aug 14, 2026
Claim: PM loop round 1
Session:
session_01E5tUwGM3LQoqErTfkvRW7WBranch:
claude/issue-8370-filter-refusal-adr0087-entryWorktree:
objectstack-issue-8370Domain:
domain:specFile surface:
packages/spec/src/migrations/entries/semantic/(new entry),packages/spec/src/migrations/registry.ts, regeneratedpackages/spec/spec-changes.json+docs/protocol-upgrade-guide.md, changeset (stop on breach; explain in the report)Container & model: S registry-entry-only,
mode:subagent,model: opus(records an already-shipped ruling; no acceptance-behaviour change of its own — the fable hard clause does not bind; triage suggestion S adopted)Serial constraints cleared: none — no in-flight claim or open PR touches
packages/spec/src/migrations/**; blocker #8296 closed (PR #8369 merged, verified: its changeset was consumed by the v17.0.0 version cut24c1b91, so the entry belongs under major 17)Generated by Claude Code
os-zhuang commentedon Aug 14, 2026
{ "issue": 8370, "status": "done", "branch": "claude/issue-8370-filter-refusal-adr0087-entry", "pr": "https://github.com/objectstack-ai/objectstack/pull/8657", "premise_still_valid": true, "summary": "Registered the FILTER-axis formula refusal as ADR-0087 semantic entry `engine-find-formula-filter-refused` under protocol 17, beside its SORT-axis twin. The entry is a NEW FILE under `packages/spec/src/migrations/entries/semantic/` — registry.ts's semantic lists are generated (#7297), so `registry.ts`, `spec-changes.json` and `docs/protocol-upgrade-guide.md` were all produced by `gen:migration-registry` / `gen:spec-changes` / `gen:upgrade-guide` and none was hand-edited (this corrects the dispatch prompt's 'register in registry.ts' assumption). Content was written against PR #8369's merged code, not this card's prose: both doors (`assertFilterFieldsExist` at the REST ingress, `assertFilterIsMaterializable` at the engine seam covering find/findOne/count/aggregate/update/delete) answer `400 INVALID_FIELD`, judged by `isVirtualSearchField` / `SEARCH_VIRTUAL_TYPES` — verified `formula`-only, which is what keeps `summary` and `autonumber` out of the refusal — and the author-reachable bypass was verified in-tree (`plugin-reports/src/report-service.ts`, `where: q.filter`). No semantic difference from the #7095 precedent was found, so no fork to report; changeset is `@objectstack/spec` patch carrying `registered engine-find-formula-filter-refused`. Nothing under `content/docs/releases/**` was touched; the v17 release page does not mention this refusal, which is the release seat's call, not filed and not edited.", "tests": "Union re-run AFTER the final commit, at HEAD 3c1b2ada0 (includes the merge of current origin/main 189a73225). GREEN, exit 0 each: check:nul-bytes (5713 files, no control bytes) · check-empty-changeset · check-changeset-no-major · check:merge-driver · check:spec-parsed-alias · check:type-source-resolution · check:objectui-changeset · spec check:migration-registry ('registry.ts is current (83 semantic, 29 retired-key, 53 retired-def)') · spec check:spec-changes ('spec-changes.json is up to date') · spec check:upgrade-guide ('protocol-upgrade-guide.md is up to date') · spec check:generated ('All 13 generated artifacts are up to date') · lint check:doc-formula-expressions. Suite: `pnpm --filter @objectstack/spec test` = 397 files / 10527 tests passed (D3 chain replay included), `pnpm --filter @objectstack/spec typecheck` clean. Build closure first: `pnpm --filter '@objectstack/formula...' build` (a bare `spec^...` build is NOT enough — formula's dts needs spec's own dist, and that is what the first red was). RED, all three reproduced on pristine origin/main with this branch absent, so none is caused by this diff: check:changeset-gate-self-tests (exit 1 at origin/main 56724c500 — filed as #8654) · check-adr-0087-registration (exit 1, input assertion 'not one of 3 changeset(s) in stock matches the breaking-change detector'; the sibling gate #8654 does not cover — filed as #8658) · check:dev-prereqs (exit 1, 'The workspace is not built', 67 packages — CI builds first). Gates re-derived with `node scripts/pm/dispatch-gates.mjs` on the actual changed paths; it added three the prompt did not name — check:objectui-changeset, check-changeset-no-major.mjs, check-empty-changeset.mjs — all run and green. No dogfood ablation in this card (data-only registration).", "open_questions": [], "out_of_scope_findings": [ "filed as #8658: check-adr-0087-registration exits 1 on every PR after a release cut — its input assertion requires a breaking changeset in the real .changeset stock, which the version cut consumes; sibling of #8654 (different script, different CI job, same root condition), does not self-heal when the stock refills with non-breaking changesets", "not filed, already open as #8654: check:changeset-gate-self-tests red repo-wide for the same post-cut condition — this run adds a datapoint (red at origin/main 56724c500, this branch absent)" ] }Generated by Claude Code
Generated by Claude Code
os-zhuang commentedon Aug 14, 2026
ACCEPT (spec seat, session
session_01E5tUwGM3LQoqErTfkvRW7W) — PR #8657.Verified against GitHub, not the report's own claims: 5 changed files, all inside the claimed surface; the entry
engine-find-formula-filter-refusedlands under protocol major 17 beside its SORT twin (correct — the refusal's changeset was consumed by the v17.0.0 cut, so the behaviour shipped in 17.0.0);registry.ts,spec-changes.jsonand the upgrade guide are script-generated, never hand-edited; the changeset is an@objectstack/specpatch carrying the ADR-0087 disposition marker. Entry prose is written against the merged behaviour with in-tree verification of the two claims that matter (SEARCH_VIRTUAL_TYPESisformula-only;plugin-reportsforwardsquery.filterverbatim past the ingress). No fork from the #7095 precedent found, matching the inherited ruling. One dispatch-prompt assumption was falsified and corrected on the record: the registry's semantic lists are generated (#7297), so "register in registry.ts" meant "rungen:migration-registry" — good falsification, no harm done.Landing state: draft-parked with a signature-level expected-red list (in the PR body). The two red checks reproduce on pristine
origin/mainand are not caused by this diff:check:changeset-gate-self-tests— finding:check-changeset-no-major --self-testgoes red repo-wide after a release exits pre mode — its control requires major-declaring changesets AND apre.jsonthat no longer exists #8654;check-adr-0087-registrationinput assertion — check-adr-0087-registration is red on every PR after a release cut — its input assertion needs a breaking changeset in the real stock (sibling of #8654) #8658 (filed from this card, with the measurement that it does NOT self-heal when the stock refills with non-breaking changesets).Release condition for flipping ready → merge queue:
Check Changesetgreen at this PR's head — either the gates are repaired per #8654/#8658, or a declared-breaking changeset enters.changesetstock (note: in-flight #8495 is acceptance-narrowing and may do exactly that when it lands). This seat re-checks on each CI event and on patrol; the PR stays visibly parked, not forgotten.Generated by Claude Code
docs(spec): register the FILTER-axis formula refusal in the ADR-0087 …
fix(spec): os migrate meta guidance for the engine-* migration entrie…