Task V3 Implementation Audit 与修复路线
状态说明(2026-07-23):本文是 2026-07-17 的 point-in-time technical snapshot,不是当前实施授权。当前路线和术语以 Task V2 → Task V2+ → Task V3 工程审计与实施基线 为准。
Source-of-truth order:live code/schema/tests → 当前批准的 engineering baseline → design proposal → PR/issue comments。Comments 只能提示调查方向,不能证明行为已经实现。
本文记录的是 point-in-time implementation audit。Task V3 Target Design Proposal 和 Task V3 高层设计评估 都是待评估输入,不覆盖 Task V2 当前产品行为。
2026-07-21 状态更新:§1–§2 的"现状"描述是 2026-07-17 审计快照(
3ea71d82)。callytics-infrastructuremain 此后已前进 19 个 commit(至d7daee1c,含 #1489/#1494/#1530/#1560/#1565)。已对d7daee1c逐条验证的变化:
- Target production seams(SMS/Call/VoiceMail consumer)已存在于 source,且
lib/config/environments.ts中全部taskV3*Enabledchecked-in defaults 为false(21 处,0 处 true)——§1 "production runtime 尚未调用 engine" 仅对代码中的legacylane 仍成立。- B4 已修复:
nextActionText已进入 engine snapshot/store(in-memory-store.ts、neon-store.ts)。- Store-scope 查询已修复:
queryCustomerHistory(phone, franchiseId, storeId)强制 server-resolvedstoreId;Contact Profile 查询强制 authorizedstoreId。- Gate A 仍未通过:
TASK_V3_GATE_A_DESIGN_REVIEW.md记录Human-ratified fixtures = 0——§3–§4 的 harness/eval 规则仍然有效,不受快照过期影响。其余 blocker(B2/B3/B5–B9)的逐条现状未在本次更新中重新验证,引用前须对 live code 复核。V3 proposal 当时记录的 implementation snapshot 见 Task V3 Target Design Proposal §0.1,但它不能替代新的 live-code audit。
复核命令:
git log --oneline 3ea71d82..d7daee1c | wc -l(19);git grep -c 'taskV3.*Enabled: false' d7daee1c -- lib/config/environments.ts(21)。
1. Current state snapshot
审计基线:callytics-infrastructure@3ea71d82b779c4575610e29ea10dbdccad5116a5,包含已合并的 PR #1493。
当前状态不是 production Task V3:
- 已有 Policy Catalog、纯 TypeScript Router/Guard/InMemory store 和 offline harness。
- registry 当前只注册
lead_conversion.v1。 - schema 已 expand 出 V3 columns/tables,其中
tasks.next_action_text已存在。 - production runtime 尚未调用
routeTaskEvidence、guardTaskProposal或InMemoryTaskStore。 - production 写路径仍由现有
task-orchestrator.ts/applyTaskAction负责。 - 当前 main 的 focused tests 为 Policy/Engine
113 pass、harness74 pass;它们证明已覆盖 contract 的 mechanics,不证明下面的遗漏不存在。
可复核命令:
2. Production wiring 前 blocker ledger
B1. Contact/store identity 必须来自 server context
现状:create proposal 可携带 model-provided contactPhone;Guard 没有 authoritative contact 参数。Router 也默认 caller 已经传入正确 store/contact 的 open tasks。
风险:同店合法 evidence 可以被绑定到错误 Contact;错误 caller scope 可能让 Router reuse/bind 另一 Contact 或另一门店 Task。
目标设计:
- Guard input 明确接收 authenticated/server-resolved
storeId + contactPhone。 - create payload 中的 phone 仅作 display/audit,必须与 authoritative phone 完全一致;后续 model schema 删除该字段。
- Router 对每个 candidate task 断言
task.storeId === evidence.storeId且task.contactPhone === authoritativeContactPhone,不满足时返回 typed reject,不能静默过滤。 - 每条 production command 在 SQL transaction 内再次校验 store scope。
测试:arbitrary-phone create、cross-contact reuse、cross-store unique-task binding 全部 fail closed 且留 audit。
B2. Evidence 必须绑定到具体 claim
现状:resolved evidence 只有泛化的 supports.completedFact 与 evidence-level verification。Guard 分别对所有 refs 做 OR,因此一条 ref 的 verification 和另一条无关 completed fact 可以拼成通过条件。
风险:booking evidence 可以被误用来证明 conversion;两条各自不充分的 evidence 可以组成 “split proof”。
目标设计:server resolver 产生 typed claims:
Guard 必须从同一 ref 或显式允许的 evidence chain 找到与 command 完全匹配的 claim,并使用该 supporting ref 的 verification/fact time。没有 matching claim 时 reject 或要求 staff input;不能退回泛化 completedFact=true。
需要进一步设计:production evidence resolver 怎样从现有 structured call/SMS/staff facts 生成 claim。Regex 只能用于 candidate discovery,不能成为 authorization-grade fact。
B3. DNC 必须在 create 与执行时 fail safe
现状:Guard 只验证 compliance_stop close,没有阻止 DNC Contact 的 auto-create。Policy executable subset 也没有 dncBehavior。
目标设计:
- Policy 表达
close / block_outbound / keep_open_for_review。 - DNC active 时禁止生成或执行 outbound Next Action。
- create/approve/execute 都重新检查最新 DNC;旧 proposal 不能绕过。
- 对无法安全创建的 proposal 留 reject/audit,不静默丢失。
- DNC 设置、清除 future outbound plan、处理 open Tasks 必须处于一个 transaction。
B4. Next Action 必须进入 aggregate
现状:model create payload 有 nextActionText,DB schema 也有 next_action_text,但 Engine create input/snapshot/event/store 没有保存它。
目标设计:
- create 时把 payload Next Action 或 Policy initial template 写入 snapshot/event。
- 增加
changeNextActionorchestrator command 与task.next_action_changedevent。 - Next Action text/time/reason 一起参与 aggregate version、idempotency 和 Suggestion adoption。
- 读 projection 不再把第一条 active AI suggestion 冒充 adopted Next Action。
B5. Suggestion adoption 必须 atomic 且 fail closed
现状:无效、wrong-task 或非 active sourceSuggestionId 会被静默跳过,但 mutation 已成功。
目标设计:mutation 前验证 Suggestion exists、same task、active、版本/expiry 合法;任何失败都不改变 Task、Suggestion 或 events。成功时 mutation + task.suggestion_decided(accepted) + supersede remaining actives 同 transaction。
B6. Business fact time 必须来自 supporting evidence
现状:progress executor 使用 run time;generic earliest-completed helper 也不能判断最早的事实是否支持当前 progress/outcome。
目标设计:matching claim 携带或指向 authority-derived factOccurredAt;unknown 保持 null,不使用 run/closed time 填充。Invalid timestamp 在 resolver boundary fail/report,而不是静默改变 business history。
B7. request_human_review 必须拆成两个 typed concept
现状:Reasoner final output 只有 disposition + proposals;driver 不读取 disposition,空 proposals 最终被写成 no_op。
目标设计:
- 已知具体 command 但没有 AI authority:proposal → Guard →
needs_staff_confirmation。 - 无法形成具体 command,且员工能补关键事实:
staff_input_required。 - 工程错误、model timeout、hallucinated/cross-store evidence:retry/reject/observability,不打扰员工。
- 不新增 Task state 或 generic approve command。
B8. Dedupe subjectKey 必须显式支持或显式拒绝
现状:Policy type 允许 subjectKey,deriveDedupeKey() 只实现 contact phone/task kind。
目标设计:dedupe input 增加 server-derived subjectKey;Policy 要求但 resolver 未提供时 typed fail closed。当前 lead policy 不受影响;未来 referral 等 kind 不能靠 model 自报 subject。
B9. Production adapter 必须复用现有 mutation authority
不能另建第二套 production Orchestrator。V3 verdict 应翻译到或扩展现有 applyTaskAction transaction,并复用其 store boundary、DNC、idempotency、Contact/Timeline audit。新 engine 负责 proposal/authority contract,不获得平行数据库写权。
3. 为什么 #1489 不是可信 Gate
3.1 当前数字说明什么
当前 provisional report 的 aggregate create/close exact match 是 56.9%。分 slice 后:
- expected close:
2/22 = 9.1% - no expected close:
27/29 = 93.1%
它说明 close journey 有严重问题,但不能被解释为最终 production accuracy,因为 evaluator 还存在结构性偏差。
3.2 Harness 必修项
staff_input_required必须保留、单独计数,不能变成no_op。- Fast Lane 只有真实产生 mutation/event 后才能记
executed=true。 applyErrors必须使 case/Gate fail。- 所有额外 decision 都进入评分;不能只处罚 create/progress/close 子集而忽略错误 Activity/reuse。
- MVP-supported corpus 与 future/unsupported task kinds 分开报告。
- SMS 按 settled-window/high-water/lease 重放,不能每条 message 都假装一次独立 production run。
- 两条 lane 使用可比 temporal contract;无法公平比较时只报告各自绝对质量,不宣称谁更优。
- 除相对 Task V2 指标外,必须有绝对 create、close、DNC、scope、staff-burden thresholds。
- Network/schema/model errors 进入固定 error policy;不能通过缩小 denominator 提高分数。
3.3 Eval integrity:禁止为了分数作弊
以下规则是 Gate 的硬约束:
- Regex 不得生成最终 ground truth 或 authorization-grade business claim。
- 不得从
expected[]反推 evidence claims、Reasoner output 或 Guard trust。 - 不能为已知 case、手机号、fixture id 或固定短语 hardcode答案。
- corpus、labels、criteria、scoring 在 run 前冻结;看到成绩后不能删难题、改分母或降低阈值。
- 不用 majority vote 掩盖 first-run instability;可以另报 stability,但 first-run 仍保留。
- 不把 extra decision、staff input、apply failure 或 unsupported kind 隐藏为
no_op。 - 不以“比 Task V2 高”代替绝对质量;例如 close
2/22必须 fail。 - Prompt/Policy/Guard 迭代在 development corpus 上完成,最终用未参与调参的 holdout corpus 验证。
- 所有失败 case 保留并进入 regression set,不能在下一轮消失。
- 宁可分数真实下降,也不允许 evaluator 与 implementation 共同迎合已知答案。
当前 fixture-builder.ts 中的 completed-fact regex 只能保留为 corpus-review candidate 标记,不能再直接写入 Guard 会信任的最终 supports。
4. Eval pyramid:不同测试回答不同问题
旧 Golden 的约 93% 属于 synthetic snapshot prompt regression;#1489 属于 longitudinal replay baseline。两者 corpus、trigger cadence、state、taxonomy 和 scoring 不同,不能用百分比直接相减。正确策略是保留四层,而不是选一个数字当“准确率”。
5. 实施 waves 与 exit criteria
Wave A:Domain safety contract
实现 B1–B8,并补 adversarial/property tests。Exit:任意 model payload 都无法绕过 authoritative contact/store、DNC、claim binding、Suggestion atomicity 或 fact time。
Wave B:Harness truthfulness
修正 disposition、Fast Lane execution、apply failure、full scoring、MVP/future split、SMS cadence 和 absolute thresholds。Exit:每个 decision、reject、staff input、apply error 都能从 report 追到 evidence/Policy/Guard/command。
Wave C:重新冻结并运行 Gate
人工 ratify labels;建立 development/holdout split;从 current head 完整 rerun。Exit:绝对 safety/quality thresholds 通过,且 results 不依赖 post-hoc corpus/threshold 变化。
Wave D:Production shadow adapter
基于现有 applyTaskAction 实现 DB/evidence adapter;先只写 run/proposal/audit,mutation authority 关闭。Exit:test/store canary 中 reconciliation 无跨店、无 silent drop、无非原子 adoption。
Wave E:Read projection 与 store rollout
接 typed API/Workbench,先 read projection,再按 store 开 mutation authority,最后 reporting。Notification、RingOut 产品化和 Scripts customization 仍不在本轮 scope。
6. 需要人工参与的事项
工程修复可以立即进行;下面几项不能由代码替用户决定:
- ratify longitudinal fixture 的 expected decisions 与 evidence claims。
- 选定 production Gate 的绝对 close/create/staff-burden thresholds。
- 决定 email-only/no-phone Contact 的 canonical identity。
- 确认
staff_input_required的前端 placement,但这不改变其 domain contract。
这些事项未完成时,系统可以继续开发和 shadow,但不能宣称 Gate 已清或打开 production authority。