From 4b635de3048c2b40925f10f7ca6849c23c0bd278 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 22 Aug 2026 04:43:51 +0000 Subject: [PATCH] docs(objectql): archiveObject's triple note points at the #10643 parse-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 (5649efbf93) 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 Claude-Session: https://claude.ai/code/session_019yDEhPBC3tcGkW9bkce1HM --- .../src/lifecycle/lifecycle-service.ts | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/objectql/src/lifecycle/lifecycle-service.ts b/packages/objectql/src/lifecycle/lifecycle-service.ts index ce70017ab9..d1f5da2b9d 100644 --- a/packages/objectql/src/lifecycle/lifecycle-service.ts +++ b/packages/objectql/src/lifecycle/lifecycle-service.ts @@ -1198,13 +1198,26 @@ export class LifecycleService { // author has not decided yet — against the retain-first posture that makes // this method refuse to hot-delete anything the cold store has not taken. // - // ⚠️ Deliberately NOT decided here: `retention` declared beside `ttl` + - // `archive`. The ttl cutoff selects, so the age window (`archive.after`, - // which the spec pins equal to `retention.maxAge`) no longer separately - // bounds the hot store for that triple. Whether the Archiver should union - // the two windows, or the triple be refused at parse time (a - // `packages/spec` accept-set question, outside this card's fence), is - // #10527 rather than a choice this diff makes silently. + // [#10643] `retention` declared beside `ttl` + `archive`: once an open + // question at this line (#10527), since decided — and decided at parse + // time rather than here. `LifecycleSchema` (`packages/spec`, the + // superRefine on the lifecycle block) refuses that triple unless the ttl + // restates the age bound exactly: `ttl.field` must be `created_at` and + // `ttl.expireAfter` must equal `retention.maxAge` — which the alignment + // refine beside it already pins equal to `archive.after`. So every triple + // that reaches this method arrives narrowed to that one shape, and on it + // the selection below reads the same column at the same declared instant + // whichever branch it takes; the hazard the old note raised (the ttl + // cutoff selects, so the age window no longer separately bounds the hot + // store) is no longer a shape the spec accepts. + // + // Still load-bearing: that equality is enforced in `packages/spec` and + // re-checked nowhere in this file. Widening the triple accept-set there + // puts the original question — union the two windows, or keep refusing — + // straight back on this line, so it is not a spec-local change. Which + // WINDOW governs is a separate leg either way: with `ttl` declared it is + // the `expireAfter` override key that applies, not `maxAge` (see the + // #10528 block below). const dueField = lc.ttl ? lc.ttl.field : 'created_at'; // [#10528] WHICH WINDOW IS DUE — resolved through ADR-0057 P4 governance,