fix(tmux,run,hooks): the four pre-existing bugs the #37 evaluation found
- tmux targets are exact (`=name`, `=name:` for panes/options): a bare `-t agenthub-lane-1` resolves by prefix to agenthub-lane-12 once lane 1 is gone, so killing a finished lane could kill another. - getRun/killRun refuse ids that are not `agenthub-lane-<n>`, so DELETE /api/run/main can no longer kill a user's own tmux session. - router/apply reports restart_required only for a running pane; getRun returns a `gone` handle, so it was always true. - needs_action is cleared only by the session that raised it (new nullable lanes.needs_action_session); a second session in the same cwd used to clear it on its second hook.
This commit is contained in:
@@ -856,9 +856,9 @@ describe("destructive lane lifecycle actions", () => {
|
||||
// Mock tmux so has-session always returns 0 (session exists), simulating a stuck session
|
||||
// Same shape as tmux.js's own exec: sync, argv only, throws on failure.
|
||||
tmux.__setExecImpl((args) => {
|
||||
if (args[0] === "has-session" && args[2] === runId) return "";
|
||||
if (args[0] === "has-session" && args[2] === `=${runId}`) return "";
|
||||
if (args[0] === "list-sessions") return `${runId}\n`;
|
||||
if (args[0] === "kill-session" && args[2] === runId) return "";
|
||||
if (args[0] === "kill-session" && args[2] === `=${runId}`) return "";
|
||||
throw Object.assign(new Error("mocked tmux failure"), { status: 1 });
|
||||
});
|
||||
|
||||
@@ -949,7 +949,12 @@ describe("destructive lane lifecycle actions", () => {
|
||||
|
||||
// Mock tmux so the session appears live
|
||||
tmux.__setExecImpl(async (cmd, args) => {
|
||||
if (cmd === "tmux" && args[0] === "has-session" && args[1] === "-t" && args[2] === runId) {
|
||||
if (
|
||||
cmd === "tmux" &&
|
||||
args[0] === "has-session" &&
|
||||
args[1] === "-t" &&
|
||||
args[2] === `=${runId}`
|
||||
) {
|
||||
return { code: 0, stdout: "", stderr: "" };
|
||||
}
|
||||
if (cmd === "tmux" && args[0] === "list-sessions") {
|
||||
@@ -1218,7 +1223,12 @@ describe("lane ensure, start mode, lane_id and releasing a finished run", () =>
|
||||
|
||||
// Mock tmux so the run appears to be live.
|
||||
tmux.__setExecImpl(async (cmd, args) => {
|
||||
if (cmd === "tmux" && args[0] === "has-session" && args[1] === "-t" && args[2] === runId) {
|
||||
if (
|
||||
cmd === "tmux" &&
|
||||
args[0] === "has-session" &&
|
||||
args[1] === "-t" &&
|
||||
args[2] === `=${runId}`
|
||||
) {
|
||||
return { code: 0, stdout: "", stderr: "" };
|
||||
}
|
||||
if (cmd === "tmux" && args[0] === "list-sessions") {
|
||||
@@ -1264,7 +1274,7 @@ describe("lane ensure, start mode, lane_id and releasing a finished run", () =>
|
||||
|
||||
// Mock tmux so the session appears to be gone (has-session fails with status 1).
|
||||
tmux.__setExecImpl((args) => {
|
||||
if (args[0] === "has-session" && args[1] === "-t" && args[2] === runId) {
|
||||
if (args[0] === "has-session" && args[1] === "-t" && args[2] === `=${runId}`) {
|
||||
const e = new Error("no such session");
|
||||
e.status = 1;
|
||||
throw e;
|
||||
|
||||
Reference in New Issue
Block a user