@stofone/dsh-agent-roster 0.9.2 → 0.10.1
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 +68 -0
- package/README.md +80 -5
- package/README.zh.md +73 -6
- package/bin/cli.mjs +228 -2
- package/docs/roster-v2.md +220 -0
- package/examples/dist/core-review-1.0.0.json +160 -0
- package/examples/dist/research-0.1.0.json +95 -0
- package/examples/roles/core-review-correctness/AGENT.md +20 -0
- package/examples/roles/core-review-lead/AGENT.md +23 -0
- package/examples/roles/core-review-lead-captain/AGENT.md +13 -0
- package/examples/roles/core-review-maintainer/AGENT.md +20 -0
- package/examples/roles/research-scout/AGENT.md +16 -0
- package/examples/roles/research-verifier/AGENT.md +16 -0
- package/examples/rosters/core-review/roster.yaml +39 -0
- package/examples/rosters/research/roster.yaml +20 -0
- package/examples-orchestration/dist/core-review-1.0.0.json +185 -0
- package/examples-orchestration/dist/core-review-1.0.0.tasks.json +76 -0
- package/examples-orchestration/roles/fixer/AGENT.md +18 -0
- package/examples-orchestration/roles/lead/AGENT.md +18 -0
- package/examples-orchestration/roles/reviewer/AGENT.md +23 -0
- package/examples-orchestration/roles/reviewer/parts/checklist.md +6 -0
- package/examples-orchestration/rosters/core-review/overrides/fixer.md +1 -0
- package/examples-orchestration/rosters/core-review/roster.yaml +43 -0
- package/index.js +8 -1
- package/lib/compile2.js +522 -0
- package/lib/format-v2.js +196 -0
- package/lib/frontmatter.js +113 -0
- package/lib/migrate.js +326 -0
- package/lib/plan.js +167 -0
- package/lib/registry.js +65 -11
- package/lib/role.js +498 -0
- package/lib/roster2.js +591 -0
- package/lib/run.js +188 -0
- package/lib/write.js +14 -8
- package/orgs/agent-roster-collective/dist/api-design-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/content-ops-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/contract-review-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/data-quality-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/db-migration-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/docs-writer-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/finance-recon-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/frontend-ui-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/i18n-l10n-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/incident-response-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/literature-review-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/market-research-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/ml-eval-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/performance-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/product-discovery-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/qa-regression-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/recruiting-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/release-manager-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/security-audit-1.0.0.json +132 -0
- package/orgs/agent-roster-collective/dist/sre-oncall-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/dist/support-triage-1.0.0.json +130 -0
- package/orgs/agent-roster-collective/roles/api-design-failure-mode/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/api-design-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/api-design-schema/AGENT.md +20 -0
- package/orgs/agent-roster-collective/roles/content-ops-distributor/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/content-ops-editor/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/content-ops-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/contract-review-clause-reader/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/contract-review-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/contract-review-risk-note/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/data-quality-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/data-quality-profiler/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/data-quality-rule-author/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/db-migration-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/db-migration-migrator/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/db-migration-verifier/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/docs-writer-example-runner/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/docs-writer-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/docs-writer-writer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/finance-recon-exception/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/finance-recon-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/finance-recon-matcher/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/frontend-ui-a11y-reviewer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/frontend-ui-implementer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/frontend-ui-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/i18n-l10n-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/i18n-l10n-reviewer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/i18n-l10n-translator/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/incident-response-commander/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/incident-response-scribe/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/incident-response-triage/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/literature-review-critic/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/literature-review-extractor/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/literature-review-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/market-research-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/market-research-researcher/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/market-research-synthesizer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/ml-eval-dataset/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/ml-eval-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/ml-eval-metric/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/performance-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/performance-load-tester/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/performance-profiler/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/product-discovery-interviewer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/product-discovery-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/product-discovery-skeptic/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/qa-regression-case-writer/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/qa-regression-flake-hunter/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/qa-regression-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/recruiting-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/recruiting-scheduler/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/recruiting-screener/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/release-manager-changelog/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/release-manager-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/release-manager-rollback/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/security-audit-code-auditor/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/security-audit-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/security-audit-threat-modeler/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/sre-oncall-capacity/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/sre-oncall-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/sre-oncall-runbook/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/support-triage-classifier/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/support-triage-lead/AGENT.md +19 -0
- package/orgs/agent-roster-collective/roles/support-triage-responder/AGENT.md +19 -0
- package/orgs/agent-roster-collective/rosters/api-design/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/content-ops/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/contract-review/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/data-quality/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/db-migration/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/docs-writer/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/finance-recon/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/frontend-ui/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/i18n-l10n/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/incident-response/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/literature-review/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/market-research/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/ml-eval/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/performance/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/product-discovery/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/qa-regression/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/recruiting/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/release-manager/roster.yaml +25 -0
- package/orgs/agent-roster-collective/rosters/security-audit/roster.yaml +30 -0
- package/orgs/agent-roster-collective/rosters/sre-oncall/roster.yaml +26 -0
- package/orgs/agent-roster-collective/rosters/support-triage/roster.yaml +25 -0
- package/package.json +3 -1
- package/schema/compiled.v1.schema.json +391 -0
- package/schema/role.v1.schema.json +240 -0
- package/schema/roster.v2.schema.json +437 -0
- package/examples/core-review/roster.yaml +0 -82
- package/examples/research/roster.yaml +0 -42
- package/orgs/agent-roster-collective/api-design/roster.yaml +0 -67
- package/orgs/agent-roster-collective/content-ops/roster.yaml +0 -55
- package/orgs/agent-roster-collective/contract-review/roster.yaml +0 -58
- package/orgs/agent-roster-collective/data-quality/roster.yaml +0 -64
- package/orgs/agent-roster-collective/db-migration/roster.yaml +0 -64
- package/orgs/agent-roster-collective/docs-writer/roster.yaml +0 -59
- package/orgs/agent-roster-collective/finance-recon/roster.yaml +0 -63
- package/orgs/agent-roster-collective/frontend-ui/roster.yaml +0 -60
- package/orgs/agent-roster-collective/i18n-l10n/roster.yaml +0 -60
- package/orgs/agent-roster-collective/incident-response/roster.yaml +0 -65
- package/orgs/agent-roster-collective/literature-review/roster.yaml +0 -61
- package/orgs/agent-roster-collective/market-research/roster.yaml +0 -60
- package/orgs/agent-roster-collective/ml-eval/roster.yaml +0 -63
- package/orgs/agent-roster-collective/performance/roster.yaml +0 -63
- package/orgs/agent-roster-collective/product-discovery/roster.yaml +0 -55
- package/orgs/agent-roster-collective/qa-regression/roster.yaml +0 -64
- package/orgs/agent-roster-collective/recruiting/roster.yaml +0 -58
- package/orgs/agent-roster-collective/release-manager/roster.yaml +0 -59
- package/orgs/agent-roster-collective/security-audit/roster.yaml +0 -65
- package/orgs/agent-roster-collective/sre-oncall/roster.yaml +0 -60
- package/orgs/agent-roster-collective/support-triage/roster.yaml +0 -58
- /package/orgs/agent-roster-collective/{security-audit → rosters/security-audit}/capabilities.yaml +0 -0
package/lib/run.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 施工图的执行回执(`dist/<id>-<version>.run.json`)。
|
|
3
|
+
*
|
|
4
|
+
* 施工图(`plan@1`)规定了「谁在什么时候做什么」,但执行发生在队长会话里。没有回执时,
|
|
5
|
+
* 一次失败只会停在某张红卡上;有了回执,下一次编译能把「上一轮哪张卡没过、为什么」带进
|
|
6
|
+
* 重试卡的 description——失败因此能回流到编译,而不是靠人记。
|
|
7
|
+
*
|
|
8
|
+
* 回执只记录可复核的东西:卡片 id、状态、门跑过的命令与退出码、失败意见的原文。
|
|
9
|
+
* 它不记录会话 id 或模型路由——那些是运行时事实,写进来就过期。
|
|
10
|
+
*
|
|
11
|
+
* @module dsh-agent-roster/run
|
|
12
|
+
*/
|
|
13
|
+
import { diagnostic } from "./parse.js";
|
|
14
|
+
|
|
15
|
+
export const RUN_KIND = "dsh-agent-roster/run@1";
|
|
16
|
+
export const RUN_STATUSES = ["passed", "failed", "skipped"];
|
|
17
|
+
const RUN_FIELDS = ["kind", "roster", "rounds", "notes"];
|
|
18
|
+
const ROUND_FIELDS = ["round", "at", "tasks"];
|
|
19
|
+
const TASK_FIELDS = ["id", "status", "findings", "commands", "note"];
|
|
20
|
+
const FINDING_FIELDS = ["severity", "problem", "requiredFix", "file", "line"];
|
|
21
|
+
const COMMAND_FIELDS = ["command", "exitCode", "outputTail"];
|
|
22
|
+
const SEVERITIES = ["low", "medium", "high", "blocker"];
|
|
23
|
+
const LIMITS = { rounds: 20, tasks: 64, findings: 32, commands: 16, text: 2000 };
|
|
24
|
+
|
|
25
|
+
function unknownKeys(value, allowed, path, file, report) {
|
|
26
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
27
|
+
report.push(diagnostic("error", "run-shape", path, `${path} 必须是对象`, file));
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
for (const key of Object.keys(value)) {
|
|
31
|
+
if (!allowed.includes(key)) {
|
|
32
|
+
report.push(diagnostic("error", "unknown-field", `${path}.${key}`, `未知字段 "${key}";可用字段:${allowed.join(" / ")}`, file));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function textField(value, path, file, report, { max = LIMITS.text, required = false } = {}) {
|
|
39
|
+
if (value === undefined || value === null) {
|
|
40
|
+
if (required) report.push(diagnostic("error", "run-field", path, `${path} 不能为空`, file));
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value !== "string") {
|
|
44
|
+
report.push(diagnostic("error", "run-field", path, `${path} 必须是字符串`, file));
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
if (value.length > max) {
|
|
48
|
+
report.push(diagnostic("error", "run-field", path, `${path} 超过 ${max} 字符`, file));
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 校验一份执行回执。不合法时返回 `run: null`,并把每条原因写成诊断。 */
|
|
55
|
+
export function validateRun(value, { file = "run.json" } = {}) {
|
|
56
|
+
const report = [];
|
|
57
|
+
if (!unknownKeys(value, RUN_FIELDS, "run", file, report)) return { ok: false, run: null, diagnostics: report };
|
|
58
|
+
if (value.kind !== RUN_KIND) {
|
|
59
|
+
report.push(diagnostic("error", "run-kind", "run.kind", `kind 必须是 "${RUN_KIND}"`, file));
|
|
60
|
+
}
|
|
61
|
+
const roster = value.roster;
|
|
62
|
+
if (roster === null || typeof roster !== "object" || Array.isArray(roster)) {
|
|
63
|
+
report.push(diagnostic("error", "run-field", "run.roster", "roster 必须是 {id, version}", file));
|
|
64
|
+
} else {
|
|
65
|
+
unknownKeys(roster, ["id", "version"], "run.roster", file, report);
|
|
66
|
+
textField(roster.id, "run.roster.id", file, report, { required: true, max: 64 });
|
|
67
|
+
textField(roster.version, "run.roster.version", file, report, { required: true, max: 64 });
|
|
68
|
+
}
|
|
69
|
+
const rounds = value.rounds;
|
|
70
|
+
if (!Array.isArray(rounds) || rounds.length === 0) {
|
|
71
|
+
report.push(diagnostic("error", "run-rounds", "run.rounds", "rounds 必须是非空数组", file));
|
|
72
|
+
} else if (rounds.length > LIMITS.rounds) {
|
|
73
|
+
report.push(diagnostic("error", "run-rounds", "run.rounds", `rounds 最多 ${LIMITS.rounds} 轮`, file));
|
|
74
|
+
} else {
|
|
75
|
+
rounds.forEach((round, index) => verifyRound(round, index, file, report));
|
|
76
|
+
}
|
|
77
|
+
if (report.some((item) => item.severity === "error")) return { ok: false, run: null, diagnostics: report };
|
|
78
|
+
return { ok: true, run: value, diagnostics: report };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function verifyRound(round, index, file, report) {
|
|
82
|
+
const path = `run.rounds[${index}]`;
|
|
83
|
+
if (!unknownKeys(round, ROUND_FIELDS, path, file, report)) return;
|
|
84
|
+
if (!Number.isInteger(round.round) || round.round < 1) {
|
|
85
|
+
report.push(diagnostic("error", "run-round", `${path}.round`, "round 必须是从 1 开始的整数", file));
|
|
86
|
+
}
|
|
87
|
+
textField(round.at, `${path}.at`, file, report, { max: 40 });
|
|
88
|
+
if (!Array.isArray(round.tasks) || round.tasks.length === 0) {
|
|
89
|
+
report.push(diagnostic("error", "run-tasks", `${path}.tasks`, "tasks 必须是非空数组", file));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (round.tasks.length > LIMITS.tasks) {
|
|
93
|
+
report.push(diagnostic("error", "run-tasks", `${path}.tasks`, `tasks 最多 ${LIMITS.tasks} 张卡`, file));
|
|
94
|
+
}
|
|
95
|
+
round.tasks.forEach((task, taskIndex) => verifyTask(task, `${path}.tasks[${taskIndex}]`, file, report));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function verifyTask(task, path, file, report) {
|
|
99
|
+
if (!unknownKeys(task, TASK_FIELDS, path, file, report)) return;
|
|
100
|
+
textField(task.id, `${path}.id`, file, report, { required: true, max: 120 });
|
|
101
|
+
if (!RUN_STATUSES.includes(task.status)) {
|
|
102
|
+
report.push(diagnostic("error", "run-status", `${path}.status`, `status 只能是 ${RUN_STATUSES.join(" / ")}`, file));
|
|
103
|
+
}
|
|
104
|
+
if (task.findings !== undefined) {
|
|
105
|
+
if (!Array.isArray(task.findings)) {
|
|
106
|
+
report.push(diagnostic("error", "run-findings", `${path}.findings`, "findings 必须是数组", file));
|
|
107
|
+
} else if (task.findings.length > LIMITS.findings) {
|
|
108
|
+
report.push(diagnostic("error", "run-findings", `${path}.findings`, `findings 最多 ${LIMITS.findings} 条`, file));
|
|
109
|
+
} else {
|
|
110
|
+
task.findings.forEach((finding, index) => verifyFinding(finding, `${path}.findings[${index}]`, file, report));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (task.commands !== undefined) {
|
|
114
|
+
if (!Array.isArray(task.commands)) {
|
|
115
|
+
report.push(diagnostic("error", "run-commands", `${path}.commands`, "commands 必须是数组", file));
|
|
116
|
+
} else if (task.commands.length > LIMITS.commands) {
|
|
117
|
+
report.push(diagnostic("error", "run-commands", `${path}.commands`, `commands 最多 ${LIMITS.commands} 条`, file));
|
|
118
|
+
} else {
|
|
119
|
+
task.commands.forEach((command, index) => verifyCommand(command, `${path}.commands[${index}]`, file, report));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
textField(task.note, `${path}.note`, file, report, { max: 500 });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function verifyFinding(finding, path, file, report) {
|
|
126
|
+
if (!unknownKeys(finding, FINDING_FIELDS, path, file, report)) return;
|
|
127
|
+
if (!SEVERITIES.includes(finding.severity)) {
|
|
128
|
+
report.push(diagnostic("error", "run-severity", `${path}.severity`, `severity 只能是 ${SEVERITIES.join(" / ")}`, file));
|
|
129
|
+
}
|
|
130
|
+
textField(finding.problem, `${path}.problem`, file, report, { required: true });
|
|
131
|
+
textField(finding.requiredFix, `${path}.requiredFix`, file, report, { required: true });
|
|
132
|
+
textField(finding.file, `${path}.file`, file, report, { max: 300 });
|
|
133
|
+
if (finding.line !== undefined && (!Number.isInteger(finding.line) || finding.line < 1)) {
|
|
134
|
+
report.push(diagnostic("error", "run-line", `${path}.line`, "line 必须是正整数", file));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function verifyCommand(command, path, file, report) {
|
|
139
|
+
if (!unknownKeys(command, COMMAND_FIELDS, path, file, report)) return;
|
|
140
|
+
textField(command.command, `${path}.command`, file, report, { required: true, max: 500 });
|
|
141
|
+
if (!Number.isInteger(command.exitCode)) {
|
|
142
|
+
report.push(diagnostic("error", "run-exit", `${path}.exitCode`, "exitCode 必须是整数", file));
|
|
143
|
+
}
|
|
144
|
+
textField(command.outputTail, `${path}.outputTail`, file, report, { max: LIMITS.text });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** 取最新一轮里失败的卡片。 */
|
|
148
|
+
export function failedTasksOf(run) {
|
|
149
|
+
const latest = run?.rounds?.at(-1);
|
|
150
|
+
return (latest?.tasks ?? []).filter((task) => task.status === "failed");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 把最新一轮的失败带进施工图:重试卡的 description 追加一段「上一轮为什么没过」。
|
|
155
|
+
*
|
|
156
|
+
* 只改重试目标那一张卡,其余卡片原样保留——施工图仍然是编译产物,不是运行态。
|
|
157
|
+
*/
|
|
158
|
+
export function mergeRunIntoPlan(plan, run) {
|
|
159
|
+
if (plan === null || run === null) return { plan, feedback: [] };
|
|
160
|
+
const failed = failedTasksOf(run);
|
|
161
|
+
const feedback = failed.map((task) => summarizeTask(task));
|
|
162
|
+
const retryId = plan.loop?.onGateFailure?.retry ?? null;
|
|
163
|
+
if (retryId === null || feedback.length === 0) return { plan, feedback };
|
|
164
|
+
const round = (run.rounds?.at(-1)?.round ?? 0) + 1;
|
|
165
|
+
const text = [
|
|
166
|
+
"",
|
|
167
|
+
`上一轮(第 ${round - 1} 轮)失败,重做时先修这些:`,
|
|
168
|
+
...feedback.map((line, index) => `${index + 1}. ${line}`),
|
|
169
|
+
].join("\n");
|
|
170
|
+
const tasks = plan.tasks.map((task) =>
|
|
171
|
+
task.id === retryId ? { ...task, description: `${task.description}${text}`, feedback: feedback } : task,
|
|
172
|
+
);
|
|
173
|
+
return { plan: { ...plan, tasks, round, feedback }, feedback };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function summarizeTask(task) {
|
|
177
|
+
const parts = [`卡 ${task.id} 未通过`];
|
|
178
|
+
for (const command of task.commands ?? []) {
|
|
179
|
+
if (command.exitCode === 0) continue;
|
|
180
|
+
const tail = String(command.outputTail ?? "").trim().split("\n").slice(-3).join(" / ");
|
|
181
|
+
parts.push(`命令 \`${command.command}\` 退出 ${command.exitCode}${tail ? `(${tail})` : ""}`);
|
|
182
|
+
}
|
|
183
|
+
for (const finding of task.findings ?? []) {
|
|
184
|
+
const where = finding.file ? ` [${finding.file}${finding.line ? `:${finding.line}` : ""}]` : "";
|
|
185
|
+
parts.push(`${finding.severity}: ${finding.problem}${where} → ${finding.requiredFix}`);
|
|
186
|
+
}
|
|
187
|
+
return parts.join(";");
|
|
188
|
+
}
|
package/lib/write.js
CHANGED
|
@@ -115,14 +115,20 @@ export function readRosterDocument(input) {
|
|
|
115
115
|
const dir = resolveRosterDir(root.rootDir, input.id);
|
|
116
116
|
if (dir === null) return { ok: false, code: "invalid-id" };
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
// 两种布局都读:v1 是 `<root>/<id>/roster.*`,v2 是 `<root>/rosters/<id>/roster.*`。
|
|
119
|
+
// 只看 id 不看布局,调用方不需要知道这座库是哪一代格式。
|
|
120
|
+
const candidates = [dir, nodePath.join(root.rootDir, "rosters", input.id)];
|
|
121
|
+
for (const candidate of candidates) {
|
|
122
|
+
for (const name of ROSTER_FILE_NAMES) {
|
|
123
|
+
const file = nodePath.join(candidate, name);
|
|
124
|
+
if (!fs.existsSync(file)) continue;
|
|
125
|
+
const relative = nodePath.relative(root.rootDir, file).split(nodePath.sep).join("/");
|
|
126
|
+
try {
|
|
127
|
+
const text = fs.readFileSync(file, "utf8");
|
|
128
|
+
return { ok: true, file: relative, format: formatOf(name), text };
|
|
129
|
+
} catch {
|
|
130
|
+
return { ok: false, code: "unreadable-file" };
|
|
131
|
+
}
|
|
126
132
|
}
|
|
127
133
|
}
|
|
128
134
|
return { ok: false, code: "not-found" };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "dsh-agent-roster/compiled@1",
|
|
3
|
+
"source": {
|
|
4
|
+
"roster": "api-design",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"title": "API 设计评审组",
|
|
7
|
+
"repo": "dsh-agent-roster/dsh-agent-roster",
|
|
8
|
+
"ref": "main",
|
|
9
|
+
"lock": null,
|
|
10
|
+
"file": "roster.yaml"
|
|
11
|
+
},
|
|
12
|
+
"targets": [
|
|
13
|
+
"agent-teams/members"
|
|
14
|
+
],
|
|
15
|
+
"captain": null,
|
|
16
|
+
"members": [
|
|
17
|
+
{
|
|
18
|
+
"name": "lead",
|
|
19
|
+
"role": "接口负责人",
|
|
20
|
+
"roleRef": "api-design-lead@1.0.0",
|
|
21
|
+
"roleName": "api-design-lead",
|
|
22
|
+
"roleVersion": "1.0.0",
|
|
23
|
+
"provider": "deepseek",
|
|
24
|
+
"model": "deepseek-v4.1-flash",
|
|
25
|
+
"reasoningEffort": "high",
|
|
26
|
+
"toolPolicy": null,
|
|
27
|
+
"executionPrompt": "你负责这次接口评审的编排:先把资源模型、边界与调用方列清楚,再分给两名评审者,最后合并成一份结论。\n不要自己写实现,也不要替调用方假设需求;需求不明就明确写“需要调用方确认”,不要补全。\n结论必须能直接贴进设计文档:决定在前、理由在后,每条都注明是哪位评审者的证据。\n证据不足时给出“暂不定”的选项,并写清还差哪一条信息才能定。",
|
|
28
|
+
"promptStats": {
|
|
29
|
+
"chars": 164,
|
|
30
|
+
"parts": [
|
|
31
|
+
{
|
|
32
|
+
"path": "roles/api-design-lead/AGENT.md",
|
|
33
|
+
"kind": "body+parts"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "body",
|
|
37
|
+
"kind": "part"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"sha256": "dd530ec48e1de4abbcd0979d51c8b7f64273be9dbcf8e7f00dbba5c946aa5aee"
|
|
41
|
+
},
|
|
42
|
+
"provenance": {
|
|
43
|
+
"role": "api-design-lead@1.0.0",
|
|
44
|
+
"sha256": "87f4c33b"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "schema",
|
|
49
|
+
"role": "结构与演进评审",
|
|
50
|
+
"roleRef": "api-design-schema@1.0.0",
|
|
51
|
+
"roleName": "api-design-schema",
|
|
52
|
+
"roleVersion": "1.0.0",
|
|
53
|
+
"provider": "deepseek",
|
|
54
|
+
"model": "deepseek-v4.1-flash",
|
|
55
|
+
"reasoningEffort": "high",
|
|
56
|
+
"toolPolicy": null,
|
|
57
|
+
"executionPrompt": "你只看结构层面:字段命名是否自解释、分页与过滤是否可组合、写操作是否幂等、错误码能否让调用方分辨“重试有用/没用”。\n不评论实现细节与性能数据,那是另一个人的事;也不要提议重写整个资源模型。\n每条问题给出最小修改方向,并标注它是“现在改”还是“下个版本改”。\n对兼容性拿不准时,写成“破坏性:是/不确定”,不要默认无害。",
|
|
58
|
+
"promptStats": {
|
|
59
|
+
"chars": 160,
|
|
60
|
+
"parts": [
|
|
61
|
+
{
|
|
62
|
+
"path": "roles/api-design-schema/AGENT.md",
|
|
63
|
+
"kind": "body+parts"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "body",
|
|
67
|
+
"kind": "part"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"sha256": "673411e6e249cd0f32c15bff495d572a7345a879388d2d8b0446b309785baec9"
|
|
71
|
+
},
|
|
72
|
+
"provenance": {
|
|
73
|
+
"role": "api-design-schema@1.0.0",
|
|
74
|
+
"sha256": "8cdfbf46"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "failure-mode",
|
|
79
|
+
"role": "失败语义评审",
|
|
80
|
+
"roleRef": "api-design-failure-mode@1.0.0",
|
|
81
|
+
"roleName": "api-design-failure-mode",
|
|
82
|
+
"roleVersion": "1.0.0",
|
|
83
|
+
"provider": "deepseek",
|
|
84
|
+
"model": "deepseek-v4.1-flash",
|
|
85
|
+
"reasoningEffort": "high",
|
|
86
|
+
"toolPolicy": null,
|
|
87
|
+
"executionPrompt": "你只问一件事:这个接口失败时调用方看到什么、能不能安全重试、会不会把一次失败放大成多次副作用。\n不讨论字段命名与版本策略;只输出失败场景、可观测信号与契约要求。\n每条场景写成“触发条件 → 调用方看到的状态 → 要求实现方保证什么”。\n无法判定是否幂等的接口,直接要求补幂等键,不要用“一般来说”糊过去。",
|
|
88
|
+
"promptStats": {
|
|
89
|
+
"chars": 152,
|
|
90
|
+
"parts": [
|
|
91
|
+
{
|
|
92
|
+
"path": "roles/api-design-failure-mode/AGENT.md",
|
|
93
|
+
"kind": "body+parts"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": "body",
|
|
97
|
+
"kind": "part"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"sha256": "5259649be58f339e703ed691df24246479b2fab73520526b2f4a2b0fb1c4c3db"
|
|
101
|
+
},
|
|
102
|
+
"provenance": {
|
|
103
|
+
"role": "api-design-failure-mode@1.0.0",
|
|
104
|
+
"sha256": "2633b9d8"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"orchestration": null,
|
|
109
|
+
"declarations": [
|
|
110
|
+
{
|
|
111
|
+
"scope": "roster",
|
|
112
|
+
"field": "defaults.route",
|
|
113
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"scope": "roster",
|
|
117
|
+
"field": "defaults.route",
|
|
118
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"scope": "roster",
|
|
122
|
+
"field": "defaults.route",
|
|
123
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"requires": {
|
|
127
|
+
"skills": [],
|
|
128
|
+
"toolPolicies": []
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "dsh-agent-roster/compiled@1",
|
|
3
|
+
"source": {
|
|
4
|
+
"roster": "content-ops",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"title": "内容运营组",
|
|
7
|
+
"repo": "dsh-agent-roster/dsh-agent-roster",
|
|
8
|
+
"ref": "main",
|
|
9
|
+
"lock": null,
|
|
10
|
+
"file": "roster.yaml"
|
|
11
|
+
},
|
|
12
|
+
"targets": [
|
|
13
|
+
"agent-teams/members"
|
|
14
|
+
],
|
|
15
|
+
"captain": null,
|
|
16
|
+
"members": [
|
|
17
|
+
{
|
|
18
|
+
"name": "lead",
|
|
19
|
+
"role": "内容负责人",
|
|
20
|
+
"roleRef": "content-ops-lead@1.0.0",
|
|
21
|
+
"roleName": "content-ops-lead",
|
|
22
|
+
"roleVersion": "1.0.0",
|
|
23
|
+
"provider": "deepseek",
|
|
24
|
+
"model": "deepseek-v4.1-flash",
|
|
25
|
+
"reasoningEffort": "high",
|
|
26
|
+
"toolPolicy": null,
|
|
27
|
+
"executionPrompt": "你定选题:读者是谁、读完能带走什么、发在哪个渠道,以及每项的验收。\n不写正文,也不做排版;你负责取舍与排期。\n产出是一页 brief:读者 · 主张 · 证据要求 · 渠道 · 截止。\n选题无法说清“读者为什么要读”时,换题而不是硬写。",
|
|
28
|
+
"promptStats": {
|
|
29
|
+
"chars": 118,
|
|
30
|
+
"parts": [
|
|
31
|
+
{
|
|
32
|
+
"path": "roles/content-ops-lead/AGENT.md",
|
|
33
|
+
"kind": "body+parts"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "body",
|
|
37
|
+
"kind": "part"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"sha256": "1e7bbbff7b441f2acd3c46e1ea3ba848e2fd5ffbf9f140c9437b8cfd76ccaede"
|
|
41
|
+
},
|
|
42
|
+
"provenance": {
|
|
43
|
+
"role": "content-ops-lead@1.0.0",
|
|
44
|
+
"sha256": "b8172fa1"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "editor",
|
|
49
|
+
"role": "成稿编辑",
|
|
50
|
+
"roleRef": "content-ops-editor@1.0.0",
|
|
51
|
+
"roleName": "content-ops-editor",
|
|
52
|
+
"roleVersion": "1.0.0",
|
|
53
|
+
"provider": "deepseek",
|
|
54
|
+
"model": "deepseek-v4.1-flash",
|
|
55
|
+
"reasoningEffort": "high",
|
|
56
|
+
"toolPolicy": null,
|
|
57
|
+
"executionPrompt": "你编辑成稿:每段一个意思,删掉无法验证的形容词,给每个主张补证据或删除。\n不改事实,也不加未经验证的数据;发现缺证据就标出来让对方补。\n交付改后稿 + 一段“我删了什么、为什么”。\n拿不准的事实一律降级为“据说/待确认”,不要保留确定性语气。",
|
|
58
|
+
"promptStats": {
|
|
59
|
+
"chars": 121,
|
|
60
|
+
"parts": [
|
|
61
|
+
{
|
|
62
|
+
"path": "roles/content-ops-editor/AGENT.md",
|
|
63
|
+
"kind": "body+parts"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "body",
|
|
67
|
+
"kind": "part"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"sha256": "a44b7f0dbb313283234bb933c3cb8d8e58a4e746279bd623b9418b155c6f6b9d"
|
|
71
|
+
},
|
|
72
|
+
"provenance": {
|
|
73
|
+
"role": "content-ops-editor@1.0.0",
|
|
74
|
+
"sha256": "4414cd52"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "distributor",
|
|
79
|
+
"role": "分发与回读",
|
|
80
|
+
"roleRef": "content-ops-distributor@1.0.0",
|
|
81
|
+
"roleName": "content-ops-distributor",
|
|
82
|
+
"roleVersion": "1.0.0",
|
|
83
|
+
"provider": "deepseek",
|
|
84
|
+
"model": "deepseek-v4.1-flash",
|
|
85
|
+
"reasoningEffort": "high",
|
|
86
|
+
"toolPolicy": null,
|
|
87
|
+
"executionPrompt": "你按渠道改写标题与首段(同一主张不同入口),并规划发布时间与配套动作。\n不改正文主张;只调整入口表达与分发节奏。\n发布后回收读数:曝光、点击、读完率,并说明哪些指标不可得。\n读数缺失时如实写“无法获取”,不要用估算值冒充实测。",
|
|
88
|
+
"promptStats": {
|
|
89
|
+
"chars": 113,
|
|
90
|
+
"parts": [
|
|
91
|
+
{
|
|
92
|
+
"path": "roles/content-ops-distributor/AGENT.md",
|
|
93
|
+
"kind": "body+parts"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": "body",
|
|
97
|
+
"kind": "part"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"sha256": "a310ca5dc37ea2051e3c4a996aa5f8c12fa225d95964d0e1bf074194975c1c20"
|
|
101
|
+
},
|
|
102
|
+
"provenance": {
|
|
103
|
+
"role": "content-ops-distributor@1.0.0",
|
|
104
|
+
"sha256": "330a108f"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"orchestration": null,
|
|
109
|
+
"declarations": [
|
|
110
|
+
{
|
|
111
|
+
"scope": "roster",
|
|
112
|
+
"field": "defaults.route",
|
|
113
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"scope": "roster",
|
|
117
|
+
"field": "defaults.route",
|
|
118
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"scope": "roster",
|
|
122
|
+
"field": "defaults.route",
|
|
123
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"requires": {
|
|
127
|
+
"skills": [],
|
|
128
|
+
"toolPolicies": []
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "dsh-agent-roster/compiled@1",
|
|
3
|
+
"source": {
|
|
4
|
+
"roster": "contract-review",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"title": "合同审阅组",
|
|
7
|
+
"repo": "dsh-agent-roster/dsh-agent-roster",
|
|
8
|
+
"ref": "main",
|
|
9
|
+
"lock": null,
|
|
10
|
+
"file": "roster.yaml"
|
|
11
|
+
},
|
|
12
|
+
"targets": [
|
|
13
|
+
"agent-teams/members"
|
|
14
|
+
],
|
|
15
|
+
"captain": null,
|
|
16
|
+
"members": [
|
|
17
|
+
{
|
|
18
|
+
"name": "lead",
|
|
19
|
+
"role": "审阅负责人",
|
|
20
|
+
"roleRef": "contract-review-lead@1.0.0",
|
|
21
|
+
"roleName": "contract-review-lead",
|
|
22
|
+
"roleVersion": "1.0.0",
|
|
23
|
+
"provider": "deepseek",
|
|
24
|
+
"model": "deepseek-v4.1-flash",
|
|
25
|
+
"reasoningEffort": "high",
|
|
26
|
+
"toolPolicy": null,
|
|
27
|
+
"executionPrompt": "你先确认我方角色与商业目标,再定红线:哪些条款出现就不签。\n不逐条解释条款;你负责范围与最终建议(签 / 改 / 不签)。\n产出是红线清单 + 建议的谈判顺序。\n立场不明时先问“最坏情况下我们能承受什么”,不要默认接受。",
|
|
28
|
+
"promptStats": {
|
|
29
|
+
"chars": 110,
|
|
30
|
+
"parts": [
|
|
31
|
+
{
|
|
32
|
+
"path": "roles/contract-review-lead/AGENT.md",
|
|
33
|
+
"kind": "body+parts"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "body",
|
|
37
|
+
"kind": "part"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"sha256": "a2b619fee43aa71724fdc4d95908e1e73c050a5edb484b0284f2d39bc5afd83f"
|
|
41
|
+
},
|
|
42
|
+
"provenance": {
|
|
43
|
+
"role": "contract-review-lead@1.0.0",
|
|
44
|
+
"sha256": "b086fec1"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "clause-reader",
|
|
49
|
+
"role": "条款识别",
|
|
50
|
+
"roleRef": "contract-review-clause-reader@1.0.0",
|
|
51
|
+
"roleName": "contract-review-clause-reader",
|
|
52
|
+
"roleVersion": "1.0.0",
|
|
53
|
+
"provider": "deepseek",
|
|
54
|
+
"model": "deepseek-v4.1-flash",
|
|
55
|
+
"reasoningEffort": "high",
|
|
56
|
+
"toolPolicy": null,
|
|
57
|
+
"executionPrompt": "你摘出关键条款:责任上限、赔偿、终止与续约、知识产权归属、保密、争议解决。\n不做商业判断;每条必须给条款编号与原文摘录。\n输出“条款 · 原文 · 位置 · 对我方的影响(有利/中性/不利)”。\n条款缺失同样重要:明确写“未见某类条款”,不要当作默认有利。",
|
|
58
|
+
"promptStats": {
|
|
59
|
+
"chars": 128,
|
|
60
|
+
"parts": [
|
|
61
|
+
{
|
|
62
|
+
"path": "roles/contract-review-clause-reader/AGENT.md",
|
|
63
|
+
"kind": "body+parts"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "body",
|
|
67
|
+
"kind": "part"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"sha256": "4a21ae8ee5c4ad9874d35ab82abbe0c0b5a0469627d56c28677b9e83a55cfbeb"
|
|
71
|
+
},
|
|
72
|
+
"provenance": {
|
|
73
|
+
"role": "contract-review-clause-reader@1.0.0",
|
|
74
|
+
"sha256": "cfd70c98"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "risk-note",
|
|
79
|
+
"role": "风险提示",
|
|
80
|
+
"roleRef": "contract-review-risk-note@1.0.0",
|
|
81
|
+
"roleName": "contract-review-risk-note",
|
|
82
|
+
"roleVersion": "1.0.0",
|
|
83
|
+
"provider": "deepseek",
|
|
84
|
+
"model": "deepseek-v4.1-flash",
|
|
85
|
+
"reasoningEffort": "high",
|
|
86
|
+
"toolPolicy": null,
|
|
87
|
+
"executionPrompt": "你把条款翻译成后果:最坏情形下赔多少、被锁定多久、退出成本多少。\n不写法律意见书,也不替代律师;你给的是量化提示与修改方向。\n输出“风险 · 触发条件 · 最坏敞口 · 建议改法(一句话)”。\n无法量化时给区间并说明假设,不要给“风险较低”这种结论。",
|
|
88
|
+
"promptStats": {
|
|
89
|
+
"chars": 125,
|
|
90
|
+
"parts": [
|
|
91
|
+
{
|
|
92
|
+
"path": "roles/contract-review-risk-note/AGENT.md",
|
|
93
|
+
"kind": "body+parts"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": "body",
|
|
97
|
+
"kind": "part"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"sha256": "fba0572e317e8a2d787254814fb970282dbeb01803495be09e0b9c9f88162b45"
|
|
101
|
+
},
|
|
102
|
+
"provenance": {
|
|
103
|
+
"role": "contract-review-risk-note@1.0.0",
|
|
104
|
+
"sha256": "b589aa0d"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"orchestration": null,
|
|
109
|
+
"declarations": [
|
|
110
|
+
{
|
|
111
|
+
"scope": "roster",
|
|
112
|
+
"field": "defaults.route",
|
|
113
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"scope": "roster",
|
|
117
|
+
"field": "defaults.route",
|
|
118
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"scope": "roster",
|
|
122
|
+
"field": "defaults.route",
|
|
123
|
+
"note": "materialized:已展开成每个成员的显式值"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"requires": {
|
|
127
|
+
"skills": [],
|
|
128
|
+
"toolPolicies": []
|
|
129
|
+
}
|
|
130
|
+
}
|