@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.
- package/CHANGELOG.md +232 -0
- package/README.en.md +115 -89
- package/README.md +111 -86
- package/dist/bin/dingtalk-agent.js +742 -152
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/actions.js +3 -2
- package/dist/src/actions.js.map +1 -1
- package/dist/src/agent-audit.js +202 -85
- package/dist/src/agent-audit.js.map +1 -1
- package/dist/src/agent-definition.js +7 -3
- package/dist/src/agent-definition.js.map +1 -1
- package/dist/src/agent-enhance.js +51 -32
- package/dist/src/agent-enhance.js.map +1 -1
- package/dist/src/agent-platform.js +4 -4
- package/dist/src/agent-platform.js.map +1 -1
- package/dist/src/bootstrap.js +6 -2
- package/dist/src/bootstrap.js.map +1 -1
- package/dist/src/development-workspace.js +210 -34
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/doctor.js +65 -9
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/dws.js +67 -3
- package/dist/src/dws.js.map +1 -1
- package/dist/src/init.js +2 -1
- package/dist/src/init.js.map +1 -1
- package/dist/src/memory/noop-receipt.js +306 -0
- package/dist/src/memory/noop-receipt.js.map +1 -0
- package/dist/src/memory/operational.js +27 -3
- package/dist/src/memory/operational.js.map +1 -1
- package/dist/src/memory/remote-state.js +2 -1
- package/dist/src/memory/remote-state.js.map +1 -1
- package/dist/src/multica-deploy.js +692 -125
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/multica-provider.js +303 -25
- package/dist/src/multica-provider.js.map +1 -1
- package/dist/src/multica-runtime-vocabulary.js +110 -0
- package/dist/src/multica-runtime-vocabulary.js.map +1 -0
- package/dist/src/opencode-evals.js +6 -6
- package/dist/src/opencode-evals.js.map +1 -1
- package/dist/src/opencode-provider.js +21 -7
- package/dist/src/opencode-provider.js.map +1 -1
- package/dist/src/opencode-workspace.js +3 -3
- package/dist/src/opencode-workspace.js.map +1 -1
- package/dist/src/personal-event-evals.js +4 -2
- package/dist/src/personal-event-evals.js.map +1 -1
- package/dist/src/promotion.js +2 -1
- package/dist/src/promotion.js.map +1 -1
- package/dist/src/remote-semantic-state-live-evals.js +14 -8
- package/dist/src/remote-semantic-state-live-evals.js.map +1 -1
- package/dist/src/remote-state-evals.js +2 -2
- package/dist/src/remote-state-evals.js.map +1 -1
- package/dist/src/robot-evals.js +3 -3
- package/dist/src/robot-evals.js.map +1 -1
- package/dist/src/schedule-plan.js +380 -0
- package/dist/src/schedule-plan.js.map +1 -0
- package/dist/src/sessions.js +1 -1
- package/dist/src/sessions.js.map +1 -1
- package/dist/src/skill-manager.js +145 -13
- package/dist/src/skill-manager.js.map +1 -1
- package/dist/src/skills.js +2 -0
- package/dist/src/skills.js.map +1 -1
- package/dist/src/tui.js +369 -0
- package/dist/src/tui.js.map +1 -0
- package/dist/src/upgrade.js +113 -33
- package/dist/src/upgrade.js.map +1 -1
- package/dist/src/waits.js +2 -1
- package/dist/src/waits.js.map +1 -1
- package/dist/src/workspace.js +12 -7
- package/dist/src/workspace.js.map +1 -1
- package/docs/AGENT-IN-PRODUCTION.md +255 -0
- package/docs/ARCHITECTURE.md +366 -0
- package/docs/INSTALLATION.md +8 -8
- package/docs/PLATFORM-GUARDRAILS.md +188 -0
- package/docs/PRIOR-ART.md +126 -0
- package/docs/SELF-TEST.md +182 -0
- package/docs/architecture/agent-platform-connection-layer.svg +120 -0
- package/docs/architecture/digital-employee-composition.svg +92 -0
- package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
- package/docs/assets/digital-employee-at-work.svg +77 -0
- package/docs/schemas/multica-deployment-plan.schema.json +3 -1
- package/docs/schemas/multica-deployment-receipt.schema.json +17 -3
- package/docs/schemas/multica-deployment-status.schema.json +6 -2
- package/docs/schemas/multica-workspace-inspection.schema.json +16 -0
- package/docs/schemas/multica-workspace-run-plan.schema.json +31 -0
- package/docs/schemas/multica-workspace-run.schema.json +161 -0
- package/docs/schemas/multica-workspace-status.schema.json +2 -0
- package/docs/schemas/project.schema.json +54 -3
- package/docs/schemas/workspace-scaffold.schema.json +38 -0
- package/examples/agents/README.md +45 -0
- package/examples/agents/fde-coach/AGENTS.md +2 -25
- package/examples/agents/fde-coach/agent/AGENTS.md +35 -0
- package/examples/agents/fde-coach/agent.bindings.json +10 -0
- package/examples/agents/release-manager/AGENTS.md +2 -25
- package/examples/agents/release-manager/agent/AGENTS.md +35 -0
- package/examples/agents/release-manager/agent.bindings.json +10 -0
- package/lab/agent-eval/catalog.json +5 -5
- package/lab/agent-eval/classic-failures.json +4 -4
- package/lab/agent-eval/completion-gate-regression.json +9 -9
- package/lab/agent-eval/personal-event-live.example.json +3 -3
- package/lab/agent-eval/remote-semantic-state-live.example.json +1 -1
- package/lab/agent-eval/workspace/opencode.json +2 -2
- package/lab/project-workspace/fake-multica-provider.mjs +171 -17
- package/lab/project-workspace/multica-deploy.fixture.json +2 -2
- package/lab/project-workspace/multica-readonly.fixture.json +4 -16
- package/lab/project-workspace/opencode-provider-suite.json +3 -3
- package/lab/project-workspace/project.fixture.json +2 -6
- package/lab/robot-eval/suite.json +1 -1
- package/lab/robot-eval/workspace/AGENTS.md +1 -1
- package/lab/robot-eval/workspace/opencode.json +2 -2
- package/lab/schemas/personal-event-eval.schema.json +1 -1
- package/package.json +18 -11
- package/skills/README.md +10 -8
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/SKILL.md +49 -24
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/AGENTS.template.md +1 -1
- package/skills/core/dta-agent-compose/assets/REPOSITORY.template.md +10 -0
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +2 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.local.template.json +2 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/hosts/opencode/opencode.template.json +3 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/evals/evals.json +4 -4
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/agent-definition-contract.md +7 -7
- package/skills/core/dta-agent-compose/references/drive-and-schedules.md +166 -0
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/host-loading-contract.md +11 -13
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/claude-code.md +13 -12
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/opencode.md +14 -13
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/SKILL.md +28 -3
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/assets/eval-catalog.template.json +1 -1
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/evals/evals.json +1 -1
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/eval-topology.md +3 -3
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/interactive-debug-channels.md +10 -4
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/SKILL.md +21 -5
- package/skills/core/dta-basic-behavior/references/event-to-behavior.md +38 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/memory-and-evolution.md +3 -1
- package/skills/core/dta-basic-behavior/references/perception-and-gates.md +87 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/risk-authority-and-privacy.md +12 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/truth-and-recovery.md +4 -2
- package/skills/core/dta-people-group-memory/COMPLETENESS.md +36 -0
- package/skills/core/dta-people-group-memory/SKILL.md +69 -0
- package/skills/core/dta-people-group-memory/references/adapters.md +273 -0
- package/skills/core/dta-people-group-memory/references/assembly-guidance.md +40 -0
- package/skills/core/dta-people-group-memory/references/binding.md +110 -0
- package/skills/core/dta-people-group-memory/references/cold-start.md +70 -0
- package/skills/core/dta-people-group-memory/references/config-binding.md +89 -0
- package/skills/core/dta-people-group-memory/references/consent-and-visibility.md +83 -0
- package/skills/core/dta-people-group-memory/references/consolidation.md +162 -0
- package/skills/core/dta-people-group-memory/references/event-ingest.md +103 -0
- package/skills/core/dta-people-group-memory/references/guided-setup.md +70 -0
- package/skills/core/dta-people-group-memory/references/model.md +148 -0
- package/skills/core/dta-people-group-memory/references/storage-port.md +107 -0
- package/skills/platforms/deap/PLATFORM.md +30 -1
- package/skills/platforms/multica-dingtalk/PLATFORM.md +35 -9
- package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/SKILL.md +10 -8
- package/skills/platforms/multica-dingtalk/dta-deploy-multica/references/multica-deployment-contract.md +67 -0
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/SKILL.md +81 -11
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/bootstrap.sh +2 -2
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/multica_ext.py +264 -16
- package/dist/src/map.js +0 -157
- package/dist/src/map.js.map +0 -1
- package/docs/SECOND-AGENT-ACCEPTANCE.md +0 -62
- package/docs/architecture/agent-memory-topology.png +0 -0
- package/docs/architecture/agent-memory-topology.svg +0 -132
- package/docs/architecture/dingtalk-agent-blueprint.png +0 -0
- package/docs/architecture/durable-async-agent-runtime.png +0 -0
- package/docs/architecture/general-agent-kernel-topology.png +0 -0
- package/docs/architecture/provider-bound-development-workspace.png +0 -0
- package/docs/architecture/task-completion-gate.png +0 -0
- package/docs/assets/agent-delivery-lifecycle.svg +0 -103
- package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +0 -24
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +0 -28
- package/skills/platforms/deap/README.md +0 -3
- package/skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica/SKILL.md +0 -40
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/multica-deployment-contract.md +0 -49
- /package/examples/agents/fde-coach/{skills → agent/skills}/fde-coach/SKILL.md +0 -0
- /package/examples/agents/release-manager/{skills → agent/skills}/release-manager/SKILL.md +0 -0
- /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/role-skill.template.md +0 -0
- /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/storage-routing.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/evidence-contract.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/failure-to-case.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/local-connector-smoke.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/scenario-taxonomy.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/storage-modes.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/task-checkpoint.json +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/action-contract.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/runtime-modes.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/task-lifecycle.md +0 -0
- /package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/references/promotion-observation-contract.md +0 -0
package/dist/src/agent-audit.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
? '
|
|
88
|
-
: '
|
|
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
|
|
95
|
-
|
|
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
|
-
?
|
|
99
|
-
|
|
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
|
|
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[
|
|
104
|
-
config.permissions[
|
|
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[
|
|
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 &&
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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 证据'
|
|
164
|
-
|
|
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), '
|
|
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 !== '
|
|
230
|
-
throw new Error('包内 canonical
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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,
|
|
503
|
-
const sourceBasic = join(sourceRoot,
|
|
504
|
-
const targetBasic = join(targetRoot, '.agents', 'skills', '
|
|
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: [
|
|
510
|
-
|
|
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,
|
|
526
|
-
|
|
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,
|
|
565
|
+
const basic = dirname(join(root, basicInstruction));
|
|
529
566
|
if (existsSync(basic)) {
|
|
530
|
-
const target = join(workspace,
|
|
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,
|
|
568
|
-
|
|
569
|
-
|
|
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/
|
|
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', '
|
|
603
|
-
const basicPath = join(sandbox, '.agents', 'skills', '
|
|
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 = [
|
|
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, '
|
|
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
|
|
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
|
|
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 ===
|
|
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/
|
|
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 ===
|
|
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
|
-
|
|
1041
|
-
|
|
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/
|
|
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: ['评审并替换
|
|
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
|
|
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: [`评审并替换
|
|
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: [
|
|
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
|
|
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: '
|
|
1275
|
-
actions: ['
|
|
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.
|
|
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: [
|
|
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: [
|
|
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 {
|