AIDAWORK / SEQUENCE

tip 已有 vs #255 · #257(未实现)

独立图页 ↗
机制说明(SoT)图是辅读 · 结论以说明与证据为准

主图仅画服务端连接器写(确认卡 → ActionProposal → 连接器派发);勿把「执行授权」(VerifiedWriteAuthority)与「连接器凭证」(ConnectorCredentialProvider)混为一谈。LF / Plugin / Router 对照见下文分节,不在主图展开。 图:write-authority.sequence.json(主路径:授权 → 写前声明 → 解析连接器凭证 → CAS 消费 → 派发 → 回执 / 读回 → 结案;缺凭证走通用失败)。关联:state-authority(孤儿 Run)、local-file-v5(LF 账本)、`vertical-plugi…

本页可直接往下读完整机制说明,不需要「演示 / 播放故事」。术语不熟先看 术语表。

先读机制说明,结论以说明与证据为准 · 基于固定代码版本核验 · 部署状态另行确认

机制说明(全文)

写权限链:授权 · 写前声明 · 一次性消费 · 读回 · 孤儿 Run

主图仅画服务端连接器写(确认卡 → ActionProposal → 连接器派发);勿把「执行授权」(VerifiedWriteAuthority)与「连接器凭证」(ConnectorCredentialProvider)混为一谈。LF / Plugin / Router 对照见下文分节,不在主图展开。 图:write-authority.sequence.json(主路径:授权 → 写前声明 → 解析连接器凭证 → CAS 消费 → 派发 → 回执 / 读回 → 结案;缺凭证走通用失败)。关联:state-authority(孤儿 Run)、local-file-v5(LF 账本)、vertical-plugin-mount(CallJournal)、trust-boundaries。 钉点:aida-agent 7f2e519936b5 · aida-desktop 4346d79eb364。背景 issue:ai/aida-agent #255(写前声明总览)、#257(授权闸与凭证闸分离),两者在 2026-10-09 读取时仍为 opened / status::inbox。 先读本机制说明,结论以 NOTES + evidence 为准。

读法:先分「tip 已有」与「目标 / 缺口」

本笔记只记录钉点源码里已经存在的机制,并单列 #255 / #257 提出但尚未实现的目标。缺口不得画成已实现。

tip 已有 ①:服务端连接器写(确认卡 → ActionProposal)— 主图范围

  1. 授权闸(对话轮内):ToolCallGate.computeDecision 对写工具依次做 read-only / capability 钉住 / 候选人身份 / 风险策略 reject / confirm 判定;最后 checkCrossTurn:聊天轮次永不授权业务效应,唯一可执行路径是 Kernel 结算后的 Outbox continuation。例外只有三类委托闸:desktop 域(desktop approval gate)、Plugin 域(Main 持有授权与 CallJournal)、local_file_v4(Interaction Kernel)。
  2. 授权落点:用户在确认卡上结算 → BusinessEffectCoordinator.registerAuthorization(granted,带 scopeDigest、有效期)。
  3. 写前声明(派发前提交):businessEffects.start 以 idempotencyKey = proposalId:payloadHash 的哈希创建 outcome 行 executing;同键重入返回已有行,不新建。
  4. 执行授权(≠ 连接器凭证):InteractionWriteAuthorityOwner.issue 先校验 proposal(approved、actor、payloadHash、未过期)与 Kernel 最新 accepted authority,再发出仅运行时可持有的 VerifiedWriteAuthority(DTO 冒充不了)。这是执行授权对象,不是连接器登录凭证。
  5. 执行器内顺序(主图焦点):toolExecutor.execute 内为 回执重放检查 → 解析连接器凭证(ConnectorCredentialProvider)→ 授权消费(CAS) → 派发。缺凭证 → ConnectorNotAuthorizedError → continuation 判定本次尝试没有完成授权 CAS(writeAuthorityConsumedHere 为假),proposal 仍 pending/approved 时 markFailed(unconsumedOnly) 并经 recordUnsentBusinessEffect 把 outcome 记为 failed(BUSINESS_EFFECT_NOT_DISPATCHED,不记 unknown、不补偿);仍无「已授权待补凭证」态。不是「CAS 后再发执行授权」,也不是「有执行授权就等于有连接器凭证」。
  6. 一次性消费 = CAS:执行器 toolExecutor.execute 在派发前调用 consumeVerifiedWriteAuthority → 再校验一次 → ActionProposalStore.markExecuting:UPDATE … SET status='executing' WHERE status='approved',写授权消费时传 requireActiveRun: true,同一句 UPDATE 还要求所属 Run 未 cancelled 且无 cancel_intent(钉点 7f2e519936b5,605e3f497):停止先提交则消费失败、不发送,消费先提交则停止排在其后并结算已认领的写;对 persistent-target 类工具还在 advisory lock + FOR UPDATE 下铸 persistentTargetClaimLease(执行租约)。CAS 失败 → WRITE_AUTHORITY_CONSUMED。源码注释:「Backend idempotency is deliberately not authorization」。
  7. 派发:带 idempotencyKey 调连接器;结果 recordOutcome → succeeded | failed | unknown(BUSINESS_EFFECT_TRANSITION_RULES)。
  8. effect 读回:连接器有 readback 合同时,「成功响应不足以结案」——connectorReceiptConfirmsWrite 不成立就 observeConnectorCommittedWrite 只读回查源系统;查不到 → unknown,任务进入 checking。
  9. 崩溃重入:重启后看到 proposal 已是 executing,永不再次调用,除非读回证明写已落地;否则记 unknown。reconcileUnknown 的 recheck 可回到 safe_to_retry | succeeded | failed | unknown。

确认后写入的自动重试(钉点 7f2e519936b5 收窄):只有能证明写没发出去时才自动重试,也就是全新连接上的 not_sent 连接错误(ECONNREFUSED / ENOTFOUND 等),以及没有业务报文的网关 503。502、504、超时、连接重置都可能发生在业务已经提交之后,只试一次,按结果未知处理。结果分类也跟着改:网关无报文(errorBody: none)和幂等守卫的 WRITE_OUTCOME_UNKNOWN 都保持不确定,走源回读或 unknown;IDEMPOTENCY_STORE_UNAVAILABLE 算确定没执行。证据:aida-agent · packages/agent/src/orchestrator/confirmation/lifecycle.ts L1799–1859 · isConfirmedWriteRetryableError · 7f2e519936b5;packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L1543–1574 · WRITE_OUTCOME_UNKNOWN_CODE · 7f2e519936b5

tip 已有 ②:本机文件改动(LF fs/change)

  1. Agent:change authorization Interaction 结算后,一个事务内 markGranted + suspendPendingResumeForRequest(Operation requested + request_digest 先落账)→ 才轮到 Desktop 拉取。
  2. Desktop Main LocalFileV4ChangeExecutor.execute:同 operationId 已有写记录 → 只回原回执(digest 不同 → conflict);否则 requireFresh 确认记录 → preflight → WriteRecordStore.begin(写前记录) → ConfirmationRecordStore.consume(本机原子 mutate 内置 consumedAt,已消费 → confirmation_consumed)→ 逐 action markActionStarted / markActionCompleted → 冻结回执。
  3. 无法证明未落地的 action 记 unknown,整单 outcome_unknown;Agent terminalizeRequested 以 status='requested' AND request_digest 条件落账。
  4. 读回 / 孤儿写:Desktop 启动时 recoverUnterminatedWritesAndReport → reconcileWriteFacts 物理重读(sha256 + 文件身份)把 unknown 判为 applied 或保留未知,再补交回执并 markDelivered。
  5. Agent 侧 TTL 过期回收 listExpiredRequested 只覆盖 fs/list|fs/search|fs/read,写操作不会被 Agent 自动过期。

tip 已有 ③:其它派发通道(对照用)

  • Plugin:PluginCallJournal admitted → dispatched → settled,屏障失败落 uncertain / failed,禁止重启盲重放(见 vertical-plugin-mount)。
  • ExecutionHostRouter:callId:bindingDigest singleflight;handle not_sent → possibly_sent 由 compareAndSet(expectedRevision) 认领;possibly_sent 先 reconcile 不盲重试。但钉点上 AgentRun 只为 server-read 宿主建 Router,handle store 缺省为 InMemoryExecutionHandleStore——进程重启即丢,不是持久写前声明。

tip 已有 ④:孤儿 Run

recoverExpiredLeaseByConversation(会话入口与持久化 helper 调用)在一个事务里:先排除受保护的 Run(durable local-read、Interaction 门持有的 pending_resume、post-model entry);lease 过期的顶层 Run 若仍有 action_proposals ∈ {pending, approved, executing} 或不可重放 checkpoint 挂着 pending tool / interaction → manual_recovery + RUN_ORPHANED(「存在未确认的操作结果,需要人工恢复」);其余 → failed + RUN_ORPHANED。Run 级恢复不重放写,写的结论仍由各自账本(business effect / LF Operation / Journal)决定。

授权闸 vs 凭证闸:tip 现状

  • 授权闸:ToolCallGate(轮内)+ 执行器边界的 consumeVerifiedWriteAuthority(再校验 + CAS)。
  • 凭证闸:ConnectorCredentialProvider(connectorIdForDomain → resolveStored/resolve,缺凭证 → ConnectorNotAuthorizedError → ToolExecutionError)。它在 toolExecutor.execute 里先于授权消费执行,没有独立命名的阶段。
  • 有授权、缺凭证:continuation 判定本次尝试未消费授权 → proposal 仍 pending/approved 时 markFailed(unconsumedOnly),outcome 记 failed(BUSINESS_EFFECT_NOT_DISPATCHED)后抛出;没有独立的「已授权、待补凭证」状态。

租约恢复、批次代际与 TLA+ 模型(钉点 e2adc9a3c325)

  • 租约丢失后的恢复:business_effect 的恢复从 index.ts 移入 continuation 的 settleInterruptedBusinessEffect。恢复从不写源系统:已结案的直接收口;未派发的(无 outcome / executing / failed BUSINESS_EFFECT_NOT_DISPATCHED)先尝试按未发送收口;被用户重试复活的批次归重试 owner。
  • 批次代际:批次成员 fence 与父结算都绑定所拥有的代际(batchRetryKey),陈旧恢复写不动新代际。
  • TLA+ 设计模型:specs/tla/confirmed-write(单个确认写;AtMostOnce、NoConsumeAfterCancel、UnknownOnlyIfConsumed、NoApprovedLimbo、UnsentWriteFreesConversation 等,baseline 全部 PASS,Bug*.cfg 变体证明检查会失败)与 specs/tla/confirmed-batch(确认批次)。是协议设计检查,不是代码测试;本轮没有运行 TLC,结果取自仓内 results/summary.txt。
  • 审批职责分离:sourceSeparationOfDuty 在多审批人节点上不再误拒另一位审批人——识别不了操作人时,发起人与审批人重叠只在只有单一审批人时判 violated,否则 undetermined,交平台 / 源系统规则兜底。
  • 证据:aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L625–655 · writeAuthorityConsumedHere · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L742–761 · recordUnsentBusinessEffect · 7f2e519936b5;aida-agent · packages/agent/src/session/action-proposal-store.ts L1031–1081 · requireActiveRun · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L1536–1565 · settleInterruptedBusinessEffect · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-batch.ts L198–211 · batchRetryKey · 7f2e519936b5;aida-agent · specs/tla/confirmed-write/results/summary.txt L4–16 · NoConsumeAfterCancel · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/admin-bypass-approval.ts L147–225 · sourceSeparationOfDuty · 7f2e519936b5

VMS 表单写入合同:确认时用确认人身份重读描述(钉点 e2adc9a3c325)

  • 这是 tip 已有 ① 的确认前来源复核(assertConfirmationSourceCurrent)中新增的一步,覆盖供应商建档、项目创建、岗位需求三个写工具(18af40288 / efd2255b4 / 71c5bc8c2)。
  • 准备时:表单描述决定必填字段;只有标准字段且后台认证可写(extraFieldsWritable)的才会问用户并自动填,其他必填字段在提问前阻断。确认卡记下 formDescriptorForm、formDescriptorDigest 与 formValidationVersion=2(1d07cf06a 起旧描述卡须重新准备)。
  • 确认时:提案的 tenant / user 必须是当前确认人;以确认人身份重读当前描述,摘要变了即拒绝执行(BUSINESS_REJECT),要求按当前字段重新准备。只有描述工具未挂载时,旧卡或显式 unavailable 证据才按标准路径放行。
  • 不改变 CAS 消费、写前声明与读回顺序;这一步发生在授权消费之前。
  • 证据:aida-agent · packages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts L14–21 · VMS_FORM_DESCRIPTOR_GUARDED_TOOLS · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts L29–139 · assertVmsFormDescriptorEvidenceCurrent · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/operation-confirmation-source-guard.ts L62–102 · assertVmsFormDescriptorEvidenceCurrent · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts L9–10 · VMS_FORM_VALIDATION_VERSION · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts L86–95 · extraFieldsWritable · 7f2e519936b5
  • 描述工具挂载:钉点里只有 202 增量配置脚本与在线 Skill 种子脚本把 describe_vms_form 写进 VMS Skill 工具清单,仓库里没有它们对各租户的执行记录,各租户是否挂载未核。证据:aida-agent · packages/agent/scripts/apply-202-vms-closure-config.ts L565–595 · describe_vms_form · 7f2e519936b5;aida-agent · packages/agent/scripts/lib/seed-online-skills.ts L164–167 · describe_vms_form · 7f2e519936b5
  • 未核:VMS 后端各租户描述工具是否已挂载;onboarding / offboarding / settlement 写入按设计文档不适用此合同。

目标 / 缺口(#255 / #257,tip 未实现)

  • #255 总合同缺失:四套账本(business effect outcome、LF Operation + Desktop WriteRecord、PluginCallJournal、ExecutionHandle)各自有声明 / 重放语义,没有一份「效应类型 → 声明落点 → 重放规则」总合同;本笔记的对照只是 tip 现状记录,不等于 #255 验收(逐路径重放语义审定、「刻意不做」边界未写)。
  • #255 Router 声明不持久:InMemoryExecutionHandleStore 缺省,Router 的 possibly_sent 认领不跨进程。
  • #257 两闸未分开命名:凭证解析与授权消费同处一个执行器函数,且凭证先行;缺凭证现在会确定地收口为 failed BUSINESS_EFFECT_NOT_DISPATCHED,但仍没有独立命名的凭证闸或待补凭证态。
  • #257「未过闸不入执行队列」:tip 没有显式「执行队列」概念;Outbox continuation 结算后直接执行。三类委托闸例外(desktop / plugin / local_file_v4)需要在 #257 里逐一登记为「另有闸」还是「债」。

已核实缺口(勿画成已覆盖)

2026-10-09 tip 再核(agent 61576cf06699 / desktop de6102a5a916;行号与钉点 e2adc9a3c325 / 8eecd12081db 一致)。不再留「未核实」。

  • 缺凭证后 outcome 收尾 — 钉点 e2adc9a3c325 已补上(链 #257;下面是 2026-10-12 时的缺口记录,保留作对照)
    现状:本次尝试未完成授权 CAS 时,executeConfirmedBusinessEffect 在 proposal 仍 pending/approved 时 markFailed(unconsumedOnly) 并 recordUnsentBusinessEffect(outcome → failed BUSINESS_EFFECT_NOT_DISPATCHED),outcome 不再停在 executing。仍缺的是 #257 要的独立待补凭证态。
    旧记录: businessEffects.start 先落 executing(business-effect-task-continuation.ts L1898);toolExecutor 凭证解析先于 CAS(tool-executor.ts L317–321),缺凭证 → ConnectorNotAuthorizedError → ToolExecutionError(无 errorType,故不进 isDeterministicWriteRejection L3047–3072)。2026-10-12 tip:确认后执行逻辑已抽到 business-effect-confirmed-execution.ts(executeConfirmedBusinessEffect),语义不变——非确定性失败且 proposal 仍 approved 时只 markFailed 后重抛(L538–548),不调用 recordOutcome。outcome 可停在 executing。
  • Desktop 离线 / fs/change 写回收 — 已核实:走另一条链 + Agent TTL 缺口(链 #255)
    • Desktop 本机:已覆盖 — 启动 recoverUnterminatedWritesAndReport(main.ts L3851)→ reconcileWriteFacts(write-recovery.ts L27)物理重读后补交回执(不在服务端写权限主链)。
    • Agent TTL:已核实未覆盖 fs/change — listExpiredRequested 仅 fs/list|fs/search|fs/read(local-file-operation-store.ts L227)。
    • 长期离线等待写回执的 Operation:无 Agent TTL 自动过期;Run 层或受 Interaction 保护,或 lease 过期进 manual_recovery/RUN_ORPHANED(run-store.ts L1898+;同一函数先关闭只等过期卡的 legacy 树,见 state-authority),不等于写权限链回收 Operation。

视图

  • main — 服务端连接器写主路径(压缩;缺凭证 / 缺口 / LF 不在主图展开)。
  • tip-vs-gaps — tip 已有 vs #255 / #257 未实现;含缺凭证通用失败。
  • lf-compare — 本机 fs/change 写前记录 · 消费对照(详路径仍见 local-file-v5)。
  • business-task-and-material-gate — 业务任务操作协调器(PgBusinessTaskOperationCoordinator)、Symbol 级新鲜材料准入与任务终态尾链核验。

业务任务操作协调器与新鲜材料准入(视图 business-task-and-material-gate)

当一条 Runtime Work 绑定了企业业务事项(businessTaskBinding: { taskId, attemptId })时,所有的模型调用、本机脚本/插件回执与任务结案都受到 PgBusinessTaskOperationCoordinator(operation-coordinator.ts)与 run-work-material-check.ts 的联合管控(见视图 business-task-and-material-gate):

  1. Common Control 独占写权与操作状态机(operation-coordinator.ts L152–402):
    • 凡是 runtime_protocol_version === 'runtime-work-v1' 的 Run,若外部直接调 reserve() 或 markReceiptPending() 会立即抛出 BUSINESS_TASK_COMMON_CONTROL_REQUIRED——所有状态变迁必须在 Root 锁事务内调用 reserveInTransaction → markReceiptPendingInTransaction → projectReceiptInTransaction;
    • 状态流转:dispatch_pending -> executing -> receipt_pending -> succeeded | failed | cancelled | outcome_unknown;
    • Unknown 传染阻断(L368–384, L479–498):只要任一操作落入 outcome_unknown,同一事务内立即将 business_tasks.coordination_status 与 business_task_attempts.status 雙雙置为 'unknown';此后任何新一轮模型请求在 admitWorkModelRequestInTx 中调 assertTaskModelExecutionInTransaction 时,都会因为 allowsKnownOperationsInTransaction 返回 false 而被 BUSINESS_TASK_OUTCOME_UNKNOWN 拦截!
  2. Symbol 级新鲜材料准入许可(FreshWorkMaterialPermit,run-work-material-check.ts L10–84 & run-work-control.ts L82–96):
    • 当未知操作通过补证(Supplement)恢复时,recordWorkMaterialCheckInTx 在 FOR UPDATE 下校验 work_supplement_digest === input.digest 且 check.sequence > previous.sequence(单调递增防重放);
    • 观察记录 ≠ 执行许可:代码注释明确指出 "Persisted available/ACK is an observation, not a reusable execution permit";只有当次事务中 recordWorkMaterialCheckInTx 返回 fresh: true 时,控制面才用模块私有 Symbol Symbol("fresh-original-owner-material") 构造内存级 FreshWorkMaterialPermit 传入 settleRuntimeWorkSkillReceiptInTx;
    • workMaterialContinuationConsumed 进一步校验补证结果不仅已 ACK,而且对应的 messages (role='tool') 确实写入了 originalReceipt.responseDigest 与 supplementaryConclusion.digest,且 run_checkpoints 已清空原挂起等待。
  3. 补证对账解锁与任务完成尾链核验(operation-coordinator.ts L500–565 & run-work-business-task-completion.ts L55–140):
    • projectWorkReconciliationInTransaction 将补证写入 business_task_evidence (kind='reconciliation') 并投影产物;当该任务下所有 outcome_unknown 操作均在 reconciled 集合中配平后,自动将 business_tasks.coordination_status 恢复为 'in_progress'(若 canActivate 为假则置 'needs_attention')、business_task_attempts.status 恢复为 'running';
    • 当模型最终调用 finishBusinessTask 时,createWorkBusinessTaskCompletion 在 withRuntimeWorkAttempt 租约围栏下:先核验 allowsAttemptActivationInTransaction,再 FOR UPDATE 锁住 run_checkpoints 核对 accepted_response_ref 对应的 Assistant 消息 SHA-256 与 finishBusinessTask 参数 { evidenceRefs, completionSummary } 100% 吻合,最后才允许调用 PgBusinessTaskCompletionCoordinator.prepareCompletionInTransaction 结案。

证据与范围

  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L179–198 · Kernel authorization · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L340–417 · willAwaitConfirm · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L602–626 · usesExternalApprovalGate · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L676–694 · checkCrossTurn · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/business-effect.ts L513–553 · start · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/business-effect.ts L586–626 · safe_to_retry · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/write-authority.ts L82–111 · VerifiedWriteAuthorityCapability · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/write-authority.ts L157–201 · markExecuting · 7f2e519936b5
  • aida-agent · packages/agent/src/session/action-proposal-store.ts L1031–1081 · persistentTargetClaimLease · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-executor.ts L300–304 · ConnectorNotAuthorizedError · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-executor.ts L388–440 · consumeVerifiedWriteAuthority · 7f2e519936b5
  • aida-agent · packages/agent/src/connectors/credential-provider.ts L1–12 · Credential boundary · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L2048–2076 · registerAuthorization · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L246–247 · recovering · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L461–475 · effect.status === "unknown" · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L510–524 · writeAuthorityOwner.issue · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L625–655 · writeAuthorityConsumedHere · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L1417–1435 · observeCommittedSourceWrite · 7f2e519936b5
  • aida-agent · packages/agent/src/connectors/effect-readback/index.ts L21–28 · observeConnectorCommittedWrite · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/local/local-file-change-continuation.ts L180–218 · suspendPendingResumeForRequest · 7f2e519936b5
  • aida-agent · packages/agent/src/session/local-file-operation-store.ts L217–238 · listExpiredRequested · 7f2e519936b5
  • aida-agent · packages/agent/src/execution-host/router.ts L159–191 · bindingDigest · 7f2e519936b5
  • aida-agent · packages/agent/src/execution-host/router.ts L461–480 · claimDispatch · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/run.ts L666–682 · InMemoryExecutionHandleStore · 7f2e519936b5
  • aida-agent · packages/agent/src/session/run-store.ts L1933–2014 · RUN_ORPHANED · 7f2e519936b5
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L145–176 · recovery CAS · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L494–565 · consumeAuthorization · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L302–331 · outcome_unknown · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/confirmation-record-store.ts L201–226 · consumedAt · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/write-recovery.ts L27–40 · reconcileWriteFacts · 4346d79eb364
  • aida-desktop · apps/desktop/electron/main.ts L3976–3987 · recoverUnterminatedWritesAndReport · 4346d79eb364

结论来自固定版本的静态源码阅读;实现存在、默认开关和生产启用分别判断。GitLab issue 状态读取于 2026-10-09。

机制说明

写权限链:授权 · 写前声明 · 一次性消费 · 读回 · 孤儿 Run

主图仅画服务端连接器写(确认卡 → ActionProposal → 连接器派发);勿把「执行授权」(VerifiedWriteAuthority)与「连接器凭证」(ConnectorCredentialProvider)混为一谈。LF / Plugin / Router 对照见下文分节,不在主图展开。 图:write-authority.sequence.json(主路径:授权 → 写前声明 → 解析连接器凭证 → CAS 消费 → 派发 → 回执 / 读回 → 结案;缺凭证走通用失败)。关联:state-authority(孤儿 Run)、local-file-v5(LF 账本)、vertical-plugin-mount(CallJournal)、trust-boundaries。 钉点:aida-agent 7f2e519936b5 · aida-desktop 4346d79eb364。背景 issue:ai/aida-agent #255(写前声明总览)、#257(授权闸与凭证闸分离),两者在 2026-10-09 读取时仍为 opened / status::inbox。 先读本机制说明,结论以 NOTES + evidence 为准。

读法:先分「tip 已有」与「目标 / 缺口」

本笔记只记录钉点源码里已经存在的机制,并单列 #255 / #257 提出但尚未实现的目标。缺口不得画成已实现。

tip 已有 ①:服务端连接器写(确认卡 → ActionProposal)— 主图范围

  1. 授权闸(对话轮内):ToolCallGate.computeDecision 对写工具依次做 read-only / capability 钉住 / 候选人身份 / 风险策略 reject / confirm 判定;最后 checkCrossTurn:聊天轮次永不授权业务效应,唯一可执行路径是 Kernel 结算后的 Outbox continuation。例外只有三类委托闸:desktop 域(desktop approval gate)、Plugin 域(Main 持有授权与 CallJournal)、local_file_v4(Interaction Kernel)。
  2. 授权落点:用户在确认卡上结算 → BusinessEffectCoordinator.registerAuthorization(granted,带 scopeDigest、有效期)。
  3. 写前声明(派发前提交):businessEffects.start 以 idempotencyKey = proposalId:payloadHash 的哈希创建 outcome 行 executing;同键重入返回已有行,不新建。
  4. 执行授权(≠ 连接器凭证):InteractionWriteAuthorityOwner.issue 先校验 proposal(approved、actor、payloadHash、未过期)与 Kernel 最新 accepted authority,再发出仅运行时可持有的 VerifiedWriteAuthority(DTO 冒充不了)。这是执行授权对象,不是连接器登录凭证。
  5. 执行器内顺序(主图焦点):toolExecutor.execute 内为 回执重放检查 → 解析连接器凭证(ConnectorCredentialProvider)→ 授权消费(CAS) → 派发。缺凭证 → ConnectorNotAuthorizedError → continuation 判定本次尝试没有完成授权 CAS(writeAuthorityConsumedHere 为假),proposal 仍 pending/approved 时 markFailed(unconsumedOnly) 并经 recordUnsentBusinessEffect 把 outcome 记为 failed(BUSINESS_EFFECT_NOT_DISPATCHED,不记 unknown、不补偿);仍无「已授权待补凭证」态。不是「CAS 后再发执行授权」,也不是「有执行授权就等于有连接器凭证」。
  6. 一次性消费 = CAS:执行器 toolExecutor.execute 在派发前调用 consumeVerifiedWriteAuthority → 再校验一次 → ActionProposalStore.markExecuting:UPDATE … SET status='executing' WHERE status='approved',写授权消费时传 requireActiveRun: true,同一句 UPDATE 还要求所属 Run 未 cancelled 且无 cancel_intent(钉点 7f2e519936b5,605e3f497):停止先提交则消费失败、不发送,消费先提交则停止排在其后并结算已认领的写;对 persistent-target 类工具还在 advisory lock + FOR UPDATE 下铸 persistentTargetClaimLease(执行租约)。CAS 失败 → WRITE_AUTHORITY_CONSUMED。源码注释:「Backend idempotency is deliberately not authorization」。
  7. 派发:带 idempotencyKey 调连接器;结果 recordOutcome → succeeded | failed | unknown(BUSINESS_EFFECT_TRANSITION_RULES)。
  8. effect 读回:连接器有 readback 合同时,「成功响应不足以结案」——connectorReceiptConfirmsWrite 不成立就 observeConnectorCommittedWrite 只读回查源系统;查不到 → unknown,任务进入 checking。
  9. 崩溃重入:重启后看到 proposal 已是 executing,永不再次调用,除非读回证明写已落地;否则记 unknown。reconcileUnknown 的 recheck 可回到 safe_to_retry | succeeded | failed | unknown。

确认后写入的自动重试(钉点 7f2e519936b5 收窄):只有能证明写没发出去时才自动重试,也就是全新连接上的 not_sent 连接错误(ECONNREFUSED / ENOTFOUND 等),以及没有业务报文的网关 503。502、504、超时、连接重置都可能发生在业务已经提交之后,只试一次,按结果未知处理。结果分类也跟着改:网关无报文(errorBody: none)和幂等守卫的 WRITE_OUTCOME_UNKNOWN 都保持不确定,走源回读或 unknown;IDEMPOTENCY_STORE_UNAVAILABLE 算确定没执行。证据:aida-agent · packages/agent/src/orchestrator/confirmation/lifecycle.ts L1799–1859 · isConfirmedWriteRetryableError · 7f2e519936b5;packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L1543–1574 · WRITE_OUTCOME_UNKNOWN_CODE · 7f2e519936b5

tip 已有 ②:本机文件改动(LF fs/change)

  1. Agent:change authorization Interaction 结算后,一个事务内 markGranted + suspendPendingResumeForRequest(Operation requested + request_digest 先落账)→ 才轮到 Desktop 拉取。
  2. Desktop Main LocalFileV4ChangeExecutor.execute:同 operationId 已有写记录 → 只回原回执(digest 不同 → conflict);否则 requireFresh 确认记录 → preflight → WriteRecordStore.begin(写前记录) → ConfirmationRecordStore.consume(本机原子 mutate 内置 consumedAt,已消费 → confirmation_consumed)→ 逐 action markActionStarted / markActionCompleted → 冻结回执。
  3. 无法证明未落地的 action 记 unknown,整单 outcome_unknown;Agent terminalizeRequested 以 status='requested' AND request_digest 条件落账。
  4. 读回 / 孤儿写:Desktop 启动时 recoverUnterminatedWritesAndReport → reconcileWriteFacts 物理重读(sha256 + 文件身份)把 unknown 判为 applied 或保留未知,再补交回执并 markDelivered。
  5. Agent 侧 TTL 过期回收 listExpiredRequested 只覆盖 fs/list|fs/search|fs/read,写操作不会被 Agent 自动过期。

tip 已有 ③:其它派发通道(对照用)

  • Plugin:PluginCallJournal admitted → dispatched → settled,屏障失败落 uncertain / failed,禁止重启盲重放(见 vertical-plugin-mount)。
  • ExecutionHostRouter:callId:bindingDigest singleflight;handle not_sent → possibly_sent 由 compareAndSet(expectedRevision) 认领;possibly_sent 先 reconcile 不盲重试。但钉点上 AgentRun 只为 server-read 宿主建 Router,handle store 缺省为 InMemoryExecutionHandleStore——进程重启即丢,不是持久写前声明。

tip 已有 ④:孤儿 Run

recoverExpiredLeaseByConversation(会话入口与持久化 helper 调用)在一个事务里:先排除受保护的 Run(durable local-read、Interaction 门持有的 pending_resume、post-model entry);lease 过期的顶层 Run 若仍有 action_proposals ∈ {pending, approved, executing} 或不可重放 checkpoint 挂着 pending tool / interaction → manual_recovery + RUN_ORPHANED(「存在未确认的操作结果,需要人工恢复」);其余 → failed + RUN_ORPHANED。Run 级恢复不重放写,写的结论仍由各自账本(business effect / LF Operation / Journal)决定。

授权闸 vs 凭证闸:tip 现状

  • 授权闸:ToolCallGate(轮内)+ 执行器边界的 consumeVerifiedWriteAuthority(再校验 + CAS)。
  • 凭证闸:ConnectorCredentialProvider(connectorIdForDomain → resolveStored/resolve,缺凭证 → ConnectorNotAuthorizedError → ToolExecutionError)。它在 toolExecutor.execute 里先于授权消费执行,没有独立命名的阶段。
  • 有授权、缺凭证:continuation 判定本次尝试未消费授权 → proposal 仍 pending/approved 时 markFailed(unconsumedOnly),outcome 记 failed(BUSINESS_EFFECT_NOT_DISPATCHED)后抛出;没有独立的「已授权、待补凭证」状态。

租约恢复、批次代际与 TLA+ 模型(钉点 e2adc9a3c325)

  • 租约丢失后的恢复:business_effect 的恢复从 index.ts 移入 continuation 的 settleInterruptedBusinessEffect。恢复从不写源系统:已结案的直接收口;未派发的(无 outcome / executing / failed BUSINESS_EFFECT_NOT_DISPATCHED)先尝试按未发送收口;被用户重试复活的批次归重试 owner。
  • 批次代际:批次成员 fence 与父结算都绑定所拥有的代际(batchRetryKey),陈旧恢复写不动新代际。
  • TLA+ 设计模型:specs/tla/confirmed-write(单个确认写;AtMostOnce、NoConsumeAfterCancel、UnknownOnlyIfConsumed、NoApprovedLimbo、UnsentWriteFreesConversation 等,baseline 全部 PASS,Bug*.cfg 变体证明检查会失败)与 specs/tla/confirmed-batch(确认批次)。是协议设计检查,不是代码测试;本轮没有运行 TLC,结果取自仓内 results/summary.txt。
  • 审批职责分离:sourceSeparationOfDuty 在多审批人节点上不再误拒另一位审批人——识别不了操作人时,发起人与审批人重叠只在只有单一审批人时判 violated,否则 undetermined,交平台 / 源系统规则兜底。
  • 证据:aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L625–655 · writeAuthorityConsumedHere · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L742–761 · recordUnsentBusinessEffect · 7f2e519936b5;aida-agent · packages/agent/src/session/action-proposal-store.ts L1031–1081 · requireActiveRun · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L1536–1565 · settleInterruptedBusinessEffect · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-batch.ts L198–211 · batchRetryKey · 7f2e519936b5;aida-agent · specs/tla/confirmed-write/results/summary.txt L4–16 · NoConsumeAfterCancel · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/admin-bypass-approval.ts L147–225 · sourceSeparationOfDuty · 7f2e519936b5

VMS 表单写入合同:确认时用确认人身份重读描述(钉点 e2adc9a3c325)

  • 这是 tip 已有 ① 的确认前来源复核(assertConfirmationSourceCurrent)中新增的一步,覆盖供应商建档、项目创建、岗位需求三个写工具(18af40288 / efd2255b4 / 71c5bc8c2)。
  • 准备时:表单描述决定必填字段;只有标准字段且后台认证可写(extraFieldsWritable)的才会问用户并自动填,其他必填字段在提问前阻断。确认卡记下 formDescriptorForm、formDescriptorDigest 与 formValidationVersion=2(1d07cf06a 起旧描述卡须重新准备)。
  • 确认时:提案的 tenant / user 必须是当前确认人;以确认人身份重读当前描述,摘要变了即拒绝执行(BUSINESS_REJECT),要求按当前字段重新准备。只有描述工具未挂载时,旧卡或显式 unavailable 证据才按标准路径放行。
  • 不改变 CAS 消费、写前声明与读回顺序;这一步发生在授权消费之前。
  • 证据:aida-agent · packages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts L14–21 · VMS_FORM_DESCRIPTOR_GUARDED_TOOLS · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts L29–139 · assertVmsFormDescriptorEvidenceCurrent · 7f2e519936b5;aida-agent · packages/agent/src/runtime/continuation/operation-confirmation-source-guard.ts L62–102 · assertVmsFormDescriptorEvidenceCurrent · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts L9–10 · VMS_FORM_VALIDATION_VERSION · 7f2e519936b5;aida-agent · packages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts L86–95 · extraFieldsWritable · 7f2e519936b5
  • 描述工具挂载:钉点里只有 202 增量配置脚本与在线 Skill 种子脚本把 describe_vms_form 写进 VMS Skill 工具清单,仓库里没有它们对各租户的执行记录,各租户是否挂载未核。证据:aida-agent · packages/agent/scripts/apply-202-vms-closure-config.ts L565–595 · describe_vms_form · 7f2e519936b5;aida-agent · packages/agent/scripts/lib/seed-online-skills.ts L164–167 · describe_vms_form · 7f2e519936b5
  • 未核:VMS 后端各租户描述工具是否已挂载;onboarding / offboarding / settlement 写入按设计文档不适用此合同。

目标 / 缺口(#255 / #257,tip 未实现)

  • #255 总合同缺失:四套账本(business effect outcome、LF Operation + Desktop WriteRecord、PluginCallJournal、ExecutionHandle)各自有声明 / 重放语义,没有一份「效应类型 → 声明落点 → 重放规则」总合同;本笔记的对照只是 tip 现状记录,不等于 #255 验收(逐路径重放语义审定、「刻意不做」边界未写)。
  • #255 Router 声明不持久:InMemoryExecutionHandleStore 缺省,Router 的 possibly_sent 认领不跨进程。
  • #257 两闸未分开命名:凭证解析与授权消费同处一个执行器函数,且凭证先行;缺凭证现在会确定地收口为 failed BUSINESS_EFFECT_NOT_DISPATCHED,但仍没有独立命名的凭证闸或待补凭证态。
  • #257「未过闸不入执行队列」:tip 没有显式「执行队列」概念;Outbox continuation 结算后直接执行。三类委托闸例外(desktop / plugin / local_file_v4)需要在 #257 里逐一登记为「另有闸」还是「债」。

已核实缺口(勿画成已覆盖)

2026-10-09 tip 再核(agent 61576cf06699 / desktop de6102a5a916;行号与钉点 e2adc9a3c325 / 8eecd12081db 一致)。不再留「未核实」。

  • 缺凭证后 outcome 收尾 — 钉点 e2adc9a3c325 已补上(链 #257;下面是 2026-10-12 时的缺口记录,保留作对照)
    现状:本次尝试未完成授权 CAS 时,executeConfirmedBusinessEffect 在 proposal 仍 pending/approved 时 markFailed(unconsumedOnly) 并 recordUnsentBusinessEffect(outcome → failed BUSINESS_EFFECT_NOT_DISPATCHED),outcome 不再停在 executing。仍缺的是 #257 要的独立待补凭证态。
    旧记录: businessEffects.start 先落 executing(business-effect-task-continuation.ts L1898);toolExecutor 凭证解析先于 CAS(tool-executor.ts L317–321),缺凭证 → ConnectorNotAuthorizedError → ToolExecutionError(无 errorType,故不进 isDeterministicWriteRejection L3047–3072)。2026-10-12 tip:确认后执行逻辑已抽到 business-effect-confirmed-execution.ts(executeConfirmedBusinessEffect),语义不变——非确定性失败且 proposal 仍 approved 时只 markFailed 后重抛(L538–548),不调用 recordOutcome。outcome 可停在 executing。
  • Desktop 离线 / fs/change 写回收 — 已核实:走另一条链 + Agent TTL 缺口(链 #255)
    • Desktop 本机:已覆盖 — 启动 recoverUnterminatedWritesAndReport(main.ts L3851)→ reconcileWriteFacts(write-recovery.ts L27)物理重读后补交回执(不在服务端写权限主链)。
    • Agent TTL:已核实未覆盖 fs/change — listExpiredRequested 仅 fs/list|fs/search|fs/read(local-file-operation-store.ts L227)。
    • 长期离线等待写回执的 Operation:无 Agent TTL 自动过期;Run 层或受 Interaction 保护,或 lease 过期进 manual_recovery/RUN_ORPHANED(run-store.ts L1898+;同一函数先关闭只等过期卡的 legacy 树,见 state-authority),不等于写权限链回收 Operation。

视图

  • main — 服务端连接器写主路径(压缩;缺凭证 / 缺口 / LF 不在主图展开)。
  • tip-vs-gaps — tip 已有 vs #255 / #257 未实现;含缺凭证通用失败。
  • lf-compare — 本机 fs/change 写前记录 · 消费对照(详路径仍见 local-file-v5)。
  • business-task-and-material-gate — 业务任务操作协调器(PgBusinessTaskOperationCoordinator)、Symbol 级新鲜材料准入与任务终态尾链核验。

业务任务操作协调器与新鲜材料准入(视图 business-task-and-material-gate)

当一条 Runtime Work 绑定了企业业务事项(businessTaskBinding: { taskId, attemptId })时,所有的模型调用、本机脚本/插件回执与任务结案都受到 PgBusinessTaskOperationCoordinator(operation-coordinator.ts)与 run-work-material-check.ts 的联合管控(见视图 business-task-and-material-gate):

  1. Common Control 独占写权与操作状态机(operation-coordinator.ts L152–402):
    • 凡是 runtime_protocol_version === 'runtime-work-v1' 的 Run,若外部直接调 reserve() 或 markReceiptPending() 会立即抛出 BUSINESS_TASK_COMMON_CONTROL_REQUIRED——所有状态变迁必须在 Root 锁事务内调用 reserveInTransaction → markReceiptPendingInTransaction → projectReceiptInTransaction;
    • 状态流转:dispatch_pending -> executing -> receipt_pending -> succeeded | failed | cancelled | outcome_unknown;
    • Unknown 传染阻断(L368–384, L479–498):只要任一操作落入 outcome_unknown,同一事务内立即将 business_tasks.coordination_status 与 business_task_attempts.status 雙雙置为 'unknown';此后任何新一轮模型请求在 admitWorkModelRequestInTx 中调 assertTaskModelExecutionInTransaction 时,都会因为 allowsKnownOperationsInTransaction 返回 false 而被 BUSINESS_TASK_OUTCOME_UNKNOWN 拦截!
  2. Symbol 级新鲜材料准入许可(FreshWorkMaterialPermit,run-work-material-check.ts L10–84 & run-work-control.ts L82–96):
    • 当未知操作通过补证(Supplement)恢复时,recordWorkMaterialCheckInTx 在 FOR UPDATE 下校验 work_supplement_digest === input.digest 且 check.sequence > previous.sequence(单调递增防重放);
    • 观察记录 ≠ 执行许可:代码注释明确指出 "Persisted available/ACK is an observation, not a reusable execution permit";只有当次事务中 recordWorkMaterialCheckInTx 返回 fresh: true 时,控制面才用模块私有 Symbol Symbol("fresh-original-owner-material") 构造内存级 FreshWorkMaterialPermit 传入 settleRuntimeWorkSkillReceiptInTx;
    • workMaterialContinuationConsumed 进一步校验补证结果不仅已 ACK,而且对应的 messages (role='tool') 确实写入了 originalReceipt.responseDigest 与 supplementaryConclusion.digest,且 run_checkpoints 已清空原挂起等待。
  3. 补证对账解锁与任务完成尾链核验(operation-coordinator.ts L500–565 & run-work-business-task-completion.ts L55–140):
    • projectWorkReconciliationInTransaction 将补证写入 business_task_evidence (kind='reconciliation') 并投影产物;当该任务下所有 outcome_unknown 操作均在 reconciled 集合中配平后,自动将 business_tasks.coordination_status 恢复为 'in_progress'(若 canActivate 为假则置 'needs_attention')、business_task_attempts.status 恢复为 'running';
    • 当模型最终调用 finishBusinessTask 时,createWorkBusinessTaskCompletion 在 withRuntimeWorkAttempt 租约围栏下:先核验 allowsAttemptActivationInTransaction,再 FOR UPDATE 锁住 run_checkpoints 核对 accepted_response_ref 对应的 Assistant 消息 SHA-256 与 finishBusinessTask 参数 { evidenceRefs, completionSummary } 100% 吻合,最后才允许调用 PgBusinessTaskCompletionCoordinator.prepareCompletionInTransaction 结案。

证据与范围

  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L179–198 · Kernel authorization · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L340–417 · willAwaitConfirm · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L602–626 · usesExternalApprovalGate · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-call-gate.ts L676–694 · checkCrossTurn · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/business-effect.ts L513–553 · start · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/business-effect.ts L586–626 · safe_to_retry · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/write-authority.ts L82–111 · VerifiedWriteAuthorityCapability · 7f2e519936b5
  • aida-agent · packages/agent/src/interaction-kernel/write-authority.ts L157–201 · markExecuting · 7f2e519936b5
  • aida-agent · packages/agent/src/session/action-proposal-store.ts L1031–1081 · persistentTargetClaimLease · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-executor.ts L300–304 · ConnectorNotAuthorizedError · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/tool-executor.ts L388–440 · consumeVerifiedWriteAuthority · 7f2e519936b5
  • aida-agent · packages/agent/src/connectors/credential-provider.ts L1–12 · Credential boundary · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L2048–2076 · registerAuthorization · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L246–247 · recovering · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L461–475 · effect.status === "unknown" · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L510–524 · writeAuthorityOwner.issue · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts L625–655 · writeAuthorityConsumedHere · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/continuation/business-effect-task-continuation.ts L1417–1435 · observeCommittedSourceWrite · 7f2e519936b5
  • aida-agent · packages/agent/src/connectors/effect-readback/index.ts L21–28 · observeConnectorCommittedWrite · 7f2e519936b5
  • aida-agent · packages/agent/src/runtime/local/local-file-change-continuation.ts L180–218 · suspendPendingResumeForRequest · 7f2e519936b5
  • aida-agent · packages/agent/src/session/local-file-operation-store.ts L217–238 · listExpiredRequested · 7f2e519936b5
  • aida-agent · packages/agent/src/execution-host/router.ts L159–191 · bindingDigest · 7f2e519936b5
  • aida-agent · packages/agent/src/execution-host/router.ts L461–480 · claimDispatch · 7f2e519936b5
  • aida-agent · packages/agent/src/orchestrator/run.ts L666–682 · InMemoryExecutionHandleStore · 7f2e519936b5
  • aida-agent · packages/agent/src/session/run-store.ts L1933–2014 · RUN_ORPHANED · 7f2e519936b5
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L145–176 · recovery CAS · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L494–565 · consumeAuthorization · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/change-executor.ts L302–331 · outcome_unknown · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/confirmation-record-store.ts L201–226 · consumedAt · 4346d79eb364
  • aida-desktop · apps/desktop/electron/local-files-v4/write-recovery.ts L27–40 · reconcileWriteFacts · 4346d79eb364
  • aida-desktop · apps/desktop/electron/main.ts L3976–3987 · recoverUnterminatedWritesAndReport · 4346d79eb364

结论来自固定版本的静态源码阅读;实现存在、默认开关和生产启用分别判断。GitLab issue 状态读取于 2026-10-09。

代码证据

引用核验检查固定 commit 的文件与范围;实现结论来自代码阅读。自动检查不证明生产环境已启用。

已核验实现

聊天轮次不授权业务写:ToolCallGate 对写工具在 reject/confirm 之后执行 checkCrossTurn,唯一可执行路径是 Kernel 结算后的 Outbox continuation;委托闸例外仅 desktop approval gate、Plugin、local_file_v4。

aida-agentpackages/agent/src/orchestrator/tool-call-gate.ts:178–1977f2e519936b57902d4907ed8026fe1ecdd146e82符号:Kernel authorization
aida-agentpackages/agent/src/orchestrator/tool-call-gate.ts:344–4217f2e519936b57902d4907ed8026fe1ecdd146e82符号:willAwaitConfirm
aida-agentpackages/agent/src/orchestrator/tool-call-gate.ts:601–6257f2e519936b57902d4907ed8026fe1ecdd146e82符号:usesExternalApprovalGate
aida-agentpackages/agent/src/orchestrator/tool-call-gate.ts:678–6937f2e519936b57902d4907ed8026fe1ecdd146e82符号:checkCrossTurn
已核验实现

确认卡结算后 registerAuthorization 写授权;businessEffects.start 以 proposalId:payloadHash 哈希为幂等键先落 executing outcome(写前声明),同键重入返回已有行;reconcileUnknown 可回到 safe_to_retry/succeeded/failed/unknown。

aida-agentpackages/agent/src/runtime/continuation/business-effect-task-continuation.ts:2334–23627f2e519936b57902d4907ed8026fe1ecdd146e82符号:registerAuthorization
aida-agentpackages/agent/src/interaction-kernel/business-effect.ts:519–5597f2e519936b57902d4907ed8026fe1ecdd146e82符号:start
aida-agentpackages/agent/src/interaction-kernel/business-effect.ts:592–6327f2e519936b57902d4907ed8026fe1ecdd146e82符号:safe_to_retry
已核验实现

执行凭据是仅运行时可持有的 VerifiedWriteAuthority;消费时再校验并以 ActionProposal markExecuting(approved→executing 条件 UPDATE,传 requireActiveRun 时同句要求所属 Run 未取消、无 cancel_intent)做一次性 CAS,persistent-target 工具另铸 persistentTargetClaimLease;执行器在派发前消费,连接器凭证在同一函数中先于消费解析。

aida-agentpackages/agent/src/interaction-kernel/write-authority.ts:139–1687f2e519936b57902d4907ed8026fe1ecdd146e82符号:VerifiedWriteAuthorityCapability
aida-agentpackages/agent/src/interaction-kernel/write-authority.ts:278–3227f2e519936b57902d4907ed8026fe1ecdd146e82符号:markExecuting
aida-agentpackages/agent/src/session/action-proposal-store.ts:1165–12157f2e519936b57902d4907ed8026fe1ecdd146e82符号:persistentTargetClaimLease
aida-agentpackages/agent/src/orchestrator/tool-executor.ts:165–2117f2e519936b57902d4907ed8026fe1ecdd146e82符号:ConnectorNotAuthorizedError
aida-agentpackages/agent/src/orchestrator/tool-executor.ts:358–4107f2e519936b57902d4907ed8026fe1ecdd146e82符号:consumeVerifiedWriteAuthority
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:551–5657f2e519936b57902d4907ed8026fe1ecdd146e82符号:writeAuthorityOwner.issue
aida-agentpackages/agent/src/connectors/credential-provider.ts:1–127f2e519936b57902d4907ed8026fe1ecdd146e82符号:Credential boundary
已核验实现

有 readback 合同的连接器写,成功响应不足以结案,需只读回查源系统;重启后见 executing proposal 永不再调用,除非读回证明已落地,否则记 unknown;缺凭证等派发前失败(本次尝试没有完成授权 CAS)时,proposal 仍为 pending/approved 则 markFailed(unconsumedOnly),并把 effect 记为 failed(BUSINESS_EFFECT_NOT_DISPATCHED),不记 unknown。

aida-agentpackages/agent/src/runtime/continuation/business-effect-task-continuation.ts:1508–15267f2e519936b57902d4907ed8026fe1ecdd146e82符号:observeCommittedSourceWrite
aida-agentpackages/agent/src/connectors/effect-readback/index.ts:21–287f2e519936b57902d4907ed8026fe1ecdd146e82符号:observeConnectorCommittedWrite
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:266–2677f2e519936b57902d4907ed8026fe1ecdd146e82符号:recovering
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:509–5237f2e519936b57902d4907ed8026fe1ecdd146e82符号:effect.status === "unknown"
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:679–7097f2e519936b57902d4907ed8026fe1ecdd146e82符号:writeAuthorityConsumedHere
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:795–8147f2e519936b57902d4907ed8026fe1ecdd146e82符号:recordUnsentBusinessEffect
已核验实现

LF fs/change:Agent 一个事务内 markGranted + Operation requested 落账;Desktop 先写 WriteRecordStore 写前记录再 consume 确认记录(consumedAt 单次),逐 action 记 started/completed,不能证明未落地记 unknown/outcome_unknown;启动时 reconcileWriteFacts 物理重读并补交回执;Agent TTL 回收只覆盖读方法。

aida-agentpackages/agent/src/runtime/local/local-file-change-continuation.ts:220–2447f2e519936b57902d4907ed8026fe1ecdd146e82符号:suspendPendingResumeForRequest
aida-desktopapps/desktop/electron/local-files-v4/change-executor.ts:176–2074346d79eb36402355e51118df0edf1f98586880c符号:recovery CAS
aida-desktopapps/desktop/electron/local-files-v4/change-executor.ts:631–7024346d79eb36402355e51118df0edf1f98586880c符号:consumeAuthorization
aida-desktopapps/desktop/electron/local-files-v4/change-executor.ts:407–4364346d79eb36402355e51118df0edf1f98586880c符号:outcome_unknown
aida-desktopapps/desktop/electron/local-files-v4/confirmation-record-store.ts:211–2364346d79eb36402355e51118df0edf1f98586880c符号:consumedAt
aida-desktopapps/desktop/electron/local-files-v4/write-recovery.ts:25–1784346d79eb36402355e51118df0edf1f98586880c符号:reconcileWriteFacts
aida-desktopapps/desktop/electron/main.ts:4609–46204346d79eb36402355e51118df0edf1f98586880c符号:recoverUnterminatedWritesAndReport
aida-agentpackages/agent/src/session/local-file-operation-store.ts:228–2507f2e519936b57902d4907ed8026fe1ecdd146e82符号:listExpiredRequested
已核验实现

ExecutionHostRouter 以 callId:bindingDigest singleflight,并用 compareAndSet 认领 not_sent→possibly_sent;钉点上 AgentRun 只为 server-read 建 Router,handle store 缺省 InMemoryExecutionHandleStore(不跨进程)。

aida-agentpackages/agent/src/execution-host/router.ts:159–1917f2e519936b57902d4907ed8026fe1ecdd146e82符号:bindingDigest
aida-agentpackages/agent/src/execution-host/router.ts:461–4807f2e519936b57902d4907ed8026fe1ecdd146e82符号:claimDispatch
aida-agentpackages/agent/src/orchestrator/run.ts:677–6937f2e519936b57902d4907ed8026fe1ecdd146e82符号:InMemoryExecutionHandleStore
已核验实现

孤儿 Run:recoverExpiredLeaseByConversation 排除受保护 Run、并先关闭只等过期卡的 legacy 树后,lease 过期且仍有 pending/approved/executing ActionProposal 或不可重放 pending checkpoint 的顶层 Run → manual_recovery RUN_ORPHANED,其余 → failed RUN_ORPHANED。

aida-agentpackages/agent/src/session/run-store.ts:2039–21347f2e519936b57902d4907ed8026fe1ecdd146e82符号:RUN_ORPHANED
已核验实现

缺连接器凭证时:businessEffects.start 已落 executing 后,toolExecutor 在 CAS 前抛 ConnectorNotAuthorizedError;continuation 判定本次尝试没有消费授权(writeAuthorityConsumedHere 为 false),proposal 仍为 pending/approved 时 markFailed(unconsumedOnly) 并经 recordUnsentBusinessEffect 把 outcome 记为 failed(BUSINESS_EFFECT_NOT_DISPATCHED),然后重抛。outcome 不再停在 executing;但仍没有独立的「已授权、待补凭证」状态。

#257 要的「授权闸 / 凭证闸分开命名、待补凭证态」仍未实现;勿画成已有待补凭证态。静态读码,本轮未运行测试。

aida-agentpackages/agent/src/runtime/continuation/business-effect-task-continuation.ts:2413–24187f2e519936b57902d4907ed8026fe1ecdd146e82符号:businessEffects.start
aida-agentpackages/agent/src/orchestrator/tool-executor.ts:188–1927f2e519936b57902d4907ed8026fe1ecdd146e82符号:ConnectorNotAuthorizedError
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:679–7097f2e519936b57902d4907ed8026fe1ecdd146e82符号:writeAuthorityConsumedHere
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:795–8147f2e519936b57902d4907ed8026fe1ecdd146e82符号:BUSINESS_EFFECT_NOT_DISPATCHED
已核验实现

fs/change 写回收:Desktop 启动 recoverUnterminatedWritesAndReport→reconcileWriteFacts 覆盖本机未完成写记录;Agent listExpiredRequested 仅 method IN (fs/list|fs/search|fs/read),不盖 fs/change。长期离线等待写回执的 Operation 无 Agent TTL 自动过期;Run 层或走 orphan/manual_recovery,不等于写权限链回收 Operation。

Desktop 本机回收已覆盖;Agent TTL 对 fs/change 已核实未实现。属 #255 相关缺口。

aida-agentpackages/agent/src/session/local-file-operation-store.ts:228–2497f2e519936b57902d4907ed8026fe1ecdd146e82符号:listExpiredRequested
aida-desktopapps/desktop/electron/main.ts:4609–46204346d79eb36402355e51118df0edf1f98586880c符号:recoverUnterminatedWritesAndReport
aida-desktopapps/desktop/electron/local-files-v4/write-recovery.ts:25–384346d79eb36402355e51118df0edf1f98586880c符号:reconcileWriteFacts
aida-agentpackages/agent/src/session/run-store.ts:2039–21207f2e519936b57902d4907ed8026fe1ecdd146e82符号:RUN_ORPHANED
已核验实现

确认后写入的自动重试收窄:isConfirmedWriteRetryableError 只对「确定没发出去」的情况重试——全新连接上的 not_sent 连接错误(ECONNREFUSED / ENOTFOUND 等)与无业务报文的网关 503;502、504、超时、连接重置都可能发生在业务已提交之后,按结果未知只尝试一次,executeConfirmedWrite 默认用这个判定。结果分类上,网关无报文(errorBody=none)的 UPSTREAM_ERROR 与幂等守卫 WRITE_OUTCOME_UNKNOWN 保持不确定(走源回读 / unknown),IDEMPOTENCY_STORE_UNAVAILABLE 视为确定未执行。

静态读码;本轮未运行 write-authority / lifecycle 测试。

aida-agentpackages/agent/src/orchestrator/confirmation/lifecycle.ts:1887–19477f2e519936b57902d4907ed8026fe1ecdd146e82符号:isConfirmedWriteRetryableError
aida-agentpackages/agent/src/orchestrator/confirmation/lifecycle.ts:1972–19767f2e519936b57902d4907ed8026fe1ecdd146e82符号:isConfirmedWriteRetryableError
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-execution.ts:1626–16577f2e519936b57902d4907ed8026fe1ecdd146e82符号:WRITE_OUTCOME_UNKNOWN_CODE
已核验实现

Run 停止与写消费的竞争:写授权消费调用 markExecuting 时传 requireActiveRun:true,CAS 同一句 UPDATE 检查所属 agent_runs 未 cancelled 且无 cancel_intent;停止先提交则消费失败、不发送,消费先提交则停止排在其后并结算已认领的写。

静态读码;本轮未运行测试。TLA+ 模型 NoConsumeAfterCancel 覆盖此性质(见下一条)。

aida-agentpackages/agent/src/interaction-kernel/write-authority.ts:281–3257f2e519936b57902d4907ed8026fe1ecdd146e82符号:requireActiveRun: true
aida-agentpackages/agent/src/session/action-proposal-store.ts:1120–11707f2e519936b57902d4907ed8026fe1ecdd146e82符号:requireActiveRun
已核验实现

租约丢失后的 business_effect 恢复从 index.ts 移入 continuation 的 settleInterruptedBusinessEffect:恢复从不写源系统;已结案的直接收口;未派发的(无 outcome / executing / failed BUSINESS_EFFECT_NOT_DISPATCHED)先尝试按未发送收口;被用户重试复活的批次归重试 owner;批次成员 fence 与父结算都绑定所拥有的代际(batchRetryKey),陈旧恢复写不动新代际。

静态读码;本轮未运行测试。

aida-agentpackages/agent/src/runtime/continuation/business-effect-task-continuation.ts:1671–17007f2e519936b57902d4907ed8026fe1ecdd146e82符号:settleInterruptedBusinessEffect
aida-agentpackages/agent/src/runtime/continuation/business-effect-confirmed-batch.ts:237–2507f2e519936b57902d4907ed8026fe1ecdd146e82符号:batchRetryKey
已核验实现

仓内新增 TLA+ 设计模型:specs/tla/confirmed-write 建模单个确认写(AtMostOnce、NoConsumeAfterCancel、UnknownOnlyIfConsumed、NoApprovedLimbo、UnsentWriteFreesConversation 等性质,baseline 全部 PASS,Bug*.cfg 变体证明检查会失败),specs/tla/confirmed-batch 建模确认批次。它们是协议设计检查,不是代码测试。

本轮未运行 TLC;结果取自仓内提交的 results/summary.txt。

aida-agentspecs/tla/confirmed-write/README.md:1–77f2e519936b57902d4907ed8026fe1ecdd146e82符号:design check
aida-agentspecs/tla/confirmed-write/results/summary.txt:4–167f2e519936b57902d4907ed8026fe1ecdd146e82符号:NoConsumeAfterCancel
aida-agentspecs/tla/confirmed-batch/README.md:1–97f2e519936b57902d4907ed8026fe1ecdd146e82符号:ConfirmedBatch.tla
已核验实现

审批职责分离 sourceSeparationOfDuty 收窄:能识别当前操作人时,只有操作人既是审批人又是发起人才判 violated;识别不了操作人时,发起人与审批人重叠只在源数据只给出单一审批人时判 violated,多审批人节点返回 undetermined,交给平台 / 源系统规则兜底,不再误拒其他审批人。

静态读码;本轮未运行测试。

aida-agentpackages/agent/src/orchestrator/capability-policy/verticals/admin-bypass-approval.ts:156–2347f2e519936b57902d4907ed8026fe1ecdd146e82符号:sourceSeparationOfDuty
已核验实现

确认时重读 VMS 表单描述(18af40288 / efd2255b4 / 71c5bc8c2):create_vms_supplier / create_vms_project_draft / create_vms_project_position 的确认写入前,assertConfirmationSourceCurrent 调 assertVmsFormDescriptorEvidenceCurrent:提案 tenant/user 必须是当前确认人;确认卡必须带 formDescriptorForm、formValidationVersion=2 与 64 位 formDescriptorDigest,并以确认人的身份(tenantId/userId/run/invocation)重读当前描述,摘要不同即 BUSINESS_REJECT 要求重新准备;只有描述工具未挂载时,旧卡或显式 unavailable 证据才保留标准兼容。

aida-agentpackages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts:22–297f2e519936b57902d4907ed8026fe1ecdd146e82符号:VMS_FORM_DESCRIPTOR_GUARDED_TOOLS
aida-agentpackages/agent/src/runtime/continuation/vms-form-descriptor-confirmation-guard.ts:40–1507f2e519936b57902d4907ed8026fe1ecdd146e82符号:assertVmsFormDescriptorEvidenceCurrent
aida-agentpackages/agent/src/runtime/continuation/operation-confirmation-source-guard.ts:62–1027f2e519936b57902d4907ed8026fe1ecdd146e82符号:assertVmsFormDescriptorEvidenceCurrent
已核验实现

准备阶段的必填字段合同(formValidationVersion 2):只有 origin=standard 且后台认证 extraFieldsWritable=true 的字段可自动填写;自定义 / 继承、选项不可得的 Dict/Enum、非 String/Text 的类型在提问前就阻断并给出恢复路径。

aida-agentpackages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts:9–107f2e519936b57902d4907ed8026fe1ecdd146e82符号:VMS_FORM_VALIDATION_VERSION
aida-agentpackages/agent/src/orchestrator/capability-policy/verticals/vms-form-extra-fields.ts:92–1017f2e519936b57902d4907ed8026fe1ecdd146e82符号:extraFieldsWritable
未核实

describe_vms_form 的挂载来源:钉点里只有 202 增量配置脚本与在线 Skill 种子脚本把它写进 VMS Skill 的工具清单;仓库里没有这两个脚本对各租户的执行记录。

各租户 Config DB 的 skills.tool_names 读不到,挂载与否未核。

aida-agentpackages/agent/scripts/apply-202-vms-closure-config.ts:569–5997f2e519936b57902d4907ed8026fe1ecdd146e82符号:describe_vms_form
aida-agentpackages/agent/scripts/lib/seed-online-skills.ts:199–2027f2e519936b57902d4907ed8026fe1ecdd146e82符号:describe_vms_form
已核验实现

历史/业务确认预览签发权威前须匹配 proposal:interaction.businessEffect.targetRef 为 proposal:id,且 tenantId/interactionId/scopeDigest(=payloadHash) 一致,否则返回 business_proposal_unavailable(503),不签发。

aida-agentpackages/agent/src/gateway/api-conversation-interactions.ts:783–7917f2e519936b57902d4907ed8026fe1ecdd146e82符号:business_proposal_unavailable