Skip to content
Closed
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 @@ -3071,7 +3071,7 @@ or moving a helper is not by itself a package exit.
| Wave / package | Reviewable delivery and TS ownership payoff | Dependencies and exit evidence |
| --- | --- | --- |
| A / L1: Monitor configuration (this slice) | Existing `todo update` config enters the TS planner/CAS/receipt; delete Python's duplicate intent field catalog. Separate authoring from observed hashes, times and generations. | Ordinary CLI/API, clear/omission, active lease proof, no-op/replay, failed display delivery, complete fixture and real providers. This does not complete delegated Chat or leased polling. |
| A / L2: Complete public mutation admission | User completion updates now share the TS edit/terminal transaction and reviewed Chat recovery. Continue the actual CLI/Turn/Chat inventory for remaining effect-owned decisions, delegated owner actions and Monitor lifecycle transitions; [caller contract](../../reference/canonical-todo-completion-update.md). | Build on merged T1 owners, not a generic raw patch. Prove permission rejection and exact caller response; remove replaced Python admission and name every remaining unsupported command. |
| A / L2: Complete public mutation admission | User completion updates share the TS edit/terminal transaction and reviewed Chat recovery. [Follow-up capture](../../reference/canonical-followup-capture.md) now uses one TS batch plan and provider CAS/receipt, with a shared legacy adapter; it no longer falls through to the fenced writer. Continue the actual CLI/Turn/Chat inventory for remaining effect-owned decisions, delegated owner actions and Monitor lifecycle transitions; [caller contract](../../reference/canonical-todo-completion-update.md). | Build on merged T1 owners, not a generic raw patch. Prove permission rejection and exact caller response; remove replaced Python admission and name every remaining unsupported command. |
| A / L3: Canonical lease lifecycle | Standalone acquire/takeover, atomic claim lease admission and maintenance reuse TS facts/decision/materialization and one provider opening fence. Explicit claimed-work transfer now commits source-authorized Todo ownership and the new lease generation together; canonical request types exclude legacy held-fence fields. Acquire success verifies current execution proof; canonical completion can recover missing display. | Full-head scope conflict, archived/ineffective holders, exact create-CAS retry, stale execution, process loss and real CLI/four-arm rehearsal are covered. [Operation and remaining callers](../../reference/canonical-lease-renew.md). Executor-held external-effect fences remain explicit work; D1–D3/default holds remain. |
| B / L4: Leased Monitor poll and settlement | Current execution proof now binds CLI intent, observation/generation/independent-successor CAS and historical business receipt. Quota pending admission is frozen before the business write; recovery preserves that decision after lease retirement. | Existing L3 lease lifecycle, real File/SQLite/PostgreSQL, mixed fixtures, process death between business/quota commits, competing renewal and unchanged polling. [Operation and snapshot rehearsal](../../reference/protocols/quota-monitor-observation-receipt-v0.md). No lease lifecycle effects or quota spend; separate authorities stay separate. Event callers, wider L2 admission and D1–D3/default remain open. |
| B / L5: Consumer and display closure | Reconcile #4316, audit Turn/quota/Dashboard/Chat source reads, and finish D1 freshness/recovery through the existing projection outbox. | CLI, Lark/Chat and packaged frontend read back their affected interactions; absent/stale display, empty canonical state, pending projection and data beyond UI limits. Delete post-promotion legacy fallbacks with each consumer. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2434,7 +2434,7 @@ canonical renew 候选,#4328 是 SQLite D2 首批测量/恢复候选;它
| 波次/PR 包 | 完整交付内容与 TS 归属收益 | 依赖与退出证据 |
| --- | --- | --- |
| A/L1:Monitor 配置(本切片) | 现有 `todo update` 配置进入 TS planner/CAS/receipt,删除 Python 重复 intent 字段表;区分配置与观察 hash、时间、代数。 | 普通 CLI/API、清除/省略、active lease proof、no-op/replay、展示失败恢复、完整 fixture 和真实 provider。不宣称完成委托 Chat 或 leased polling。 |
| A/L2:公共 mutation admission 闭合 | 用户 completion update 已共用 TS 编辑/terminal 事务与 Chat 审阅后恢复;继续盘点剩余 effect-owned 决策、委托 owner 动作和 Monitor lifecycle 的 CLI/Turn/Chat caller。见[调用合同](../../reference/canonical-todo-completion-update.md)。 | 复用已合并 T1 owner,不开通通用 raw patch;验证权限拒绝和 caller 响应,删除替代的 Python admission,列全未支持命令。 |
| A/L2:公共 mutation admission 闭合 | 用户 completion update 共用 TS 编辑/terminal 事务与 Chat 审阅后恢复;[后续任务批量捕获](../../reference/canonical-followup-capture.md) 已用同一 TS 计划与 provider CAS/回执,legacy 仅适配共享计划,不再进入被 fence 的旧 writer。继续盘点剩余 effect-owned 决策、委托 owner 动作和 Monitor lifecycle 的 CLI/Turn/Chat caller。见[调用合同](../../reference/canonical-todo-completion-update.md)。 | 复用已合并 T1 owner,不开通通用 raw patch;验证权限拒绝和 caller 响应,删除替代的 Python admission,列全未支持命令。 |
| A/L3:canonical lease 生命周期 | 独立 acquire/接管、原子 claim 的 lease 准入及维护复用 TS facts/decision/materializer 与同一 provider opening fence。显式联合交接由源持有者授权,一次提交 Todo 归属与新租约 generation;canonical 请求类型不再携带 legacy 持锁字段。Acquire 成功必须校验当前执行 proof;canonical 完成可恢复缺失展示。 | 已覆盖完整 head scope 冲突、归档/失效 holder、创建 CAS 原样重试、旧执行、进程中断、真实 CLI 与四臂演练。[操作及剩余 caller](../../reference/canonical-lease-renew.md)。跨外部 effect 的 executor 持锁 fence 仍为明确工作;保留 D1–D3/default hold。 |
| B/L4:leased Monitor poll 与 settlement | 当前 execution proof 贯穿 CLI intent、观察/generation/独立 successor CAS 和历史业务回执;业务写入前冻结 quota 准入,租约结束后仍按原决策恢复结算。 | 既有 L3 lease lifecycle、真实 File/SQLite/PostgreSQL、混合 fixture、业务与 quota 间真实进程退出、并发 renewal 和 unchanged poll;见[操作与快照演练](../../reference/protocols/quota-monitor-observation-receipt-v0.md)。不操作 lease lifecycle、不消耗 quota,不把两个 authority 假装成同一事务。Event caller、更广 L2 准入及 D1–D3/default 仍开放。 |
| B/L5:consumer 与展示闭合 | 核对 #4316,审计 Turn/quota/Dashboard/Chat 的来源,复用 projection outbox 完成 D1 新鲜度和恢复。 | 验证 CLI、Lark/Chat、打包 frontend 的受影响交互;缺失/陈旧展示、权威空状态、pending 投影及超过 UI 上限的数据。逐个删除晋升后的 legacy fallback。 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,12 @@ requires differential proof; record its deletion trigger when introduced.
Current implementation status: Stage 1, the bounded Stage 2A proofs, and the
shipped Stage 2B cutovers are in place:

- [Follow-up capture](../../reference/canonical-followup-capture.md): TypeScript owns
complete batch selection, full-text duplicate identity, metadata and canonical
CAS/receipt recovery. Python retains one locked renderer/shadow write for
legacy Goals and provider transport/outbox for promoted Goals. This deletes
Python selection and per-item add decisions; it is T1/L2 command closure,
not L7 capture qualification or a new-Goal default change.
- Turn settlement/commit: TypeScript owns preflight authorization,
ordered-prefix and replay validation, provider failure classification,
receipt construction, terminal closeout joining, and the canonical result.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ coordination 路径使用同一份语言中立的 `coordination_state_contract_v
仅将 typed read result 适配为兼容 summary。这是 contract 检查点,不是已经完成的
CLI lifecycle cutover。

### 后续任务批量捕获收敛

[`capture-followups`](../../reference/canonical-followup-capture.md) 的完整批次筛选、
全文去重、metadata 和 canonical CAS/历史回执由 TS 持有。Python 删除筛选与逐条
add 决策,保留 legacy 锁/渲染/shadow 写入及 promoted provider transport/outbox。
修复 500 字符展示截断误作身份及 continuation policy 丢失;覆盖完整混合图、竞争
CAS、no-op 封存、lost acknowledgement 和真实 provider/只读快照演练。
这是 T1/L2 的一个完整命令,不是 L7 shadow capture 连续性或新 Goal 默认切换。

### Lease 领取与生命周期收敛(2026-09-18)

独立 acquire/接管和维护共用 local provider/source fence。`task_lease_acquire_decision.ts`
Expand Down
122 changes: 122 additions & 0 deletions docs/reference/canonical-followup-capture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Canonical follow-up capture

`todo capture-followups` records a bounded batch of **unclaimed Agent Todos**.
It does not complete another Todo, acquire a lease, authorize an executor, or
perform the captured work. The built-in Todo planner owns selection and metadata;
coordination owns the canonical transaction. No new capability or provider is
introduced.

## Use and recover

On an already promoted Goal:

```bash
loopx --format json todo capture-followups --goal-id example \
--capture-operation-id followups-review-1 \
--follow-up 'Validate the recovery boundary' \
--follow-up 'Document the operator recovery command' \
--evidence 'validation://reviewed-capture' \
--continuation-policy same_agent_non_delivery \
--required-capability code_review --dry-run
```

Remove `--dry-run` to commit. Reuse the same operation id **and intent** after a
lost response; changing the evidence, metadata, order or follow-ups under that
id is rejected. Omit the id for a fresh operation on every invocation. Preview
writes no business receipt, so its id can be used for the subsequent commit.
An explicit id requires canonical authority; legacy Markdown cannot promise a
durable command receipt and rejects that option before writing.

Read back through `loopx --format json todo list --goal-id example`. File and
SQLite use the existing local selector. PostgreSQL uses the same transaction
through the existing service-owned store factory, with its own authentication
and tenant admission; this command does not introduce standalone PostgreSQL CLI
configuration or silently fall back when a selected provider is unavailable.

## Selection and atomicity

One TypeScript plan processes the whole request in order:

1. Empty text is skipped.
2. Existing public-safe boundary heuristics reject local paths, credential-like
literals and internal-only markers. Unsafe **evidence rejects the batch**;
an unsafe follow-up is reported as skipped. These are bounded heuristics,
not comprehensive secret detection or a grant to publish captured text.
3. Duplicate full text is skipped after Python-compatible whitespace compaction.
All Agent Todos in the active section count, including done and deferred
records. User and archived records do not suppress capture.
4. At most two new Todos are accepted; skipped items do not consume that limit.

The old 500-character **display** limit no longer defines capture identity.
Distinct long texts remain distinct, and rereading the legacy source uses an
explicit lossless decoder mode. Machine projection also validates through lossless source/metadata codecs rather
than status summaries; long records can be delivered instead of remaining pending.
Missing native priority/title annotations are derived for display, while explicit
contradictions still fail parity. Other display callers retain their limits.
`--continuation-policy`, previously accepted but dropped by the CLI, now reaches
both writers. Invalid metadata or a malformed tail rejects the entire request;
invalid requirements are not silently removed. This applies even to a batch
whose texts would all be duplicates. Optional routing metadata is returned
when supplied, rather than as an unrelated catalog of empty fields.

The legacy adapter holds its existing lock, renders only the accepted plan,
and writes once through shadow capture. It no longer owns regex classification,
selection, cap, duplicate identity or per-item add decisions. The canonical
adapter reads the full head, shares native Todo creation admission/materialization,
then commits all accepted rows and one receipt under one provider CAS. A stale
CAS cannot leave the first row committed without the second. Original Todo,
lease and standing-decision records remain untouched.

A no-op batch also seals a receipt while leaving the domain head unchanged;
its provider revision can advance even though `changed=false`. After later
archive/edit operations, retrying that id still returns the original no-op.
On replay, `changed=false` describes this invocation, while `recorded_count`,
`items[].added` and `original_receipt` describe the historical batch. A receipt
never grants current execution authority.

## Display delivery and boundaries

Markdown is delivered separately through the existing committed-authority outbox.
A display failure returns successful business state with
`projection_delivery=pending`; it does not roll the batch back. Retry the same
operation, or use the existing `todo project-markdown` recovery command for the
current provider revision. Delivery renders the **latest head**, not a stale
receipt snapshot. Missing Markdown does not prevent canonical capture or preview.
A missing/unavailable canonical provider also blocks preview; it must not invent
success from legacy Markdown.

The affected entry point is the CLI/Python capture API and its shared TS runtime.
There is no dedicated capture-followups frontend or Lark editor; existing Todo
readers consume its ordinary unclaimed records and the normal projection outbox.
No UI setting or new default is added. Reverting this code requires keeping
promoted Goals fenced and withholding this command until its transaction is
restored; do not re-enable the old Markdown writer as a rollback shortcut.

## Validation and roadmap checkpoint

Native conformance runs over File, SQLite, NoKV and real isolated PostgreSQL,
including complete synthetic graphs, legacy/native records, no-op/replay,
competing CAS, invalid input, source changes and lost acknowledgements. Python
coverage exercises the public CLI on real File/SQLite, missing display,
projection failure/recovery and provider failure without legacy fallback.

The read-only snapshot rehearsal compares legacy, File, SQLite and the
PostgreSQL service runtime. Supply a disposable PostgreSQL server explicitly:

```bash
uv run --extra test python examples/control_plane/authority-followup-capture-rehearsal.py \
--registry <registry> --goal-id <goal> --execute-isolated-postgresql \
--private-diagnostics <ignored-diagnostic-file>
```

`LOOPX_TEST_POSTGRES_URL` selects that isolated server. All effects target temporary
copies and a disposable tenant. Reports contain bounded counts/digests, and the
source is checked unchanged afterward. This is a command qualification, not a
whole-Goal promotion or a long-duration soak.

This closes capture-followups within shared-authority **L2** and TS **T1**.
It does not close the separate **L7 shadow-capture continuity** package. Remaining
public mutation/effect admission, consumers, D1/D2/D3, whole-Goal rollback,
new-Goal defaults and final legacy-writer retirement retain their existing
owners and acceptance gates. Consult the [shared-authority program](../architecture/rfcs/shared-goal-authority-state-provider-v0.md)
and [TS migration roadmap](../architecture/rfcs/typescript-control-plane-migration-v0.md).
Loading
Loading