docs(adr-0053): name driver-memory's analytics face in slice 5's implementation map - #17380
Conversation
…ementation map Slice 5's implementation map named only `service-analytics` files. `driver-memory`'s `memory-analytics.ts` folds bucket keys with `bucketDateKey(value, granularity, timezone)` in `AnalyticsQuery.timezone`, so it implements the same slice on a second face and is now named as one. The note records the scope of the agreement it establishes: the reference zone is shared with the `dateRange` PRESET arm, while the explicit `[a, b]` arm keeps its published instant reading and therefore does not share the bucket's calendar frame. Claude-Session: https://claude.ai/code/session_01XTBcV7zZHmokdyQgXjbyEU Co-authored-by: Claude <noreply@anthropic.com>
Seat verdict — ACCEPT, and this PR is now PARKED for a human merge
⛔ This is where an agent seat stops on this PR, and that is the correct final state — not a stall.
CI: 30 checks, 0 red, 0 pending, with the legacy combined status read separately → What I verified myself rather than taking from the reportThe row asserts an identity between two things, so I read both on
⭐ The row's best line is the one it was not asked for. It scopes the agreement to the Dispositions
⛔ One thing I am not repeating as verified: the round report describes the earlier Card #17207 is deliberately NOT closed out. It keeps Generated by Claude Code |
Fixes #17207
Clause-②: no— nothing executable moves. The entire diff is one ADR file.⛔ Governed surface — this PR is draft-only, and a draft is its correct final state
docs/adr/**is one of the five governed surfaces (docs/adr/**,.claude/**,skills/**,AGENTS.md,CLAUDE.md). Stated here so no reader has to rediscover it at the merge queue:docs/adr/alone. Adding a code file would not help this land; it would park unrelated work behind a human review queue.GOVERNED_APPROVERShuman merge. It sitting as a draft after delivery is the intended outcome, not a failed round.⭐ This card exists because of that rule. The ruling on #16178 asked for this row inside PR #17206; that implementer declined and escalated instead, correctly — complying would have traded a landable repair for a one-line documentation row and removed it from the queue permanently. This PR does not repeat the trade in reverse by widening into code.
What changed
One row in ADR-0053 Phase 2's implementation map, which named only
service-analyticsfiles for slice 5, plus the short note the row needs in order to be read correctly.docs/adr/0053-date-and-datetime-semantics.mdThe new row:
⭐ The premise was re-measured here, by symbol, rather than inherited
Triage held this card on 2026-09-09T20:33Z on a reading that was correct at the time: the behaviour did not exist on
main,granularityreading 0 hits in the driver's analytics file at08e38c63. PR #17206 has landed since (f03f6c74c9), which discharges the hold — but that was another seat's reading, and documenting an implementation that is not there is precisely the defect the hold protected against, and no gate catches it. So it was re-taken on this branch's own base59db8a02cb:packages/drivers/driver-memory/src/memory-analytics.ts08e38c6359db8a02cbgranularitybucketDateKeybuckettimezone/dateRangeRead at the call sites, not only counted: the file imports
bucketDateKeyandisBucketGranularityfrom@objectstack/core, collects aTimeBucketper granulartimeDimensionsentry, cuts the pipeline at its$group, and writesbucketDateKey(readFieldPath(row, bucket.fieldPath), bucket.granularity, timezone)onto the selected rows, wheretimezoneisquery.timezone. The behaviour the row records is present.Why the row's note says preset, and what it deliberately does not decide
The card warned that the wording follows PR #17206's final contract-review verdict. That verdict is PASS (
5613749246, 2026-09-10T05:39Z); it did not disturb the seat's option-A reading of the seam, and the patch round's F5 carved the seam out in the changeset rather than closing it.So the note states the agreement and its scope: the bucket label and the
dateRangepreset arm share one reference zone, while the explicit[a, b]arm is discriminated at the call site and keeps its published instant reading (#16179), so it does not share the bucket's calendar frame. An unqualified "the window and the bucket agree" would have been false for that arm. The note records the seam; ⛔ it does not re-decide it, and nothing here adjudicates the option-A ruling either way.Each claim in the note was checked against the code rather than copied from the card:
bucketDateKey(value, granularity, timezone)packages/core/src/utils/datetime.ts:267'UTC'/ invalid zone keeps UTC bucketing"2026-Q2/2026-W23aggregateWithTimeBuckets[a, b]arm never reachesparseDateRangeStringdateRangecall site, and that method's doc blockVerification
Change set derived from git by
scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(no path argument): 1 path. Reconciled with--rancarrying an exit code per family:All 18 exit 0, each captured by redirect-then-
$?, never across a pipe. They includecheck:adr-links,check:adr-symbol-anchors,check:adr-anchors,check:doc-authoring,check:closing-keyword-parity,check:nul-bytes,check:pm-governed-mergesandcheck:driver-memory-census.PREREQUISITE NOT MET— and was not reported as a pass:check:doc-formula-expressionsrefused against an unbuilt@objectstack/formula/@objectstack/lint. Those two were built (VERDICT command-exit 0underscripts/pm/os-verify-lock.sh) and the gate then exited 0.No package is touched, so there is no affected-package build, test or typecheck to owe: the single path lives under
docs/, in no workspace package.Repo-wide lint, narrowed — and the narrowing is a measurement, not a guess. The changed file is outside eslint's population entirely:
ESLint#isPathIgnoredanswers true for it,eslint.config.mjscarries no markdown entry, andeslint --format jsonon that path reports 1 file, 0 errors, 1 warning, the warning being "File ignored because no matching configuration was supplied." Invariance on untouched files: this repo enables no type-aware linting — the control.tsfile answersparserOptions.project: undefinedandprojectService: undefinedwhile still carrying rules, so the reader fires — therefore this diff cannot move the verdict on any file it does not contain.Control characters:
check:nul-bytesexit 0, plus a direct scan of the changed file for the wider control-byte class, which matched nothing.Acceptance notes
#5499— thedriver-memoryinvestment freeze does not bite, and was not tested against. The freeze is on investment in that driver's code; this PR changes zero driver code and documents behaviour that already shipped.packages/drivers/driver-memory/**is untouched, not even a comment.ADR-0053reads 0 in the driver's analytics file but 4 inpackages/core/src/utils/datetime.ts, which is where the decision is implemented and which the driver delegates to (firing control:timezonereads 11 and 8 in the two files). Not a finding, and noscripts/adr-anchors/entry is owed by this diff.granularity(#16178) #17206 hoisted the forward labeller into@objectstack/core(bucketDateKey) and made@objectstack/objectql'sbucketDateValuea delegate, neither is named in the slice-5 row either. This is a missing member in a list rather than an error in one, so it is not a fileable class, and widening this governed diff to chase it is exactly what the card warns against. Successor who will touch this file: none currently known.维护者速读(草稿)
改了什么 — ADR-0053 第二阶段的实现映射表里,slice 5(分析分桶的时区)原先只点名了
service-analytics的三个文件。本 PR 加一行,点名packages/drivers/driver-memory/src/memory-analytics.ts,并在表下补一小段说明:它用AnalyticsQuery.timezone折算桶标签,而这正是dateRange预设分支解析所用的同一个参考时区,所以选行的窗口与贴标签的桶对「一天从哪里开始」的看法一致。共 1 个文件、+17 行、0 删除,不含任何代码改动。为什么改 — PR #17206 让 driver-memory 的分析面真正按
granularity分桶了,于是它和service-analytics一样实现了 slice 5;而实现映射没写它。后果是读这份 ADR 的人会以为只有service-analytics一侧需要考虑,从而在下一次改动里把 driver-memory 落下。这一行原本被要求写在 #17206 里,当时的实现者按受管面规则拒绝并升级,是对的——所以它落在这张单独的卡上。风险与代价(含回滚) — 纯文档,无运行时影响、无发布内容变动,因此无 changeset。风险只有一种:句子写得不准。为此逐条对着代码核了签名、默认时区、桶标签取值样例与两个
dateRange分支的差别,并把「一致」的范围限定在预设分支上,显式记下显式[a, b]数组分支按瞬时取窗、不共享日历框(该缝已由domain:engine席裁为既定行为,#17206 的契约复审终局为 PASS,未推翻)。回滚 = 还原这一个文件,无任何下游。席位意见 —
你要做的 — 这是受管面 PR,⛔ 任何 agent 席位都不会把它翻成 ready、不入队、不挂 auto-merge;落地需要
GOVERNED_APPROVERS名单内的账户人工审阅并合并。请确认这一行的措辞是否是你想留在 ADR 里的说法,尤其是表下那段「一致范围仅限预设分支」的限定——如果你更希望 ADR 不记这道缝,说一声即可删掉那段引用块,行本身不受影响。Generated by Claude Code