Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ const capabilityCopy: Record<WorkspaceLocale, Record<string, LocalizedCopy>> = {
description: "Synchronizes accepted LoopX work state to the configured Lark Kanban heartbeat surface.",
},
local_authority_shadow: {
displayName: "Local authority shadow",
description: "Observes post-commit Todo and task-lease state through the shared authority contract without taking write authority.",
displayName: "Retired authority observation",
description: "No longer writes observations. Retained records are read-only, not promotion evidence.",
readOnlyReason: "Clear the old setting with configure-goal --clear-local-authority-shadow. Runtime shadow requires separate configuration and bootstrap.",
},
coordination_runtime_shadow: {
displayName: "Coordination runtime shadow",
Expand Down Expand Up @@ -111,8 +112,9 @@ const capabilityCopy: Record<WorkspaceLocale, Record<string, LocalizedCopy>> = {
description: "把 LoopX 已接受的工作状态同步到配置好的飞书看板心跳界面。",
},
local_authority_shadow: {
displayName: "本地 Authority 影子观测",
description: "通过共享 Authority contract 观测提交后的 Todo 与 task lease 状态,但不取得写入权。",
displayName: "已退役的 Authority 观测",
description: "不再写入观测。保留记录只读,不能作为晋升证据。",
readOnlyReason: "通过 configure-goal --clear-local-authority-shadow 清理旧设置;Runtime shadow 需要另行配置与 bootstrap。",
},
coordination_runtime_shadow: {
displayName: "协调 Runtime 影子",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export function CapabilityEditorStatus({ available, description, t }: Readonly<{
}

function capabilityPresentationTier(capability: CapabilityDescriptor) {
if (capability.availability === "retired") return 5;
if (capability.availability?.includes("experimental")) return 4;
if (capability.capability_id === "multi_subagent") return 3;
if (capability.configuration_editor.writable_scopes.length === 0) return 2;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# One writable shadow lineage

- Inventory baseline: `d64c4d377` (`main`), 2026-09-24.
- Goal: #4574 R5/G2, shared authority §12 question 14, TS T2/T4.
- Gap: post-commit observation still writes a second history after transaction-bound outbox capture shipped.
- Outcome: remove the obsolete writer, expose retirement at configuration/CLI/runtime/settings boundaries, preserve historical reads and require explicit replacement bootstrap.

## Reconciled delivery plan

Do not reuse the old “5–8” or “7–9” ranges. They mixed new implementation,
open PRs and qualification into one number. This snapshot has **four proposed
new implementation batches including this retirement**, alongside already-open
work. After this PR, **three named batches remain planned**; that is a delivery
plan, not proof that precisely three future PRs will suffice for every Goal.
Split a batch only when a demonstrated integration defect requires it, and
record that defect rather than keeping an unchanged numerical range.

| Batch | Observable completion | Current boundary |
| --- | --- | --- |
| Retire duplicate observation | No post-commit resampling or second-store writes; old settings cannot enable it; historical data survives; explicit outbox bootstrap works. | Independent cleanup of the already-shipped capture owner; no provider-default claim. |
| Executor liveness | A real Host renews during execution and is cancelled on fence loss; expired/reclaimed execution cannot settle as its successor. | Current acquire/readback is point-in-time proof. RFC §12 question 6 remains open. External systems still need their own effect identity/fencing. |
| Event capture + whole-Goal journey | Bind actual event publication to source locks/outbox lineage; verify mixed writers, drain, reviewed promotion, consumer reads, export/rollback. | Reuse #5003; preserve `event_log_writer_not_bound` until binding is proved. |
| Default onboarding + bounded Python retirement | Qualified profile selected consistently by new Goal creation/settings/install; explicit migration for existing Goals; remove switched business writers. | Depends on integration and applicable D1–D3 gates. Python host IO/rendering/import-export need not disappear. |

Existing open implementations are tracked separately: #5006 complete-source
transport, #5003 atomic event-owned completion, #4994 leased handoff continuation,
#4995 Monitor proof projection, #4991 reservation cleanup, #4992 deferred receipt
selection, and #4931 SQLite retained-proof optimization. Do not propose these
again. #4915 filesystem placement is not authority-provider selection.

Merged source assembly/capture delivery (#4967/#4968), canonical pagination
(#4922), reviewed cutover/drain planning (#4888/#4920), SQLite admission (#4960)
and display recovery (#4961) are existing implementations, not missing projects.
#5006 is still open at this baseline: its larger source transport should be
integrated, not copied into this independent retirement PR.


SQLite D2 is evidence, not an invented PR allocation. #4224 reports failed
1 MiB receipt/scan budgets and missing workload/RSS/recovery/restore/runtime/soak
coverage; #4931 addresses proof encoding but does not certify all those rows.
At least ten days of natural soak, exact-profile qualification and D3 cohort
approval remain separate. File-only cutover, qualified SQLite default and
migration of all existing Goals are different acceptance scopes. PostgreSQL
continues to reuse the typed contract while deployed transport, tenant policy,
operations and service qualification remain medium-term work.

## Semantics and evidence

[Operator transition](../../../../reference/authority-observation-retirement.md)
covers rejection, clearing, bootstrap and rollback. Primary Todo/lease rules,
source checks, event holds and active capture bindings do not change. The old
settings entry is read-only in both languages; stale clients fail before writes.
The old RPC is a typed rejection tombstone. Historical codecs and reads remain,
but Python post-commit projection/retry and TS observation commit are deleted.
State migration retains its response field with `retired/attempted=false`.

Validation exercises public CLI replacement bootstrap, lease writes with old
and absent settings, invalid-setting cleanup, retained-store readback, and
process death between source replacement and committed marker followed by
single-entry recovery. Existing transaction, source-fencing and configuration
suites remain the oracle; tests for intentionally removed observation behavior
are replaced rather than preserved as a second implementation.

A witness-checked detached snapshot of the real local Goal exercises Todo add,
retired-setting clear/readback and unchanged historical bytes. All writes target
the disposable runtime explicitly; private source content is not published.
This proves the affected upgrade path, not full migration or D2 qualification.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 单一可写 shadow

- 盘点基线:`d64c4d377`(`main`),2026-09-24。
- 目标:#4574 R5/G2、shared authority §12 第 14 问、TS T2/T4。
- 缺口:事务绑定的 outbox 已交付,但后提交观察器仍写另一份历史。
- 结果:删除旧 writer,配置、CLI、runtime、设置页共同声明退役;保留历史读取,新链显式 bootstrap。

## 校准交付计划

不再沿用“5–8”或“7–9”。旧估算混合了未开发、已提 PR 和资格验收三个不同单位。
本检查点规划 **四个新增实现批次,包括本次退役**;本 PR 之后仍规划 **三个明确批次**。
这是开发计划,不是“恰好再合三次即可迁移所有 Goal”的保证。若集成发现实际缺陷,
应列出缺陷和新增边界,不能默默维持一个固定区间。

| 批次 | 可验收结果 | 当前边界 |
| --- | --- | --- |
| 退役重复观测(本 PR) | 不再二次采样和写另一份历史,旧开关不能启用,旧数据保留,新链必须 bootstrap。 | 独立收尾,不宣称切默认。 |
| 执行过程的租约保护 | 真实 Host 执行期间续租,失去执行权后取消;失效执行不能冒用新执行权结算。 | 当前读回只是时点证明,外部系统仍需自己的副作用防重与 fence。 |
| 事件捕获及整 Goal 迁移旅程 | 将事件发布接入来源锁和 outbox,验证混合写入、排空、评审晋升、消费与回退。 | 复用 #5003,真实绑定证明前保留拒绝条件。 |
| 默认入口及剩余 Python 业务退役 | 新 Goal、设置、安装一致选择已合格 profile;旧 Goal 显式迁移;删除已切换的业务 writer。 | 依赖集成与 D1–D3,不要求删除保留的 Python IO、渲染与合法导入导出。 |

单独跟踪已有在途实现:#5006 完整来源传输、#5003 事件 Todo 原子完成、#4994 租约交接、
#4995 Monitor proof、#4991 reservation 清理、#4992 回执绑定选择、#4931 SQLite 读取优化。
不得重复开发。#4915 是目录迁移,不是 provider 默认选择。

#4967/#4968 来源组装与捕获投递、#4922 分页、#4888/#4920 晋升及排空计划、#4960 SQLite
准入、#4961 展示恢复已有实现。#5006 此时仍在途;本 PR 不重复拷贝其大来源传输改动。

SQLite D2 不是可随意换算成 PR 的单位。#4224 报告 1 MiB 回执/扫描预算失败及真实负载、
RSS、恢复、restore、runtime、soak 缺失;#4931 修读取证明成本,不等于所有行通过。
至少十天自然 soak、精确 profile 资格及 D3 cohort 批准仍独立存在。File 限域切换、
SQLite 合格默认和所有旧 Goal 迁移不是同一验收范围。PostgreSQL 复用 typed 合同,
部署传输、租户策略、运维与服务资格仍属中期目标。

## 语义与证据

[操作说明](../../../../reference/authority-observation-retirement.md)覆盖拒绝、清理、
bootstrap 与回退。主 Todo/租约规则、来源校验、事件 hold 和活跃绑定不变。中英文
设置中旧入口只读,旧客户端写入前拒绝;旧 RPC 保留 typed 拒绝入口。历史 codec/read
保留,删除 Python 后采样/重试与 TS observation 提交。目录迁移结果明确不再 seed。

验证真实 CLI bootstrap、旧配置/无配置的租约写入、非法配置清理、历史读回,以及
主文件替换后 committed marker 前进程死亡的单次恢复。保留现有事务、fence 与配置
验证;已退役行为的旧测试替换为升级验收,不保留第二套实现。
本机真实 Goal 经来源 witness 校验后复制到隔离 runtime,验证 Todo 添加、旧配置清理
及历史字节不变;写入显式指向隔离 runtime,私有内容不发布。这不是整 Goal 迁移或 D2 证明。
82 changes: 30 additions & 52 deletions docs/architecture/rfcs/shared-goal-authority-state-provider-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ are not a guaranteed total PR count. Use the [reconciled inventory and exits](le

`e94759d88` adds [PostgreSQL service admission](../../reference/postgresql-authority-service-v0.md), with authentication/tenant verification injection and identity rotation. It is an in-process service boundary, not a deployed network service. The P lane should reuse it and finish transport, real identity policy, pool/cancellation/failover and operations qualification rather than rebuilding admission. R7 must separately report registration, active executors and measured capacity. Directory, presence, a plan or one source read grants no shared authority. Existing fail-closed source, receipt/replay and rollback contracts remain.

## Observation retirement checkpoint (2026-09-24)

[Current delivery inventory](ledger/shared-goal-authority-state-provider-v0/2026-09-24-observation-retirement.md)
separates merged code, open PRs and qualification gates. This delivery removes
the obsolete Python observation writer and TS observation commit path; it does
not implement executor liveness or event-writer binding. There is one writable
shadow lineage, still default-off and subject to explicit bootstrap.

## Current implementation checkpoint

The current [event transaction and default-cutover plan](ledger/shared-goal-authority-state-provider-v0/2026-09-24-event-completion-transaction.md) estimates 5–8 complete packages conditionally. #4967 source assembly and #4968 capture delivery are already delivered; event-writer binding remains open, with atomic completion repaired here as a prerequisite. Earlier counts below describe historical checkpoints, not additional current work.
Expand All @@ -45,16 +53,18 @@ after promotion. Legacy event-only claims reject rather than disappear at a
Markdown boundary; event append locks protect the observation through writeback.
Canonical changes reuse durable command receipt recovery. This is an L2/L3
compatibility correction with Python decision deletion, not cohort migration,
SQLite D2 completion or a default flip. Remaining work is classified in the current delivery frontier rather than
counted as unchanged packages.
SQLite D2 completion or a default flip. Remaining work depends on executor/consumer closure, qualification,
integrated migration and onboarding; it is classified in the current delivery frontier rather than counted as
unchanged packages, and historical package ranges are not a current PR count.
[Operation, repair and recovery](../../reference/handoff-mode.md).

The terminal caller family now binds review and validation to the canonical
source and recovers historical receipts independently of private argv. Agent
completion and Monitor stop share current-head display acknowledgement with
ordinary edits. [Caller and recovery contract](../../reference/canonical-terminal-review.md).
This advances L2/L5 without closing executor-held fences, D1–D3 or default
onboarding; use the current reconciled inventory for remaining work.
onboarding; use the current reconciled inventory for remaining work, and historical package estimates below are
superseded by the current inventory.

The local registry witness now spans canonical create/claim/update/Monitor poll
and terminal mutations through one TS owner. File, SQLite and service-injected
Expand Down Expand Up @@ -1570,40 +1580,13 @@ that provider metadata is absent from the logical revision projection. This is
Stage 1 parity evidence, not provider promotion or a claim that all later
provider profiles are qualified.

#### Stage 2C observation foundation: local post-commit capture
#### Stage 2C observation foundation: retired

The first half of Stage 2C is an explicit, default-off product path. Preview
and enable it with:

```bash
loopx configure-goal --goal-id GOAL --local-authority-shadow-file
loopx configure-goal --goal-id GOAL --local-authority-shadow-file --execute
```

Todo, handoff-mode, follow-up, and task-lease facades sample the full current
local projection after their primary write returns committed, then ask
`FileAuthorityStore` to retain that snapshot. `observation_trigger` records
why sampling began; it is not the primary transaction identity. A concurrent
primary commit may therefore appear in the sampled snapshot. A `captured` or
`replayed` result proves only the candidate-side observation commit. It does
not compare the source and candidate and carries `parity_verdict=not_evaluated`.

Candidate bytes live under
`authority-shadow/file/` outside the legacy per-Goal runtime tree, so state
migration never copies a store identity or revision; an executed migration
seeds a new target lineage from the migrated local state. Candidate failure is
reported as an observation result but never reverses the completed local write.

Disable the observer in one command with
`loopx configure-goal --goal-id GOAL --clear-local-authority-shadow --execute`.
This is rollback of observation only: the local Markdown and task-lease files
remain canonical throughout. The slice does not read the candidate for a
decision, fence a legacy writer, qualify a remote provider, or complete the
second Stage 2C promotion. A process crash after the local commit but before
the observer call may miss that individual observation; a later committed
write or migration seed refreshes the full current projection, but no durable
shadow outbox or transaction-correlated receipt is claimed here. This plumbing
is not parity evidence and cannot by itself support Stage 2C promotion.
The historical post-commit observer has been removed. Existing configuration
is readable but inactive, enable requests reject, and state migration no longer
seeds a second observation history. Retained files are not deleted. Use the
existing transaction-bound runtime shadow after explicit bootstrap; no old
observation is promoted into evidence. [Transition and compatibility](../../reference/authority-observation-retirement.md).

#### Implementation prerequisite: put local file mode behind the same coordination contract

Expand Down Expand Up @@ -2159,6 +2142,10 @@ shipped production capability.

#### Stage-ladder end-to-end evidence (2026-09-03)

Historical delivery record: the observation-writer rows described below were
retired on 2026-09-24. The [current ladder](../../../examples/shared-goal-authority-e2e/README.md)
uses transaction-bound Stage 1 readback and explicit Stage 2C upgrade acceptance.

What exists on this branch is one incremental end-to-end "stage ladder" that
exercises every completed stage claim of this RFC through the real
`python -m loopx.cli` and reports a machine-checkable verdict per row:
Expand Down Expand Up @@ -2431,22 +2418,13 @@ remain reviewable in the same bounded slice.
the promotion PR; two local aggregate formats cannot both be canonical.
Flipping the file profile's `qualification_holds` to `[]` and its `stage`
literal happens only inside that PR.*
14. `main` now carries two default-off shadow lineages for the same writers:
the observation capture of #3818 (`coordination.authority_shadow`,
`authority-shadow/file/<goal>`, projection v0) and the runtime shadow
(`coordination.runtime_shadow`, `authority-shadow/file-v0`, projection v0
with `inspect`, `qualify`, `bootstrap`, `rollback`, and `read-candidate`).
Both re-sample the source after the primary commit, so both share the
concurrent-writer and commit-to-dispatch loss windows that the review of
#3818 named. Which lineage is Stage 2C's, and what closes those windows?
*Proposed answer: the runtime shadow is the lineage, because the parity
report, bootstrap, quarantine rollback, read shape, and promotion kernel
already bind to it. The transaction-bound outbox of the parity half
(prepared entry inside the writer's own lock, committed marker after the
primary write, bounded drain with `operation_id = entry id`) becomes the
durable capture that feeds `coordination.runtime_shadow.commit`, and the
#3818 observation path retires once that capture is wired. The RFC must
not keep two shadow record formats.*
14. Which shadow lineage remains writable? *Resolved by this retirement:
`coordination.runtime_shadow` is the sole writable lineage. Its existing
transaction-bound outbox prepares under the source writer lock and drains
by stable entry identity. The old `coordination.authority_shadow` writer
is removed; historical records remain readable, but cannot qualify capture
or promotion. Unsupported event writers still fail closed until their own
transaction boundary is bound; retiring observation does not close that gap.*

---

Expand Down
Loading
Loading