fix: keep task completion, cancel, pause, and undo honest
Pending earlier-revision jobs no longer skip completion repair; late cancels preserve real exits; begin clears pause; partial undo keeps snapshots; permissions and worktree failure paths are hardened. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+39
-7
@@ -979,7 +979,20 @@ static void sandbox_escalate(turn_t *t, cst_tool_ctx_t *ctx,
|
||||
cst_perms_allow_tool(a->perms, c->name);
|
||||
}
|
||||
hook_status(t, "rerunning outside the sandbox");
|
||||
if (a->cancel || !cst_runtime_check(a->cfg.runtime, t->revision, 1, 0)) return;
|
||||
if (a->cancel || !cst_runtime_check(a->cfg.runtime, t->revision, 1, 0)) {
|
||||
const char *note =
|
||||
"\n[cst: the user allowed rerunning outside the sandbox, but the "
|
||||
"task was cancelled or its instructions changed before the "
|
||||
"rerun; sandbox output above is unchanged]\n";
|
||||
cst_buf_t b = {0};
|
||||
if (tr->out)
|
||||
cst_buf_append(&b, tr->out, tr->out_len);
|
||||
cst_buf_puts(&b, note);
|
||||
free(tr->out);
|
||||
tr->out_len = b.len;
|
||||
tr->out = cst_buf_steal(&b);
|
||||
return;
|
||||
}
|
||||
cst_tool_result_free(tr);
|
||||
memset(tr, 0, sizeof(*tr));
|
||||
ctx->sandbox = 0;
|
||||
@@ -3200,15 +3213,34 @@ static int run_turn_once(cst_agent_t *a, const char *user_text,
|
||||
}
|
||||
if (!a->cfg.depth && a->cfg.tool_profile != CST_TOOLS_MINIMAL) {
|
||||
char why[256];
|
||||
if (cst_runtime_jobs_pending(a->cfg.runtime))
|
||||
cst_runtime_finish(a->cfg.runtime, "partial", "Earlier-revision jobs remain active; inspect task_state for their outcomes.", 0, why, sizeof(why));
|
||||
if (cst_runtime_finish(a->cfg.runtime, "completed", body, tools_ran, why, sizeof(why))) {
|
||||
/* Do not pre-mark partial before finish(completed): that made the
|
||||
* intentional no-op (already partial → return 0) look like success and
|
||||
* skipped the one-shot completion repair. Pending earlier-revision
|
||||
* jobs fail completed with an explicit reason instead. */
|
||||
if (cst_runtime_jobs_pending(a->cfg.runtime)) {
|
||||
snprintf(why, sizeof(why),
|
||||
"Earlier-revision jobs remain active; inspect task_state "
|
||||
"for their outcomes.");
|
||||
if (!completion_repairs++) {
|
||||
append_reply(&t, body, NULL, meta_json("progress", proto));
|
||||
append_msg(a, CST_ROLE_USER, why, NULL, NULL, NULL, meta_json("completion_repair", proto));
|
||||
turn_free(&t); continue;
|
||||
append_msg(a, CST_ROLE_USER, why, NULL, NULL, NULL,
|
||||
meta_json("completion_repair", proto));
|
||||
turn_free(&t);
|
||||
continue;
|
||||
}
|
||||
cst_runtime_finish(a->cfg.runtime, "partial", body, 0, why, sizeof(why));
|
||||
cst_runtime_finish(a->cfg.runtime, "partial", body, 0, why,
|
||||
sizeof(why));
|
||||
} else if (cst_runtime_finish(a->cfg.runtime, "completed", body,
|
||||
tools_ran, why, sizeof(why))) {
|
||||
if (!completion_repairs++) {
|
||||
append_reply(&t, body, NULL, meta_json("progress", proto));
|
||||
append_msg(a, CST_ROLE_USER, why, NULL, NULL, NULL,
|
||||
meta_json("completion_repair", proto));
|
||||
turn_free(&t);
|
||||
continue;
|
||||
}
|
||||
cst_runtime_finish(a->cfg.runtime, "partial", body, 0, why,
|
||||
sizeof(why));
|
||||
}
|
||||
}
|
||||
append_reply(&t, body, NULL, meta_json(NULL, proto));
|
||||
|
||||
Reference in New Issue
Block a user