补齐策划会话投影失败任务的 phase 白名单

统一 planning-session-projection-failed 的写入与读取常量

补充稀有持久化 phase 的 Runtime task journal 回归测试
This commit is contained in:
2026-08-26 11:36:23 +00:00
parent 15c0d6f028
commit 0e84ea1ed9
3 changed files with 24 additions and 3 deletions
@@ -519,7 +519,7 @@ fn start_game_creator_agent_background_task_with_link_in_session_lane_with_proje
let error = redact_agent_runtime_project_paths(root, &error, 500);
let failed_task = AgentRuntimeTaskRecord {
status: "failed".to_string(),
phase: "planning-session-projection-failed".to_string(),
phase: AGENT_RUNTIME_TASK_PHASE_PLANNING_SESSION_PROJECTION_FAILED.to_string(),
current_action: "Fast GDD session 未能安全绑定,后台任务未执行".to_string(),
terminal_detail: Some(error.clone()),
error: Some(error.clone()),
@@ -4,6 +4,12 @@ static AGENT_RUNTIME_EVENT_ID_SEQUENCE: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(1);
pub(crate) const AGENT_RUNTIME_PUBLIC_STATUS_MESSAGE_ID_PREFIX: &str = "runtime-public-status-";
/// task journal 只在**读**的时候校验 phase 白名单,写侧不校验。所以一个没登记的
/// phase 落盘之后,整份 journal 从那一行起再也读不出来:`agent.run_status` 对该
/// Agent 永久失败,父 run 只能瞎转到 needs-reconciliation。实测就是这么炸的。
/// 让写方和白名单引用同一个常量,两边不可能再漂移。
pub(crate) const AGENT_RUNTIME_TASK_PHASE_PLANNING_SESSION_PROJECTION_FAILED: &str =
"planning-session-projection-failed";
fn game_creator_agent_runtime_public_status_message_id(
agent_id: &str,
@@ -4089,6 +4095,7 @@ fn validate_game_creator_agent_runtime_task_status_phase(
| "completion-contract-failed"
| "conversation-write-failed"
| "public-status-write-failed"
| AGENT_RUNTIME_TASK_PHASE_PLANNING_SESSION_PROJECTION_FAILED
| "parent-terminal"
| "parent-link-missing"
) {
@@ -235,19 +235,33 @@ fn runtime_task_reader_accepts_rare_persisted_phases() {
"failed",
"public-status-write-failed",
);
// 写侧不校验 phase,只有读侧校验:白名单漏登记一个 phase,落盘之后整份 journal
// 从那一行起再也读不出来,`agent.run_status` 对该 Agent 永久失败。这里用写方
// 引用的同一个常量,漏登记会在这条用例上先红。
let planning_session_projection_failed = runtime_task_json_line(
"planning-session-projection-failed-run",
"failed",
AGENT_RUNTIME_TASK_PHASE_PLANNING_SESSION_PROJECTION_FAILED,
);
fs::write(
&path,
format!("{brief}\n{parent_link_missing}\n{public_status_write_failed}\n"),
format!(
"{brief}\n{parent_link_missing}\n{public_status_write_failed}\n{planning_session_projection_failed}\n"
),
)
.expect("write rare persisted task phases");
let records = read_all_game_creator_agent_runtime_tasks(&path)
.expect("known persisted task phases must remain readable");
assert_eq!(records.len(), 3);
assert_eq!(records.len(), 4);
assert_eq!(records[0].phase, "brief");
assert_eq!(records[1].phase, "parent-link-missing");
assert_eq!(records[2].phase, "public-status-write-failed");
assert_eq!(
records[3].phase,
AGENT_RUNTIME_TASK_PHASE_PLANNING_SESSION_PROJECTION_FAILED
);
fs::remove_dir_all(root).ok();
}