@xdxer/dingtalk-agent 0.1.5-beta.8 → 0.1.5-beta.9

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 (47) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.en.md +1 -0
  3. package/README.md +1 -0
  4. package/dist/bin/dingtalk-agent.js +115 -14
  5. package/dist/bin/dingtalk-agent.js.map +1 -1
  6. package/dist/src/agent-audit.js +108 -9
  7. package/dist/src/agent-audit.js.map +1 -1
  8. package/dist/src/development-workspace.js +37 -1
  9. package/dist/src/development-workspace.js.map +1 -1
  10. package/dist/src/dws.js +9 -0
  11. package/dist/src/dws.js.map +1 -1
  12. package/dist/src/multica-deploy.js +347 -105
  13. package/dist/src/multica-deploy.js.map +1 -1
  14. package/dist/src/multica-provider.js +151 -27
  15. package/dist/src/multica-provider.js.map +1 -1
  16. package/dist/src/multica-runtime-vocabulary.js +110 -0
  17. package/dist/src/multica-runtime-vocabulary.js.map +1 -0
  18. package/dist/src/promotion.js +2 -1
  19. package/dist/src/promotion.js.map +1 -1
  20. package/dist/src/schedule-plan.js +192 -24
  21. package/dist/src/schedule-plan.js.map +1 -1
  22. package/docs/AGENT-IN-PRODUCTION.md +255 -0
  23. package/docs/ARCHITECTURE.md +5 -1
  24. package/docs/PLATFORM-GUARDRAILS.md +188 -0
  25. package/docs/schemas/multica-deployment-plan.schema.json +3 -1
  26. package/docs/schemas/multica-deployment-receipt.schema.json +15 -1
  27. package/docs/schemas/multica-deployment-status.schema.json +6 -2
  28. package/docs/schemas/multica-workspace-inspection.schema.json +16 -0
  29. package/docs/schemas/multica-workspace-status.schema.json +2 -0
  30. package/docs/schemas/workspace-scaffold.schema.json +1 -0
  31. package/lab/project-workspace/fake-multica-provider.mjs +97 -7
  32. package/lab/project-workspace/multica-deploy.fixture.json +2 -2
  33. package/lab/project-workspace/multica-readonly.fixture.json +2 -2
  34. package/lab/project-workspace/project.fixture.json +1 -1
  35. package/lab/robot-eval/suite.json +1 -1
  36. package/package.json +5 -2
  37. package/skills/core/dta-agent-compose/SKILL.md +1 -1
  38. package/skills/core/dta-agent-compose/references/drive-and-schedules.md +22 -2
  39. package/skills/core/dta-basic-behavior/SKILL.md +1 -1
  40. package/skills/core/dta-basic-behavior/references/memory-and-evolution.md +1 -1
  41. package/skills/core/dta-people-group-memory/SKILL.md +4 -4
  42. package/skills/core/dta-people-group-memory/references/model.md +1 -1
  43. package/skills/platforms/multica-dingtalk/PLATFORM.md +2 -2
  44. package/skills/platforms/multica-dingtalk/dta-deploy-multica/SKILL.md +6 -5
  45. package/skills/platforms/multica-dingtalk/dta-deploy-multica/references/multica-deployment-contract.md +14 -4
  46. package/skills/platforms/multica-dingtalk/dta-ops-multica/SKILL.md +33 -7
  47. package/skills/platforms/multica-dingtalk/dta-ops-multica/scripts/multica_ext.py +118 -12
@@ -133,16 +133,37 @@ export function auditAgent(root, options = {}) {
133
133
  let currentHostVersion = '';
134
134
  let loadReportError = '';
135
135
  let sideEffect = false;
136
+ const loadAttempts = [];
136
137
  if (options.verifyLoad) {
137
138
  if (!options.yes)
138
139
  throw new Error('agent audit --verify-load 会调用 OpenCode;必须同时传 --yes');
139
140
  if (staticPrerequisitesReady) {
140
- const execution = executeLoadAudit(rootReal, options, loadTargetHash, definitionInstruction, basicInstruction, effectiveModel, () => currentLoadTargetHash(rootReal, options, requiredSkills, effectiveModel));
141
- loadReport = execution.report;
142
- loadReportPath = execution.evidencePath;
143
- verifiedReportPath = execution.reportPath;
144
- currentHostVersion = execution.currentHostVersion;
145
- 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
+ }
146
167
  }
147
168
  }
148
169
  else if (options.loadReport) {
@@ -167,9 +188,19 @@ export function auditAgent(root, options = {}) {
167
188
  ? 'missing-report' : 'static-prerequisites-failed'),
168
189
  },
169
190
  };
191
+ const loadFailureHighlights = Array.isArray(load.evidence.failureSummary)
192
+ ? load.evidence.failureSummary.slice(0, 2) : [];
170
193
  add('host.load-probe', 'load', load.passed ? 'pass' : 'fail', true, load.passed ? 'Agent Definition 原生 rule canary、Basic load probe 与 Session directory 均通过'
171
- : '尚未取得与当前 Definition、Basic 全树 hash 绑定的 Host load 证据', { report: loadReportPath ? relative(rootReal, loadReportPath) : '',
172
- 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
+ } : {}) });
173
204
  let remoteReportPath = '';
174
205
  if (remote) {
175
206
  let loaded = null;
@@ -966,6 +997,20 @@ function readLoadEvidence(root, input, expectedTargetHash) {
966
997
  }
967
998
  return { path: loaded.path, reportPath: report.path, report: report.value };
968
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
+ }
969
1014
  function verifyLoadReport(root, reportPath, report, basic, definitionInstruction, model, currentHostVersion) {
970
1015
  const configuration = 'with_skill';
971
1016
  const comparison = 'without_skill';
@@ -1023,9 +1068,60 @@ function verifyLoadReport(root, reportPath, report, basic, definitionInstruction
1023
1068
  report.summary?.loadGate === true && gate?.passed === true && probeSet.passed &&
1024
1069
  definitionPassed && referencePassed && inheritanceEvidenceValid &&
1025
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
+ }
1026
1121
  return {
1027
1122
  passed,
1028
1123
  evidence: {
1124
+ failureSummary,
1029
1125
  schema: report.$schema || '', configuration, sourceHash: source?.hash || '',
1030
1126
  expectedHash: basic.hash, loadGate: report.summary?.loadGate === true,
1031
1127
  passedProbes: probeSet.passedPrimary,
@@ -1305,7 +1401,10 @@ function repairFor(id) {
1305
1401
  if (id === 'host.load-probe')
1306
1402
  return {
1307
1403
  id, why: '静态目录和配置不能证明 Host 已解析 Agent Definition 并让模型读到 Basic 正文。',
1308
- 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
+ ],
1309
1408
  };
1310
1409
  if (id === 'authority.dws')
1311
1410
  return {