feat(lanes): Antigravity lanes, release exited panes, fresh Codex starts

- antigravity: a third lane tool running Antigravity's `agy` CLI. `-i`
  carries the first prompt, `--continue` resumes; `agy` has no model,
  effort or permission flag, and `--dangerously-skip-permissions` is never
  emitted. No pipeline, no agents install, and no AI Router (native only,
  else EUNSUPPORTED). Add lane gains an Antigravity choice and the binary
  probe maps it to `agy`.
- UI: the lane card no longer renders a frame holding only a "Codex" chip,
  and the prompt box names the lane's CLI ("Ask Codex anything…"), via
  LANE_TOOL_LABEL.
- runs: a pane that exits is released on a 10 s server beat
  (healAllRunIds, DASHBOARD_RUN_HEAL_MS). Codex and Antigravity fire no
  hook, so their lanes stayed "running" until something re-read them.
- codex: Start no longer sends resumeLast — only "Resume last session"
  continues the previous thread.
This commit is contained in:
2026-09-28 10:22:07 +07:00
parent 952e8584f0
commit 9d096b61f7
31 changed files with 257 additions and 93 deletions
@@ -96,13 +96,16 @@ function makeLane(overrides: Partial<Lane> = {}): Lane {
}
describe("LaneCard lane tool badge", () => {
it("badges a codex lane and leaves a claude lane unbadged", () => {
const { rerender } = render(
<LaneCard {...{ lane: makeLane({ tool: "codex" }), onAction: vi.fn() }} />
);
expect(screen.getByText("Codex")).toBeInTheDocument();
rerender(<LaneCard {...{ lane: makeLane({ tool: "claude" }), onAction: vi.fn() }} />);
expect(screen.queryByText("Codex")).not.toBeInTheDocument();
// The strip tile already names the CLI; a card holding only that tag was an
// empty frame in the lane detail.
it("renders nothing for a codex or antigravity lane with nothing else to show", () => {
for (const tool of ["codex", "antigravity"] as const) {
const { container, unmount } = render(
<LaneCard {...{ lane: makeLane({ tool }), onAction: vi.fn() }} />
);
expect(container.querySelector('[data-testid="lane-card-1"]')).toBeEmptyDOMElement();
unmount();
}
});
});