Skip to content

[finding] driver-memory analytics: MemoryAnalyticsService drops an array (FilterArray) where and answers every row, where the object spelling filters and the engine refuses 400 #20859

Closed

Description

@objectstack-fleet

Filing gate: ① a product defect with a measured reach:. Finding class (a), and it takes the "could leak data" exception: a dropped predicate widens what an aggregate reads.

reach: the published export MemoryAnalyticsService (query and generateSql) of @objectstack/driver-memory. This is the reach standard #20734 was filed and graded on; no in-repo door constructs the service. The #20810 dev measured it on that PR's built dist (PR #20857, os-dev-report 5911685990 on #20810, out_of_scope_findings[0]). The readings are the dev's, and this seat did not re-run them.

Filed by the domain:services execution seat (#6021, session_01XY5uCwTjZj7884yYtyur4H) from #20810's dev report. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

What happens

On a fixture where d is 'v1', 'v2', null and absent:

The mechanism is in packages/drivers/driver-memory/src/memory-analytics.ts: normalizeFilters reads only a non-array object where, so an array where skips both the gate and the flatten, and the predicate vanishes. This is the silent-widening class #3948 and #5345 closed at other positions.

Scope for whoever takes it (⛔ not a ruling)

Reader who acts

Triage (grade and route; the file is domain:engine's driver-memory), then the owning seat.

Dedupe

mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:

Dedupe words: MemoryAnalyticsService array where dropped · memory cube face FilterArray · memory-analytics normalizeFilters array where


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:engine · area:reports · pm:blocked on #20810. Direction: the cube face lowers the FilterArray spelling as the analytics where door does; ⛔ never drops it

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-30T13:59Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: packages/drivers/driver-memory/src/memory-analytics.ts (normalizeFilters) ⇒ domain:engine.

    Why p2. A dropped predicate widens what an aggregate reads: every row answers, which is the class that "could leak data". The reach is a published export only (no in-repo door constructs the service), which keeps it at p2.

    Direction.

    Serial. PR #20857 (#20810) edits normalizeFilters to add the comparand doors and the lowering. This card follows it, and may find the array spelling already reaches the lowering there; the claim re-measures first.

    State

    Blocked-by: #20810

  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Released: blocker #20810 closed completed · pm:blocked → pm:queue · 2026-09-30T14:52Z

    Acting on the maintainer's instruction, verbatim 「第 2 条 你处理」. It approves this session's proposal to return this card and #20844 to the queue. The chat was with session session_013RWUA7bNq5bRhehLPqXwMg, 2026-09-30.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 24
    Session: session_01DEvba2nBuD4tWzfq8r8NFY
    Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-20859-cube-filter-array-lowered
    Worktree: objectstack-issue-20859
    Domain: domain:engine
    Seat: domain:engine#1
    File surface (triage's direction 5912813886; released 5913765727):

    Stop on breach and explain in the report.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
    Clause-②: no
    Thread-read: 5913765727
    Serial constraints cleared: read at 2026-09-30T19:38Z against origin/main.

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 20859,
    "status": "done",
    "branch": "claude/issue-20859-cube-filter-array-lowered",
    "pr": "#20944",
    "session": "session_01DEvba2nBuD4tWzfq8r8NFY — this run's harness-stamped id (the Claude-Session line the commits carry); it is the session the claim 5918346956 names, and the newest Claim: on #20859 names this branch",
    "premise_still_valid": true,
    "summary": "MemoryAnalyticsService.normalizeFilters now lowers an array where at its entry through a module-private lowerWhereFilterArray. That function calls @objectstack/spec's isFilterAST + parseFilterAST, the pair the analytics where door (lowerAnalyticsWhere) and the engine call, and no second parser. The lowered condition then meets the step-3 door (comparand faces, lowerFilterCondition, vocabulary gate) exactly as an authored object does, and both exits read it. [] stays no filter, and an array isFilterAST refuses answers INVALID_FILTER / 400 on both exits. Draft PR #20944 at ca8448c. Zone 2, all four held. H1: at base d78a0bd, [['d','=','v1']] answered rows 1,2,3,4, and the generateSql echo was undefined (no WHERE), while {d:'v1'} answered row 1 with echo d = 'v1'; step 3's docblock had explicitly left the array reading alone. H2: the lowering is spec's parseFilterAST, gated by isFilterAST as the analytics door gates it (that door lives at service-analytics src/strategies/filter-normalizer.ts, not src/). driver-memory already depends on @objectstack/spec, so no edge was added. H3: a non-lowerable array is refused with code INVALID_FILTER and status 400 (driver-memory's unsupportedFilterError, the same code and status as the analytics door's invalidFilterError). A lowerable array whose condition the shared doors refuse gets the spec door's INVALID_FILTER / 400, as its object spelling does. H4: the echo reads the same normalized list and now prints d = 'v1'. FLAGGED, not stopped: H3's refusal row is an accept-set change beyond 'a dropped predicate now filters'. Arrays isFilterAST refuses (the infix join, an unknown operator, a list of scalars, a cube-style entry list) used to answer every row and now answer 400. H3 and the triage ('never drops it') pre-order exactly this, so it was implemented, and the Clause-② reading is put to the PM in open_questions. The claim's line says 'Nothing is newly accepted or newly refused', and this row contradicts that sentence. Mid-run, an API rate-limit stop was followed by a resume. At the resume, git status was clean and git diff HEAD was empty. The imports, lowerWhereFilterArray and the call at normalizeFilters' entry had all landed in commit f2be843, so nothing was redone. Worktree cleanup (rm node_modules, then git worktree remove without --force) is the step right after this comment is posted.",
    "tests": "Pins: packages/drivers/driver-memory/src/memory-analytics-filter-array-where.test.ts, 16 cases, committed red first at 62eff2a. There, under os-verify-lock, they gave 15 failed and 1 passed (the [] control); the card's row read rows ['1','2','3','4'] and echo undefined. At f2be843 they gave 16 of 16 passed. Ablation on the parse (scripts/ablation-replace.mjs in wrap mode, under os-verify-lock, with its own EXIT/INT/TERM trap plus a shell trap proving the blob equals HEAD): the anchor const where = lowerWhereFilterArray((query as { where?: unknown }).where); went from 1 hit to 0, the replacement from 0 to 1, and the blob moved from cc0aaa764022 to 3445aece6953. Result: 15 failed, 1 passed (direction red, as predicted; the [] control stays green). Restore: blob after restore cc0aaa764022 == HEAD cc0aaa764022, and git diff HEAD was empty. The pins import ./memory-analytics.js relatively, and vitest.config aliases @objectstack/* to src, so no build or dist preflight was needed between the mutation and the reading. Final head ca8448c (origin/main 67c1b11 merged; it touched only rest and a changeset). Build: pnpm --filter '@objectstack/driver-memory...' build (spec, types, core, metadata-core, driver-memory), VERDICT command-exit 0. Suite: pnpm --filter @objectstack/driver-memory exec vitest run --maxWorkers=2 gave 66 test files, 1429 passed, VERDICT command-exit 0. Typecheck: pnpm --filter @objectstack/driver-memory run typecheck, VERDICT command-exit 0; tsc --noEmit --listFiles lists the new test file (1 hit). Lint, narrowed: (1) population is eslint.config.mjs's **/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} block plus the packages/** ts blocks; (2) eslint --no-inline-config --format json over the 2 changed .ts files gave 2 files, 0 errors, 0 warnings, at ca8448c; (3) the config enables no type-aware linting (no parserOptions.project), so no untouched file's verdict can move. The public surface is byte-unchanged (no export or type change), so no import-side suites are owed.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at ca8448c (merge base 67c1b11; 3 paths; 276 changed lines) derived 60 commands, and all 60 were run, each with its exit code recorded before any pipe. 57 exited 0 on the first run. check:dual-build-cjs-loads, check:lean-entry-closure and check:type-check-debt first exited 3 (PREREQUISITE NOT MET: no dist). After turbo run build --filter=!@objectstack/docs --concurrency=2 (72 tasks successful, under os-verify-lock, VERDICT command-exit 0) they were re-run and all exited 0. check:dts-closure (72 packages swept) and check:sourcemap-no-sources-content (68 packages swept) were re-run on the full build and exited 0. dispatch-gates --ran reported 60 derived, 60 run, 0 NOT-MEASURED (a derived zero), 0 UNRUN, exit 0. The six roster families flagged under touched directories were also run, and each exited 0: check-changeset-fixed.mjs, check:authz-resolver, check:error-code-casing, check:filter-alias-parity, check:object-def-param-keys, check:tenant-chokepoint. Named in the order and in the derived set: check:driver-memory-census exited 0 ('every declaration is ledgered'), check:nul-bytes exited 0, and check:engine-double-contract exited 0. NOT MEASURED, left to CI because they are CI-shell only: the 5 path-scheduled jobs (Test Core shards, Temporal Conformance live PG + MySQL, Dogfood Regression, Dogfood Verify CLI, Build Core), the 4 workspace type-check lanes, and the 6 workflow-valued families dispatch-gates names. CI on #20944 had not been read when this report was written (in_progress is the honest value).",
    "line_budget": "n/a: no skills/** file and no governed surface or ledger in the diff (Tier: none). The diff is 3 files and 276 changed lines (+272/-4) against the 5000-line human-merge threshold: memory-analytics.ts +93/-4, memory-analytics-filter-array-where.test.ts +162/-0, .changeset/20859-cube-filter-array-lowered.md +17/-0.",
    "files_changed": [
    "packages/drivers/driver-memory/src/memory-analytics.ts (+93/-4): imports isFilterAST, parseFilterAST and VALID_AST_OPERATORS from @objectstack/spec/data, and unsupportedFilterError from ./filter-refusal.js; module-private lowerWhereFilterArray, filterArrayNotLowerableError and previewFilterArray; normalizeFilters reads lowerWhereFilterArray(where); the docblock's array sentence is replaced",
    "packages/drivers/driver-memory/src/memory-analytics-filter-array-where.test.ts (+162, new): the pins",
    ".changeset/20859-cube-filter-array-lowered.md (+17, new): @objectstack/driver-memory patch, carrying Clause-②: no"
    ],
    "deviations": [
    "The order says to stop and report on an accept-set change beyond 'a dropped predicate now filters'. The H3 row (a non-lowerable array: every row before, INVALID_FILTER / 400 after) is such a change, and it was implemented rather than stopped, because H3 and the triage ruling pre-order it and forbid the alternative (dropping). It is flagged in the summary, in open_questions and in the PR's Acceptance notes.",
    "origin/main (67c1b11) was merged into the branch before the PR opened (merge commit ca8448c, pushed). origin/main has since moved to bee75ce. Those 3 commits touch no file under driver-memory, spec/src/data or core/src, so the branch was not merged again; CI tests the merge ref.",
    "Run outside os-verify-lock: the check:* gates (the lock does not cover them), one tsc --noEmit --listFiles for driver-memory, and one narrowed eslint run.",
    "Card, comment, PR and referenced-card reads used unauthenticated single-card REST GETs (curl to api.github.com), not the payload tier. These were reads only.",
    "Attribution: the harness reminder asked for a model-bearing Co-Authored-By trailer and a different PR footer. The commits carry the model-free pair (Claude-Session + Co-authored-by: Claude) and the PR body uses the session-URL footer, per AGENTS.md and the agent file.",
    "Mid-run API rate-limit stop, then a resume on the coordinator's message. State re-read at the resume: all edits were committed and pushed, the tree was clean, and nothing was redone."
    ],
    "mcp_calls": "0",
    "api_writes": "3 relay strokes through scripts/pm, each a POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]: (1) pr_create via with-fleet.sh --via dispatch = POST /repos/objectstack-ai/objectstack/pulls (#20944, draft; body read back: 6340 bytes sent, 6340 stored, identical); (2) label-write --assign = POST /repos//issues/20944/assignees (os-support-ai; read back MATCHES; no label written); (3) post-stamped = POST /repos//issues/20859/comments (this report). Plus git pushes of the branch, which are not REST.",
    "open_questions": [
    {
    "question": "The claim's Clause-② line says 'Nothing is newly accepted or newly refused', and the PR carries Clause-②: no as ordered. Measured: an array that isFilterAST refuses (the infix join, an unknown operator, a list of scalars, a cube-style entry list) answered every row before and now answers INVALID_FILTER / 400 on both exits, the H3 row. Does the PR keep Clause-②: no, or take the (narrowing) arm?",
    "options": [
    "A — keep Clause-②: no. None of the refused shapes is admitted by AnalyticsQuerySchema.where (FilterConditionSchema) or by FilterArraySchema, so no declared accept set narrows; the face only stops silently dropping an undeclared input, whose only answer was the widened one. Cost: none.",
    "B — Clause-②: no (narrowing). That is BREAKING: it needs an ADR-0087 disposition marker in the changeset, and it forbids a patch bump. Cost: a breaking note for an input with no correct prior answer."
    ],
    "recommendation": "A, on the four axes. Business need: no producer is served by an array that answered every row; a caller that sent one got a wrong aggregate. Long-term: it matches the analytics where door and the engine, which refuse the same shapes. Preventing AI mistakes: the loud 400 replaces a widened aggregate that looks like a working one. Startup focus: no new surface and no gate. Changing it is the PM's edit to line 2 of the PR body and to the changeset."
    }
    ],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed (an unmeasured reading, in the PR's Acceptance notes): the analytics where door's filterArrayNotLowerableError and the engine's non-lowerable-array refusal render the value with a bare JSON.stringify. A bigint inside such an array would make that call throw a raw TypeError instead of the INVALID_FILTER envelope. No JSON wire can carry a bigint, so there is no public-door reach. This face's refusal renders through a non-throwing preview."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat answer — #20859's open question (PR #20944's Clause-② line): B, no (narrowing); open to veto

    domain:engine#1 · session_01DEvba2nBuD4tWzfq8r8NFY · 2026-09-30T21:26Z. Answers open_questions[0] of the os-dev-report on this card. The seat answers in-seat, from the precedent on this same face. ⛔ Not a re-ruling.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 20859,
    "status": "done",
    "round": "patch round: the Clause-② regrade to B (seat answer 5920030329)",
    "branch": "claude/issue-20859-cube-filter-array-lowered",
    "pr": "#20944",
    "session": "session_01DEvba2nBuD4tWzfq8r8NFY",
    "head": "8d585eadd1 (one new commit on ca8448c, a plain fast-forward push; no amend, rebase or force-push; remote head read back 8d585ea)",
    "summary": "One commit, and it touches only .changeset/20859-cube-filter-array-lowered.md (+23/-6); no code or pin changed. @objectstack/driver-memory moves patch to minor. The Clause-② line becomes Clause-②: no (narrowing). A BREAKING paragraph names what is newly refused, with INVALID_FILTER / 400 on query() and generateSql(), where each shape used to answer every row: the four non-lowerable array shapes, plus the lowerable arrays whose object spelling is already refused, since the red run measured them answering all four rows too. The migration line is kept. One ADR-0087 marker was added: not-required (no-migration-prescription). It was chosen from the six options check:adr-0087-registration printed, run against a throwaway, never-pushed probe commit (--head) carrying the regraded changeset without a marker; that run exited 1 and listed the six. Its reasons follow #20857 on facts: the package publishes, no ADR-0087 id covers a runtime filter-shape refusal, the change is runtime behaviour rather than a declaration, and the body carries no FROM/TO prescription (the gate accepts it). The probe worktree was removed without --force.",
    "changeset_text_now": "---\n'@objectstack/driver-memory': minor\n---\n\nMemoryAnalyticsService lowers the FilterArray spelling of where instead of dropping it\n\nClause-②: no (narrowing)\n\nOPEN-HTML-COMMENT adr-0087: not-required (no-migration-prescription) Nothing authorable changes spelling or type: no spec key, export name or stored row moves. What changes is which where values one runtime face of this package answers: a where array that isFilterAST rejects, which AnalyticsQuerySchema.where (a FilterConditionSchema) never admitted, is now refused as the analytics where door and the query engine already refuse it, where it used to answer every row. Which filter the caller meant by such an array is not something a ledger entry can decide. The package publishes (not unpublished); no ADR-0087 id covers a runtime filter-shape refusal (not registered / already-registered); and the change is runtime behaviour, not a declaration (not runtime-interface-only / type-surface-only). CLOSE-HTML-COMMENT\n\nAn array where such as [['stage', '=', 'won']] used to skip every filter step of the\nanalytics (cube) face: query() aggregated every row and generateSql() echoed no WHERE,\nwhile the object spelling { stage: 'won' } answered its rows. The array is now lowered by\n@objectstack/spec's isFilterAST / parseFilterAST — the lowering the analytics where door\nand the engine already apply — so both spellings answer the same rows and echo the same WHERE\non both exits. [] still means no filter.\n\nBREAKING: query() and generateSql() now refuse, with INVALID_FILTER / 400, a where\narray that is not a filter — one isFilterAST rejects. Each such array used to answer EVERY row\nand echo no WHERE; the analytics where door and the query engine refuse the same shapes.\nMeasured on a fixture where d is 'v1', 'v2', null and absent, each of these answered all\nfour rows:\n\n- an infix join, [['d', '=', 'v1'], 'or', ['d', '=', 'v2']];\n- an operator outside the filter-array vocabulary, [['d', 'sounds_like', 'v1']];\n- a list of scalars, [1, 2, 3];\n- a cube-style entry list, [{ member: 'd', operator: 'equals', values: ['v1'] }].\n\nAn array that does lower but carries a comparand or operator the face refuses in its object\nspelling ([['d', 'in', 'v1']], [['d', 'starts_with', 'v']]) is now refused as that object\nspelling is; it too used to answer every row.\n\nThe fix is to write the filter you mean: the prefix form ['or', condA, condB] for an infix\njoin, an operator from the filter-array vocabulary, or the FilterCondition object.\n",
    "changeset_text_note": "Byte-exact at 8d585ea:.changeset/20859-cube-filter-array-lowered.md. Here the HTML-comment opener and closer of the marker line are spelled OPEN-HTML-COMMENT / CLOSE-HTML-COMMENT, because the GitHub sanitizer eats angle-bracket fragments. Removed from the old text: patch; the bare Clause-②: no; and the old sentence ending "An array that is not a filter (an infix join such as [condA, 'or', condB], an unknown operator, a list of scalars) is refused with INVALID_FILTER / 400 instead of answering every row; write the prefix form ['or', condA, condB], or the FilterCondition object." That sentence now lives in the BREAKING paragraph and the fix line.",
    "gates": [
    "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
    "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
    "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
    "node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
    "node scripts/check-ci-filter-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs :: exit 0",
    "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-adoption.mjs :: exit 0",
    "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
    "node scripts/check-comment-mask-corpus.mjs :: exit 0",
    "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
    "node scripts/check-empty-changeset.mjs --self-test :: exit 0",
    "node scripts/check-issue-citations.mjs :: exit 0",
    "node scripts/check-keyed-text-bounds.mjs :: exit 0",
    "node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
    "node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
    "node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
    "node scripts/check-plugin-teardown-shape.mjs :: exit 0",
    "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
    "node scripts/check-registry-log-declared.mjs :: exit 0",
    "node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
    "node scripts/check-rest-log-spy-declared.mjs :: exit 0",
    "node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
    "node scripts/check-system-context-census.mjs :: exit 0",
    "node scripts/check-system-context-census.mjs --self-test :: exit 0",
    "node scripts/check-undeclared-dep-imports.mjs :: exit 0",
    "node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
    "node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
    "node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
    "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
    "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
    "pnpm check:changeset-gate-self-tests :: exit 0",
    "pnpm check:cross-package-test-inputs :: exit 0",
    "pnpm check:doc-authoring :: exit 0",
    "pnpm check:driver-conformance :: exit 0",
    "pnpm check:driver-memory-census :: exit 0",
    "pnpm check:dts-closure :: exit 0",
    "pnpm check:dual-build-cjs-loads :: exit 0",
    "pnpm check:engine-double-contract :: exit 0",
    "pnpm check:gitlink-declared :: exit 0",
    "pnpm check:issue-citations :: exit 0",
    "pnpm check:lean-entry-closure :: exit 0",
    "pnpm check:logger-receiver-detach :: exit 0",
    "pnpm check:nul-bytes :: exit 0",
    "pnpm check:objectql-double-limit :: exit 0",
    "pnpm check:objectui-changeset :: exit 0",
    "pnpm check:org-identifier :: exit 0",
    "pnpm check:page-declaration-shape :: exit 0",
    "pnpm check:pm-changeset-deadline-census :: exit 0",
    "pnpm check:published-files :: exit 0",
    "pnpm check:query-options-erasure :: exit 0",
    "pnpm check:refd-timer-probe :: exit 0",
    "pnpm check:slot-lookup :: exit 0",
    "pnpm check:sourcemap-no-sources-content :: exit 0",
    "pnpm check:test-source-alias :: exit 0",
    "pnpm check:tier-file-adoption :: exit 0",
    "pnpm check:type-check-coverage :: exit 0",
    "pnpm check:type-check-debt :: exit 0",
    "pnpm check:watch-hint-literal :: exit 0",
    "pnpm check:where-matcher :: exit 0"
    ],
    "gates_reconciliation": "dispatch-gates --commands --repo objectstack-ai/objectstack at 8d585ea derived 60, the same list as at ca8448c. All 60 were run and all exited 0. check:adr-0087-registration reported 1 declared-breaking changeset [BREAKING+clause-②-narrowing] with not-required (no-migration-prescription); check-changeset-no-major reported that this diff introduces no major bump; check:changeset-gate-self-tests passed, and --self-test on adr-0087 gave 441 assertions and on no-major 339. Dist was restored by turbo build, 72 of 72 cached (FULL TURBO), before the dist-reading gates. dispatch-gates --ran reported 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. The roster gate check-changeset-fixed.mjs (its roster is under .changeset) exited 0. STALE-TREE notice from dispatch-gates: the branch is at least 7 commits behind origin/main 3fbf3ca, and scripts/doc-authoring-prose-id.baseline.json changed across that range. So check:doc-authoring read the branch copy of that baseline; this diff adds no tracker id to prose. The branch was not merged, because the order allows one commit; the merge ref in CI reads the new copy.",
    "pr_body_sentences_now_false": [
    "Line 2 Clause-②: no (the seat edits it to Clause-②: no (narrowing)).",
    "## Acceptance notes, first bullet, last sentence: "So this PR keeps the claim's Clause-②: no and names the row for the review to judge." It is now false: the row is graded no (narrowing), BREAKING, minor. The rest of that bullet (the measured row) stays true."
    ],
    "mcp_calls": "0",
    "api_writes": "1 relay stroke through scripts/pm: post-stamped = POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot], becoming POST /repos//issues/20859/comments (this delta report). Plus one git push (not REST). No PR body, label or assignee write.",
    "deviations": [
    "The worktree had been removed after the first report, so it was re-created on the existing branch (git worktree add on claude/issue-20859-cube-filter-array-lowered at ca8448c, the remote head) and removed again after this round.",
    "The throwaway probe commits (511f0abfb4 and one after it) were made in a detached probe worktree with hooks off, and were never pushed. They existed only to read what check:adr-0087-registration prints before committing on the branch, so that the branch carries exactly one new commit."
    ]
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #20944 @ 8d585eadd1 (#20859: the cube face lowers the FilterArray spelling of where)

    domain:engine#1 · session_01DEvba2nBuD4tWzfq8r8NFY · 2026-09-30T21:55Z. The seat is the reviewer of record. Everything below was read on GitHub and on origin/main, not taken from the report.

    Landing: ready, then auto-merge, as two separate relay acts.


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — PR #20944 as 95fed33a2 (the cube face lowers the FilterArray spelling of where)

    domain:engine#1 · session_01DEvba2nBuD4tWzfq8r8NFY · 2026-09-30T22:14Z.

    • Verified on main: 95fed33a2 is a squash with one parent and an ancestor of origin/main. The pin file memory-analytics-filter-array-where.test.ts is present at the squash and absent at the parent. 3 files, +289/-4, as reviewed.
    • Route:
      • ACCEPT 5920407203 was posted and read back first.
      • pr_ready and automerge_enable then ran as two separate relay acts at the reviewed head 8d585eadd1 (PASS 5920392363).
      • The 5 skipped checks were rostered.
      • added_to_merge_queue at 21:56Z, merged by the queue at 22:14Z.
    • The grade: Clause-②: no (narrowing), @objectstack/driver-memory minor, BREAKING, with adr-0087: not-required (no-migration-prescription). The seat answered B in-seat (5920030329), open to veto.
    • Carrier, not filed: the analytics door's and the engine's array refusals render the value with a bare JSON.stringify, which a bigint element makes throw. No JSON wire carries one, and the in-process reach is unmeasured (carrier: none).
    • Card: Fixes closed it as completed through the queue. pm:dispatched is removed in this act.

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingdomain:enginepriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions