Skip to content

docs(objectql): archiveObject's triple note points at the #10643 parse-time refusal - #11007

Merged
os-elon merged 1 commit into
mainfrom
claude/issue-10865-archive-triple-comment
Aug 22, 2026
Merged

docs(objectql): archiveObject's triple note points at the #10643 parse-time refusal#11007
os-elon merged 1 commit into
mainfrom
claude/issue-10865-archive-triple-comment

Conversation

@os-elon

@os-elonos-elon commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Fixes#10865

Comment-only. The archiveObject docblock paragraph immediately above the dueField selection still called the retention + ttl + archive triple an open question (#10527) and warned about a shape the spec no longer accepts. #10643 (5649efbf93) answered it with the parse-time-refusal disposition, so the paragraph now says so and points there.

Citation, not a control

Nothing here is broken and nothing is unenforced, so there is no behaviour to fix and no test to add. What can be established is that the replacement prose is true, and the evidence is a citation of the refine that was read at packages/spec/src/data/object.zod.ts (read-only for this card — unchanged):

if(lc.retention&&lc.ttl&&lc.archive&&(lc.ttl.field!=='created_at'||lc.ttl.expireAfter!==lc.retention.maxAge)){ctx.addIssue({/* … "must restate retention.maxAge … when retention, ttl and archive are all declared" */});}

and, a few lines above it in the same superRefine, the alignment refine that has always been there:

if(lc.archive&&lc.retention&&lc.archive.after!==lc.retention.maxAge){/* reject */}

Together: a triple that parses today has ttl.field === 'created_at' and ttl.expireAfter === retention.maxAge === archive.after. lifecycleDuration is a plain regex-validated string with no transform (object.zod.ts, LIFECYCLE_DURATION_REGEX), so those equalities are literal-for-literal — '30d' vs '720h' is refused too. On such a triple the selection below the comment reads the same column at the same declared instant whichever branch it takes, so the hazard the old note raised ("the age bound no longer separately bounds the hot store") is not a shape that can reach this method. packages/spec/src/data/object.test.ts pins the accept/reject pairs (describe('retention + ttl + archive triple (#10527)')).

What was preserved

The old paragraph was not only a stale question. Two things in it are still live and are kept, restated:

  • The equality is enforced in packages/spec and re-checked nowhere in this file — so widening the triple accept-set there brings the original union-vs-refuse question straight back to this line. That is the constraint the paragraph is now defending, in place of the question it used to pose.
  • Which WINDOW governs is a separate leg: with ttl declared it is the expireAfter override key that applies, not maxAge (the settings override map carries those as two distinct optional keys, and floorFor(object, policy) is keyed by policy). The [#10528] block below owns that reasoning; the new text only points at it, so a reader does not read "the two windows are the same instant" as "a triple behaves identically to an archive-only object in every respect".

Non-effects

No behaviour change, no test change, no packages/spec change. The diff touches only // comment lines — mechanically checked: git diff HEAD~1 -U0, keeping only added/removed lines and dropping the file headers, leaves zero lines that are not a // comment.

Verification

Gate union derived with node scripts/pm/dispatch-gates.mjs (no path arguments) after the final commit, at 4b635de304; every family it named was run at that same sha, exits captured before any pipe. All eight green:

gateverdict line
pnpm check:durability-log-level✓ durability-degradation log levels: 30 durability-critical catch seam(s), all loud …
pnpm check:slot-lookup✓ slot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none new …
pnpm check:test-source-aliascheck-test-source-alias OK — 72 packages with tests scanned …
pnpm check:type-source-resolutioncheck-type-source-resolution OK — 77 packages with a tsconfig.json scanned …
node scripts/check-ci-filter-parity.mjsOK: all 82 declared cross-package glob(s) (71 unique) are covered …
node scripts/check-engine-split-ratio.mjsmetric report, exit 0 (ratio 97.5%, unchanged by this diff)
node scripts/check-plugin-teardown-shape.mjs✓ check:plugin-teardown-shape: 61 Plugin implementation(s) … baseline fully burned down
node scripts/docs-audit/check-affected-docs.mjs✓ affected-docs self-test: 339 cases pass.

Declared narrowing:@objectstack/objectql's own test/typecheck were not run locally. Building that package's dependency closure to type-check a diff that is provably comment-only buys nothing the shared verify lock's cost justifies, and CI runs the farm regardless. In their place: the comment-only proof above, plus a real parse of the edited file (esbuild packages/objectql/src/lifecycle/lifecycle-service.ts --outfile=/dev/null, exit 0), which is what a comment edit can actually break.

Changeset

None, deliberately: nothing user-visible ships — no published behaviour, API or type changes, only a source comment. skip-changeset is the repo's only exemption path for changeset-check (the gate has no file-type carve-out, by design), so it belongs on this PR; the label write from this seat is reported in the dev report on #10865.

Body note: an earlier revision of this description spelled a TypeScript mapped type inline and GitHub's body sanitizer ate the angle-bracketed half of it, leaving a sentence that read as if the override map had one key. Rephrased above without angle brackets.


Generated by Claude Code

…e-time refusal
The `retention` + `ttl` + `archive` paragraph in the `archiveObject`
docblock still called #10527 an open question and warned about a shape the
spec no longer accepts. #10643 (5649efb) decided it: `LifecycleSchema`
refuses that triple unless `ttl.field` is `created_at` and
`ttl.expireAfter` equals `retention.maxAge` (itself pinned equal to
`archive.after`), so every triple reaching this method selects the same
column at the same declared instant on either branch.
The rewrite keeps the still-live half: the equality is enforced in
`packages/spec` and re-checked nowhere in this file, so widening that
accept-set brings the union-vs-refusal question back to this line.
Comment-only; no executable line changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yDEhPBC3tcGkW9bkce1HM
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ✅

What this run could not see
  • the SDK route bridge reached 45 of 221 client-bound route-ledger rows — the other 176 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: node scripts/docs-audit/affected-docs.mjs --bridge-coverage

Coarse fallback — 14 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 490879ad0fe22c57d74799828a49feac6860757apackageMentionDocs.

Which tree this was computed on

This run read content/docs from 3a4153dd6a028787fdc117801dc889fc4bb562c5 — the merge of head 4b635de3048c2b40925f10f7ca6849c23c0bd278 into base 490879ad0fe22c57d74799828a49feac6860757a, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3a4153dd6a028787fdc117801dc889fc4bb562c5 && git checkout 3a4153dd6a028787fdc117801dc889fc4bb562c5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 490879ad0fe22c57d74799828a49feac6860757a 4b635de3048c2b40925f10f7ca6849c23c0bd278 && git checkout -B drift-repro 490879ad0fe22c57d74799828a49feac6860757a && git merge --no-ff 4b635de3048c2b40925f10f7ca6849c23c0bd278
node scripts/docs-audit/affected-docs.mjs --json 490879ad0fe22c57d74799828a49feac6860757a

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@os-elonos-elon added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 22, 2026 — with Claude
@os-elon
os-elon marked this pull request as ready for review August 22, 2026 04:56
@os-elon
os-elon enabled auto-merge August 22, 2026 04:56
@os-elon
os-elon added this pull request to the merge queueAug 22, 2026
Merged via the queue into main with commit 434af30Aug 22, 2026
38 checks passed
@os-elon
os-elon deleted the claude/issue-10865-archive-triple-comment branch August 22, 2026 05:15
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 32553282881 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Console Pin Gate — 失败步骤: Build the Console SPA at the pinned objectui SHA

    ✗ Build failed in 6.26s
    

↳ 失败原因 是判读的关键:超时Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 81 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

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

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(objectql): archiveObject's triple-declaration comment still calls a decided question undecided

2 participants

@os-elon@claude