|
| 1 | +# Todo continuation and closure readback |
| 2 | + |
| 3 | +Todo list, status and quota distinguish a completed record from a closed work |
| 4 | +slice. A completed tracked advancement Todo still needs an existing successor |
| 5 | +or an explicit `no_followup=true`. This read policy lives in |
| 6 | +`control_plane/todos/succession.ts`; Python normalizes legacy input and renders |
| 7 | +its decisions. It belongs to the existing Todo control plane, uses the selected |
| 8 | +AuthorityStore, and adds no capability or extension provider. |
| 9 | + |
| 10 | +## Relationship evidence |
| 11 | + |
| 12 | +The policy evaluates the complete available Todo graph before role, status, |
| 13 | +Agent, ID or display-limit selection. It recognizes explicit |
| 14 | +`successor_todo_ids`, `superseded_by`, and advancement records pointing back |
| 15 | +through `unblocks_todo_id` or `resume_when=todo_done:<source>`. |
| 16 | + |
| 17 | +- A declared successor must exist and differ from the source. A dangling or |
| 18 | + self reference does not close work. A retained archived record remains |
| 19 | + relationship evidence; it does not become active work. |
| 20 | +- Explicit links retain their existing role-neutral meaning. Inferred |
| 21 | + successors require an advancement task. `monitor_changed` is a resume |
| 22 | + condition, not an inferred work successor. |
| 23 | +- An existing successor records continuation lineage. It does not prove that |
| 24 | + the successor has executed, been accepted or acquired a lease. This is not a |
| 25 | + transitive Goal acceptance proof or a cycle-freedom certificate. |
| 26 | +- Basic historical checkboxes without structured execution context keep their |
| 27 | + compatibility behavior. Explicit no-follow-up remains an independent closeout |
| 28 | + choice. Deferred work is never classified as a completed advancement gap. |
| 29 | + |
| 30 | +Both completed-work warnings and handoff gates use that same graph. Previously |
| 31 | +handoff ignored explicit successor lists, while completed-work warnings accepted |
| 32 | +nonexistent/self links. Filtering or archiving a valid inferred successor could |
| 33 | +also manufacture a warning that was absent on the full source. |
| 34 | + |
| 35 | +| Handoff facts, in precedence order | State | |
| 36 | +| --- | --- | |
| 37 | +| Existing, non-self supersession target | `superseded` | |
| 38 | +| Deferred source | `deferred` | |
| 39 | +| Source has not completed | `blocking` | |
| 40 | +| Completed with explicit no-follow-up | `cleared_no_followup` | |
| 41 | +| Completed with a resolved successor | `cleared_with_successor` | |
| 42 | +| Completed without either | `cleared_without_successor` | |
| 43 | + |
| 44 | +Only active dependency-linked executor exclusions are handoff gates. These |
| 45 | +states describe the gate; none changes claims, grants, leases or stored Todos. |
| 46 | +The existing legacy stale-closeout prose hint remains a compatibility adapter |
| 47 | +until route-closeout writers supply the explicit replan flag. Its substring |
| 48 | +matching can overmatch narrative and is not used for successor resolution, |
| 49 | +handoff state or permission. An explicit boolean replan flag takes precedence. |
| 50 | + |
| 51 | +## Selection, proofs and transport |
| 52 | + |
| 53 | +A fresh full-source evaluation accompanies each internal summary row as an |
| 54 | +ephemeral Python attribute, outside dictionary fields and JSON serialization. Its fact |
| 55 | +digest prevents reuse after relevant item edits; it is a consistency check, |
| 56 | +not authentication. Fresh parsing/canonical reads always recompute it rather |
| 57 | +than trusting stored evaluations. Shadow capture discards this derived field; |
| 58 | +canonical records and durable source digests do not gain a second authority. |
| 59 | +Public parser rows keep their existing dictionary schema. Final list/status |
| 60 | +responses copy plain dictionaries, retaining decision fields without exposing |
| 61 | +the internal evaluation or expanding the hot-path payload. |
| 62 | + |
| 63 | +Legacy archive/recreate can retain one archived and one active record with the |
| 64 | +same logical Todo ID. The active record owns that ID's inferred edges regardless |
| 65 | +of source order; archived metadata cannot supply stale edges for the replacement. |
| 66 | +Two active or two archived records with the same ID remain ambiguous and reject. |
| 67 | +This read precedence does not relax canonical capture's unique-identity contract. |
| 68 | + |
| 69 | +A status/ID/Agent-filtered list describes that selection but emits no Goal-source |
| 70 | +or terminal-closure proof. A display limit alone does not change the source: |
| 71 | +counts, warning decisions and proof eligibility are computed first. Handoff |
| 72 | +state, successor count and executor exclusions survive the bounded list view. |
| 73 | + |
| 74 | +Terminal closure additionally requires no deferred/convergent work, unresolved |
| 75 | +handoff, successor gap or route-replan obligation. Watch-only monitors retain |
| 76 | +the existing convergent-work exception. It remains separate from Goal acceptance. |
| 77 | + |
| 78 | +Field-presence sets are interned inside a succession RPC request so long archive |
| 79 | +histories do not repeat identical metadata shapes. The full graph is retained; |
| 80 | +no record sampling, per-page rule evaluation or RPC limit increase is used. |
| 81 | + |
| 82 | +## Migration and operation |
| 83 | + |
| 84 | +The shared archive-capture owner retains the reachable continuation graph as |
| 85 | +well as resume dependencies and standing decisions. It preserves real record |
| 86 | +status, including deferred history: capturing a deferred record does **not** |
| 87 | +satisfy `todo_done`. Duplicate identities, invalid archive state and incompatible |
| 88 | +role/authority combinations still reject capture. Unrelated archive records |
| 89 | +remain outside the bounded canonical capture. |
| 90 | + |
| 91 | +The internal request is `todo_archive_dependency_capture_request_v1`. Python |
| 92 | +and the bundled TS runtime must be upgraded together; an older runtime rejects |
| 93 | +the new request instead of silently omitting continuation edges. Existing |
| 94 | +historical capture/promotion receipts are not rewritten or upgraded in place. |
| 95 | +Requalify capture on this runtime before a future promotion. |
| 96 | + |
| 97 | +Use existing read commands; no activation or new option is needed: |
| 98 | + |
| 99 | +```bash |
| 100 | +loopx --registry registry.json todo list --goal-id example-goal --format json |
| 101 | +loopx --registry registry.json todo list --goal-id example-goal --todo-id todo_source --limit 1 --format json |
| 102 | +``` |
| 103 | + |
| 104 | +Completion retries also close a receipt/head read race: if the first receipt |
| 105 | +lookup misses a peer commit but the head already shows completion, recheck the |
| 106 | +matching operation receipt before interpreting a supplied validation receipt. |
| 107 | +This returns the committed result without repeating effects; no matching |
| 108 | +receipt still follows the existing validation and identity guards. |
| 109 | + |
| 110 | +Reads do not repair Markdown, mutate Todo/lease state or replay a business |
| 111 | +operation. Missing promoted Markdown is acceptable; an unavailable provider is |
| 112 | +not an empty Goal. No frontend configuration changes are needed: CLI, manager |
| 113 | +Chat details and existing status/quota consumers retain their current entry |
| 114 | +points. To reverse a business decision, use its ordinary mutation, not a read |
| 115 | +model or restored Markdown. Code rollback retains provider state and fences; |
| 116 | +old read policies can again misclassify these cases. |
| 117 | + |
| 118 | +## 中文 |
| 119 | + |
| 120 | +“这个 Todo 已完成”与“这一段工作已闭环”不同。结构化推进任务完成后,要有真实 |
| 121 | +存在的后继,或明确声明 `no_followup=true`。TS 现在统一解析显式后继、替代关系和 |
| 122 | +反向交接关系;Python 保留旧输入规范化与展示。不存在的 ID、自指 ID 不再遮住 |
| 123 | +未闭环工作,归档与筛选也不再凭空制造后继缺口。 |
| 124 | + |
| 125 | +关系在完整可用源上判定,然后才筛选、分页。按状态、ID 或 Agent 筛出的列表不能 |
| 126 | +为整个源出具闭环证明;仅限制显示条数不会改变完整源上的计数与判断。handoff 的 |
| 127 | +状态与排除执行者信息不会在压缩展示时丢失。派生判断带相关事实摘要以防陈旧复用, |
| 128 | +但不是授权凭据,也不写回 provider。旧 prose replan 提示仍仅用于兼容;显式 |
| 129 | +布尔标记优先,不能靠标题里的几个词推导后继存在或授予权限。 |
| 130 | + |
| 131 | +归档捕获现在保留与当前工作有关的后继图和原有依赖、standing decision。延后历史 |
| 132 | +可以被保留,但状态仍是 deferred,绝不会因此满足 `todo_done`。新的内部 v1 请求 |
| 133 | +要求 Python 与 TS 配套升级;旧回执不被重新解释。长历史重复字段集合采用无损共享, |
| 134 | +没有放宽 RPC 上限或丢弃历史节点。 |
| 135 | + |
| 136 | +本阶段关闭一组 T3/L5 读语义及其 L7 捕获依赖,不代表 D1 投影投递、D2 耐久性、 |
| 137 | +D3 整 Goal 切换完成,也不修改默认 provider。PostgreSQL 使用相同规则,服务部署与 |
| 138 | +资格仍独立。复杂 fixture 和只读快照演练不是长期 soak 或生产晋升许可。 |
0 commit comments