Feat/design agent simple #305
@@ -28,10 +28,6 @@ const SECTION_FILES: &[(&str, &str)] = &[
|
||||
("supervisorPlaybook", "supervisor/playbook.md"),
|
||||
("supervisorClaimGate", "supervisor/claim-gate.md"),
|
||||
("supervisorRepair", "supervisor/repair.md"),
|
||||
("planCommon", "plan/common.md"),
|
||||
("planSupervisorIdentity", "plan/supervisor-identity.md"),
|
||||
("planSupervisorPlaybook", "plan/supervisor-playbook.md"),
|
||||
("projectPlanningRoleBrief", "roles/project-planning.md"),
|
||||
(
|
||||
"providerIsolatedToolContract",
|
||||
"provider/isolated-tool-contract.md",
|
||||
@@ -144,14 +140,6 @@ fn valid_manifest() -> Value {
|
||||
"supervisorClaimGate",
|
||||
"supervisorRepair"
|
||||
],
|
||||
"supervisorPlan": [
|
||||
"$header",
|
||||
"planCommon",
|
||||
"isolatedAgentContract",
|
||||
"planSupervisorIdentity",
|
||||
"planSupervisorPlaybook",
|
||||
"supervisorRepair"
|
||||
],
|
||||
"supervisorChat": {
|
||||
"identity": "supervisorIdentityContract",
|
||||
"finalReply": "supervisorFinalReplyContract"
|
||||
@@ -167,12 +155,7 @@ fn valid_manifest() -> Value {
|
||||
"editorUnavailable": "supervisorVisualWithoutEditor"
|
||||
}
|
||||
},
|
||||
"roleOverlays": [
|
||||
{
|
||||
"agentId": "project-planning",
|
||||
"sections": ["projectPlanningRoleBrief"]
|
||||
}
|
||||
],
|
||||
"roleOverlays": [],
|
||||
"providerFragments": {
|
||||
"isolatedToolContract": "providerIsolatedToolContract",
|
||||
"autonomousRunProfile": "providerAutonomousRunProfile",
|
||||
@@ -199,21 +182,6 @@ fn valid_manifest() -> Value {
|
||||
}
|
||||
]
|
||||
},
|
||||
"planning": {
|
||||
"id": "planning",
|
||||
"label": "立项策划",
|
||||
"role": "Project Planning",
|
||||
"briefPathName": "project-planning.md",
|
||||
"roles": [
|
||||
{
|
||||
"id": "project-planning",
|
||||
"role": "Project Planning",
|
||||
"taskId": "project-planning",
|
||||
"toolId": "agent.runtime.project-planning",
|
||||
"briefPathName": "project-planning.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": "code",
|
||||
@@ -622,34 +590,73 @@ fn rejects_unused_registered_and_unregistered_markdown_sections() {
|
||||
.contains("未登记的 Markdown section"));
|
||||
}
|
||||
|
||||
// 基础 fixture 不携带 overlay(与生产 manifest 一致);本测试自带一份合法 overlay,
|
||||
// 再逐项破坏它。overlay section 必须先落盘成普通文件——编译器先读完全部 section
|
||||
// 文件才做语义校验。
|
||||
fn overlay_fixture() -> Fixture {
|
||||
let mut fixture = Fixture::new();
|
||||
fs::create_dir_all(fixture.root().join("roles")).expect("create roles directory");
|
||||
fs::write(
|
||||
fixture.root().join("roles/code-director-brief.md"),
|
||||
"SECTION:codeDirectorRoleBrief\n",
|
||||
)
|
||||
.expect("write overlay section");
|
||||
fixture.manifest["sections"]["codeDirectorRoleBrief"] =
|
||||
json!("roles/code-director-brief.md");
|
||||
fixture.manifest["roleOverlays"] = json!([{
|
||||
"agentId": "code-director",
|
||||
"sections": ["codeDirectorRoleBrief"]
|
||||
}]);
|
||||
fixture.write_manifest();
|
||||
fixture
|
||||
}
|
||||
|
||||
fn compile_overlay_after(mutator: impl FnOnce(&mut Value)) -> Result<(), String> {
|
||||
let mut fixture = overlay_fixture();
|
||||
mutator(&mut fixture.manifest);
|
||||
fixture.write_manifest();
|
||||
fixture.compile().map(|_| ())
|
||||
}
|
||||
|
||||
fn assert_overlay_compile_error(mutator: impl FnOnce(&mut Value), expected: &str) {
|
||||
let error = compile_overlay_after(mutator).expect_err("manifest must fail closed");
|
||||
assert!(
|
||||
error.contains(expected),
|
||||
"expected error containing {expected:?}, got {error:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_invalid_role_overlays() {
|
||||
assert_compile_error(
|
||||
overlay_fixture()
|
||||
.compile()
|
||||
.expect("valid overlay manifest must compile");
|
||||
assert_overlay_compile_error(
|
||||
|manifest| manifest["roleOverlays"][0]["agentId"] = json!("unknown-agent"),
|
||||
"未知 agentId",
|
||||
);
|
||||
assert_compile_error(
|
||||
assert_overlay_compile_error(
|
||||
|manifest| manifest["roleOverlays"][0]["sections"] = json!([]),
|
||||
"sections 不能为空",
|
||||
);
|
||||
assert_compile_error(
|
||||
assert_overlay_compile_error(
|
||||
|manifest| manifest["roleOverlays"][0]["sections"] = json!(["missingSection"]),
|
||||
"未知 section",
|
||||
);
|
||||
assert_compile_error(
|
||||
assert_overlay_compile_error(
|
||||
|manifest| {
|
||||
manifest["roleOverlays"][0]["sections"] = json!(["supervisorClaimGate"]);
|
||||
},
|
||||
"Prompt section 跨语义所有者复用:supervisorClaimGate",
|
||||
);
|
||||
assert_compile_error(
|
||||
assert_overlay_compile_error(
|
||||
|manifest| {
|
||||
manifest["roleOverlays"][0]["sections"] =
|
||||
json!(["projectPlanningRoleBrief", "projectPlanningRoleBrief"]);
|
||||
json!(["codeDirectorRoleBrief", "codeDirectorRoleBrief"]);
|
||||
},
|
||||
"重复 section",
|
||||
);
|
||||
assert_compile_error(
|
||||
assert_overlay_compile_error(
|
||||
|manifest| {
|
||||
let overlay = manifest["roleOverlays"][0].clone();
|
||||
manifest["roleOverlays"] = json!([overlay.clone(), overlay]);
|
||||
|
||||
Reference in New Issue
Block a user