AIDAWORK / SEQUENCE

salary-smartcalc:调用与回执

独立图页 ↗

先看「视图」里的主路径;每条失败链都有同名成功对偶(fail-x ↔ ok-x)。

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

aida-plugins 包 com.caidao.salary-smartcalc(薪资智算)以 plugin.json + contracts/tools.json 声明 hostApi、targets 与工具合同;runtime 自 594ef08c 起由 native sidecar 改为 Python(runtime.kind: python,entry salary_plugin.provider:create_plugin)(如 analyze_salary_logic);包本身不持有服务端 Run 状态。

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

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

机制说明(全文)

纵向业务挂载:salary-smartcalc 与 attendance-tally

平台 × 业务接缝

aida-plugins 包 com.caidao.salary-smartcalc(薪资智算)以 plugin.json + contracts/tools.json 声明 hostApi、targets 与工具合同;runtime 自 594ef08c 起由 native sidecar 改为 Python(runtime.kind: python,entry salary_plugin.provider:create_plugin)(如 analyze_salary_logic);包本身不持有服务端 Run 状态。

Desktop Main PluginHost 发现/加载不可变包,经 taskProjections / listProjections 产出 PluginToolProjection 广告。企业 chat 流把投影带进 Agent;resolveExplicitPluginTask 按显式选择解析,失败不得静默退回内置能力。钉点 e2adc9a3c325 起,「用 xxx-cli」若与已安装独立 Skill 同名且没有命中插件,则跳过、交给 Skill 目录,不再当作插件选择失败。

调用 / 回执

PluginCallJournal 相位 admitted → dispatched → settled:dispatch 屏障失败则落 uncertain / failed 回执,禁止重启后盲重放。Agent 侧 parseBoundPluginReply 校验 pluginId/version/toolId/contractDigest(及 optional runtimeRevision)与 outputSchema / maxResultBytes;不一致返回 null。

归属边与非目标

  • Owner:包合同在 aida-plugins;Host/Journal 在 Desktop Main;绑定校验在 Agent。
  • 非目标:不把 Worker 画进服务端 Runtime;不展开全部薪资算法实现。
  • 相关:capability-plugins、plugin-v2-host-runtime、plugin-run-projection、trust-boundaries。

视图

  • main — 合同 → Host → 投影 → 解析。

  • call-receipt — salary-smartcalc 工具调用与回执校验。

  • fail-plugin-settle — 调用失败 / 回执拒收 / journal settle。

  • fail-manifest — Manifest/投影缺工具。

  • ok-plugin-settle — Plugin journal settle 成功(对偶 fail-plugin-settle)。

  • ok-manifest — Manifest/投影命中工具(对偶 fail-manifest)。

  • attendance-workflow — 考勤核算(attendance-tally):7 阶段端到端工作流、M01–M11 编译与单向算子 DAG。

  • attendance-desktop-loop — Desktop × 考勤核算(attendance-tally):React 视图桥接、CAS/只读保护与 userActionOnly 闭环。

  • attendance-rework-compile — 考勤深潜:Rework 局部失效状态机、M01–M11 编译冲突裁决与 M11 额度批次扣减。

成功对偶(与失败链入口相同)

  1. ok-plugin-settle:markDispatched → settle succeeded → parseBoundPluginReply 接受。
  2. ok-manifest:taskProjections 含 skills → resolveExplicit 唯一候选。

失败链(深挖)

  1. fail-plugin-settle:dispatch 屏障失败 → uncertain/failed;parseBoundPluginReply null;禁重启盲重放。
  2. fail-manifest:空投影 / 无 skills → PLUGIN_TASK_UNAVAILABLE;resolveExplicitPluginTask 同码;不静默退回内置。

普通入口冻结已选插件(钉点 e2adc9a3c325)

以前只有显式带 pluginTask 的入口会冻结插件绑定。现在普通 Work 入口也会:路由选中某个插件能力时,从本轮 Desktop 已公布的插件投影里解析出这个插件,冻结绑定,并把唯一匹配的那份投影随 Work 存下。对不上(不是恰好一个、投影里没工具、能力 id 不符)就拒绝受理,错误码 RUNTIME_WORK_PLUGIN_SOURCE_INVALID,不会静默换成别的插件。

Agent 内 verticals/ 接缝(MR-6a~6g,钉点 e2adc9a3c325)

7 个提交把内核里的垂直特例平移到同层 verticals/ 目录:6a 路由注释去垂直词;6b VMS 入职批次路由→gateway/verticals/route-packs.ts;6c 确认/续办工具特征与权限拒绝→orchestrator/**/verticals;6d 入职批次工具与 SOW 定时处理器→runtime/work/verticals、scheduler/verticals;6e VMS 角色守卫→routing/verticals/operation-role-guard.ts;6f 业务对象意图表→routing/verticals/business-intent-catalog.ts;6g Child Kernel 招聘分支→agent-as-tool/verticals/recruit-child-run-policy.ts。

决定:不单独成题、不画新图。 理由:全是行为不变的搬家,没有新运行时边、状态、持久化或信任边界;现有图的节点和箭头都不变。只在这里记下「内核不带垂直知识、由组合根接线」这条约定。残留:child-run-orchestrator.ts L2916 仍有 recruit 字面量。未运行 Agent 测试。

证据与范围

  • aida-plugins · plugins/salary-smartcalc/plugin.json L1–38 · "kind": "python" · a33ce3733365

  • aida-plugins · plugins/salary-smartcalc/contracts/tools.json L5–35 · analyze_salary_logic · a33ce3733365

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L195–199 · PluginHost · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–655 · taskProjections · 4346d79eb364

  • aida-desktop · apps/desktop/electron/agent-loop/enterprise-adapter.ts L92–123 · preparePluginTools · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L29–61 · phase · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L266–297 · settle · 4346d79eb364

  • aida-agent · packages/agent/src/runtime/local/plugin-task.ts L17–47 · resolveExplicitPluginTask · e2adc9a3c325

  • aida-agent · packages/agent/src/runtime/local/plugin-task.ts L72–77 · isStandaloneSkill · e2adc9a3c325

  • aida-agent · packages/agent/src/runtime/local/plugin-tool-receipt.ts L33–64 · parseBoundPluginReply · e2adc9a3c325

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–645 · taskProjections/PLUGIN_TASK_UNAVAILABLE · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L263–327 · settle/markDispatched · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–655 · taskProjections · 4346d79eb364

结论来自固定版本的静态源码与合同阅读;实现存在、默认开关和生产启用分别判断。本站代码证据面板列出声明状态与具体限制。

  • aida-agent · packages/agent/src/gateway/workbench-route-preparation.ts L108–115 · resolveExplicitPluginTask · e2adc9a3c325
  • aida-agent · packages/agent/src/session/chat-submission-store.ts L759–769 · RUNTIME_WORK_PLUGIN_SOURCE_INVALID · e2adc9a3c325
  • aida-agent · packages/agent/src/gateway/verticals/route-packs.ts L1–18 · mountGatewayVerticalRoutes · e2adc9a3c325
  • aida-agent · packages/agent/src/routing/verticals/operation-role-guard.ts L14–47 · roleGuardOwnsSlotCollection · e2adc9a3c325
  • aida-agent · packages/agent/src/orchestrator/agent-as-tool/verticals/recruit-child-run-policy.ts L28–199 · prepareChildCapabilityRequest · e2adc9a3c325
  • aida-agent · packages/agent/src/routing/router.ts L2740–2744 · NO_INTENT_PACKS · e2adc9a3c325

考勤核算(com.caidao.attendance-tally 2.1.16)完整架构拆解(视图 attendance-workflow & attendance-desktop-loop,钉点 d220086aa495)

1. 四大核心设计铁律:AI 负责“语义理解”,Plugin 负责“台账、编译与确定性计算”

  1. 原话证据链(Fact & Provenance):用户每说一句话,Agent 必须先通过 attendance_task_record_turn 登记原话并切分句子(sentenceRanges),将提取出的规则字段与客户原话片段绑定(factId / sourceText);明确政策写入 changes,缺失细节登记为 ask 追问,推断项记为 propose,跨领域记为 unsupported,严禁大模型脑补默认政策。
  2. 双模型分离与确定性编译(RuleModel → CalculationModel):
    • RuleModel(M01–M11):客户审阅确认后的业务政策唯一真源(rule-model-2.0.schema.json)。
    • CalculationModel:由编译器(domain/compiler.py:compile_rule_model)将已确认的 RuleModel 确定性编译出的算子有向无环图(DAG,calculation-model-2.0.schema.json)。
    • 本地确定性执行:计算引擎(domain/runtime.py:CalculationEngine.run)在本地执行 Excel 数据核算,员工原始数据、中间结果与导出工作簿只留在本机。
  3. 四道人工门禁(userActionOnly)与乐观锁(expectedRevision CAS):
    • 规则确认(attendance_task_confirm)、员工日计划确认、发起计算(attendance_task_calculate)、模型发布四个关键写操作声明 userActionOnly: true,必须由用户在 UI 视图亲自点击并携带宿主签发的 userActionReceipt,Agent 无法代点或绕过。
    • AttendanceTaskWorkbench 所有状态修改强制校验 expectedRevision === self.revision。
  4. 随时局部返工(Rework)与跨月客户模型复用(Registry & Customer):
    • 用户在后续步骤修改规则或替换输入文件时,通过 input_rework / rule_workbook / rule_rebase 触发 ReworkChangeSet 与 ReworkProgress,精确标记受波及的下游确认项(如日计划确认、实绩检查),未受影响阶段无需推倒重来。
    • 通过 attendance-model-registry(声明 suggestedBaseUrl)发布或拉取已确认的 CustomerRuleModelSnapshot 与 CustomerCalculationModelSnapshot,支持跨会话/下月一键复用。

2. 端到端 7 阶段工作流与 10 个前端视图(plugin.json + task-tools.json)

插件声明 10 个前端视图(rules、sources、mapping、input_rework、rule_workbook、plan、calculation、results、registry、customer)与 39 个工具,每次调用在 workflow.nextAction 返回唯一确定的下一步指引:

  • 阶段 1–2(规则采集 → 审阅确认):自然语言访谈或导入 v3 访谈表(rule_workbook)→ rules 视图展开 M01–M11 核对纠错并点击确认 → 编译生成 CalculationModel。
  • 阶段 3–4(周期与文件导入 → 表头映射与预检):sources 视图设置核算周期与上传花名册/日历/打卡/休假/加班/覆盖声明 → mapping 视图完成字段映射与关联表预检。
  • 阶段 5–7(员工日计划与实绩预检 → 确定性计算 → 结果复核与发布):plan 视图生成并人工确认《员工日计划表》后执行 attendance_task_check_actuals → calculation 视图人工点击触发 CalculationEngine → results / registry 视图查看日明细、月汇总、异常表并导出 Artifact 或发布至模型库。

3. 考勤领域模型(M01–M11)与单向确定性计算顺序

业务规则拆分为 11 个正交子模型(每个子模型统一包含 definitions 可复用定义与 policies 适用范围策略):

模块 名称 核心职责
M01 日历与考勤周期 考勤周期起止边界、政策统一有效期(policyEffectivePeriod)、法定节假日与企业调休历
M02 员工资格与适用范围 标准花名册字段要求、人员分组(scope)、入离职折算边界
M03 班次与排班 固定班次、弹性班次(flex_shifts)、跨夜班次、休息时段、最低出勤要求
M04 打卡与出勤凭证 原始打卡窗口识别、免打卡人群/一次到岗(day_only)规则、打卡证据有效性
M05 异常考勤 迟到、早退、缺卡、旷工判定阈值、宽限期与计量方式
M06 假期与休假考勤 假期类型定义、计假单位/取整、休假对出勤义务的免除效果
M07 加班与调休 工作日/休息日/节假日三类加班方案、来源路由(审批单 vs 打卡识别)、转调休比例
M08 特殊出勤 出差、外勤、培训等特殊事项对工作日/休息日工时的贡献边界
M09 补卡与更正 补卡记录替换原始缺卡、次数上限控制、幂等与重算范围
M10 工时归集与结算 汇总实际出勤、休假、特殊出勤与异常,完成每日评价与周期结算小计
M11 额度变动与结转 期初余额 + 本期新增(含 M07 加班转调休)汇总,按假种与批次优先级(先到期/先旧后新)扣减,输出非负余额与不足异常
  • 单向确定性计算 DAG(严禁循环试算与反向推翻): 基准员工日计划 (C04) ➔ 原始打卡筛选与有效补卡 (C09) 及弹性班次顺延 (C04F) ➔ 实际工作事实固定 (C10A) ➔ 休假规范化与出勤义务计算 (M06) ➔ 加班认定与转调休新增 (M07) ➔ 期初与新增额度汇总及按批次扣减 (M11) ➔ 正常出勤/迟到早退/旷工最终裁决与汇总导出 (M05/M10)。例如额度不足只报额度异常,绝不反向推翻已认定的休假或重算加班。

4. Desktop × 考勤 React UI 双端交互与状态保护(视图 attendance-desktop-loop)

  • window.aida 桥接与只读横幅(mayAct):前端 ui/src/app.tsx 挂载在 Desktop PluginMainView 中,通过 getTaskContext() 与只读 stateToolId(attendance_view_state)拉取快照;当用户在历史卡片查看旧视图(!task.context.mayAct)时,顶部展示黄色告警横幅“此视图当前仅供查看。请在主任务打开新的操作入口”,禁用全部提交按钮(app.tsx L45–49)。

  • 未保存草稿防切页丢稿保护(task.dirty):ui/src/state/use-task.ts 维护编辑缓冲区 dirtyCount;当用户在规则或映射界面存在未保存修改(task.dirty === true)而主任务在后台推进 requestedView 时,app.tsx(L19, L32–35)拦截自动切页并提示“主任务已切换页面,此处仍有未保存输入”,直至用户确认放弃草稿或完成保存。

  • task_provider.py 纯路由与准入前确定性拒绝(2.1.16):入口收敛为 55 行纯路由;无规则基线、未采用草稿或缺少连接等准入前拒绝由 calculation_rejection.py 在零写入前提下显式标记 executionState = "completed"(配套 AdmissionOutcome.tla),避免 Host 将未发生副作用的业务拒绝误判为 unknown;工作簿与回执摘要化使单任务状态体积约减三成。

  • aida-plugins · plugins/attendance-tally/plugin.json L1–69 · com.caidao.attendance-tally / mainView · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/contracts/task-tools.json L215–234 / L1663–1672 / L2054–2063 · attendance_task_record_turn / userActionOnly · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/task_workbench.py L77–113 / L1275–1305 · AttendanceTaskWorkbench / expectedRevision · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/compiler.py L486–535 · compile_rule_model · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/runtime.py L176–268 · CalculationEngine · a33ce3733365

  • aida-plugins · plugins/attendance-tally/ui/src/app.tsx L14–52 · task.dirty / task.context.mayAct · a33ce3733365

  • aida-plugins · plugins/attendance-tally/ui/src/state/use-task.ts L15–130 · getTaskContext / submitAction · a33ce3733365

5. Rework 局部失效状态机、M01–M11 编译冲突裁决与额度批次扣减(视图 attendance-rework-compile)

  • Rework 事务与闭包影响分析(rework_lifecycle.py / rework_impact.py / rework_transaction.py):

    • begin_change 与 stage_change 绑定 baseRevision 与 draftVersion,经过四路预检(preflight_rule_change、preflight_workbook_change、preflight_profile_change、preflight_input_change)。
    • rework_impact.py:analyze_change 比较变更前后状态,并沿 M01–M11 模块依赖图求传递闭包(_closure),生成 ReworkChangeSet。
    • ReworkTransaction._invalidate(rework_transaction.py L625–676)仅清除受波及的下游确认位(例如仅更换打卡表时不退回规则确认),并通过 rework_input_history.py:preserve_input_baseline 保留未受影响的输入基线。
  • M01–M11 编译期冲突检测与引用完整性(scope_overlap.py / rework_rule_references.py):

    • domain/scope_overlap.py(policies_may_overlap、expressions_disjoint、periods_disjoint)在编译期静态判定同一模块内两条策略的适用人群与有效期是否可能重叠且缺少显式优先级。
    • application/rework_rule_references.py(reference_issues、cycles)校验跨模块实体引用(班次、假种、日历、排班周期)的存在性与有向图无环。
  • M11 额度批次扣减与 Run 依赖快照发布(quota_period.py / rework_run_publication.py):

    • domain/quota_period.py(apply_policy、expired)将期初余额与 M07 加班转调休新增按假种与批次有效期排序(先过滤已过期批次,再按先到期/先旧后新单向扣减),输出非负余额与不足异常,绝不反向推翻已认定的休假。
    • application/rework_run_publication.py(RunPublication.register / publish)绑定 CalculationDependencies 快照指纹,并对回执做摘要化保留(rework_receipt_retention.py:compact_receipts)。
  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_lifecycle.py L137–235 · begin_change / stage_change · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_impact.py L154–215 · _closure / analyze_change · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_transaction.py L633–698 · _invalidate / apply · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/scope_overlap.py L68–105 · expressions_disjoint / policies_may_overlap · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/quota_period.py L70–105 · apply_policy / expired · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_run_publication.py L276–385 · class RunPublication · a33ce3733365

机制说明

纵向业务挂载:salary-smartcalc 与 attendance-tally

平台 × 业务接缝

aida-plugins 包 com.caidao.salary-smartcalc(薪资智算)以 plugin.json + contracts/tools.json 声明 hostApi、targets 与工具合同;runtime 自 594ef08c 起由 native sidecar 改为 Python(runtime.kind: python,entry salary_plugin.provider:create_plugin)(如 analyze_salary_logic);包本身不持有服务端 Run 状态。

Desktop Main PluginHost 发现/加载不可变包,经 taskProjections / listProjections 产出 PluginToolProjection 广告。企业 chat 流把投影带进 Agent;resolveExplicitPluginTask 按显式选择解析,失败不得静默退回内置能力。钉点 e2adc9a3c325 起,「用 xxx-cli」若与已安装独立 Skill 同名且没有命中插件,则跳过、交给 Skill 目录,不再当作插件选择失败。

调用 / 回执

PluginCallJournal 相位 admitted → dispatched → settled:dispatch 屏障失败则落 uncertain / failed 回执,禁止重启后盲重放。Agent 侧 parseBoundPluginReply 校验 pluginId/version/toolId/contractDigest(及 optional runtimeRevision)与 outputSchema / maxResultBytes;不一致返回 null。

归属边与非目标

  • Owner:包合同在 aida-plugins;Host/Journal 在 Desktop Main;绑定校验在 Agent。
  • 非目标:不把 Worker 画进服务端 Runtime;不展开全部薪资算法实现。
  • 相关:capability-plugins、plugin-v2-host-runtime、plugin-run-projection、trust-boundaries。

视图

  • main — 合同 → Host → 投影 → 解析。

  • call-receipt — salary-smartcalc 工具调用与回执校验。

  • fail-plugin-settle — 调用失败 / 回执拒收 / journal settle。

  • fail-manifest — Manifest/投影缺工具。

  • ok-plugin-settle — Plugin journal settle 成功(对偶 fail-plugin-settle)。

  • ok-manifest — Manifest/投影命中工具(对偶 fail-manifest)。

  • attendance-workflow — 考勤核算(attendance-tally):7 阶段端到端工作流、M01–M11 编译与单向算子 DAG。

  • attendance-desktop-loop — Desktop × 考勤核算(attendance-tally):React 视图桥接、CAS/只读保护与 userActionOnly 闭环。

  • attendance-rework-compile — 考勤深潜:Rework 局部失效状态机、M01–M11 编译冲突裁决与 M11 额度批次扣减。

成功对偶(与失败链入口相同)

  1. ok-plugin-settle:markDispatched → settle succeeded → parseBoundPluginReply 接受。
  2. ok-manifest:taskProjections 含 skills → resolveExplicit 唯一候选。

失败链(深挖)

  1. fail-plugin-settle:dispatch 屏障失败 → uncertain/failed;parseBoundPluginReply null;禁重启盲重放。
  2. fail-manifest:空投影 / 无 skills → PLUGIN_TASK_UNAVAILABLE;resolveExplicitPluginTask 同码;不静默退回内置。

普通入口冻结已选插件(钉点 e2adc9a3c325)

以前只有显式带 pluginTask 的入口会冻结插件绑定。现在普通 Work 入口也会:路由选中某个插件能力时,从本轮 Desktop 已公布的插件投影里解析出这个插件,冻结绑定,并把唯一匹配的那份投影随 Work 存下。对不上(不是恰好一个、投影里没工具、能力 id 不符)就拒绝受理,错误码 RUNTIME_WORK_PLUGIN_SOURCE_INVALID,不会静默换成别的插件。

Agent 内 verticals/ 接缝(MR-6a~6g,钉点 e2adc9a3c325)

7 个提交把内核里的垂直特例平移到同层 verticals/ 目录:6a 路由注释去垂直词;6b VMS 入职批次路由→gateway/verticals/route-packs.ts;6c 确认/续办工具特征与权限拒绝→orchestrator/**/verticals;6d 入职批次工具与 SOW 定时处理器→runtime/work/verticals、scheduler/verticals;6e VMS 角色守卫→routing/verticals/operation-role-guard.ts;6f 业务对象意图表→routing/verticals/business-intent-catalog.ts;6g Child Kernel 招聘分支→agent-as-tool/verticals/recruit-child-run-policy.ts。

决定:不单独成题、不画新图。 理由:全是行为不变的搬家,没有新运行时边、状态、持久化或信任边界;现有图的节点和箭头都不变。只在这里记下「内核不带垂直知识、由组合根接线」这条约定。残留:child-run-orchestrator.ts L2916 仍有 recruit 字面量。未运行 Agent 测试。

证据与范围

  • aida-plugins · plugins/salary-smartcalc/plugin.json L1–38 · "kind": "python" · a33ce3733365

  • aida-plugins · plugins/salary-smartcalc/contracts/tools.json L5–35 · analyze_salary_logic · a33ce3733365

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L195–199 · PluginHost · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–655 · taskProjections · 4346d79eb364

  • aida-desktop · apps/desktop/electron/agent-loop/enterprise-adapter.ts L92–123 · preparePluginTools · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L29–61 · phase · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L266–297 · settle · 4346d79eb364

  • aida-agent · packages/agent/src/runtime/local/plugin-task.ts L17–47 · resolveExplicitPluginTask · e2adc9a3c325

  • aida-agent · packages/agent/src/runtime/local/plugin-task.ts L72–77 · isStandaloneSkill · e2adc9a3c325

  • aida-agent · packages/agent/src/runtime/local/plugin-tool-receipt.ts L33–64 · parseBoundPluginReply · e2adc9a3c325

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–645 · taskProjections/PLUGIN_TASK_UNAVAILABLE · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-call-journal.ts L263–327 · settle/markDispatched · 4346d79eb364

  • aida-desktop · apps/desktop/electron/plugin-host/plugin-host.ts L625–655 · taskProjections · 4346d79eb364

结论来自固定版本的静态源码与合同阅读;实现存在、默认开关和生产启用分别判断。本站代码证据面板列出声明状态与具体限制。

  • aida-agent · packages/agent/src/gateway/workbench-route-preparation.ts L108–115 · resolveExplicitPluginTask · e2adc9a3c325
  • aida-agent · packages/agent/src/session/chat-submission-store.ts L759–769 · RUNTIME_WORK_PLUGIN_SOURCE_INVALID · e2adc9a3c325
  • aida-agent · packages/agent/src/gateway/verticals/route-packs.ts L1–18 · mountGatewayVerticalRoutes · e2adc9a3c325
  • aida-agent · packages/agent/src/routing/verticals/operation-role-guard.ts L14–47 · roleGuardOwnsSlotCollection · e2adc9a3c325
  • aida-agent · packages/agent/src/orchestrator/agent-as-tool/verticals/recruit-child-run-policy.ts L28–199 · prepareChildCapabilityRequest · e2adc9a3c325
  • aida-agent · packages/agent/src/routing/router.ts L2740–2744 · NO_INTENT_PACKS · e2adc9a3c325

考勤核算(com.caidao.attendance-tally 2.1.16)完整架构拆解(视图 attendance-workflow & attendance-desktop-loop,钉点 d220086aa495)

1. 四大核心设计铁律:AI 负责“语义理解”,Plugin 负责“台账、编译与确定性计算”

  1. 原话证据链(Fact & Provenance):用户每说一句话,Agent 必须先通过 attendance_task_record_turn 登记原话并切分句子(sentenceRanges),将提取出的规则字段与客户原话片段绑定(factId / sourceText);明确政策写入 changes,缺失细节登记为 ask 追问,推断项记为 propose,跨领域记为 unsupported,严禁大模型脑补默认政策。
  2. 双模型分离与确定性编译(RuleModel → CalculationModel):
    • RuleModel(M01–M11):客户审阅确认后的业务政策唯一真源(rule-model-2.0.schema.json)。
    • CalculationModel:由编译器(domain/compiler.py:compile_rule_model)将已确认的 RuleModel 确定性编译出的算子有向无环图(DAG,calculation-model-2.0.schema.json)。
    • 本地确定性执行:计算引擎(domain/runtime.py:CalculationEngine.run)在本地执行 Excel 数据核算,员工原始数据、中间结果与导出工作簿只留在本机。
  3. 四道人工门禁(userActionOnly)与乐观锁(expectedRevision CAS):
    • 规则确认(attendance_task_confirm)、员工日计划确认、发起计算(attendance_task_calculate)、模型发布四个关键写操作声明 userActionOnly: true,必须由用户在 UI 视图亲自点击并携带宿主签发的 userActionReceipt,Agent 无法代点或绕过。
    • AttendanceTaskWorkbench 所有状态修改强制校验 expectedRevision === self.revision。
  4. 随时局部返工(Rework)与跨月客户模型复用(Registry & Customer):
    • 用户在后续步骤修改规则或替换输入文件时,通过 input_rework / rule_workbook / rule_rebase 触发 ReworkChangeSet 与 ReworkProgress,精确标记受波及的下游确认项(如日计划确认、实绩检查),未受影响阶段无需推倒重来。
    • 通过 attendance-model-registry(声明 suggestedBaseUrl)发布或拉取已确认的 CustomerRuleModelSnapshot 与 CustomerCalculationModelSnapshot,支持跨会话/下月一键复用。

2. 端到端 7 阶段工作流与 10 个前端视图(plugin.json + task-tools.json)

插件声明 10 个前端视图(rules、sources、mapping、input_rework、rule_workbook、plan、calculation、results、registry、customer)与 39 个工具,每次调用在 workflow.nextAction 返回唯一确定的下一步指引:

  • 阶段 1–2(规则采集 → 审阅确认):自然语言访谈或导入 v3 访谈表(rule_workbook)→ rules 视图展开 M01–M11 核对纠错并点击确认 → 编译生成 CalculationModel。
  • 阶段 3–4(周期与文件导入 → 表头映射与预检):sources 视图设置核算周期与上传花名册/日历/打卡/休假/加班/覆盖声明 → mapping 视图完成字段映射与关联表预检。
  • 阶段 5–7(员工日计划与实绩预检 → 确定性计算 → 结果复核与发布):plan 视图生成并人工确认《员工日计划表》后执行 attendance_task_check_actuals → calculation 视图人工点击触发 CalculationEngine → results / registry 视图查看日明细、月汇总、异常表并导出 Artifact 或发布至模型库。

3. 考勤领域模型(M01–M11)与单向确定性计算顺序

业务规则拆分为 11 个正交子模型(每个子模型统一包含 definitions 可复用定义与 policies 适用范围策略):

模块 名称 核心职责
M01 日历与考勤周期 考勤周期起止边界、政策统一有效期(policyEffectivePeriod)、法定节假日与企业调休历
M02 员工资格与适用范围 标准花名册字段要求、人员分组(scope)、入离职折算边界
M03 班次与排班 固定班次、弹性班次(flex_shifts)、跨夜班次、休息时段、最低出勤要求
M04 打卡与出勤凭证 原始打卡窗口识别、免打卡人群/一次到岗(day_only)规则、打卡证据有效性
M05 异常考勤 迟到、早退、缺卡、旷工判定阈值、宽限期与计量方式
M06 假期与休假考勤 假期类型定义、计假单位/取整、休假对出勤义务的免除效果
M07 加班与调休 工作日/休息日/节假日三类加班方案、来源路由(审批单 vs 打卡识别)、转调休比例
M08 特殊出勤 出差、外勤、培训等特殊事项对工作日/休息日工时的贡献边界
M09 补卡与更正 补卡记录替换原始缺卡、次数上限控制、幂等与重算范围
M10 工时归集与结算 汇总实际出勤、休假、特殊出勤与异常,完成每日评价与周期结算小计
M11 额度变动与结转 期初余额 + 本期新增(含 M07 加班转调休)汇总,按假种与批次优先级(先到期/先旧后新)扣减,输出非负余额与不足异常
  • 单向确定性计算 DAG(严禁循环试算与反向推翻): 基准员工日计划 (C04) ➔ 原始打卡筛选与有效补卡 (C09) 及弹性班次顺延 (C04F) ➔ 实际工作事实固定 (C10A) ➔ 休假规范化与出勤义务计算 (M06) ➔ 加班认定与转调休新增 (M07) ➔ 期初与新增额度汇总及按批次扣减 (M11) ➔ 正常出勤/迟到早退/旷工最终裁决与汇总导出 (M05/M10)。例如额度不足只报额度异常,绝不反向推翻已认定的休假或重算加班。

4. Desktop × 考勤 React UI 双端交互与状态保护(视图 attendance-desktop-loop)

  • window.aida 桥接与只读横幅(mayAct):前端 ui/src/app.tsx 挂载在 Desktop PluginMainView 中,通过 getTaskContext() 与只读 stateToolId(attendance_view_state)拉取快照;当用户在历史卡片查看旧视图(!task.context.mayAct)时,顶部展示黄色告警横幅“此视图当前仅供查看。请在主任务打开新的操作入口”,禁用全部提交按钮(app.tsx L45–49)。

  • 未保存草稿防切页丢稿保护(task.dirty):ui/src/state/use-task.ts 维护编辑缓冲区 dirtyCount;当用户在规则或映射界面存在未保存修改(task.dirty === true)而主任务在后台推进 requestedView 时,app.tsx(L19, L32–35)拦截自动切页并提示“主任务已切换页面,此处仍有未保存输入”,直至用户确认放弃草稿或完成保存。

  • task_provider.py 纯路由与准入前确定性拒绝(2.1.16):入口收敛为 55 行纯路由;无规则基线、未采用草稿或缺少连接等准入前拒绝由 calculation_rejection.py 在零写入前提下显式标记 executionState = "completed"(配套 AdmissionOutcome.tla),避免 Host 将未发生副作用的业务拒绝误判为 unknown;工作簿与回执摘要化使单任务状态体积约减三成。

  • aida-plugins · plugins/attendance-tally/plugin.json L1–69 · com.caidao.attendance-tally / mainView · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/contracts/task-tools.json L215–234 / L1663–1672 / L2054–2063 · attendance_task_record_turn / userActionOnly · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/task_workbench.py L77–113 / L1275–1305 · AttendanceTaskWorkbench / expectedRevision · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/compiler.py L486–535 · compile_rule_model · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/runtime.py L176–268 · CalculationEngine · a33ce3733365

  • aida-plugins · plugins/attendance-tally/ui/src/app.tsx L14–52 · task.dirty / task.context.mayAct · a33ce3733365

  • aida-plugins · plugins/attendance-tally/ui/src/state/use-task.ts L15–130 · getTaskContext / submitAction · a33ce3733365

5. Rework 局部失效状态机、M01–M11 编译冲突裁决与额度批次扣减(视图 attendance-rework-compile)

  • Rework 事务与闭包影响分析(rework_lifecycle.py / rework_impact.py / rework_transaction.py):

    • begin_change 与 stage_change 绑定 baseRevision 与 draftVersion,经过四路预检(preflight_rule_change、preflight_workbook_change、preflight_profile_change、preflight_input_change)。
    • rework_impact.py:analyze_change 比较变更前后状态,并沿 M01–M11 模块依赖图求传递闭包(_closure),生成 ReworkChangeSet。
    • ReworkTransaction._invalidate(rework_transaction.py L625–676)仅清除受波及的下游确认位(例如仅更换打卡表时不退回规则确认),并通过 rework_input_history.py:preserve_input_baseline 保留未受影响的输入基线。
  • M01–M11 编译期冲突检测与引用完整性(scope_overlap.py / rework_rule_references.py):

    • domain/scope_overlap.py(policies_may_overlap、expressions_disjoint、periods_disjoint)在编译期静态判定同一模块内两条策略的适用人群与有效期是否可能重叠且缺少显式优先级。
    • application/rework_rule_references.py(reference_issues、cycles)校验跨模块实体引用(班次、假种、日历、排班周期)的存在性与有向图无环。
  • M11 额度批次扣减与 Run 依赖快照发布(quota_period.py / rework_run_publication.py):

    • domain/quota_period.py(apply_policy、expired)将期初余额与 M07 加班转调休新增按假种与批次有效期排序(先过滤已过期批次,再按先到期/先旧后新单向扣减),输出非负余额与不足异常,绝不反向推翻已认定的休假。
    • application/rework_run_publication.py(RunPublication.register / publish)绑定 CalculationDependencies 快照指纹,并对回执做摘要化保留(rework_receipt_retention.py:compact_receipts)。
  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_lifecycle.py L137–235 · begin_change / stage_change · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_impact.py L154–215 · _closure / analyze_change · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_transaction.py L633–698 · _invalidate / apply · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/scope_overlap.py L68–105 · expressions_disjoint / policies_may_overlap · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/domain/quota_period.py L70–105 · apply_policy / expired · a33ce3733365

  • aida-plugins · plugins/attendance-tally/runtime/src/attendance_plugin/application/rework_run_publication.py L276–385 · class RunPublication · a33ce3733365

代码证据

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

已核验实现

salary-smartcalc 以 plugin.json id com.caidao.salary-smartcalc 声明 hostApi 2、darwin/win32 targets 与 contracts/tools.json 工具合同;runtime 已由 native sidecar 改为 Python(runtime.kind=python,entry salary_plugin.provider:create_plugin)。

aida-pluginsplugins/salary-smartcalc/plugin.json:1–38a33ce3733365db48413a4b97a0f4f65066856175符号:"kind": "python"
已核验实现

contracts/tools.json 声明 analyze_salary_logic 等工具 id/effect/timeout 与输入合同,包不持有服务端 Run 状态。

aida-pluginsplugins/salary-smartcalc/contracts/tools.json:5–35a33ce3733365db48413a4b97a0f4f65066856175符号:analyze_salary_logic
已核验实现

Desktop PluginHost 在 Main 内管理包与 taskProjections;企业适配器可 preparePluginTools 把投影送入 chat。

aida-desktopapps/desktop/electron/plugin-host/plugin-host.ts:96–1274346d79eb36402355e51118df0edf1f98586880c符号:export class PluginHost
aida-desktopapps/desktop/electron/plugin-host/plugin-host.ts:846–8864346d79eb36402355e51118df0edf1f98586880c符号:taskProjections
aida-desktopapps/desktop/electron/agent-loop/enterprise-adapter.ts:173–2044346d79eb36402355e51118df0edf1f98586880c符号:preparePluginTools
已核验实现

PluginCallJournal 相位 admitted/dispatched/settled:settle 持久化回执;dispatch 后写失败落 uncertain,禁止盲重放。

aida-desktopapps/desktop/electron/plugin-host/plugin-call-journal.ts:332–3644346d79eb36402355e51118df0edf1f98586880c符号:phase
aida-desktopapps/desktop/electron/plugin-host/plugin-call-journal.ts:559–5904346d79eb36402355e51118df0edf1f98586880c符号:settle
已核验实现

Agent resolveExplicitPluginTask 按投影显式解析插件任务;未命中不得静默退回内置能力。钉点 2141b561dc97 起,名称与已安装独立 Skill 相同的「用 xxx-cli」指令在没有命中插件时跳过(交给 Skill 目录),不再当作插件选择失败。

aida-agentpackages/agent/src/runtime/local/plugin-task.ts:17–477f2e519936b57902d4907ed8026fe1ecdd146e82符号:resolveExplicitPluginTask
aida-agentpackages/agent/src/runtime/local/plugin-task.ts:97–1027f2e519936b57902d4907ed8026fe1ecdd146e82符号:isStandaloneSkill
已核验实现

parseBoundPluginReply 校验回执与绑定的 pluginId/version/toolId/contractDigest 及 outputSchema/maxResultBytes,不一致返回 null。

aida-agentpackages/agent/src/runtime/local/plugin-tool-receipt.ts:38–697f2e519936b57902d4907ed8026fe1ecdd146e82符号:parseBoundPluginReply
已核验实现

失败链:PluginCallJournal dispatch 屏障失败或 settle 写失败时落 failed/unknown(uncertain),禁止重启后盲重放;parseBound 拒错绑定。

aida-desktopapps/desktop/electron/plugin-host/plugin-call-journal.ts:559–5904346d79eb36402355e51118df0edf1f98586880c符号:settle
aida-agentpackages/agent/src/runtime/local/plugin-tool-receipt.ts:38–697f2e519936b57902d4907ed8026fe1ecdd146e82符号:parseBoundPluginReply
已核验实现

失败链:taskProjections 缺失或 resolveExplicitPluginTask 候选不为 1 时抛 PLUGIN_TASK_UNAVAILABLE,不得静默退回内置能力。

aida-desktopapps/desktop/electron/plugin-host/plugin-host.ts:929–9594346d79eb36402355e51118df0edf1f98586880c符号:PLUGIN_TASK_UNAVAILABLE_CODE
aida-agentpackages/agent/src/runtime/local/plugin-task.ts:121–1517f2e519936b57902d4907ed8026fe1ecdd146e82符号:PLUGIN_TASK_UNAVAILABLE
已核验实现

PluginCallJournal.execute 在 markDispatched 成功后 settle 写入 phase=settled 与成功 reply,供后续幂等观察。

aida-desktopapps/desktop/electron/plugin-host/plugin-call-journal.ts:559–5904346d79eb36402355e51118df0edf1f98586880c符号:settle
已核验实现

PluginHost.taskProjections 在选择有效且投影含工具时返回投影列表;缺失则抛 PLUGIN_TASK_UNAVAILABLE。

aida-desktopapps/desktop/electron/plugin-host/plugin-host.ts:846–8864346d79eb36402355e51118df0edf1f98586880c符号:taskProjections
已核验实现

普通 Work 入口在调用方未显式传 pluginTask 时,按路由选中的 capabilityId 从本轮已公布的插件投影解析 Plugin(resolveExplicitPluginTask),再 freezePluginTaskBinding 冻结;受理时只保留与绑定精确匹配的唯一投影,匹配不是恰好一个、投影无工具或 capability 不符则 RUNTIME_WORK_PLUGIN_SOURCE_INVALID。

aida-agentpackages/agent/src/gateway/workbench-route-preparation.ts:273–2807f2e519936b57902d4907ed8026fe1ecdd146e82符号:resolveExplicitPluginTask
aida-agentpackages/agent/src/session/chat-submission-store.ts:1478–14887f2e519936b57902d4907ed8026fe1ecdd146e82符号:RUNTIME_WORK_PLUGIN_SOURCE_INVALID
已核验实现

MR-6a~6g 把 Agent 内核里的垂直业务特例(VMS 入职批次网关路由、确认/续办工具特征、启动期入职批次工具与 SOW 定时处理器、VMS 角色守卫、业务对象意图表、Child Kernel 招聘分支)平移到各层 */verticals/ 模块,由内核以注入/导入方式调用;行为保持不变,未新增运行时边、状态或持久化。router 内核默认 intent pack 为空,由组合根接线。

静态读 7 个 MR-6 提交 diff 与钉点文件;未运行 Agent 测试。child-run-orchestrator.ts L2758 仍留 recruit / create_and_recommend_candidate 字面量,迁移非 100% 干净。

aida-agentpackages/agent/src/gateway/verticals/route-packs.ts:11–217f2e519936b57902d4907ed8026fe1ecdd146e82符号:mountGatewayVerticalRoutes
aida-agentpackages/agent/src/orchestrator/confirmation/verticals/confirmation-tool-traits.ts:50–777f2e519936b57902d4907ed8026fe1ecdd146e82符号:verticalOwnsConfirmedSummary
aida-agentpackages/agent/src/runtime/work/verticals/onboarding-batch-bootstrap.ts:32–747f2e519936b57902d4907ed8026fe1ecdd146e82符号:installOnboardingBatchTools
aida-agentpackages/agent/src/routing/verticals/operation-role-guard.ts:25–557f2e519936b57902d4907ed8026fe1ecdd146e82符号:roleGuardOwnsSlotCollection
aida-agentpackages/agent/src/routing/verticals/business-intent-catalog.ts:4–447f2e519936b57902d4907ed8026fe1ecdd146e82符号:STANDARD_PACK_INTENT_OBJECTS
aida-agentpackages/agent/src/orchestrator/agent-as-tool/verticals/recruit-child-run-policy.ts:24–1947f2e519936b57902d4907ed8026fe1ecdd146e82符号:prepareChildCapabilityRequest
aida-agentpackages/agent/src/routing/router/selection.ts:35–357f2e519936b57902d4907ed8026fe1ecdd146e82符号:NO_INTENT_PACKS
已核验实现

考勤核算插件(attendance-tally 2.1.16)边界收敛:task_provider.py 收敛为 55 行纯路由入口;calculation_rejection.py 在准入前确定性拒绝时记录未执行回执;plugin.json 为 attendance-model-registry 声明 suggestedBaseUrl。

aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/task_provider.py:4–44a33ce3733365db48413a4b97a0f4f65066856175符号:def call
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/application/calculation_rejection.py:115–155a33ce3733365db48413a4b97a0f4f65066856175符号:def record_rejection
aida-pluginsplugins/attendance-tally/plugin.json:182–192a33ce3733365db48413a4b97a0f4f65066856175符号:suggestedBaseUrl
已核验实现

考勤核算(com.caidao.attendance-tally)工作流与确定性编译执行:plugin.json 声明 10 个 mainView 视图;task-tools.json 声明 attendance_task_record_turn 原话采集及 userActionOnly 门禁工具(attendance_task_confirm / attendance_task_calculate 等);compile_rule_model 将 M01–M11 RuleModel 编译为 CalculationModel,由 CalculationEngine.run 在本地单向确定性执行。

aida-pluginsplugins/attendance-tally/plugin.json:1–84a33ce3733365db48413a4b97a0f4f65066856175符号:mainView
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/contracts/task-tools.json:4469–4479a33ce3733365db48413a4b97a0f4f65066856175符号:attendance_task_confirm
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/domain/compiler.py:485–525a33ce3733365db48413a4b97a0f4f65066856175符号:def compile_rule_model
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/domain/runtime.py:186–258a33ce3733365db48413a4b97a0f4f65066856175符号:class CalculationEngine
已核验实现

Desktop × 考勤 React UI 状态保护与 CAS 乐观锁:ui/src/app.tsx 在 !task.context.mayAct 时渲染只读告警横幅,在 task.dirty 且主任务后台切页时拦截自动跳转防丢稿;ui/src/state/use-task.ts 通过 getTaskContext 与 submitAction 传递 expectedRevision,后端 AttendanceTaskWorkbench 强制校验 expectedRevision === self.revision。

aida-pluginsplugins/attendance-tally/ui/src/app.tsx:14–52a33ce3733365db48413a4b97a0f4f65066856175符号:task.dirty
aida-pluginsplugins/attendance-tally/ui/src/state/use-task.ts:115–130a33ce3733365db48413a4b97a0f4f65066856175符号:submitAction
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/application/task_workbench.py:1331–1371a33ce3733365db48413a4b97a0f4f65066856175符号:expectedRevision
已核验实现

考勤 Rework 局部失效状态机、M01–M11 编译期冲突检测与 M11 额度批次扣减:rework_impact.py (analyze_change / _closure) 求模块变更传递闭包,rework_transaction.py (_invalidate) 仅清除受波及确认位并由 preserve_input_baseline 保留有效基线;scope_overlap.py (policies_may_overlap) 在编译期阻断无优先级的范围重叠;quota_period.py (apply_policy / expired) 按有效期与批次顺序单向扣减额度,RunPublication 绑定依赖指纹发布。

aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/application/rework_impact.py:154–215a33ce3733365db48413a4b97a0f4f65066856175符号:def analyze_change
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/application/rework_transaction.py:633–693a33ce3733365db48413a4b97a0f4f65066856175符号:def _invalidate
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/domain/scope_overlap.py:68–105a33ce3733365db48413a4b97a0f4f65066856175符号:def policies_may_overlap
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/domain/quota_period.py:70–105a33ce3733365db48413a4b97a0f4f65066856175符号:def apply_policy
aida-pluginsplugins/attendance-tally/runtime/src/attendance_plugin/application/rework_run_publication.py:276–345a33ce3733365db48413a4b97a0f4f65066856175符号:class RunPublication