Skip to content

Commit 6a5ac72

Browse files
authored
refactor(authority): centralize coordination state rules (#3410)
Centralize the existing todo, handoff, and task-lease coordination rules in one provider-neutral, side-effect-free decision core (loopx/control_plane/coordination/authority_core.py), keeping legacy / soft_claim / hard_lease behavior, public error codes, local Markdown/JSON formats, lock order, and lease tombstone fencing intact while removing duplicated rule ownership from the writers. - decide(snapshot, command) -> TransitionPlan is the single entry point; the writers keep I/O and locking and persist the returned plan (version, lease_epoch, owner, idempotency key) instead of re-deriving rules. - ownership_gate_requirement and the terminal-fence auto-acquire eligibility are single-sourced in the core; mutation probes flip end-to-end CLI behavior for the delegated door, the holder gate, and the completion fence, proving the core is load-bearing rather than a parallel copy. - local_snapshot.py / local_lease_record.py own the behavior-preserving adapter edge (mapping normalization; JSON/tombstone shape). Disclosed fail-closed change, pinned by test: hand-corrupted lease records (negative or non-integer version, corrupt replay-fingerprint ttl) are typed corrupt_lease rejections instead of silent input or raw ValueError. - The Workbench MCP sidecar forwards the already-required lease version for complete_task; the kunluncode settlement test pins the forwarding through the 5-command settlement flow. - The bilingual RFC gains the Stage 1 Part 2 boundary: no provider persistence, no synthetic revisions, no durable semantic receipts here; the file-backed provider shadow and the NoKV runner remain Stage 2. Validation at the merged head: coordination core suite 44 passed; focused handoff/lease/authority/CLI suites 187 passed; kunluncode settlement 35 passed; tests/control_plane + tests/canary 1697 passed with 4 failures that reproduce identically on unmodified origin/main in the same environment; architecture + maintainability ratchet + m6 gates 25 passed; mypy and changed-path ruff clean; canary premerge including the public boundary scan passed.
1 parent 02a714f commit 6a5ac72

17 files changed

Lines changed: 3369 additions & 620 deletions

‎docs/architecture/rfcs/shared-goal-authority-state-provider-v0.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,38 @@ only the `load` / `compare_and_put` provider. This prerequisite does not create
655655
a generic storage abstraction over registry, run history, quota, scheduler, or
656656
evidence; those ledgers retain the owners defined in Section 3.
657657

658+
#### Stage 1 Part 2 boundary
659+
660+
This slice is a behavior-preserving extraction of a pure decision core for the
661+
todo lifecycle, task-lease lifecycle, and `handoff_mode` rules that the current
662+
writers already enforce. Markdown goal state and task-lease files remain
663+
canonical. The extraction does not synthesize todo, authorization, dependency,
664+
or gate revisions for domains that have no current revision publisher. It also
665+
does not replace today's separate claim and lease verbs with the atomic
666+
`claim_work` command described above; that command belongs to the future shared
667+
aggregate.
668+
669+
Keep three layers distinct as the provider work proceeds:
670+
671+
1. `DomainDecision` is the pure apply/reject/no-change judgment over an explicit
672+
coordination snapshot and command.
673+
2. Authority execution and its result own locking, revalidation, committing the
674+
decision, and eventually the durable semantic receipt.
675+
3. The provider result reports storage observations such as
676+
`loaded | missing | conflict | unavailable | failed` and an opaque provider
677+
generation; it is not a domain decision or a semantic receipt.
678+
679+
Stage 1 Part 2 does not claim durable semantic receipts or A/B/A replay. Those
680+
require the Stage 2 aggregate and provider shadow. That aggregate must treat
681+
`handoff_mode` as a real, revision-covered decision input. Its provider
682+
contract must never collapse `missing` into `unavailable` or `failed`.
683+
`provider_generation`, `authority_revision`, and `lease_epoch` remain three
684+
independent version domains. Likewise, a restore may preserve frozen bytes and
685+
lineage without granting current authority: promoting restored state to the
686+
live authority head requires an explicit lineage and binding fence.
687+
688+
The file-backed provider shadow is Stage 2. It has not started in this slice.
689+
658690
Durable completion continuation read-back
659691
(`durable_completion.py`: `read_persisted_todo_record` /
660692
`project_durable_completion_outcome`) is a provider read point: it re-reads

‎docs/architecture/rfcs/shared-goal-authority-state-provider-v0.zh-CN.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,35 @@ gate/dependency ref、claim/lease field 与按 privacy class 标注的 opaque po
565565
history、quota、scheduler 或 evidence 的通用存储抽象,这些账继续遵守第 3 节的 owner
566566
边界。
567567

568+
#### Stage 1 Part 2 边界
569+
570+
这一切片只做行为保持的抽取:把现有 writer 已经执行的 todo lifecycle、task-lease
571+
lifecycle 与 `handoff_mode` 规则收敛进纯决策 core。Markdown goal state 与
572+
task-lease 文件仍是 canonical。此次抽取不会为目前没有 revision publisher 的 todo、
573+
authorization、dependency 或 gate 域凭空制造 revision;也不会把今天相互分开的
574+
claim 与 lease verb 偷换成上文的 atomic `claim_work`。后者属于未来的 shared
575+
aggregate。
576+
577+
后续 provider 工作必须始终分开三层:
578+
579+
1. `DomainDecision` 只根据显式 coordination snapshot 与 command,纯函数式地给出
580+
apply / reject / no-change 判断。
581+
2. Authority execution 及其 result 负责加锁、重验、提交该判断,并最终持有 durable
582+
semantic receipt。
583+
3. Provider result 只报告 `loaded | missing | conflict | unavailable | failed` 等存储
584+
observation 与 opaque provider generation;它既不是领域判断,也不是 semantic
585+
receipt。
586+
587+
Stage 1 Part 2 不声称已经提供 durable semantic receipt 或 A/B/A replay;它们需要
588+
Stage 2 的 aggregate 与 provider shadow。该 aggregate 必须把 `handoff_mode` 当作
589+
真实且由 revision 覆盖的决策输入。Provider 合同绝不能把 `missing` 折叠成
590+
`unavailable` 或 `failed`。`provider_generation`、`authority_revision` 与
591+
`lease_epoch` 始终是三个独立版本域。同样,restore 可以保存 frozen bytes 与
592+
lineage,却不会因此获得当前权威;把恢复状态晋升为 live authority head,必须经过
593+
显式的 lineage 与 binding fence。
594+
595+
File-backed provider shadow 属于 Stage 2;这一切片尚未开始它。
596+
568597
完成续接(continuation)的持久化读回
569598
(`durable_completion.py`:`read_persisted_todo_record` /
570599
`project_durable_completion_outcome`)是一个 provider read point:它在完成写入之后、
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Provider-neutral coordination domain rules."""

0 commit comments

Comments
 (0)