Skip to content

[bug] Delegation is single-use — the Pilot ends the session its own driver requires, and the error blames the runner #271

Description

@serge-ivo

#257 shipped its history half — loadRepoTimeline, migration 0077, repo-scoped fetch in the
console. Good fix. The session-lifecycle half was raised in a comment after that issue closed,
so it is currently untracked. This is that half.

Delegation is single-use

Two facts, both still true at 5f28af8:

// lib/loop-drivers.ts:117 — the driver REQUIRES a live session
const session = await getActiveSessionForRepo(env, instanceId, userId, repo.id);
if (!session) return { ok: false, status: 409, error: `${repo.name} has no live coding session…` };

// workflows/coding-session.ts:447 — the Pilot ENDS the session when its run completes
await endSession(env, instanceId, userId, sessionId, status);

So every delegated job consumes the session it needed:

open a session by hand → ask for work → start_work → Pilot completes → Pilot ends session
                       → ask again → 409 → open another by hand

Verified three times today on FAS platform (964594b6), runner online throughout:

03:44:50 session opened (by hand)
03:45:23 start_work → Pilot ran git pull — worked
03:45:36 Pilot ended the session
~05:40 asked again → 409 no live coding session
~06:05 asked again after confirming → 409 again

Also why the Coder Lead could not delegate to any of four subordinates (#259).

The error message tells the user to fix the wrong thing

loop-drivers.ts:122:

${repo.name} has no live coding session — start one on its Coding tab (and run \pags up`), then try again.`

The (and run \pags up`)is unconditional. It fires when the runner is **already connected** — verified at the moment of the 409:runnerOnline: true, relayConnected: true, reachable: true,
runnerVersion 0.4.32, lastSeenAt` current.

So a perfectly-behaved agent relays it faithfully and misinforms the user. Both retests above ended
with the agent telling the user to start a runner that was running. That is not the agent's fault —
it is repeating platform text that conflates two independent conditions.

Suggested shape

The design question first: should a completed Pilot run end the session, or only mark the run
done?
Ending it is what makes delegation single-use, forces a fresh empty timeline per job, and
means a supervisor cannot supervise without a human opening a session first. Leaving the session
idle-but-live for the next goal removes all three at once.

If ending stays, the driver must be able to start a session itself when none is live and a
runner is connected — otherwise delegate_goal is only ever usable by someone sitting in the
console.

Either way, split the error by actual cause:

  • runner not connected → say so, name the machine, pags up
  • runner connected, no session → say that, and (once the above lands) just start one

Verification

  • Two consecutive delegated jobs succeed without a human opening a session between them.
  • With the runner online and no session, the message never mentions pags up.
  • With the runner offline, it does — and names the node.
  • The Coder Lead can delegate to an idle subordinate whose runner is connected.

Adjacent observation

The #256 run-history injection changed behaviour in a way worth watching: asked "Pull latest
changes" (an imperative), the agent answered about the 2-hour-old pull run and asked for
confirmation rather than acting. Grounded and honest — a clear improvement on denial — but it is
now possible for injected history to satisfy a request for new work. Worth a look if it recurs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions