diff --git a/docs/reference/local-authority-provider-selection.md b/docs/reference/local-authority-provider-selection.md index 2fb8bd79a4..3b88ec22e5 100644 --- a/docs/reference/local-authority-provider-selection.md +++ b/docs/reference/local-authority-provider-selection.md @@ -188,3 +188,56 @@ CLI 使用上面的完整 JSON 和 preview/apply/inspect/bootstrap 命令;App 删除 fence 或重新开放旧 writer。既有 Goal 升级仍需备份、停止写入、结算租约和 审核计划;反向迁移须保留新增写入。受支持的旧备份、格式和原回执恢复能力保留。 此路径不代表完整升级、D2 长期资格或发布默认已通过。 + +## Retirement boundaries before changing the release default + +SQLite adoption and Python retirement need separate evidence. A canonical Goal +can bypass a source writer while supported unmigrated Goals still call it. +Changing the creation default does not migrate those Goals or settle their +capture history. Use the existing [retirement cadence](../architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md) +to qualify each last caller family independently. + +| Retained boundary | Current value and owner | Evidence needed before removal | +| --- | --- | --- | +| `todos.py`, `bootstrap.py`, `todos/line_update.py` | Unmigrated source creation and Todo edits still use Markdown writes. Canonical lifecycle decisions belong to the typed provider transactions. | Migrate the corresponding supported callers; run creation, update and recovery with the old writer physically absent. Keep Markdown display projection and supported import/export. | +| `runtime_shadow_writer_adapter.py`, `local_authority_shadow_outbox.py` | Source writers prepare capture before the primary write and record commit afterward; outbox records preserve interrupted operations. Typed coordination owners interpret the captured mutations. | Stop the corresponding source producers, classify every pending prepared/committed entry against its source and exact receipt, and prove recovery after producer removal. Clearing configuration cannot cancel an active capture obligation. | +| `local_authority_shadow_projection.py` | Python transports full source artifacts, rejects floats and unsafe integers before Python/JS digest comparison, and checks identity, size, digest and regular-file readback. `coordination.source.project` remains the typed projection owner. | Preserve exact-byte and malformed-input behavior in the replacement, including symlink rejection, bounded transfer and ambiguous-operation errors. A language-only rewrite is insufficient. | +| `runtime_shadow.py`, `local_authority_shadow_adapter.py` | Explicit bootstrap, inspect, candidate read, drain and recovery still consume full source snapshots, cursor history and digest comparison. | Qualify the replacement management/recovery entrypoints and supported historical evidence; a canonical write passing does not establish these readers are unused. | +| `authority_core.py` | Live Todo adapters delegate to typed mutation/ownership rules; scope overlap delegates to the typed lease owner. The lease-mode input compatibility contract is explicitly retained. | Trace direct, internal, dynamic and exported callers separately. Review registered historical input support before retiring its vocabulary; do not infer a fresh grant from old `legacy` inputs. | + +Paths in the table are under `loopx/` or its `control_plane/coordination/` and +`control_plane/todos/` subdirectories. Keep host locking, atomic replacement, +process cleanup, private validation declarations and supported backup/original +receipt readers where they still serve real callers. Their I/O or recovery +value is distinct from a duplicated decision owner. + +For each proposed deletion, record the supported caller, replacement owner, +persisted obligations and rollback. Search references and exports, then exercise +the real CLI and installed package in a disposable runtime with the retired +path absent. Include interrupted writes, restart/replay, malformed evidence and +unavailable selected-provider cases. The provider must fail visibly without +falling back to a Markdown writer. Keep historical recovery coverage; reverse +cutover must retain writes made after the original migration. + +Useful existing regressions include `test_source_projection.py`, +`test_source_transfer.py`, `test_local_authority_shadow_outbox.py`, +`test_runtime_shadow_bounded_e2e.py`, `test_shadow_writer_boundaries.py` and +`test_shadow_cursor_recovery_e2e.py` under `tests/control_plane/`. Transport +fault tests use injected faults; source/recovery tests also run real CLI/native +writers against disposable File stores. These are bounded regression evidence, +not sustained SQLite, PostgreSQL, packaged App or release-default qualification. + +### 切换发布默认前的退役边界 + +canonical 写入绕过旧 writer,不代表未迁移 Goal 的调用方已消失。默认值修改也不 +迁移已有 Goal 或结算 capture 历史。按调用族分别验收,不把整项迁移设成所有小批 +退役的前置依赖;仍有调用的 writer/producer 在对应迁移后删,已无调用的内部桥接 +可先删,受支持的备份、格式、原回执恢复与 Markdown 展示继续保留。 + +上表中的精确数字与摘要校验、安全文件传输、prepare→主写入→commit 顺序、游标 +恢复和 Host I/O 都有实际价值。替代实现须保留它们;Python 行数减少不能代替语义 +验收。静态引用、内部调用、动态入口、导出兼容与安装态要分别核验。删除前在隔离 +环境中让旧路径实际不存在,验证创建、修改、中断、重启、原操作重放及 provider +不可用时明确失败;不降级到 Markdown writer,不破坏历史恢复,回退保留迁移后的 +新写入。现有回归覆盖不等于长期 SQLite、真实 PostgreSQL、打包 App 或发布默认 +已通过,trial 与正式默认的资格继续分别记录。