@xdxer/dingtalk-agent 0.1.4 → 0.1.5-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/README.en.md +115 -89
  3. package/README.md +111 -86
  4. package/dist/bin/dingtalk-agent.js +742 -152
  5. package/dist/bin/dingtalk-agent.js.map +1 -1
  6. package/dist/src/actions.js +3 -2
  7. package/dist/src/actions.js.map +1 -1
  8. package/dist/src/agent-audit.js +202 -85
  9. package/dist/src/agent-audit.js.map +1 -1
  10. package/dist/src/agent-definition.js +7 -3
  11. package/dist/src/agent-definition.js.map +1 -1
  12. package/dist/src/agent-enhance.js +51 -32
  13. package/dist/src/agent-enhance.js.map +1 -1
  14. package/dist/src/agent-platform.js +4 -4
  15. package/dist/src/agent-platform.js.map +1 -1
  16. package/dist/src/bootstrap.js +6 -2
  17. package/dist/src/bootstrap.js.map +1 -1
  18. package/dist/src/development-workspace.js +210 -34
  19. package/dist/src/development-workspace.js.map +1 -1
  20. package/dist/src/doctor.js +65 -9
  21. package/dist/src/doctor.js.map +1 -1
  22. package/dist/src/dws.js +67 -3
  23. package/dist/src/dws.js.map +1 -1
  24. package/dist/src/init.js +2 -1
  25. package/dist/src/init.js.map +1 -1
  26. package/dist/src/memory/noop-receipt.js +306 -0
  27. package/dist/src/memory/noop-receipt.js.map +1 -0
  28. package/dist/src/memory/operational.js +27 -3
  29. package/dist/src/memory/operational.js.map +1 -1
  30. package/dist/src/memory/remote-state.js +2 -1
  31. package/dist/src/memory/remote-state.js.map +1 -1
  32. package/dist/src/multica-deploy.js +692 -125
  33. package/dist/src/multica-deploy.js.map +1 -1
  34. package/dist/src/multica-provider.js +303 -25
  35. package/dist/src/multica-provider.js.map +1 -1
  36. package/dist/src/multica-runtime-vocabulary.js +110 -0
  37. package/dist/src/multica-runtime-vocabulary.js.map +1 -0
  38. package/dist/src/opencode-evals.js +6 -6
  39. package/dist/src/opencode-evals.js.map +1 -1
  40. package/dist/src/opencode-provider.js +21 -7
  41. package/dist/src/opencode-provider.js.map +1 -1
  42. package/dist/src/opencode-workspace.js +3 -3
  43. package/dist/src/opencode-workspace.js.map +1 -1
  44. package/dist/src/personal-event-evals.js +4 -2
  45. package/dist/src/personal-event-evals.js.map +1 -1
  46. package/dist/src/promotion.js +2 -1
  47. package/dist/src/promotion.js.map +1 -1
  48. package/dist/src/remote-semantic-state-live-evals.js +14 -8
  49. package/dist/src/remote-semantic-state-live-evals.js.map +1 -1
  50. package/dist/src/remote-state-evals.js +2 -2
  51. package/dist/src/remote-state-evals.js.map +1 -1
  52. package/dist/src/robot-evals.js +3 -3
  53. package/dist/src/robot-evals.js.map +1 -1
  54. package/dist/src/schedule-plan.js +380 -0
  55. package/dist/src/schedule-plan.js.map +1 -0
  56. package/dist/src/sessions.js +1 -1
  57. package/dist/src/sessions.js.map +1 -1
  58. package/dist/src/skill-manager.js +145 -13
  59. package/dist/src/skill-manager.js.map +1 -1
  60. package/dist/src/skills.js +2 -0
  61. package/dist/src/skills.js.map +1 -1
  62. package/dist/src/tui.js +369 -0
  63. package/dist/src/tui.js.map +1 -0
  64. package/dist/src/upgrade.js +113 -33
  65. package/dist/src/upgrade.js.map +1 -1
  66. package/dist/src/waits.js +2 -1
  67. package/dist/src/waits.js.map +1 -1
  68. package/dist/src/workspace.js +12 -7
  69. package/dist/src/workspace.js.map +1 -1
  70. package/docs/AGENT-IN-PRODUCTION.md +255 -0
  71. package/docs/ARCHITECTURE.md +366 -0
  72. package/docs/INSTALLATION.md +8 -8
  73. package/docs/PLATFORM-GUARDRAILS.md +188 -0
  74. package/docs/PRIOR-ART.md +126 -0
  75. package/docs/SELF-TEST.md +182 -0
  76. package/docs/architecture/agent-platform-connection-layer.svg +120 -0
  77. package/docs/architecture/digital-employee-composition.svg +92 -0
  78. package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
  79. package/docs/assets/digital-employee-at-work.svg +77 -0
  80. package/docs/schemas/multica-deployment-plan.schema.json +3 -1
  81. package/docs/schemas/multica-deployment-receipt.schema.json +17 -3
  82. package/docs/schemas/multica-deployment-status.schema.json +6 -2
  83. package/docs/schemas/multica-workspace-inspection.schema.json +16 -0
  84. package/docs/schemas/multica-workspace-run-plan.schema.json +31 -0
  85. package/docs/schemas/multica-workspace-run.schema.json +161 -0
  86. package/docs/schemas/multica-workspace-status.schema.json +2 -0
  87. package/docs/schemas/project.schema.json +54 -3
  88. package/docs/schemas/workspace-scaffold.schema.json +38 -0
  89. package/examples/agents/README.md +45 -0
  90. package/examples/agents/fde-coach/AGENTS.md +2 -25
  91. package/examples/agents/fde-coach/agent/AGENTS.md +35 -0
  92. package/examples/agents/fde-coach/agent.bindings.json +10 -0
  93. package/examples/agents/release-manager/AGENTS.md +2 -25
  94. package/examples/agents/release-manager/agent/AGENTS.md +35 -0
  95. package/examples/agents/release-manager/agent.bindings.json +10 -0
  96. package/lab/agent-eval/catalog.json +5 -5
  97. package/lab/agent-eval/classic-failures.json +4 -4
  98. package/lab/agent-eval/completion-gate-regression.json +9 -9
  99. package/lab/agent-eval/personal-event-live.example.json +3 -3
  100. package/lab/agent-eval/remote-semantic-state-live.example.json +1 -1
  101. package/lab/agent-eval/workspace/opencode.json +2 -2
  102. package/lab/project-workspace/fake-multica-provider.mjs +171 -17
  103. package/lab/project-workspace/multica-deploy.fixture.json +2 -2
  104. package/lab/project-workspace/multica-readonly.fixture.json +4 -16
  105. package/lab/project-workspace/opencode-provider-suite.json +3 -3
  106. package/lab/project-workspace/project.fixture.json +2 -6
  107. package/lab/robot-eval/suite.json +1 -1
  108. package/lab/robot-eval/workspace/AGENTS.md +1 -1
  109. package/lab/robot-eval/workspace/opencode.json +2 -2
  110. package/lab/schemas/personal-event-eval.schema.json +1 -1
  111. package/package.json +18 -11
  112. package/skills/README.md +10 -8
  113. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/SKILL.md +49 -24
  114. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/AGENTS.template.md +1 -1
  115. package/skills/core/dta-agent-compose/assets/REPOSITORY.template.md +10 -0
  116. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +2 -2
  117. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.local.template.json +2 -2
  118. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/hosts/opencode/opencode.template.json +3 -2
  119. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/evals/evals.json +4 -4
  120. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/agent-definition-contract.md +7 -7
  121. package/skills/core/dta-agent-compose/references/drive-and-schedules.md +166 -0
  122. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/host-loading-contract.md +11 -13
  123. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/claude-code.md +13 -12
  124. package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/opencode.md +14 -13
  125. package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/SKILL.md +28 -3
  126. package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/assets/eval-catalog.template.json +1 -1
  127. package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/evals/evals.json +1 -1
  128. package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/eval-topology.md +3 -3
  129. package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/interactive-debug-channels.md +10 -4
  130. package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/SKILL.md +21 -5
  131. package/skills/core/dta-basic-behavior/references/event-to-behavior.md +38 -0
  132. package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/memory-and-evolution.md +3 -1
  133. package/skills/core/dta-basic-behavior/references/perception-and-gates.md +87 -0
  134. package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/risk-authority-and-privacy.md +12 -0
  135. package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/truth-and-recovery.md +4 -2
  136. package/skills/core/dta-people-group-memory/COMPLETENESS.md +36 -0
  137. package/skills/core/dta-people-group-memory/SKILL.md +69 -0
  138. package/skills/core/dta-people-group-memory/references/adapters.md +273 -0
  139. package/skills/core/dta-people-group-memory/references/assembly-guidance.md +40 -0
  140. package/skills/core/dta-people-group-memory/references/binding.md +110 -0
  141. package/skills/core/dta-people-group-memory/references/cold-start.md +70 -0
  142. package/skills/core/dta-people-group-memory/references/config-binding.md +89 -0
  143. package/skills/core/dta-people-group-memory/references/consent-and-visibility.md +83 -0
  144. package/skills/core/dta-people-group-memory/references/consolidation.md +162 -0
  145. package/skills/core/dta-people-group-memory/references/event-ingest.md +103 -0
  146. package/skills/core/dta-people-group-memory/references/guided-setup.md +70 -0
  147. package/skills/core/dta-people-group-memory/references/model.md +148 -0
  148. package/skills/core/dta-people-group-memory/references/storage-port.md +107 -0
  149. package/skills/platforms/deap/PLATFORM.md +30 -1
  150. package/skills/platforms/multica-dingtalk/PLATFORM.md +35 -9
  151. package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/SKILL.md +10 -8
  152. package/skills/platforms/multica-dingtalk/dta-deploy-multica/references/multica-deployment-contract.md +67 -0
  153. package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/SKILL.md +81 -11
  154. package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/bootstrap.sh +2 -2
  155. package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/multica_ext.py +264 -16
  156. package/dist/src/map.js +0 -157
  157. package/dist/src/map.js.map +0 -1
  158. package/docs/SECOND-AGENT-ACCEPTANCE.md +0 -62
  159. package/docs/architecture/agent-memory-topology.png +0 -0
  160. package/docs/architecture/agent-memory-topology.svg +0 -132
  161. package/docs/architecture/dingtalk-agent-blueprint.png +0 -0
  162. package/docs/architecture/durable-async-agent-runtime.png +0 -0
  163. package/docs/architecture/general-agent-kernel-topology.png +0 -0
  164. package/docs/architecture/provider-bound-development-workspace.png +0 -0
  165. package/docs/architecture/task-completion-gate.png +0 -0
  166. package/docs/assets/agent-delivery-lifecycle.svg +0 -103
  167. package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +0 -24
  168. package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +0 -28
  169. package/skills/platforms/deap/README.md +0 -3
  170. package/skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica/SKILL.md +0 -40
  171. package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/multica-deployment-contract.md +0 -49
  172. /package/examples/agents/fde-coach/{skills → agent/skills}/fde-coach/SKILL.md +0 -0
  173. /package/examples/agents/release-manager/{skills → agent/skills}/release-manager/SKILL.md +0 -0
  174. /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/role-skill.template.md +0 -0
  175. /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/storage-routing.md +0 -0
  176. /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/evidence-contract.md +0 -0
  177. /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/failure-to-case.md +0 -0
  178. /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/local-connector-smoke.md +0 -0
  179. /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/scenario-taxonomy.md +0 -0
  180. /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/storage-modes.md +0 -0
  181. /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
  182. /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/task-checkpoint.json +0 -0
  183. /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/action-contract.md +0 -0
  184. /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/runtime-modes.md +0 -0
  185. /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/task-lifecycle.md +0 -0
  186. /package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/references/promotion-observation-contract.md +0 -0
@@ -9,10 +9,11 @@ import { prepareOpenCodeEvalAgent, resolveOpenCodeEvalAgent, readOpenCodeVersion
9
9
  import { bindRequiredBasicSkill, verifyRequiredBasicSkill } from './opencode-workspace.js';
10
10
  import { countInstructionsForPath } from './instruction-path.js';
11
11
  import { resolvePackageRoot } from './package-root.js';
12
- import { bundledSkillPath } from './skill-manager.js';
12
+ import { bundledSkillPath, isBasicSkillName } from './skill-manager.js';
13
13
  import { createIsolatedOpenCodeHost } from './opencode-isolation.js';
14
14
  const COMPOSE_TEMPLATE_MARKER = /<(?:Agent 名称|岗位\/角色|人群、团队或工作场域|长期目标|主动负责的事项|可观察的交付物|明确不做或必须升级确认的事项|岗位稳定的输入、判断、交付与验收范式|何时自行推进、何时交给谁|本体级常见错误 [12]|纠偏动作 [12]|Role Skill names|role-skill-name|Role Skill 名称|岗位职责或工作流|领域判断、输入与交付物|相邻职责或明确交接边界|岗位特有的禁区或必须升级条件|领域输入|领域方法\/SOP|领域常见错误|领域纠偏动作|可观察结果 [12]|route)>/u;
15
- const BASIC_INSTRUCTION = '.agents/skills/dingtalk-basic-behavior/SKILL.md';
15
+ const BASIC = 'dta-basic-behavior';
16
+ const BASIC_INSTRUCTION = '.agents/skills/dta-basic-behavior/SKILL.md';
16
17
  const DEFINITION_PROBE_PROMPT = '这是 Agent Definition 继承探针。只依据已强制加载的角色宪法末尾注释回答;' +
17
18
  '严格输出纯文本 dta-definition-probe=<值>,若看不到则输出纯文本 ' +
18
19
  'dta-definition-probe=not-loaded。不要使用反引号或代码块;禁止猜测、调用工具或解释。';
@@ -28,7 +29,7 @@ export function auditAgent(root, options = {}) {
28
29
  const hydrated = bootstrap(rootReal, { ...(options.bootstrap || {}), deferRemote: true });
29
30
  const definition = hydrated.definition;
30
31
  const requiredSkills = [...new Set((options.requiredSkills || [])
31
- .map((item) => item.trim()).filter((item) => item && item !== 'dingtalk-basic-behavior'))];
32
+ .map((item) => item.trim()).filter((item) => item && !isBasicSkillName(item)))];
32
33
  const checks = [];
33
34
  const add = (id, surface, level, blocking, summary, evidence = {}) => checks.push({ id, surface, level, blocking, summary, evidence });
34
35
  const memoryMounted = definition.storage.memory.startsWith('dingtalk-doc:') ||
@@ -65,7 +66,7 @@ export function auditAgent(root, options = {}) {
65
66
  : '远端语义状态缺少 DWS profile 或 expected user', { remoteSlots: remoteSlots.length, profileConfigured: Boolean(definition.authority.dwsProfile),
66
67
  expectedUserConfigured: Boolean(definition.authority.expectedUserId) });
67
68
  const roleSkills = new Map(definition.skills
68
- .filter((item) => item.name !== 'dingtalk-basic-behavior')
69
+ .filter((item) => !isBasicSkillName(item.name))
69
70
  .map((item) => [item.name, item]));
70
71
  for (const name of requiredSkills) {
71
72
  const skill = roleSkills.get(name);
@@ -77,42 +78,49 @@ export function auditAgent(root, options = {}) {
77
78
  }
78
79
  }
79
80
  const basic = readCanonicalBasicSkill();
80
- const basicExposurePath = join(rootReal, '.agents', 'skills', 'dingtalk-basic-behavior', 'SKILL.md');
81
+ // legacy 名也认一次:改名过渡期里 Definition 可能仍声明旧名。认出来之后 exposure
82
+ // 检查照常严格比对 canonical(旧副本必然 hash 不符,本来就该 fail)——这里放宽的只是
83
+ // 「找得到那份文件」,好让报告指向真正陈旧的路径,而不是含糊地说缺失。
84
+ const packagedBasic = definition.skills.find((item) => isBasicSkillName(item.name));
85
+ const declaredBasic = packagedBasic?.name || BASIC;
86
+ const basicExposurePath = packagedBasic?.path || join(rootReal, '.agents', 'skills', BASIC, 'SKILL.md');
81
87
  const basicExposure = inspectSkill(basicExposurePath);
82
88
  const basicExposureTree = inspectSkillTree(basicExposurePath);
83
89
  add('host.basic-exposure', 'host', basicExposure.exists && basicExposure.name === basic.name &&
84
90
  basicExposure.version === basic.version && basicExposure.hash === basic.hash &&
85
91
  basicExposureTree.hash === basic.treeHash ? 'pass' : 'fail', true, basicExposure.exists && basicExposure.hash === basic.hash &&
86
92
  basicExposureTree.hash === basic.treeHash
87
- ? 'OpenCode Basic Skill 全树 exposure 与 canonical source 一致'
88
- : 'OpenCode Basic Skill 入口、references 或 assets 缺失或发生漂移', { expected: basic, actual: { ...basicExposure, treeHash: basicExposureTree.hash,
93
+ ? 'Agent package 的 Basic Skill 全树与 canonical source 一致'
94
+ : 'Agent package 的 Basic Skill 入口、references 或 assets 缺失或发生漂移', { expected: basic, actual: { ...basicExposure, treeHash: basicExposureTree.hash,
89
95
  files: basicExposureTree.files, error: basicExposureTree.error } });
90
96
  const config = inspectOpenCodeConfig(rootReal);
91
97
  const definitionInstruction = definition.body?.path
92
98
  ? relative(rootReal, definition.body.path).split('\\').join('/') : '';
93
99
  const definitionInstructionCount = countInstructionsForPath(rootReal, config.instructions, definitionInstruction);
94
- const definitionRuleReady = !config.error && definitionInstruction === 'AGENTS.md' &&
95
- definitionInstructionCount === 0;
100
+ const definitionInstructionExpected = definitionInstruction === 'AGENTS.md' ? 0 : 1;
101
+ const definitionRuleReady = !config.error && Boolean(definitionInstruction) &&
102
+ definitionInstructionCount === definitionInstructionExpected;
96
103
  add('host.definition-rule', 'host', definitionRuleReady
97
104
  ? 'pass' : 'fail', true, definitionRuleReady
98
- ? 'OpenCode 使用项目根 AGENTS.md 原生 rule,且未重复声明 custom instruction'
99
- : 'Agent Definition 必须是项目根 AGENTS.md,且不能重复加入 opencode instructions', { path: config.path, error: config.error, instruction: definitionInstruction,
105
+ ? definitionInstruction === 'AGENTS.md'
106
+ ? 'OpenCode 使用项目根开发兼容模式的原生 Agent Definition'
107
+ : 'OpenCode 以唯一 custom instruction 加载独立 Agent Definition'
108
+ : 'Agent Definition 未形成唯一加载路径', { path: config.path, error: config.error, instruction: definitionInstruction,
100
109
  instructionCount: definitionInstructionCount });
101
- const instructionCount = countInstructionsForPath(rootReal, config.instructions, '.agents/skills/dingtalk-basic-behavior/SKILL.md');
110
+ const basicInstruction = relative(rootReal, basicExposurePath).split('\\').join('/');
111
+ const instructionCount = countInstructionsForPath(rootReal, config.instructions, basicInstruction);
102
112
  add('host.basic-instruction', 'host', !config.error && instructionCount === 1 &&
103
- config.permissions['dingtalk-basic-behavior'] === 'allow' ? 'pass' : 'fail', true, !config.error && instructionCount === 1 &&
104
- config.permissions['dingtalk-basic-behavior'] === 'allow'
113
+ config.permissions[declaredBasic] === 'allow' ? 'pass' : 'fail', true, !config.error && instructionCount === 1 &&
114
+ config.permissions[declaredBasic] === 'allow'
105
115
  ? 'OpenCode 每 Session 强制加载 Basic Skill'
106
116
  : 'opencode.json 未形成唯一 Basic instruction + allow 合同', { path: config.path, error: config.error, instructionCount,
107
- permission: config.permissions['dingtalk-basic-behavior'] || '' });
117
+ permission: config.permissions[declaredBasic] || '' });
108
118
  for (const name of requiredSkills) {
109
119
  const source = roleSkills.get(name);
110
- const exposure = inspectSkill(join(rootReal, '.agents', 'skills', name, 'SKILL.md'));
111
120
  const permission = config.permissions[name] || '';
112
- const matched = Boolean(source?.hash && exposure.exists && exposure.name === name &&
113
- exposure.hash === source.hash && permission === 'allow');
114
- add(`host.role-exposure.${name}`, 'host', matched ? 'pass' : 'fail', true, matched ? `Role Skill ${name} exposure 与 Definition 一致`
115
- : `Role Skill ${name} exposure、hash 或 permission 不一致`, { sourceHash: source?.hash || '', exposure, permission });
121
+ const matched = Boolean(source?.hash && source.path && permission === 'allow');
122
+ add(`host.role-exposure.${name}`, 'host', matched ? 'pass' : 'fail', true, matched ? `Role Skill ${name} 单一发布源与 Host permission 一致`
123
+ : `Role Skill ${name} 发布源或 permission 不一致`, { sourceHash: source?.hash || '', sourcePath: source?.path || '', permission });
116
124
  }
117
125
  const staticPrerequisitesReady = checks
118
126
  .filter((item) => item.blocking)
@@ -125,16 +133,37 @@ export function auditAgent(root, options = {}) {
125
133
  let currentHostVersion = '';
126
134
  let loadReportError = '';
127
135
  let sideEffect = false;
136
+ const loadAttempts = [];
128
137
  if (options.verifyLoad) {
129
138
  if (!options.yes)
130
139
  throw new Error('agent audit --verify-load 会调用 OpenCode;必须同时传 --yes');
131
140
  if (staticPrerequisitesReady) {
132
- const execution = executeLoadAudit(rootReal, options, loadTargetHash, definitionInstruction, effectiveModel, () => currentLoadTargetHash(rootReal, options, requiredSkills, effectiveModel));
133
- loadReport = execution.report;
134
- loadReportPath = execution.evidencePath;
135
- verifiedReportPath = execution.reportPath;
136
- currentHostVersion = execution.currentHostVersion;
137
- sideEffect = 'local-opencode-eval';
141
+ // 门禁语义不变:ready 断言「当前 hash 组合下 Host 必然加载」这个确定性属性,而
142
+ // 单次 LLM 抽样失败混入了噪声维度(实测 3 个同构 Agent 首轮 1 pass/2 fail、零改动
143
+ // 重跑全过)。仅对探针执行类失败做一次全新 Session 的二次确认;attempt 之间
144
+ // targetHash/Host 漂移仍会中止整条命令。每次 attempt 都记进 verification.attempts
145
+ // ——flaky 不是被吞掉,而是从不可归因变成有账可查。--out 模式禁用重试(第二次
146
+ // attempt 会拒绝覆盖用户指定的输出路径)。
147
+ const maxAttempts = options.strictSingleRun || options.out ? 1 : 2;
148
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
149
+ const execution = executeLoadAudit(rootReal, options, loadTargetHash, definitionInstruction, basicInstruction, effectiveModel, () => currentLoadTargetHash(rootReal, options, requiredSkills, effectiveModel));
150
+ loadReport = execution.report;
151
+ loadReportPath = execution.evidencePath;
152
+ verifiedReportPath = execution.reportPath;
153
+ currentHostVersion = execution.currentHostVersion;
154
+ sideEffect = 'local-opencode-eval';
155
+ const verdict = verifyLoadReport(rootReal, verifiedReportPath, loadReport, basic, definitionInstruction, effectiveModel, currentHostVersion);
156
+ const summary = Array.isArray(verdict.evidence.failureSummary)
157
+ ? verdict.evidence.failureSummary : [];
158
+ loadAttempts.push({
159
+ attempt,
160
+ passed: verdict.passed,
161
+ evidencePath: relative(rootReal, execution.evidencePath),
162
+ failureSummary: summary,
163
+ });
164
+ if (verdict.passed || !shouldRetryLoadAudit(summary))
165
+ break;
166
+ }
138
167
  }
139
168
  }
140
169
  else if (options.loadReport) {
@@ -159,9 +188,19 @@ export function auditAgent(root, options = {}) {
159
188
  ? 'missing-report' : 'static-prerequisites-failed'),
160
189
  },
161
190
  };
191
+ const loadFailureHighlights = Array.isArray(load.evidence.failureSummary)
192
+ ? load.evidence.failureSummary.slice(0, 2) : [];
162
193
  add('host.load-probe', 'load', load.passed ? 'pass' : 'fail', true, load.passed ? 'Agent Definition 原生 rule canary、Basic load probe 与 Session directory 均通过'
163
- : '尚未取得与当前 Definition、Basic 全树 hash 绑定的 Host load 证据', { report: loadReportPath ? relative(rootReal, loadReportPath) : '',
164
- targetHash: loadTargetHash, ...load.evidence });
194
+ : '尚未取得与当前 Definition、Basic 全树 hash 绑定的 Host load 证据' +
195
+ (loadFailureHighlights.length ? `(${loadFailureHighlights.join(';')})` : ''), { report: loadReportPath ? relative(rootReal, loadReportPath) : '',
196
+ targetHash: loadTargetHash, ...load.evidence,
197
+ ...(loadAttempts.length ? {
198
+ verification: {
199
+ attempts: loadAttempts,
200
+ passedOnAttempt: (loadAttempts.find((item) => item.passed) || { attempt: 0 }).attempt,
201
+ strictSingleRun: Boolean(options.strictSingleRun),
202
+ },
203
+ } : {}) });
165
204
  let remoteReportPath = '';
166
205
  if (remote) {
167
206
  let loaded = null;
@@ -224,14 +263,14 @@ export function auditAgent(root, options = {}) {
224
263
  };
225
264
  }
226
265
  function readCanonicalBasicSkill() {
227
- const path = join(bundledSkillPath(resolvePackageRoot(import.meta.url), 'dingtalk-basic-behavior'), 'SKILL.md');
266
+ const path = join(bundledSkillPath(resolvePackageRoot(import.meta.url), 'dta-basic-behavior'), 'SKILL.md');
228
267
  const inspected = inspectSkill(path);
229
- if (!inspected.exists || inspected.name !== 'dingtalk-basic-behavior' || !inspected.version) {
230
- throw new Error('包内 canonical dingtalk-basic-behavior 非法');
268
+ if (!inspected.exists || inspected.name !== 'dta-basic-behavior' || !inspected.version) {
269
+ throw new Error('包内 canonical dta-basic-behavior 非法');
231
270
  }
232
271
  const tree = inspectSkillTree(path);
233
272
  if (!tree.hash)
234
- throw new Error(`包内 canonical dingtalk-basic-behavior 全树非法: ${tree.error}`);
273
+ throw new Error(`包内 canonical dta-basic-behavior 全树非法: ${tree.error}`);
235
274
  return {
236
275
  name: inspected.name, version: inspected.version, path,
237
276
  hash: inspected.hash, treeHash: tree.hash,
@@ -374,17 +413,14 @@ function currentLoadTargetHash(root, options, requiredSkills, model) {
374
413
  const hydrated = bootstrap(root, { ...(options.bootstrap || {}), deferRemote: true });
375
414
  const definition = hydrated.definition;
376
415
  const basic = readCanonicalBasicSkill();
377
- const exposedPath = join(root, '.agents', 'skills', 'dingtalk-basic-behavior', 'SKILL.md');
416
+ const packagedBasic = definition.skills.find((item) => item.name === BASIC);
417
+ const exposedPath = packagedBasic?.path || join(root, '.agents', 'skills', BASIC, 'SKILL.md');
378
418
  const exposed = inspectSkill(exposedPath);
379
419
  const exposedTree = inspectSkillTree(exposedPath);
380
420
  const config = inspectOpenCodeConfig(root);
381
421
  const roleSkills = new Map(definition.skills
382
- .filter((item) => item.name !== 'dingtalk-basic-behavior')
422
+ .filter((item) => !isBasicSkillName(item.name))
383
423
  .map((item) => [item.name, item]));
384
- const roleExposureHashes = Object.fromEntries(requiredSkills.map((name) => [
385
- name,
386
- inspectSkill(join(root, '.agents', 'skills', name, 'SKILL.md')).hash || '',
387
- ]));
388
424
  const roleSourceHashes = Object.fromEntries(requiredSkills.map((name) => [
389
425
  name, roleSkills.get(name)?.hash || '',
390
426
  ]));
@@ -402,11 +438,10 @@ function currentLoadTargetHash(root, options, requiredSkills, model) {
402
438
  opencodeConfigHash: config.hash,
403
439
  requiredSkills,
404
440
  roleSourceHashes,
405
- roleExposureHashes,
406
441
  model,
407
442
  }));
408
443
  }
409
- function executeLoadAudit(root, options, targetHash, definitionInstruction, model, revalidate) {
444
+ function executeLoadAudit(root, options, targetHash, definitionInstruction, basicInstruction, model, revalidate) {
410
445
  const runId = `agent_audit_${Date.now()}_${randomUUID().slice(0, 8)}`;
411
446
  const outputInspection = inspectContainedPath(root, options.out || join('.dingtalk-agent', 'agent-audit', 'results', runId));
412
447
  const outputRoot = outputInspection.path;
@@ -424,8 +459,8 @@ function executeLoadAudit(root, options, targetHash, definitionInstruction, mode
424
459
  const host = createIsolatedOpenCodeHost(model.split('/')[0]);
425
460
  try {
426
461
  const command = process.env.DTA_OPENCODE_BIN || 'opencode';
427
- const sourcePreflight = inspectSourceOpenCodeRuntime(command, root, host.environment, definitionInstruction);
428
- materializeAuditProbeWorkspace(root, auditWorkspace, definitionInstruction);
462
+ const sourcePreflight = inspectSourceOpenCodeRuntime(command, root, host.environment, definitionInstruction, basicInstruction);
463
+ materializeAuditProbeWorkspace(root, auditWorkspace, definitionInstruction, basicInstruction);
429
464
  const suitePath = join(auditWorkspace, 'suite.json');
430
465
  writeAtomic(suitePath, JSON.stringify({
431
466
  $schema: 'dingtalk-agent/robot-eval-suite@1',
@@ -442,7 +477,7 @@ function executeLoadAudit(root, options, targetHash, definitionInstruction, mode
442
477
  execution: { host: 'opencode-only', tools: 'none' },
443
478
  prompt: '这是装配验收。保留评测 marker,并用一句话确认已进入直接工作状态;不要提问。',
444
479
  expectations: [{ id: 'no-question', type: 'maxQuestions', max: 0 }],
445
- sourceRefs: ['skills/core/dingtalk-agent-compose/references/hosts/opencode.md'],
480
+ sourceRefs: ['skills/core/dta-agent-compose/references/hosts/opencode.md'],
446
481
  manualChecks: [],
447
482
  }],
448
483
  }, null, 2) + '\n');
@@ -494,20 +529,20 @@ function executeLoadAudit(root, options, targetHash, definitionInstruction, mode
494
529
  rmSync(auditWorkspace, { recursive: true, force: true });
495
530
  }
496
531
  }
497
- function materializeAuditProbeWorkspace(sourceRoot, targetRoot, definitionInstruction) {
498
- if (definitionInstruction !== 'AGENTS.md') {
499
- throw new Error('OpenCode 原生 Definition 探针只接受项目根 AGENTS.md');
500
- }
532
+ function materializeAuditProbeWorkspace(sourceRoot, targetRoot, definitionInstruction, basicInstruction) {
501
533
  mkdirSync(targetRoot, { recursive: true });
502
- writeAtomic(join(targetRoot, 'AGENTS.md'), readFileSync(join(sourceRoot, 'AGENTS.md'), 'utf8'));
503
- const sourceBasic = join(sourceRoot, '.agents', 'skills', 'dingtalk-basic-behavior');
504
- const targetBasic = join(targetRoot, '.agents', 'skills', 'dingtalk-basic-behavior');
534
+ writeAtomic(join(targetRoot, definitionInstruction), readFileSync(join(sourceRoot, definitionInstruction), 'utf8'));
535
+ const sourceBasic = dirname(join(sourceRoot, basicInstruction));
536
+ const targetBasic = join(targetRoot, '.agents', 'skills', 'dta-basic-behavior');
505
537
  mkdirSync(dirname(targetBasic), { recursive: true });
506
538
  cpSync(sourceBasic, targetBasic, { recursive: true });
507
539
  const config = {
508
540
  $schema: 'https://opencode.ai/config.json',
509
- instructions: [BASIC_INSTRUCTION],
510
- permission: { skill: { 'dingtalk-basic-behavior': 'allow' } },
541
+ instructions: [
542
+ ...(definitionInstruction === 'AGENTS.md' ? [] : [definitionInstruction]),
543
+ BASIC_INSTRUCTION,
544
+ ],
545
+ permission: { skill: { 'dta-basic-behavior': 'allow' } },
511
546
  plugin: [],
512
547
  mcp: {},
513
548
  share: 'disabled',
@@ -515,19 +550,21 @@ function materializeAuditProbeWorkspace(sourceRoot, targetRoot, definitionInstru
515
550
  };
516
551
  writeAtomic(join(targetRoot, 'opencode.json'), JSON.stringify(config, null, 2) + '\n');
517
552
  }
518
- function inspectSourceOpenCodeRuntime(command, root, environment, definitionInstruction) {
553
+ function inspectSourceOpenCodeRuntime(command, root, environment, definitionInstruction, basicInstruction) {
519
554
  const parent = mkdtempSync(join(tmpdir(), 'dta-source-config-preflight-'));
520
555
  const workspace = join(parent, 'workspace');
521
556
  let stdout = '';
522
557
  try {
523
558
  mkdirSync(workspace, { recursive: true });
524
559
  cpSync(join(root, 'opencode.json'), join(workspace, 'opencode.json'));
525
- if (existsSync(join(root, 'AGENTS.md'))) {
526
- cpSync(join(root, 'AGENTS.md'), join(workspace, 'AGENTS.md'));
560
+ if (existsSync(join(root, definitionInstruction))) {
561
+ const target = join(workspace, definitionInstruction);
562
+ mkdirSync(dirname(target), { recursive: true });
563
+ cpSync(join(root, definitionInstruction), target);
527
564
  }
528
- const basic = join(root, '.agents', 'skills', 'dingtalk-basic-behavior');
565
+ const basic = dirname(join(root, basicInstruction));
529
566
  if (existsSync(basic)) {
530
- const target = join(workspace, '.agents', 'skills', 'dingtalk-basic-behavior');
567
+ const target = dirname(join(workspace, basicInstruction));
531
568
  mkdirSync(dirname(target), { recursive: true });
532
569
  cpSync(basic, target, {
533
570
  recursive: true,
@@ -564,9 +601,10 @@ function inspectSourceOpenCodeRuntime(command, root, environment, definitionInst
564
601
  throw new Error('OpenCode 原项目 resolved instructions 不是 string array');
565
602
  }
566
603
  const definitionCount = countInstructionsForPath(root, instructions, definitionInstruction);
567
- const basicCount = countInstructionsForPath(root, instructions, BASIC_INSTRUCTION);
568
- if (definitionInstruction !== 'AGENTS.md' || definitionCount !== 0 || basicCount !== 1) {
569
- throw new Error(`OpenCode 原项目 resolved config 未形成原生 AGENTS.md + 唯一 Basic: ` +
604
+ const basicCount = countInstructionsForPath(root, instructions, basicInstruction);
605
+ const expectedDefinitionCount = definitionInstruction === 'AGENTS.md' ? 0 : 1;
606
+ if (definitionCount !== expectedDefinitionCount || basicCount !== 1) {
607
+ throw new Error(`OpenCode 原项目 resolved config 未形成唯一 Agent Definition + Basic: ` +
570
608
  `definition=${definitionCount} basic=${basicCount}`);
571
609
  }
572
610
  if (value.agent?.['dta-eval'] !== undefined) {
@@ -588,7 +626,7 @@ function inspectSourceOpenCodeRuntime(command, root, environment, definitionInst
588
626
  };
589
627
  }
590
628
  function executeInheritanceProbe(sourceRoot, model, command, timeoutMs, reportEvidenceRoot, definitionInstruction, environment) {
591
- const referenceInstruction = '.agents/skills/dingtalk-basic-behavior/references/risk-authority-and-privacy.md';
629
+ const referenceInstruction = '.agents/skills/dta-basic-behavior/references/risk-authority-and-privacy.md';
592
630
  const definitionProbe = randomUUID();
593
631
  const referenceProbeStart = randomUUID();
594
632
  const referenceProbeEnd = randomUUID();
@@ -599,8 +637,8 @@ function executeInheritanceProbe(sourceRoot, model, command, timeoutMs, reportEv
599
637
  initializeProbeWorktree(sandbox);
600
638
  const sourceDefinitionPath = resolve(sourceRoot, definitionInstruction);
601
639
  const definitionPath = resolve(sandbox, definitionInstruction);
602
- const sourceBasicPath = join(sourceRoot, '.agents', 'skills', 'dingtalk-basic-behavior');
603
- const basicPath = join(sandbox, '.agents', 'skills', 'dingtalk-basic-behavior');
640
+ const sourceBasicPath = join(sourceRoot, '.agents', 'skills', 'dta-basic-behavior');
641
+ const basicPath = join(sandbox, '.agents', 'skills', 'dta-basic-behavior');
604
642
  const referencePath = resolve(sandbox, referenceInstruction);
605
643
  if (!isInside(sourceRoot, sourceDefinitionPath) || !existsSync(sourceDefinitionPath) ||
606
644
  !isInside(sandbox, definitionPath) || !existsSync(sourceBasicPath)) {
@@ -625,14 +663,17 @@ function executeInheritanceProbe(sourceRoot, model, command, timeoutMs, reportEv
625
663
  !Array.isArray(sourceConfig.permission) ? sourceConfig.permission : {};
626
664
  const skill = permission.skill && typeof permission.skill === 'object' &&
627
665
  !Array.isArray(permission.skill) ? permission.skill : {};
628
- sourceConfig.instructions = [BASIC_INSTRUCTION];
666
+ sourceConfig.instructions = [
667
+ ...(definitionInstruction === 'AGENTS.md' ? [] : [definitionInstruction]),
668
+ BASIC_INSTRUCTION,
669
+ ];
629
670
  delete sourceConfig.provider;
630
671
  sourceConfig.plugin = [];
631
672
  sourceConfig.mcp = {};
632
673
  sourceConfig.permission = {
633
674
  ...permission,
634
675
  external_directory: 'deny',
635
- skill: { ...skill, 'dingtalk-basic-behavior': 'allow' },
676
+ skill: { ...skill, 'dta-basic-behavior': 'allow' },
636
677
  };
637
678
  writeAtomic(join(sandbox, 'opencode.json'), JSON.stringify(sourceConfig, null, 2) + '\n');
638
679
  const probeEnvironment = { ...environment, PWD: sandbox };
@@ -665,7 +706,7 @@ function executeInheritanceProbe(sourceRoot, model, command, timeoutMs, reportEv
665
706
  const definitionRaw = persistProbeExecution(reportEvidenceRoot, 'definition', definitionExecution);
666
707
  const referenceRaw = persistProbeExecution(reportEvidenceRoot, 'reference', referenceExecution);
667
708
  const result = {
668
- passed: definitionInstruction === 'AGENTS.md' && basicResolvedCount === 1 &&
709
+ passed: Boolean(definitionInstruction) && basicResolvedCount === 1 &&
669
710
  definitionPermissionPassed && referencePermissionPassed &&
670
711
  definitionExecution.exitCode === 0 && definitionExecution.directoryMatched &&
671
712
  definitionExecution.toolCalls === 0 &&
@@ -830,7 +871,7 @@ function validRandomProbe(value, name) {
830
871
  const count = name === 'dta-reference-probe' ? 2 : 1;
831
872
  return new RegExp(`^${name}=${uuid}${count === 2 ? `:${uuid}` : ''}$`).test(value);
832
873
  }
833
- function verifyLoadProbeSet(root, reportPath, report, primaryName, comparisonName, basic, expectedRuns) {
874
+ function verifyLoadProbeSet(root, reportPath, report, primaryName, comparisonName, basic, definitionInstruction, expectedRuns) {
834
875
  const all = Array.isArray(report.loadProbes) ? report.loadProbes : [];
835
876
  const declaredRuns = Number(report.summary?.runsPerConfiguration);
836
877
  const primary = all.filter((item) => item.configuration === primaryName);
@@ -841,7 +882,12 @@ function verifyLoadProbeSet(root, reportPath, report, primaryName, comparisonNam
841
882
  items.every((item) => Number.isInteger(item.runNumber) &&
842
883
  item.runNumber >= 1 && item.runNumber <= expectedRuns);
843
884
  const common = (item) => {
844
- const expectedInstructions = item.expectsLoad === true ? [BASIC_INSTRUCTION] : [];
885
+ const expectedInstructions = item.expectsLoad === true
886
+ ? [
887
+ BASIC_INSTRUCTION,
888
+ ...(definitionInstruction === 'AGENTS.md' ? [] : [definitionInstruction]),
889
+ ].sort()
890
+ : [];
845
891
  return loadProbeCorePassed(item, version) &&
846
892
  stableStringify(item.resolvedInstructions) === stableStringify(expectedInstructions) &&
847
893
  verifyLoadProbeRaw(root, reportPath, item, String(report.engine?.model || ''));
@@ -951,10 +997,24 @@ function readLoadEvidence(root, input, expectedTargetHash) {
951
997
  }
952
998
  return { path: loaded.path, reportPath: report.path, report: report.value };
953
999
  }
1000
+ /**
1001
+ * 只有「探针执行类」失败值得一次全新 Session 的二次确认——模型抖动、超时、回显不精确、
1002
+ * session 导出缺失都是瞬时面。静态类失败(schema/hash/绑定/host 漂移)重跑必然复现,
1003
+ * 直接判死,不浪费第二次探针。
1004
+ */
1005
+ export function shouldRetryLoadAudit(failureSummary) {
1006
+ if (!Array.isArray(failureSummary) || !failureSummary.length)
1007
+ return false;
1008
+ const staticPrefixes = [
1009
+ 'report.schema', 'report.dingtalk-side-effect', 'basic.binding',
1010
+ 'inheritance.evidence', 'source-config.evidence', 'host.binding',
1011
+ ];
1012
+ return failureSummary.every((item) => typeof item === 'string' && !staticPrefixes.some((prefix) => item.startsWith(prefix)));
1013
+ }
954
1014
  function verifyLoadReport(root, reportPath, report, basic, definitionInstruction, model, currentHostVersion) {
955
1015
  const configuration = 'with_skill';
956
1016
  const comparison = 'without_skill';
957
- const probeSet = verifyLoadProbeSet(root, reportPath, report, configuration, comparison, basic, 1);
1017
+ const probeSet = verifyLoadProbeSet(root, reportPath, report, configuration, comparison, basic, definitionInstruction, 1);
958
1018
  const probes = probeSet.primary;
959
1019
  const source = report.skills?.[configuration];
960
1020
  const gate = report.summary?.configurationLoadGates?.[configuration];
@@ -966,7 +1026,7 @@ function verifyLoadReport(root, reportPath, report, basic, definitionInstruction
966
1026
  Array.isArray(definition.toolNames) && definition.toolNames.length === 0 &&
967
1027
  Array.isArray(definition.toolPaths) && definition.toolPaths.length === 0 &&
968
1028
  Array.isArray(definition.toolTrace) && definition.toolTrace.length === 0 &&
969
- definition.nativeRule === 'AGENTS.md' && definitionInstruction === 'AGENTS.md' &&
1029
+ definition.nativeRule === definitionInstruction && Boolean(definitionInstruction) &&
970
1030
  definition.permissionPassed === true &&
971
1031
  zeroToolPermission(definition.evalAgent || {});
972
1032
  const referenceTrace = Array.isArray(reference.toolTrace) ? reference.toolTrace : [];
@@ -986,7 +1046,7 @@ function verifyLoadReport(root, reportPath, report, basic, definitionInstruction
986
1046
  Array.isArray(reference.toolPaths) && reference.toolPaths.length === 1 &&
987
1047
  reference.toolPaths[0] === reference.path;
988
1048
  const referencePassed = reference.path ===
989
- '.agents/skills/dingtalk-basic-behavior/references/risk-authority-and-privacy.md' &&
1049
+ '.agents/skills/dta-basic-behavior/references/risk-authority-and-privacy.md' &&
990
1050
  validRandomProbe(reference.expected, 'dta-reference-probe') &&
991
1051
  reference.answer === reference.expected && reference.exitCode === 0 &&
992
1052
  reference.directoryMatched === true && referenceRead && referenceFullRead &&
@@ -1008,16 +1068,67 @@ function verifyLoadReport(root, reportPath, report, basic, definitionInstruction
1008
1068
  report.summary?.loadGate === true && gate?.passed === true && probeSet.passed &&
1009
1069
  definitionPassed && referencePassed && inheritanceEvidenceValid &&
1010
1070
  sourceConfigEvidenceValid && hostMatched;
1071
+ // 失败可归因:把每个失败面折成一行带关键数值的摘要。探针的 exitCode/durationMs 本来
1072
+ // 就在 evidence 深处,缺的是提到人读得到的地方——此前失败只有一句通用的「尚未取得
1073
+ // 证据」,没人能区分模型抖动、超时还是配置真错了(发布门禁 flaky 却无从归因)。
1074
+ const failureSummary = [];
1075
+ if (!passed) {
1076
+ if (report.$schema !== 'dingtalk-agent/opencode-eval-report@1') {
1077
+ failureSummary.push(`report.schema: ${String(report.$schema || '(missing)')}`);
1078
+ }
1079
+ if (report.passed !== true)
1080
+ failureSummary.push('report.passed: false');
1081
+ if (report.summary?.hardGate !== true)
1082
+ failureSummary.push('report.hard-gate: false');
1083
+ if (report.dingtalkSideEffect !== false)
1084
+ failureSummary.push('report.dingtalk-side-effect: not false');
1085
+ if (source?.name !== basic.name || source?.version !== basic.version ||
1086
+ source?.hash !== basic.hash) {
1087
+ failureSummary.push('basic.binding: got ' +
1088
+ `${source?.name || '(none)'}@${source?.version || '?'} ` +
1089
+ `hash=${String(source?.hash || '').slice(0, 12) || '?'}, expected ` +
1090
+ `${basic.name}@${basic.version} hash=${basic.hash.slice(0, 12)}`);
1091
+ }
1092
+ if (report.summary?.loadGate !== true || gate?.passed !== true) {
1093
+ failureSummary.push('load-gate: false');
1094
+ }
1095
+ if (!probeSet.passed) {
1096
+ failureSummary.push(`load-probes: ${probeSet.passedPrimary}/${probes.length} primary ` +
1097
+ `passed, anti-guess=${probeSet.passedComparison}`);
1098
+ }
1099
+ if (!definitionPassed) {
1100
+ failureSummary.push('inheritance.definition: ' +
1101
+ `answer=${definition.answer === definition.expected ? 'exact' : 'mismatch'} ` +
1102
+ `exitCode=${definition.exitCode ?? '?'} durationMs=${definition.durationMs ?? '?'} ` +
1103
+ `toolCalls=${definition.toolCalls ?? '?'}`);
1104
+ }
1105
+ if (!referencePassed) {
1106
+ failureSummary.push('inheritance.reference: ' +
1107
+ `answer=${reference.answer === reference.expected ? 'exact' : 'mismatch'} ` +
1108
+ `exitCode=${reference.exitCode ?? '?'} durationMs=${reference.durationMs ?? '?'} ` +
1109
+ `fullRead=${reference.fullRead === true}`);
1110
+ }
1111
+ if (!inheritanceEvidenceValid)
1112
+ failureSummary.push('inheritance.evidence: hash/binding invalid');
1113
+ if (!sourceConfigEvidenceValid)
1114
+ failureSummary.push('source-config.evidence: invalid');
1115
+ if (!hostMatched) {
1116
+ failureSummary.push('host.binding: ' +
1117
+ `report=${report.engine?.model || '?'}@${report.engine?.version || '?'} ` +
1118
+ `current=@${currentHostVersion || '?'}`);
1119
+ }
1120
+ }
1011
1121
  return {
1012
1122
  passed,
1013
1123
  evidence: {
1124
+ failureSummary,
1014
1125
  schema: report.$schema || '', configuration, sourceHash: source?.hash || '',
1015
1126
  expectedHash: basic.hash, loadGate: report.summary?.loadGate === true,
1016
1127
  passedProbes: probeSet.passedPrimary,
1017
1128
  baselineAntiGuessProbes: probeSet.passedComparison,
1018
1129
  expectedRunsPerConfiguration: probeSet.expectedRuns,
1019
1130
  definitionInstruction,
1020
- definitionNativeRule: definition.nativeRule === 'AGENTS.md',
1131
+ definitionNativeRule: definition.nativeRule === definitionInstruction,
1021
1132
  totalProbes: probes.length,
1022
1133
  definitionProbePassed: definitionPassed,
1023
1134
  referenceProbePassed: referencePassed,
@@ -1037,8 +1148,11 @@ function verifySourceConfigEvidence(root, reportPath, summary, evidence) {
1037
1148
  return false;
1038
1149
  const value = summary;
1039
1150
  const manifest = evidence;
1040
- if (value.passed !== true || value.definitionInstruction !== 'AGENTS.md' ||
1041
- value.definitionInstructionCount !== 0 || value.basicInstructionCount !== 1 ||
1151
+ const expectedDefinitionCount = value.definitionInstruction === 'AGENTS.md' ? 0 : 1;
1152
+ if (value.passed !== true || typeof value.definitionInstruction !== 'string' ||
1153
+ !value.definitionInstruction ||
1154
+ value.definitionInstructionCount !== expectedDefinitionCount ||
1155
+ value.basicInstructionCount !== 1 ||
1042
1156
  typeof value.rawHash !== 'string' || !value.rawHash ||
1043
1157
  manifest.rawHash !== value.rawHash)
1044
1158
  return false;
@@ -1162,7 +1276,7 @@ function persistedToolPaths(event) {
1162
1276
  typeof value !== 'string')
1163
1277
  continue;
1164
1278
  const normalized = value.replace(/\\/g, '/').replace(/^\.\//, '');
1165
- const target = '.agents/skills/dingtalk-basic-behavior/references/' +
1279
+ const target = '.agents/skills/dta-basic-behavior/references/' +
1166
1280
  'risk-authority-and-privacy.md';
1167
1281
  paths.push(normalized === target || normalized.endsWith(`/${target}`)
1168
1282
  ? target : normalized);
@@ -1227,12 +1341,12 @@ function repairFor(id) {
1227
1341
  if (id === 'definition.semantic-contract')
1228
1342
  return {
1229
1343
  id, why: '结构化模板不能替代真实的本体定义、岗位底线、做事范式和常犯错误。',
1230
- actions: ['评审并替换 AGENTS.md 中所有 <...> 占位符,再复跑 audit。'],
1344
+ actions: ['评审并替换 manifest 中 agent.definition 指向文件的所有 <...> 占位符,再复跑 audit。'],
1231
1345
  };
1232
1346
  if (id === 'definition.body')
1233
1347
  return {
1234
1348
  id, why: 'Agent 必须有长期定义、岗位底线、做事范式和常犯错误。',
1235
- actions: ['从 compose Skill 的 AGENTS.template.md 创建 AGENTS.md,再复跑 audit。'],
1349
+ actions: ['从 compose Skill 的 AGENTS.template.md 创建 agent/AGENTS.md,并由 manifest 的 agent.definition 指向它,再复跑 audit。'],
1236
1350
  };
1237
1351
  if (id === 'storage.memory')
1238
1352
  return {
@@ -1257,37 +1371,40 @@ function repairFor(id) {
1257
1371
  if (id.startsWith('skill.role.') && id.endsWith('.semantic'))
1258
1372
  return {
1259
1373
  id, why: 'Role Skill 必须包含真实的领域输入、方法、产物和验收,而不是模板提示。',
1260
- actions: [`评审并替换 skills/${id.slice('skill.role.'.length, -'.semantic'.length)}/SKILL.md 中所有 <...> 占位符。`],
1374
+ actions: [`评审并替换 agent.skillsRoot 下 ${id.slice('skill.role.'.length, -'.semantic'.length)}/SKILL.md 中所有 <...> 占位符。`],
1261
1375
  };
1262
1376
  if (id.startsWith('skill.role.'))
1263
1377
  return {
1264
1378
  id, why: '领域职责需要独立 Role Skill,不能写回 Basic Behavior。',
1265
- actions: [`创建 skills/${id.slice('skill.role.'.length)}/SKILL.md,并确保目录名等于 frontmatter name。`],
1379
+ actions: [`在 manifest 声明的 agent.skillsRoot 下创建 ${id.slice('skill.role.'.length)}/SKILL.md,并确保目录名等于 frontmatter name。`],
1266
1380
  };
1267
1381
  if (id === 'host.basic-exposure')
1268
1382
  return {
1269
1383
  id, why: 'OpenCode 只能从项目 exposure 完整继承本次装配的 Basic Skill 入口、references 与 assets。',
1270
- actions: ['把 canonical dingtalk-basic-behavior 全树物化到 .agents/skills/dingtalk-basic-behavior。'],
1384
+ actions: ['把 canonical dta-basic-behavior 全树放入 agent.skillsRoot;由 dta 在隔离 Host 工作区临时物化 exposure。'],
1271
1385
  };
1272
1386
  if (id === 'host.definition-rule')
1273
1387
  return {
1274
- id, why: 'OpenCode 只会把项目根 AGENTS.md 作为本地原生 rule;重复 custom instruction 会形成冗余通道。',
1275
- actions: ['把项目本体统一为根目录 AGENTS.md,并从 opencode.json#instructions 删除其等价路径。'],
1388
+ id, why: 'Agent Definition 与仓库开发约束必须分离,重复 custom instruction 会形成冗余通道。',
1389
+ actions: [' managed Host 只加载一次 manifest 的 agent.definition;仓库根 AGENTS.md 仅保留 Coding Agent 开发约束。'],
1276
1390
  };
1277
1391
  if (id === 'host.basic-instruction')
1278
1392
  return {
1279
1393
  id, why: '目录发现不等于正文进入每个 Session。',
1280
- actions: ['合并 opencode.json:Basic path 仅出现一次,并设置 permission.skill.dingtalk-basic-behavior=allow。'],
1394
+ actions: ['合并 opencode.json:Basic path 仅出现一次,并设置 permission.skill.dta-basic-behavior=allow。'],
1281
1395
  };
1282
1396
  if (id.startsWith('host.role-exposure.'))
1283
1397
  return {
1284
1398
  id, why: 'Role Skill 的发布源、Host exposure 与权限必须指向同一版本。',
1285
- actions: [`物化 .agents/skills/${id.slice('host.role-exposure.'.length)},校验 hash 并设置 permission=allow。`],
1399
+ actions: [`修复 agent.skillsRoot 下 ${id.slice('host.role-exposure.'.length)} 的唯一发布源;由 dta 临时物化 Host exposure、校验 hash 并设置 permission=allow。`],
1286
1400
  };
1287
1401
  if (id === 'host.load-probe')
1288
1402
  return {
1289
1403
  id, why: '静态目录和配置不能证明 Host 已解析 Agent Definition 并让模型读到 Basic 正文。',
1290
- actions: ['执行 dta agent audit --verify-load --yes --json,保留 resolved instructions、随机 probe 与 Session directory 证据。'],
1404
+ actions: [
1405
+ '执行 dta agent audit --verify-load --yes --json,保留 resolved instructions、随机 probe 与 Session directory 证据。',
1406
+ '若探针已执行仍失败,先读 evidence 里的 failureSummary 与 verification.attempts 定位失败面(模型抖动/超时/hash 绑定),不要盲目改本体重跑。',
1407
+ ],
1291
1408
  };
1292
1409
  if (id === 'authority.dws')
1293
1410
  return {