Repository navigation
ADR-0057 data lifecycle follow-ups: retire per-plugin sweepers, dev telemetry datasource + db:clean, Studio surface, PG rotation (tracking) #2834
Description
Activity
④ PostgreSQL native-partition Rotator — evaluated, deferred with a design sketch (not shipping unverified DDL)
Neither this environment nor CI has a PostgreSQL service (driver-sql tests run better-sqlite3 only), so a
PARTITION BY RANGEimplementation would land as code no test can ever execute — exactly the unverified-claim class ADR-0049/0054 exist to block. Current behavior on PG is already correct (rotation falls back to an equivalent age-based reap; the declared bound holds — only reclamation is row-wise instead of O(1)), so this is an optimization, not a gap.Design sketch for whenever a PG service lands in CI:
SqlDriver.supportsRotationbecomes dialect-aware (isSqlite || isPostgres).- PG path in
ensureRotation: base table converted once toPARTITION BY RANGE (created_at)(requires a rebuild: rename → create partitioned → attach legacy as the first partition); per-period partitions<table>__r<key>created viaCREATE TABLE … PARTITION OF … FOR VALUES FROM/TO; expiry =DETACH PARTITION CONCURRENTLY+DROP TABLE(O(1), lock-light). - No view needed (unlike SQLite): the partitioned parent IS the queryable name, and writes route by the partition key natively — the shard-wise write redirects the SQLite path needs don't apply.
- Prereqs: a
postgresservice container in the CIdogfood/driver jobs + asql-driver-rotation.pg.test.tsgated onOS_TEST_PG_URL.
Also noted while doing ③ (i18n regen): the
*.objects.generated.tsbundles have extract-config drift. The committed bundles carry curated zh-CN translations for objects (e.g.sys_audit_log) that live outsidepackages/platform-objects/scripts/i18n-extract.config.ts's import set (plugin-audit etc.) — so a plain re-run ofos i18n extractdeletes those curated translations. ③'s PR therefore regenerated only themetadata-formsbundles and left the objects bundles untouched. Fix candidates: import the missing sys_* objects into the extract config, or split per-package bundles. Worth its own small item before anyone re-runs the extractor for object keys.🤖 Generated with Claude Code
Generated by Claude Code
Closing — every item is now resolved:
- ①–③ shipped in feat(lifecycle): ADR-0057 follow-ups — retire per-plugin sweepers, dev telemetry datasource + db:clean, Studio lifecycle form (#2834) #2835; ①'s remaining caveat (no status predicate) was closed by
retention.onlyWhenin feat(lifecycle): retention.onlyWhen status predicate + declarative automation run-history retention + i18n bundle ownership guard (#2834) #2837. - ④ (PG native-partition Rotator) is dropped by decision: the age-based fallback on PG is correct and the retention bound holds, so native partitioning is a pure reclamation optimization — not worth an open tracking item while CI has no PostgreSQL service to verify the DDL against. The design sketch above stands if it's ever picked back up.
- ⑤ shipped in feat(lifecycle): retention.onlyWhen status predicate + declarative automation run-history retention + i18n bundle ownership guard (#2834) #2837 (stray sys_* translations pruned to their owning packages' bundles + the
bundle-ownership.test.tsguard); verified on currentmainthat the platform-objects bundles are clean and the guard is in place.
🤖 Generated with Claude Code
Generated by Claude Code
- ①–③ shipped in feat(lifecycle): ADR-0057 follow-ups — retire per-plugin sweepers, dev telemetry datasource + db:clean, Studio lifecycle form (#2834) #2835; ①'s remaining caveat (no status predicate) was closed by
- added a commit that references this issue
on Jul 26, 2026 - added a commit that references this issue
on Oct 7, 2026
Follow-up tracking for ADR-0057 (system data lifecycle & retention) after P1–P4 shipped in #2791 (docs/skills in #2818, tracking issue #2786 closed). Each item is independently shippable.
Items
JobRunRetention/NotificationRetention(+retentionDays/retentionSweepMsoptions) removed; the LifecycleService is the one sweeper. Included a fix: the blanket 30d lifecycle retention onsys_automation_run(from feat(lifecycle): ADR-0057 P1–P4 — lifecycle contract, Reaper/Rotator/Archiver, datasource separation, governance (#2786) #2791) could strand suspended approval runs — removed at the time because the declarative contract had no status predicate. That gap was closed in feat(lifecycle): retention.onlyWhen status predicate + declarative automation run-history retention + i18n bundle ownership guard (#2834) #2837:retention.onlyWhenlanded,sys_automation_runnow declaresretention: { maxAge: '30d', onlyWhen: { status: { $in: ['completed', 'failed'] } } }, and the automation store's bespoke age sweep (pruneHistory+runHistoryRetentionDays/runHistorySweepMs) is retired too — the LifecycleService is now genuinely the one sweeper.db:clean— shipped in feat(lifecycle): ADR-0057 follow-ups — retire per-plugin sweepers, dev telemetry datasource + db:clean, Studio lifecycle form (#2834) #2835.objectstack devprovisions<primary>.telemetry.<ext>as thetelemetrydatasource for file-backed SQLite primaries (OS_TELEMETRY_DB=0opts out,<path>opts in anywhere); newos db cleanruns the one-timeVACUUM(smoke-verified 48.9 MB → 0.01 MB,auto_vacuum=2adopted).lifecycle— shipped in feat(lifecycle): ADR-0057 follow-ups — retire per-plugin sweepers, dev telemetry datasource + db:clean, Studio lifecycle form (#2834) #2835.object.form.tsexposes the full lifecycle block; metadata-forms i18n bundles regenerated with curated zh-CN. The objects-bundle drift this uncovered became item ⑤.④ PostgreSQL native-partition Rotator— dropped (2026-07-15). Current PG behavior is correct: rotation falls back to an equivalent age-based reap and the declared bound holds — nativePARTITION BY RANGEwould only make reclamation O(1) instead of row-wise, a pure optimization not worth carrying as an open item while CI has no PostgreSQL service to verify the DDL. The design sketch is preserved in the comments below should it ever be revisited.*.objects.generated.ts— shipped in feat(lifecycle): retention.onlyWhen status predicate + declarative automation run-history retention + i18n bundle ownership guard (#2834) #2837. Resolved by moving ownership rather than widening the config: the stray sys_* translation copies (sys_audit_log/sys_activity/sys_comment/sys_presence) were pruned from the platform-objects bundles and live in their owning packages' bundles (plugin-audit / service-realtime, per ADR-0029 D8) — verified line-by-line, zero translation loss. A newbundle-ownership.test.tsguard turns any future stray (in either direction) into a red build, so a plain re-run ofos i18n extractis safe again.References
docs/adr/0057-system-data-lifecycle-and-retention.md(P0–P4 implemented)retention.onlyWhen: feat(lifecycle): retention.onlyWhen status predicate + declarative automation run-history retention + i18n bundle ownership guard (#2834) #2837 · original tracking: ADR-0057 data lifecycle P1–P4: retention contract, rotation, separation, governance (tracking) #2786🤖 Generated with Claude Code