Repository navigation
Remove dead object enable.trash / enable.mru capability flags (ADR-0049 enforce-or-remove) #3207
Description
Activity
裁决(维护者 2026-08-02 委托,按四轴评估:长远合理性 / 防 AI 静默犯错 / 实际业务 / 不扩边界):remove —— 删除
enable.trash/enable.mru;#3146 维持 parked,现阶段不实现软删除。- 边界:回收站是一整条产品线(UI、保留期、清空、权限),当前没有业务需求拉动(Implement soft delete (recycle bin):
enable.trash/softDeleteare spec-only with zero runtime readers #3146 零运行时读者、已 parked)。创业阶段不为一个死键立一个功能。 - 防 AI 犯错:spec-only 的
enable.trash让作者以为自己有了回收站——典型静默失效(ADR-0078 点名的形状),删除即修复。 - 长远:未来真做软删除时,以实现驱动重新设计 spec 形状(经 ADR),而不是被一个从未生效的旧键绑架。
实施走
spec-property-retirement流程,UNKNOWN_KEY_GUIDANCE墓碑指向 #3146 作为立项位。v17 major 窗口内落地。
Generated by Claude Code
- 边界:回收站是一整条产品线(UI、保留期、清空、权限),当前没有业务需求拉动(Implement soft delete (recycle bin):
这个功能暂时不是重点,可以移除
🔒 认领(A 道 · ADR-0049 批次;#2902 已核实为 PR #2943 既有实现并关单,#3715 按 owner call 维持搁置)
- 会话:
session_0176qgxgCXTJCUv4YFLtusP9 - 分支:
claude/issue-3207-retire-enable-trash-mru - 方向:remove,按 2026-08-02 裁决(维护者本人已于 19:53Z 评论确认)。走
spec-property-retirement流程,UNKNOWN_KEY_GUIDANCE墓碑指向 Implement soft delete (recycle bin):enable.trash/softDeleteare spec-only with zero runtime readers #3146。 - 两点现势修正:① 正文第 7 步「minor changeset(launch-window 政策)」已过时,现为 v17 pre/rc 窗口,按现行纪律定 major(实测
mode: pre2026-08-03 00:30Z);② 昨夜落地的 authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 门禁(PR fix(spec): authorable-surface 被删基线行必须自证合法 — merge-base 锚定 + 可达性窄例外 (#4650) #4726)对被删基线行要求门禁内自证——本单按退役正路走(tombstone + ADR-0087 登记),不删基线行。
Generated by Claude Code
- 会话:
✅ 验收通过(ACCEPT) — PR #4734 已转正并开 auto-merge。
重要事实修正:本单主体工作早在 2026-07-24 已由 PR #3414(
88346ba58)落地(schema 移除 +.strict()墓碑、~45 处 setter 删除、ledger/form/i18n/docs 全套),issue 未随之关闭——与 #2902/#2943 同型的「实现了没关单」。实施 agent 按纪律动手前重验现场,避免了二次实现,并把 PR 收窄到对照 2026-08-02 裁决的两处真实缺口:- 补 ADR-0087 D2 conversion(
object-enable-trash-mru-removed,protocol 17,retiredFromLoadPath,嵌套下钻外科式剥离):此前存量 16.xsys_metadata行重放后仍带死键,被.strict()诊断永久误标metadata_spec_invalid(违反 [P2] The spec contract stops at authored source — stored metadata is rehydrated unparsed, unconverted, and ungated #3903 不变式),且os migrate meta --from 16无法改写源码。fixture + stored 重放测试 + cli e2e 全绿。 - 墓碑死指针修正:feat(spec)!: remove dead enable.trash/mru capability flags (#2377 close-out, ADR-0049) #3414 落的墓碑指向已关闭的 [P2] Aspirational config — prune or mark experimental #1893,违背裁决「指向 Implement soft delete (recycle bin):
enable.trash/softDeleteare spec-only with zero runtime readers #3146 作为立项位」;现 trash → Implement soft delete (recycle bin):enable.trash/softDeleteare spec-only with zero runtime readers #3146(parked)、restore guidance 与 api-derivation 注释同步修正,pin 断言含 Implement soft delete (recycle bin):enable.trash/softDeleteare spec-only with zero runtime readers #3146 且不含 [P2] Aspirational config — prune or mark experimental #1893。
对 diff 逐项核对通过;两个实施判断予以确认:mru 墓碑不硬指 #3146(该单只立项软删除,精确指针优于字面遵从),已消费 changeset 由 minor 翻正 major(v17 pre 窗口,
check-changeset-no-major有 RC EXEMPTION;breaking 移除列在 Minor Changes 会误导升级 agent)。流程教训入档:#2902、#3207 一天内两例「已实现未关单」。后续派单前 PM 先做 main 现势快查;os-dev 动手前重验现场的纪律继续保持。附带产出:#4736(i18n config 常驻噪音,未认领)。
Generated by Claude Code
- 补 ADR-0087 D2 conversion(
- added a commit that references this issue
on Aug 3, 2026 - added a commit that references this issue
on Oct 7, 2026
Follow-up to #2377 (ADR-0049 enforce-or-remove). The final
objectdead-property slice deliberately deferred from #3199 (merged as5754a23).What
Two object capability flags in the
enableblock are ledger-classified dead but still authored across the system objects:enable.trashobject.zod.ts:110—z.boolean().default(true)spec/liveness/object.json→status: dead, "no behavior-changing reader"enable.mruobject.zod.ts:113—z.boolean().default(true)spec/liveness/object.json→status: dead, "no behavior-changing reader"No runtime consumer reads either flag — verified by grep across plugins/services/objectql/runtime. The only non-setter references are the generated i18n form labels (
capabilities.trash/capabilities.mru) and theauthorWarn-skip note inlint-liveness-properties.ts. Authoring them is a false affordance: toggling "Enable Recycle Bin" or "Track Recently Viewed" off changes nothing.Why it was deferred (not a quick win)
Unlike the other #2377 removals, these are inert
default(true)flags explicitly set by the system-object definitions:trash:set in 44*.object.tsfilesmru:set in 39*.object.tsfiles(mostly
sys-*.object.tsacrosspackages/metadata-coreandpackages/platform-objects). Removing the schema property is breaking (next major) and forces touching all ~44 files to drop the now-rejected keys. High churn, low value — so #3199 left themdead+ authorWarn-skipped rather than block that PR.Proposed work (same pattern as #3199)
trashandmrufrom theenablecapabilities schema inpackages/spec/src/data/object.zod.ts.enable.trash/enable.mruinUNKNOWN_KEY_GUIDANCE(point authors at the removal, matching thetags/active/abstracttombstones).enable: { … trash, mru … }entries from all ~44 setter*.object.tsfiles.packages/spec/liveness/object.jsonand update the ledger README count table.capabilities.trash/capabilities.mruentries from the object authoring form (object.form.ts) and regenerate the metadata-forms i18n bundles (os i18n extract, all 4 locales).api-surface.json+ reference docs (gen:schema+gen:docs); runcheck:docs.minorchangeset (launch-window policy — breaking spec changes ship asminor, percheck-changeset-no-major), with a migration note: the flags never gated behavior, so removal is drop-the-key only.Verification
pnpm --filter @objectstack/spec test(full)check-liveness.mts)ObjectSchema.create()unknown-key throwcheck:docs+check:api-surfaceNotes
ObjectSchema.parse(), which strips unknown keys — a staletrash/mruin a persisted payload is a no-op, not an error. The break is purely author-side (ObjectSchema.create()on hand-authored*.object.ts).