状态:Completed
前置阶段:阶段 3
目标版本:0.5.0(Schema 5)· 完成日期:2026-08-31
架构依据:§10 Note、§11 Task 与前瞻记忆、§12 CognitiveEvent、§17 Schedule/Tick、§36 阶段 4、ADR-0012
交付低成本捕获、正式计划、前瞻触发和宿主投递闭环。阶段结束时,系统能区分“记录事项”“计划行动”“提醒已送达”和“外部效果已完成”,并在重复投递或宿主切换下保持正确。
- Note 是独立 Canonical 对象,
review_after不是删除时间,Pin/承诺/活动 Task 来源不得自动删除。 - 对话提取的 Task 默认是
proposed;只有显式工具、确定性策略或管理员能激活。 - Task/Step 完成需要独立状态转换;外部效果要求实际成功 Observation/Evidence。
- CognitiveEvent 采用 At-least-once;ACK 只表示宿主承担处理责任,不表示 Task 完成。
- Trigger 只允许声明式语法和操作符,禁止任意代码、脚本或隐式工具执行。
| 需求 ID | 基线要求 | 工作包 | 验证门禁 | 结果 |
|---|---|---|---|---|
| P4-NOTE-01 | Note 独立生命周期、复查、保留与晋升 | 4.1 | 状态机、保留、Schedule 与 Promotion 测试 | 通过(见退出门禁 1) |
| P4-TASK-01 | Task/Step Revision、Evidence、状态转换与依赖 | 4.2 | 性质、并发、环检测和 Evidence 测试 | 通过(见退出门禁 2) |
| P4-TRIGGER-01 | 受限 Trigger、时区、Occurrence 幂等与 Misfire | 4.3 | DST、Catch-up、重复 Tick 与重启测试 | 通过(见退出门禁 3、6) |
| P4-EVENT-01 | CognitiveEvent At-least-once、ACK、重投与过期 | 4.4 | Holder 切换、重复 ACK、过期和摘要测试 | 通过(见退出门禁 4) |
| P4-SAFETY-01 | ACK/投递/失败不得伪造 Task 完成或外部效果 | 4.2–4.4 | 端到端负向契约和审计测试 | 通过(见退出门禁 5) |
domain/note.py:§10.2 状态机(inbox/pinned/snoozed/archived/promoted/tombstoned;promoted/tombstoned 终态)、内容与分值校验、note_content_hash(重复关联哈希,非删除标准)、extended_review_after。storage/plans.py::NoteRepository+application/notes.py::NoteService:创建/更新/归档/晋升全部走 Expected Revision CAS + 幂等键,同事务写 Revision、Pointer、Audit、Watermark、note.changedOutbox。- 复查扫描(
note.reviewhandler):唤醒到期 snooze(唤醒即执行被推迟的复查:重复关联 + 后续整理同遍完成)、content_hash 重复关联(resource_link,不删除)、follow_up/promise 一次性物化 proposed Task(幂等:已晋升/已关联不再创建)、未解决 Note 前移 review_after。无任何删除路径。 - Promotion seam:
task真实物化(proposed Task +promoted_tolink + id 回填);claim/episode只记录类型,id 留空(Phase 5 属主)。
domain/task.py:Task 7 态状态机(proposed 只能显式激活或取消;completed/cancelled 只能归档;archived 终态);Step 8 态(pending/ready 为派生态,手动 →ready 被拒);may_activate激活特权;would_create_cycleDFS 环检测;compute_step_status双向派生;EVIDENCE_RESOURCE_TYPES = {observation}(三轮收敛:artifact 结构性拒绝直至 Phase 5 canonical 仓储与其 validator 存在)+ 声明式 condition_spec 白名单(9 操作符,缺 comparand 拒绝)。application/tasks.py::TaskService:create/patch/transition/steps/dependencies/triggers;激活特权在写事务内校验(access_denied);expected_effect Step 完成必须引用 committed Observation(partial 拒绝);Task 完成要求全部 Step 终态;同 Task 依赖 + 环稳定task_dependency_cycle;完成/跳过 Step 确定性重算后继 readiness;Note 晋升物化 proposed Task。- 并发仲裁(ADR-0012 §2):相同并发请求落败方(status 已是目标且 revision 落后)得到
revision_mismatch。
- 五种 kind 全实现:at_time / recurrence(复用 ADR-0009 受限日程语法 + IANA 时区 + DST policy)/ observation_kind / state_condition / task_transition;spec 白名单外一律
invalid_request。 - Occurrence 身份:
UNIQUE(trigger_id, trigger_revision, scheduled_at_us, occurrence_key)——重复扫描/重启/时钟回拨坍缩同一行;spec revision(含启停)变更使身份分叉。调度位置(next_fire_at/last_scan)NULL-aware CAS 推进,不写 spec revision。 - 扫描(
task.trigger_scanhandler):misfire/catch-up 复用plan_catch_up(超窗/超限记skipped+ reason,不静默丢弃);每次 Occurrence 与其 CognitiveEvent 同事务原子创建;cognitive_event.changed指针检查随投递写入。
- 五态生命周期 + 完整投递 revision 历史(attempts/last_delivery/lease id/epoch/ack_id)。
- 拉取:pending→delivered(lease 戳记 + attempts++);未到期/已过期/终态不投递;无活动 Holder 保持 pending。ACK 仅 delivered→acknowledged,任意幂等键重放返回首次 ack_id,revision 链不增长。
- Fence 重投:delivered 且未 ACK、记录的 lease 不再授权(epoch 落后/非活跃)→ 回 pending,向新 Holder 重投同一 event id;无 lease 投递不触发 fence(安全网是过期 horizon)。
- 过期:horizon 或尝试上限 → expired;单次清扫超阈值折叠为
summary.expired_events(计数 + 有界 id 列表 + links)。取消为终态。 - Recall 集成:
tasks路由为最高优先级结构化信号(category priority 0,due 任务 + rehydrate 终检);pending_event_ids只广播 id(≤50),正文留在事件端点授权之后。
migrations/0005_phase4_notes_tasks_events.sql(online_safe=true,lock_ms=200,min_app=0.5.0,recovery=none;SHA-25632ecc6f37f32b27443d03eb33c5365c4a0a9895b42c7df24fad6aa4a5a46f9e2),13 张 STRICT 表;0001–0004 与 HEADb4587b1逐字节一致。- Schema 4→5 在线升级(真实 Phase 3 数据升级测试通过);runtime 兼容窗口 [4,5];空库安装 =5。
- 备份恢复不变量扩展:六个新聚合指针解析、occurrence→trigger/event 引用、acknowledged 必有 ack_id、terminal 事件不残留 lease;Phase 1–3 备份路径保留。
- 契约 add-only:contract 1.2.0→1.3.0、schema 4→5、package 0.5.0;新增
notes.v1、tasks.v1、cognitive-events.v1capability;13 条新路径(GET/POST /v1/notes、PATCH/:archive/:promote、GET/POST /v1/tasks、PATCH/:transition、steps、steps/:transition、dependencies、triggers、GET /v1/cognitive-events、:ack);错误码新增task_dependency_cycle;fixtures 35→52;OpenAPI 3.1 + 14 份独立 JSON Schema + mock server + 双 SDK(Python 12 方法/TS 12 方法,lockfile 更新)同步。 - 回退(ADR-0012 迁移影响):先停用
note.review/task.trigger_scan与事件领取,保留 Pending Event/Tick/Occurrence Ledger,用兼容二进制或备份恢复;不把 Delivered/ACK 反推为完成态。
- 状态机与 DAG 性质:Note/Task/Step/CognitiveEvent 状态机与 Dependency 无环/ready 派生各 200 个固定种子序列(
tests/unit/test_phase4_domain.py,3614 个参数化用例全绿)。 - 50 并发相同 Expected Revision:
test_fifty_threads_same_expected_revision_one_winner实测 ok=1、mismatch=49(稳定码)、revision 行=2、task.active 审计=1、transition outbox=1、watermark 恰好 +1。 - 同一 Trigger Revision/计划时刻重复 100 次:
test_recurrence_scans_are_idempotent_hundred_times实测 2 个到期时刻 → 恰好 2 个 Occurrence + 2 个逻辑 CognitiveEvent,100 轮扫描零新增。 - 同一 Event 重复投递/ACK 100 次:
test_ack_is_idempotent_hundred_times实测同一 ack_id、恰 3 个 revision(created→delivered→acknowledged)、attempts=1。 - 时间矩阵:UTC、Europe/Berlin、America/New_York、Asia/Tokyo(+ 澳洲半时区)覆盖 DST 缺失(skip/postpone)、重复(first/second)、前跳、回拨(
test_clock_back_slew_does_not_duplicate)、休眠(test_sleep_then_catch_up_bounded:10 秒沉睡 → 有界 3 个 enqueued + 显式 skipped)与重启 catch-up(test_restart_recovers_from_persisted_marker)。 - 20 次 Holder fence 场景:
test_twenty_fence_scenarios_redeliver_same_id实测 20 轮抢占式 fence 全部重投同一 event id,最终恰 20 个事件、零重复。 - 负向端到端:delivered/acked/expired/投递失败四场景下 Task/Step 状态与证据引用零变化;CognitiveEvent 作为完成证据被结构性拒绝。
- 故障注入:新增 9 个边界(task_transition pre_revision/pre_pointer/pre_commit/post_commit、trigger_scan pre_occurrence/pre_commit/post_commit、event_ack pre_commit/post_commit)× 20 = 180 次真 SIGKILL,恢复后
verify_database_invariants零违例且重放收敛。
- Note Pin/Snooze/Review/Promotion/Forget 状态机和保留规则测试通过。
(tests/integration/test_notes.py15 例:全状态机走查、非法迁移稳定码、复查唤醒/重复关联/一次性晋升/复查延展、pinned 保留、tombstone 隐藏) - Task/Step 非法转换、Expected Revision 竞争和 Dependency 环被稳定拒绝。
(tests/integration/test_tasks.py16 例(含跨租户/Agent/跨空间证据终检与 artifact 结构性拒绝)+test_phase4_domain.py状态机/DAG 200 种子;50 并发 CAS 门禁) - 重复 Tick/Occurrence 只生成一个逻辑 CognitiveEvent。
(test_recurrence_scans_are_idempotent_hundred_times、test_at_time_fires_once_then_never_again、test_clock_back_slew_does_not_duplicate、test_restart_recovers_from_persisted_marker) - Event 重投和重复 ACK 幂等,ACK、Delivered 均不会推进 Task/Step 完成。
(tests/integration/test_events.py30 例:100×ACK、20×fence 同 id 重投、清扫路径 fence 重投、可配置尝试上限、pull 信封/lease 终检(SQL 内信封、epoch 必携、时间性过期 lease)、先清扫后投递、列表状态覆盖、ACK 持有者验证(含 lease 存活)、四场景负向完成门禁、事件证据拒绝、摘要 scope 分组、逻辑死亡行不饿死尾部、pull 返回推进后 current) - 发送或工具执行失败不会产生完成 Evidence;成功 Observation 后仍需显式转换。
(test_completion_of_expected_effect_step_requires_committed_evidence:无证据/partial Observation 拒绝,committed Observation 后仍需显式 complete) - 时区、DST、Catch-up 和过期 Policy 测试通过。
(tests/integration/test_triggers.py34 例(含TestAuditRegressions12 例:DST 策略、数字 comparand、积压收敛、批次公平、跨作用域终检、at_time 退休、观察/被观察聚合空间终检、step tombstone、注入时钟与 TTL)+TestDstCatchUpMatrix四时区矩阵;过期/摘要合并/取消见test_events.py) - Migration/Job 兼容/回退方案、需求追踪和交付证据已完成评审。
(tests/integration/test_migrations_phase4.py19 例:0001–0004 字节不变、Phase 3 数据 4→5、空库=5、七类伪造指针/引用拒绝、备份三轮往返;ADR-0012;验证报告)
- 代码/变更:Phase 4 实现提交(工作区待人工复核)。核心新增:
domain/{note,task,event}.py、storage/plans.py(Note/Task/Trigger/Occurrence/Event 五仓储 + 指针 CAS + 调度位置 CAS)、application/{notes,tasks,events,write_support}.py、recall tasks 路由 +pending_event_ids、jobs/handlers.pyPhase 4 handlers +phase4_handlers;扩展storage/uow.py、application/ports.py、storage/backup.py(Phase 4 不变量)、storage/runtime.py(窗口 [4,5])、domain/jobs.py(5 个启用 kind)、契约生成器/mock server/双 SDK。 - ADR:ADR-0012(Note 复查语义与 seam、激活特权与 Evidence 类型集、并发仲裁规则、Occurrence 身份与调度位置分离、fence/过期/摘要语义、tasks 路由与 pending_event_ids 边界、job kind 推进、泄漏纪律)。
- Schema/Migration:
migrations/0005_phase4_notes_tasks_events.sql(SHA-25632ecc6f37f32b27443d03eb33c5365c4a0a9895b42c7df24fad6aa4a5a46f9e2),13 张 STRICT 表;Schema 4→5 在线升级;窗口 [4,5];0001–0004 与 HEADb4587b1逐字节一致。 - 测试/性能报告:phase-04 验证报告(
make ci全绿——初版 4351 passed / 85.80%,一轮 4366 / 85.87%,二轮 4377 / 85.92%,三轮审核修订后复跑 4414 passed / 85.99%,四轮审核修订后复跑 4418 passed / 86.05%,五轮审核修订后复跑 4422 passed / 86.10%;量化门禁实测、契约与泄漏扫描证据、审核修订 §8/§8.1/§8.2/§8.3/§8.4、已知限制)。 - 审核修订:2026-09-01 人工审核(2 P0 / 5 P1 / 3 P2)十项全部核实并修复——证据/拉取的按 ID 作用域终检、fence 候选独立于过期候选、DST 策略委托、有序操作符合法输入、扫描游标收敛与批次公平、一次性 at_time 退休、最小请求面一致;语义并入 ADR-0012 §9,回归测试见验证报告 §8。同日二轮审核(3 P0 / 5 P1 / 1 P2)九项全部核实并修复——证据与条件触发器的完整 scope_allows 终检(越界观察记 ledger)、lease epoch 必携与 expires_us 检查、时间性过期即 fence、pull 先清扫后投递、空间信封下沉 SQL、列表信封与状态参数化、ACK 持有者验证、触发事件时钟/TTL 注入;语义并入 ADR-0012 §10,回归测试见验证报告 §8.1。同日三轮审核(4 P0 / 3 P1)七项全部核实并修复——证据类型收敛为 {observation}(artifact 结构性拒绝直至 canonical 仓储存在)、Required 在线门禁接入全部 13 个 Phase 4 应用平面写(当轮实现曾把 lease proof 纳入幂等指纹,已由四轮 §12 反转;维护平面不设闸)、过期摘要按完整 scope 分组继承(禁止 agent 级提权与跨组拼接)、recall pending_event_ids 服从请求 scope(SQL 内 LIMIT 前过滤)、ACK 持有者存活验证、pending 有效期/tombstone 下沉 SQL、pull 返回推进后 current;契约/双 SDK/mock server/fixture 同步承载 lease proof。语义并入 ADR-0012 §11,回归测试见验证报告 §8.2(含
test_phase4_surface_gate.py29 例模式矩阵)。同日四轮审核(2 P0 / 2 P1 / 2 P2)六项全部核实并修复——proof 绑定持有者身份(check_online具名调用者必须是记录持有者,current()外借的 proof 在写/pull/ACK 三路全部失效)、门禁移到幂等缓存之前且 proof 移出指纹(required 下含缓存回放的每次成功响应都持活 lease,lease 轮换后的合法重试回放而非idempotency_key_reused)、pull proof 按 off/advisory/required 模式矩阵处理(off 忽略无效 proof、advisory 警告不拒)、Pythonack_cognitive_event与 TS 四个写方法的 lease proof 透传(两侧以实际请求体断言)、advisory ACK warning 入审计、三份文档残留的{observation, artifact}声明统一收敛;语义并入 ADR-0012 §12,回归测试见验证报告 §8.3。同日五轮审核(2 P0 / 1 P1 / 1 P2)修复 Holder 在 Observation 的匿名绕过、缓存预检后的抢占窗口、Create 授权顺序与文档不实声明,并把 Observe 对齐双阶段门禁与 proof 非指纹语义;语义并入 ADR-0012 §13,回归测试见验证报告 §8.4。 - 已知限制:见验证报告"已知限制"节——condition 类触发的扫描粒度为每 agent 有界批(跨 tick 收敛)、state_condition 按值对象
value键求值(有序比较为数字语义)、无 FastAPI 传输层(沿用应用层契约 + mock server 模式)、tasks 路由需显式注入服务;§25.3 的全应用平面覆盖仍需后续跨阶段工作补齐 Phase 3 Focus 与 Phase 6 Recall 请求面。
- 不执行 Task 中的外部动作,不保存可执行脚本或任意条件代码。
- 不支持跨 Task Dependency。
- 不让后台模型直接创建 Active Task 或高权威 Claim。
Phase 5 可以使用 Note/Task Promotion seam(claim/episode 目标类型 + 待回填 id + resource_link/审计事件)和 CognitiveEvent Evidence 语义(事件不是证据,committed Observation 才是);Phase 6 可以在 tasks 路由与 pending_event_ids 之上增加路由而不重定义既有语义;Phase 11/12 可以依赖稳定的事件拉取/ACK 语义。