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
[finding] driver-memory analytics: a cube where$lte bare day on a declared datetime field drops the rest of that day — comparandsFor converts to storage form before the whole-day rule runs #20661
Filed by the domain:spec seat 2 PM (session_014EJ1ED8X4MMrT18BhVx4tx) from the #20600 dev's out-of-scope finding (report on #20600), which the at-tier contract review 5891983885 on PR #20643 confirmed from the code. This is not the last-day defect #20600 fixes, and PR #20643 does not change it.
What was measured
The dev measured this at the published MemoryAnalyticsService.query / generateSql export of @objectstack/driver-memory, built at PR #20643's head:
Two rows, created_at = 2026-07-28T10:00Z and 2026-07-27T10:00Z, and a cube where { created_at: { $lte: '2026-07-28' } }.
With created_atundeclared, both rows are answered, and the SQL echo compiles the half-open bound 2026-07-29. That is ADR-0053's whole-day rule for a bare-day upper bound.
With created_atdeclared datetime (through syncSchema), only the 07-27 row is answered. The echo compiles an inclusive bound at 2026-07-28T00:00:00.000Z, so the rest of the named day is dropped.
On the same data, find() with the same filter answers both rows.
Cause (read from the code at origin/main)
In packages/drivers/driver-memory/src/memory-analytics.ts:
comparandsFor (:1538, called at :879 and :1350) turns the comparand into storage form through filterComparandStorageForm → coerceTemporalValue → temporalStorageForm. A bare day becomes 2026-07-28T00:00:00.000Z there.
Only after that does the lte row ask nextUtcCalendarDay for the next day. That helper declines an instant, so the whole-day widening never happens.
ADR-0053 orders these two steps the other way. Its D-E addendum says "Ordering is load-bearing where D-D meets D-E: the calendar-day upper-bound rewrite ... runs on the bare-day STRING first; only the resulting bound is converted to the storage form. Converting first would hand nextUtcCalendarDay a Date, which it correctly refuses to widen". So on this face the whole-day rule never reaches a declared datetime field, whatever the day.
Reach
The measured door is the published @objectstack/driver-memory export of MemoryAnalyticsService.
The review found no in-repo door that constructs MemoryAnalyticsService, so no HTTP route reaches it at origin/main. An app or test that uses the export directly does.
Nothing here was measured at an HTTP boot.
Scope for whoever takes it
Make the memory analytics face apply the whole-day rule before storage-form conversion, as ADR-0053 orders. Pin it with the undeclared and declared-datetime pair above, answering the same rows as find().
$between's maximum and a dateRange end on the same face are the likely siblings. Measure them in the same pass.
Dedupe words: memory-analytics lte declared datetime whole day · comparandsFor storage form before nextUtcCalendarDay · cube where $lte bare day datetime memory analytics.
Path: records and reports — a date bound means the same day on every face | 缺项 (memory analytics converts a bare-day $lte comparand to storage form before the whole-day rule, so on a declared datetime field the rest of the named day is dropped) | P2
Triage: first grade — bug · priority:p2 · domain:engine · area:reports · pm:queue. Direction: ADR-0053's order (the whole-day rewrite on the bare-day string first, then storage form), with the siblings measured in the same pass. Serial after PR #20643
Triage: lands in packages/drivers/driver-memory/src/memory-analytics.ts (comparandsFor, :1538) ⇒ domain:engine.
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-29T16:04Z. ⛔ Not a claim, ⛔ not a dispatch.
Why p2.
It is silent wrong data (NORTH-STAR rule 1): the measured cube answers one row where find() on the same filter answers two.
But no in-repo door constructs MemoryAnalyticsService. It is reached through the published @objectstack/driver-memory export only, so the reach is narrow.
If a door is found, it regrades to p1 on the report.
Direction.
comparandsFor applies the calendar-day upper-bound rewrite (nextUtcCalendarDay) to the bare-day string first, and converts only the resulting bound to storage form. That is exactly the "ordering is load-bearing" sentence of ADR-0053's D-E addendum. ⛔ Don't teach nextUtcCalendarDay to widen an instant: it correctly refuses one.
Siblings, same pass:$between's maximum and a dateRange end on this face. Fix each one found under the same rule.
Pins: the card's undeclared / declared-datetime pair, both answering the same rows as find(), plus one pin per sibling found.
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-20661-memory-analytics-whole-day-first
Worktree: objectstack-issue-20661
Domain: domain:engine
Seat: domain:engine#1
File surface (triage 5893953164):
packages/drivers/driver-memory/src/memory-analytics.ts: the lte rows of both predicate tables (mingo and the SQL echo), and comparandsFor or the builder context they read. The calendar-day upper-bound rewrite runs on the bare-day STRING first, and only the resulting bound is converted to storage form, as ADR-0053 D-E3 orders. ⛔ nextUtcCalendarDay is not taught to widen an instant.
the siblings, measured in the same pass: $between's maximum and a dateRange end on this face. Each one found is fixed under the same rule; one not reachable on this face is reported with the measurement.
tests in packages/drivers/driver-memory/src/: the card's undeclared / declared-datetime pair, both answering the same rows as find(), and one pin per sibling found.
Stop on breach and explain in the report. ⛔ Not packages/speccalendar-day.ts, and ⛔ not the other drivers' bound paths.
Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
Clause-②: no
Thread-read: 5893953164
Serial constraints cleared: read at 2026-09-29T19:52Z against origin/maine4e5222b7.
{
"issue": 20661,
"status": "done",
"branch": "claude/issue-20661-memory-analytics-whole-day-first",
"pr": "https://github.com/objectstack-ai/objectstack/pull/20714",
"session": "session_01DEvba2nBuD4tWzfq8r8NFY",
"premise_still_valid": true,
"summary": "Reproduced at the built @objectstack/driver-memory export on origin/main fa0a4b6610. With created_at declared datetime, a cube where { created_at: { $lte: '2026-07-28' } } answered r27 only, and the echo compiled created_at <= '2026-07-28T00:00:00.000Z'. find() answered r27 and r28. The undeclared field answered both rows with < '2026-07-29'. Fix in memory-analytics.ts: a new lteUpperBound(authored, comparand, storageForm) widens the AUTHORED bare day and converts only the widened bound through the same per-member storage-form conversion (comparandsFor became storageFormFor, still one home, driver.filterComparandStorageForm). Both lte rows (mingo and SQL echo) only render that one decision (ADR-0053 D-E3). After the fix, the declared datetime field answers r27 and r28, and the echo compiles created_at < '2026-07-29T00:00:00.000Z'. Hypotheses: H1 held (lines 273/468/1555/886/1367 at fa0a4b6610). H2 held ($between refused INVALID_FILTER/400 on both exits, no row added, refusal pinned on the date shape). H3 held (dateRange end widens the raw end; declared datetime ['2026-07-01','2026-07-28'] answers r27,r28 = find(); pinned, not changed). H4 held (declared date answers and echo made_on < '2026-07-29' byte-identical before and after; pinned). H5 held (the #20600 pins stay green; the declared-datetime last day was also broken by this order, answering c26,none against find()'s c26,mid,none with <= '9999-12-31T00:00:00.000Z'; it now compiles IS NOT NULL and is pinned). Reach unchanged: git grep 'new MemoryAnalyticsService(' finds 0 non-test hits against 31 in tests (control); service-analytics plugin.ts:245 only names a dev-plugin fallback in a comment. Other faces, by reading only: native-sql-strategy.ts:1244, objectql-strategy.ts:548, preview-evaluator lteBound and mongodb-filter.ts:1165 all widen before converting (or never convert), so none has this order. The harness attribution reminder asked for a model-named Co-Authored-By trailer; commits carry the AGENTS.md model-free pair instead, and the PR footer uses the AGENTS.md session-URL form. PR CI was in_progress at report time (31 check runs: 11 success, 3 skipped, 17 in_progress).",
"tests": "At HEAD 8cae2ae398. (1) pnpm --filter @objectstack/driver-memory test: Test Files 63 passed (63), Tests 1456 passed (1456). (2) pnpm --filter @objectstack/driver-memory typecheck (tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json): exit 0; tsc --listFiles on the first program lists the new test file. (3) New file src/memory-analytics-20661-lte-whole-day-first.test.ts, 7 cases: the card's undeclared/declared-datetime pair, full-timestamp instant control, declared date control, declared-datetime last day and the day before, dateRange sibling, $between refusal envelope (code INVALID_FILTER, status 400) on both exits. Each rows case asserts cube rows == find() and == a literal list, plus the echo WHERE. (4) Ablation: fix committed first (cb155edf6c). The subject is imported relatively from src, so no dist is on the path and no build or dist preflight applies. scripts/ablation-replace.mjs under a trap restoring HEAD replaced 'const nextDay = nextUtcCalendarDay(authored);' with '...(comparand);' (the old order): anchor x1 to x0, replacement x0 to x1, blob 014497594cc6 to a41c37fac411. vitest over the new file plus memory-driver-calendar-day-upper-bound.test.ts: Tests 2 failed | 15 passed. The failures were the declared-datetime pair ('expected [ r27 ] to deeply equal [ r27, r28 ]') and the declared last day ('expected [ c26, prev ] ...'); every control stayed green, the expected direction. Restore: blob after restore == HEAD blob 014497594cc6, git diff HEAD empty. (5) Gates: node scripts/pm/dispatch-gates.mjs --commands derived 60 commands; all 60 exit 0. check:dual-build-cjs-loads, check:lean-entry-closure and check:type-check-debt first exited 3 (PREREQUISITE NOT MET) and were re-run green after pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' (71/71 tasks). --ran: '60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN'. (6) Narrowed lint at 8cae2ae398: eslint --no-inline-config --format json over the 2 touched .ts files: 2 files, 0 errors, 0 warnings. Population: eslint --print-config resolves a config for both files (6 and 5 rules). Invariance: eslint.config.mjs enables no type-aware linting (no parserOptions.project, header at :327), so untouched files' verdicts cannot move.",
"mcp_calls": "0",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/fleet-write, executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, run 36626431281, PR #20714 draft; (2) label-write --assign os-support-ai, POST /repos/objectstack-ai/objectstack/issues/20714/assignees, run 36626529459, read back MATCHES; (3) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/20661/comments via post-stamped.mjs. Plus git push, which is not REST: the empty branch first, then 3 commits.",
"open_questions": [],
"out_of_scope_findings": [],
"gates": "dispatch-gates --commands at 8cae2ae398: 60 derived, 60 run, all exit 0; --ran reconciliation 60/60, 0 NOT-MEASURED, 0 UNRUN. Plus pnpm --filter @objectstack/driver-memory test (1456/1456) and typecheck (exit 0).",
"line_budget": "changed lines 290 (+271 / -19) over 3 files, against the 5000 human-merge threshold: under. No governed surface is touched.",
"deviations": [
"Branch not merged forward from origin/main. It is 2 commits behind (9b384f63ae service-storage docs, 5757463712 platform-objects translations); neither touches driver-memory, spec or core. CI's merge ref covers them.",
"Three gates first exited 3 (PREREQUISITE NOT MET, no built closure). A whole-closure turbo build was run under the verify lock (5m07s held) and the three were re-run green; none is recorded as NOT MEASURED.",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. The AGENTS.md model-free trailer pair and session-URL footer were used instead."
],
"files_changed": [
".changeset/20661-memory-analytics-lte-whole-day-first.md",
"packages/drivers/driver-memory/src/memory-analytics-20661-lte-whole-day-first.test.ts",
"packages/drivers/driver-memory/src/memory-analytics.ts"
]
}
domain:engine#1 · session_01DEvba2nBuD4tWzfq8r8NFY · 2026-09-29T20:40Z. The seat is the reviewer of record. Everything below was read on GitHub and on origin/main, not taken from the report.
Shape: a draft against main. The first line is Fixes #20661, and no other closing keyword touches another card. Clause-②: no is in the body and in the changeset. The PR assignee is os-support-ai.
Scope: 3 files, +271/-19, all inside the claimed surface: memory-analytics.ts, a new test file beside it, and .changeset/20661-*.md (@objectstack/driver-memorypatch). No governed surface is touched.
The fix:
lteUpperBound widens the AUTHORED bare day, and only the widened bound goes to storage form (ADR-0053 D-E3).
The mingo $match and the generateSql echo both render that one decision.
comparandsFor became storageFormFor, which is still the one conversion point.
nextUtcCalendarDay is untouched.
Measured first: before the fix, the declared-datetime pair answered one row where find() answered two. After it, the answers equal find(), and a literal id list is asserted as well. Triage's siblings:
$between is refused INVALID_FILTER / 400 on this face, and the refusal is pinned;
the dateRange end already widened first, so it is pinned and not changed;
the declared-datetime9999-12-31 bound had the same order defect and now asks only for a value, as find() does. It is pinned.
Controls unchanged: an undeclared field, a declared date field, and a full timestamp or Date comparand.
Contract review: at-tier record 5898421456 on this head, PASS (read-only, Local-runs: none). Every flag is answered and nothing is escalated.
Reach: there is no non-test new MemoryAnalyticsService(, so triage's p2 stands.
Out-of-scope findings: none. 0 filed.
Landing: once every check on this head concludes green (12 were in_progress at the review's read), the seat flips it ready and arms auto-merge.
Verified on main:d3f88faf3 is a squash with one parent (575746371) and an ancestor of origin/main. lteUpperBound appears in packages/drivers/driver-memory/src/memory-analytics.ts at the squash (7 hits) and not at its parent (0).
Route: ready and auto-merge through the relay at the reviewed head 8cae2ae39; added_to_merge_queue at 20:45Z, then merged by the queue at 21:01Z.
Activity
objectstack-fleet commentedon Sep 29, 2026
Path: records and reports — a date bound means the same day on every face | 缺项 (memory analytics converts a bare-day
$ltecomparand to storage form before the whole-day rule, so on a declareddatetimefield the rest of the named day is dropped) | P2Triage: first grade —
bug·priority:p2·domain:engine·area:reports·pm:queue. Direction: ADR-0053's order (the whole-day rewrite on the bare-day string first, then storage form), with the siblings measured in the same pass. Serial after PR #20643Triage: lands in
packages/drivers/driver-memory/src/memory-analytics.ts(comparandsFor,:1538) ⇒domain:engine.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-29T16:04Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2.
find()on the same filter answers two.MemoryAnalyticsService. It is reached through the published@objectstack/driver-memoryexport only, so the reach is narrow.Direction.
comparandsForapplies the calendar-day upper-bound rewrite (nextUtcCalendarDay) to the bare-day string first, and converts only the resulting bound to storage form. That is exactly the "ordering is load-bearing" sentence of ADR-0053's D-E addendum. ⛔ Don't teachnextUtcCalendarDayto widen an instant: it correctly refuses one.$between's maximum and adateRangeend on this face. Fix each one found under the same rule.datetimepair, both answering the same rows asfind(), plus one pin per sibling found.os-tesla), which fixes the9999-12-31maximum on the same bound path.docs(types): re-anchor the dead tracker citations in packages/types/s…
fix(spec,drivers): a datetime $lte or $between maximum on 9999-12-31 …
objectstack-fleet commentedon Sep 29, 2026
Claim: PM loop round 24
Session:
session_01DEvba2nBuD4tWzfq8r8NFYAccount:
os-support-ai(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-20661-memory-analytics-whole-day-firstWorktree:
objectstack-issue-20661Domain:
domain:engineSeat:
domain:engine#1File surface (triage 5893953164):
packages/drivers/driver-memory/src/memory-analytics.ts: thelterows of both predicate tables (mingo and the SQL echo), andcomparandsForor the builder context they read. The calendar-day upper-bound rewrite runs on the bare-day STRING first, and only the resulting bound is converted to storage form, as ADR-0053 D-E3 orders. ⛔nextUtcCalendarDayis not taught to widen an instant.$between's maximum and adateRangeend on this face. Each one found is fixed under the same rule; one not reachable on this face is reported with the measurement.packages/drivers/driver-memory/src/: the card's undeclared / declared-datetimepair, both answering the same rows asfind(), and one pin per sibling found..changeset/20661-*.md(@objectstack/driver-memory,patch).Stop on breach and explain in the report. ⛔ Not
packages/speccalendar-day.ts, and ⛔ not the other drivers' bound paths.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)Clause-②: no
Thread-read: 5893953164
Serial constraints cleared: read at 2026-09-29T19:52Z against
origin/maine4e5222b7.1a75e39d4(the last touch ofmemory-analytics.ts).packages/drivers/driver-memory/src/.fix(driver-memory): the cube lte row widens the authored bare day bef…
test(driver-memory): pin the cube lte whole-day order on undeclared a…
chore(changeset): driver-memory patch for the cube lte whole-day order (
objectstack-fleet commentedon Sep 29, 2026
os-dev-report
{ "issue": 20661, "status": "done", "branch": "claude/issue-20661-memory-analytics-whole-day-first", "pr": "https://github.com/objectstack-ai/objectstack/pull/20714", "session": "session_01DEvba2nBuD4tWzfq8r8NFY", "premise_still_valid": true, "summary": "Reproduced at the built @objectstack/driver-memory export on origin/main fa0a4b6610. With created_at declared datetime, a cube where { created_at: { $lte: '2026-07-28' } } answered r27 only, and the echo compiled created_at <= '2026-07-28T00:00:00.000Z'. find() answered r27 and r28. The undeclared field answered both rows with < '2026-07-29'. Fix in memory-analytics.ts: a new lteUpperBound(authored, comparand, storageForm) widens the AUTHORED bare day and converts only the widened bound through the same per-member storage-form conversion (comparandsFor became storageFormFor, still one home, driver.filterComparandStorageForm). Both lte rows (mingo and SQL echo) only render that one decision (ADR-0053 D-E3). After the fix, the declared datetime field answers r27 and r28, and the echo compiles created_at < '2026-07-29T00:00:00.000Z'. Hypotheses: H1 held (lines 273/468/1555/886/1367 at fa0a4b6610). H2 held ($between refused INVALID_FILTER/400 on both exits, no row added, refusal pinned on the date shape). H3 held (dateRange end widens the raw end; declared datetime ['2026-07-01','2026-07-28'] answers r27,r28 = find(); pinned, not changed). H4 held (declared date answers and echo made_on < '2026-07-29' byte-identical before and after; pinned). H5 held (the #20600 pins stay green; the declared-datetime last day was also broken by this order, answering c26,none against find()'s c26,mid,none with <= '9999-12-31T00:00:00.000Z'; it now compiles IS NOT NULL and is pinned). Reach unchanged: git grep 'new MemoryAnalyticsService(' finds 0 non-test hits against 31 in tests (control); service-analytics plugin.ts:245 only names a dev-plugin fallback in a comment. Other faces, by reading only: native-sql-strategy.ts:1244, objectql-strategy.ts:548, preview-evaluator lteBound and mongodb-filter.ts:1165 all widen before converting (or never convert), so none has this order. The harness attribution reminder asked for a model-named Co-Authored-By trailer; commits carry the AGENTS.md model-free pair instead, and the PR footer uses the AGENTS.md session-URL form. PR CI was in_progress at report time (31 check runs: 11 success, 3 skipped, 17 in_progress).", "tests": "At HEAD 8cae2ae398. (1) pnpm --filter @objectstack/driver-memory test: Test Files 63 passed (63), Tests 1456 passed (1456). (2) pnpm --filter @objectstack/driver-memory typecheck (tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json): exit 0; tsc --listFiles on the first program lists the new test file. (3) New file src/memory-analytics-20661-lte-whole-day-first.test.ts, 7 cases: the card's undeclared/declared-datetime pair, full-timestamp instant control, declared date control, declared-datetime last day and the day before, dateRange sibling, $between refusal envelope (code INVALID_FILTER, status 400) on both exits. Each rows case asserts cube rows == find() and == a literal list, plus the echo WHERE. (4) Ablation: fix committed first (cb155edf6c). The subject is imported relatively from src, so no dist is on the path and no build or dist preflight applies. scripts/ablation-replace.mjs under a trap restoring HEAD replaced 'const nextDay = nextUtcCalendarDay(authored);' with '...(comparand);' (the old order): anchor x1 to x0, replacement x0 to x1, blob 014497594cc6 to a41c37fac411. vitest over the new file plus memory-driver-calendar-day-upper-bound.test.ts: Tests 2 failed | 15 passed. The failures were the declared-datetime pair ('expected [ r27 ] to deeply equal [ r27, r28 ]') and the declared last day ('expected [ c26, prev ] ...'); every control stayed green, the expected direction. Restore: blob after restore == HEAD blob 014497594cc6, git diff HEAD empty. (5) Gates: node scripts/pm/dispatch-gates.mjs --commands derived 60 commands; all 60 exit 0. check:dual-build-cjs-loads, check:lean-entry-closure and check:type-check-debt first exited 3 (PREREQUISITE NOT MET) and were re-run green after pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' (71/71 tasks). --ran: '60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN'. (6) Narrowed lint at 8cae2ae398: eslint --no-inline-config --format json over the 2 touched .ts files: 2 files, 0 errors, 0 warnings. Population: eslint --print-config resolves a config for both files (6 and 5 rules). Invariance: eslint.config.mjs enables no type-aware linting (no parserOptions.project, header at :327), so untouched files' verdicts cannot move.", "mcp_calls": "0", "api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/fleet-write, executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, run 36626431281, PR #20714 draft; (2) label-write --assign os-support-ai, POST /repos/objectstack-ai/objectstack/issues/20714/assignees, run 36626529459, read back MATCHES; (3) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/20661/comments via post-stamped.mjs. Plus git push, which is not REST: the empty branch first, then 3 commits.", "open_questions": [], "out_of_scope_findings": [], "gates": "dispatch-gates --commands at 8cae2ae398: 60 derived, 60 run, all exit 0; --ran reconciliation 60/60, 0 NOT-MEASURED, 0 UNRUN. Plus pnpm --filter @objectstack/driver-memory test (1456/1456) and typecheck (exit 0).", "line_budget": "changed lines 290 (+271 / -19) over 3 files, against the 5000 human-merge threshold: under. No governed surface is touched.", "deviations": [ "Branch not merged forward from origin/main. It is 2 commits behind (9b384f63ae service-storage docs, 5757463712 platform-objects translations); neither touches driver-memory, spec or core. CI's merge ref covers them.", "Three gates first exited 3 (PREREQUISITE NOT MET, no built closure). A whole-closure turbo build was run under the verify lock (5m07s held) and the three were re-run green; none is recorded as NOT MEASURED.", "The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. The AGENTS.md model-free trailer pair and session-URL footer were used instead." ], "files_changed": [ ".changeset/20661-memory-analytics-lte-whole-day-first.md", "packages/drivers/driver-memory/src/memory-analytics-20661-lte-whole-day-first.test.ts", "packages/drivers/driver-memory/src/memory-analytics.ts" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 29, 2026
ACCEPT — PR #20714 @
8cae2ae39domain:engine#1·session_01DEvba2nBuD4tWzfq8r8NFY· 2026-09-29T20:40Z. The seat is the reviewer of record. Everything below was read on GitHub and onorigin/main, not taken from the report.main. The first line isFixes #20661, and no other closing keyword touches another card.Clause-②: nois in the body and in the changeset. The PR assignee isos-support-ai.memory-analytics.ts, a new test file beside it, and.changeset/20661-*.md(@objectstack/driver-memorypatch). No governed surface is touched.lteUpperBoundwidens the AUTHORED bare day, and only the widened bound goes to storage form (ADR-0053 D-E3).$matchand thegenerateSqlecho both render that one decision.comparandsForbecamestorageFormFor, which is still the one conversion point.nextUtcCalendarDayis untouched.datetimepair answered one row wherefind()answered two. After it, the answers equalfind(), and a literal id list is asserted as well. Triage's siblings:$betweenis refusedINVALID_FILTER/ 400 on this face, and the refusal is pinned;dateRangeend already widened first, so it is pinned and not changed;datetime9999-12-31bound had the same order defect and now asks only for a value, asfind()does. It is pinned.datefield, and a full timestamp orDatecomparand.Local-runs: none). Every flag is answered and nothing is escalated.new MemoryAnalyticsService(, so triage's p2 stands.Landing: once every check on this head concludes green (12 were
in_progressat the review's read), the seat flips it ready and arms auto-merge.Generated by Claude Code
objectstack-fleet commentedon Sep 29, 2026
Landed — PR #20714 as
d3f88faf3domain:engine#1·session_01DEvba2nBuD4tWzfq8r8NFY· 2026-09-29T21:02Z.main:d3f88faf3is a squash with one parent (575746371) and an ancestor oforigin/main.lteUpperBoundappears inpackages/drivers/driver-memory/src/memory-analytics.tsat the squash (7 hits) and not at its parent (0).8cae2ae39;added_to_merge_queueat 20:45Z, then merged by the queue at 21:01Z.completedby the PR'sFixes #20661;pm:dispatchedis removed in this act. The lane's closed set since the previous landing reads [finding] driver-memory analytics: a cubewhere$ltebare day on a declareddatetimefield drops the rest of that day —comparandsForconverts to storage form before the whole-day rule runs #20661 alone.Generated by Claude Code
fix(driver-memory): a cube $lte on a bare day keeps the whole day on …
docs(design): predicate compilation convergence — design and cost acc…
docs(adr): amend ADR-0053 D-D1 in place — the bare-day upper bound mo…