fix(web): keep unattended planner state auditable
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-09-03 22:39:08 +08:00
parent 9ad74fdd4a
commit e00972b309
3 changed files with 21 additions and 2 deletions

View File

@@ -188,6 +188,7 @@ def fast_path_status(status: dict) -> dict:
latest_batch = scheduler.get("latestBatch") if isinstance(scheduler.get("latestBatch"), dict) else {}
cache = _read_json(CONTROL_ROOT / "context-cache.json")
ledger = _read_json(CONTROL_ROOT / "failure-ledger.json")
planner = _read_json(CONTROL_ROOT / "auto-planner.json")
return {
"batch": {
"batchId": latest_batch.get("batchId"),
@@ -204,6 +205,12 @@ def fast_path_status(status: dict) -> dict:
"entryCount": len(ledger.get("entries", [])) if isinstance(ledger.get("entries"), list) else 0,
"hydratedLogs": len(ledger.get("hydratedLogs", [])) if isinstance(ledger.get("hydratedLogs"), list) else 0,
},
"autoPlanner": {
"status": planner.get("status", "MISSING"),
"reason": planner.get("reason"),
"pending": planner.get("pending", {}).get("count") if isinstance(planner.get("pending"), dict) else None,
"nextAction": planner.get("nextAction"),
},
"commandBudget": {"maxCommands": 48, "maxReadCommands": 16},
"verificationPolicy": "incremental-context-only-until-final-audit",
}
@@ -219,6 +226,7 @@ def format_progress(progress: dict, fast_path: dict | None = None) -> list[str]:
batch = fast_path.get("batch", {})
context_cache = fast_path.get("contextCache", {})
ledger = fast_path.get("failureLedger", {})
planner = fast_path.get("autoPlanner", {})
return [
"",
"Project migration progress",
@@ -233,6 +241,7 @@ def format_progress(progress: dict, fast_path: dict | None = None) -> list[str]:
f" fast path: batch={batch.get('batchId') or 'none'} selected={batch.get('selectedRecordCount', 0)} completed={batch.get('completed', False)}",
f" context cache: {context_cache.get('status', 'MISSING')} task={context_cache.get('task') or 'none'} inputs={context_cache.get('inputCount', 0)}; failure ledger entries={ledger.get('entryCount', 0)} hydratedLogs={ledger.get('hydratedLogs', 0)}",
f" command budget: max={fast_path.get('commandBudget', {}).get('maxCommands', 48)}, read/exploration max={fast_path.get('commandBudget', {}).get('maxReadCommands', 16)}; verification={fast_path.get('verificationPolicy', 'n/a')}",
f" auto planner: {planner.get('status', 'MISSING')} pending={planner.get('pending', 'n/a')} next={planner.get('nextAction') or 'none'}",
]

View File

@@ -60,7 +60,7 @@
},
"taskContext": {
"path": "tests/golden/WBV2-P1162-001/task-context.json",
"sha256": "376f89e31e0d34a413c9aff68780cf005f26d6cf2a5ebe51e38673cc8b9a5af5"
"sha256": "296e19f4147f8d9fa324f118c02ebb08af98c787e52fdc0670c76e475f93820f"
}
},
"assertions": {

View File

@@ -90,7 +90,17 @@ const collect = () => {
const supervisorLock = lockInfo(supervisorLockPath);
const handoff = latestHandoff();
const active = schedulerLock.alive || (guardianLock.alive && supervisorLock.alive);
const blocked = scheduler?.state === "blocked" || guardian?.state === "blocked" || supervisor?.state === "blocked";
let terminalQueue = false;
try {
const manifest = queue.task ? readJson(`tests/golden/${queue.task}/manifest.json`) : null;
const index = readJson("tests/golden/WBV2/task-index.json");
terminalQueue = !active && index?.activeTask === null && manifest?.status === "done" && manifest?.nextTask === null;
} catch { /* A malformed pointer remains visible as a normal checkpoint failure. */ }
const checkpointBlocked = scheduler?.state === "blocked" || guardian?.state === "blocked" || supervisor?.state === "blocked";
// A terminal task can leave a historical blocked checkpoint behind (for
// example, after a push retry). The watchdog owns the next planner attempt;
// do not report that stale checkpoint as a live execution block.
const blocked = checkpointBlocked && !terminalQueue;
const state = blocked ? "BLOCKED" : active ? "RUNNING" : "IDLE";
const phase = blocked ? "blocked" : scheduler?.state === "running" ? "scheduler-task" : supervisor?.state === "running" ? "task-or-gate" : scheduler?.state ?? supervisor?.state ?? "unknown";
const observed = new Date().toISOString();