Skip to content

[codex] fix prompt delivery and select backends per sub-task#193

Open
Juarezduterter wants to merge 4 commits into
johannesjo:mainfrom
Juarezduterter:codex/detect-redraw-damaged-codex-prompt
Open

[codex] fix prompt delivery and select backends per sub-task#193
Juarezduterter wants to merge 4 commits into
johannesjo:mainfrom
Juarezduterter:codex/detect-redraw-damaged-codex-prompt

Conversation

@Juarezduterter

@Juarezduterter Juarezduterter commented Jul 1, 2026

Copy link
Copy Markdown

What changed

  • Recognize Claude Code's current empty-prompt suggestion form (❯ Try "...").
  • Recognize Codex prompt frames whose split CSI redraw sequences collapse the suggestion and status footer onto one line.
  • Add recorded-frame regression coverage through both the prompt classifier and coordinator delivery tests.
  • Add an optional backend argument to the coordinator's create_task MCP tool.
  • Allow each sub-task to select claude, codex, gemini, opencode, copilot, or antigravity; omission preserves the existing coordinator-backend inheritance.
  • Validate backend selection at both MCP and HTTP boundaries and map Antigravity to its agy executable.
  • Clear a coordinator's submitted initial prompt even when Claude compacts the long bracketed paste and no literal echo is available, preventing the prompt field from being repopulated after deletion.
  • Allow Codex land_self cleanup to remove committed AGENTS.md preambles and ignore only untracked worktree-local .claude sandbox files; tracked .claude changes remain visible to Git.

Why

With Claude Code 2.1.197 and Codex CLI 0.142.4, coordinated child tasks could spawn successfully but never receive their initial assignment. The backend repeatedly classified the visible ready prompt as no_prompt, leaving the assignment queued indefinitely.

Root cause

The readiness classifier only accepted a standalone Claude/Codex prompt glyph. Current Claude renders rotating suggestion text after the glyph, while Codex PTY redraw output can lose split CSI introducers and collapse the suggestion plus model footer into a q-separated line.

Validation

  • npm test — 1456 passed, 25 skipped
  • npm run check
  • Real authenticated CLI smoke test: Claude Code 2.1.197
  • Real authenticated CLI smoke test: Codex CLI 0.142.4

Both real-agent tests logged coordinator.initial_prompt — delivered after the change; both reproduced continuous reason: "no_prompt" before it.

The multi-backend path is covered from the MCP schema through HTTP validation and coordinator spawn selection, including rejection before worktree creation for unsupported values.

Coordinator prompt cleanup is restricted to genuine [COORDINATOR MODE] initial prompts; ordinary tasks retain the existing missing-echo retry behavior.

Codex landing cleanup normalizes both the worktree and HEAD versions of injected preamble files before deciding whether user-authored changes exist.

@Juarezduterter Juarezduterter changed the title [codex] fix coordinator prompt detection for current agent CLIs [codex] fix prompt delivery and select backends per sub-task Jul 1, 2026
@Juarezduterter Juarezduterter marked this pull request as ready for review July 1, 2026 12:47
@johannesjo

Copy link
Copy Markdown
Owner

Review

Solid fix for the no_prompt delivery stall, and the multi-backend selector is validated cleanly at every boundary (MCP → HTTP → coordinator, with rejection before worktree creation) and well covered by tests. One thing to confirm before merge, plus a few minor notes.

Needs confirmation

antigravity sub-tasks probably never receive the <sub-task-mode> preamble.

In coordinator.ts, the preamble target file is chosen from agentCmd:

codex / opencode → AGENTS.md
gemini           → GEMINI.md
copilot          → .agent.md
else (Claude)    → .claude/settings.local.json

antigravity maps to the agy command, which matches none of those .includes(...) checks, so it falls into the Claude else branch and the preamble is written to .claude/settings.local.json. Antigravity is a Gemini-lineage CLI (auth dir ~/.gemini/antigravity-cli per pty.ts), so it almost certainly doesn't read Claude's settings file — and there's no arg-based delivery fallback, injection is purely file-based. Net effect: antigravity children likely don't get the sub-task-mode rules and never learn to call land_self.

Since the PR ships antigravity as a selectable backend (with a passing test asserting it spawns as agy), this leaves the feature partially non-functional for that one backend. If antigravity reads GEMINI.md, the fix is a one-liner — route agy alongside gemini:

} else if (agentCmd.includes('gemini') || agentCmd === 'agy') {

Could you confirm which context file agy actually reads? If it's none of these, it may be cleaner to drop antigravity from the selectable set until it's wired up.

Minor

  • Selecting a backend replaces all coordinator base args (selectedAgentArgs becomes the backend's built-in default, []). Dropping --model opus when switching to a different backend is correct, but selecting the same backend as the coordinator (e.g. backend: "claude" under a claude --model opus coordinator) also silently drops the model flag. Worth either inheriting args when the selected backend matches the coordinator, or noting "specifying backend opts out of all coordinator arg inheritance" in the tool description.

  • ensureSymlinkExcludes(worktreePath, [...createdSymlinks, '.claude']) writes to --git-common-dir's info/exclude, which is shared by the main working tree and every worktree (the sibling ensureSandboxExcludes docstring even calls it "shared"). So root-anchored /.claude also hides newly-created untracked .claude/ files in the main checkout and other worktrees, not just this sandbox. Intended for the placeholder files, but the reach is broader than the comment implies — a one-line note would help.

  • Codex redraw pattern (?:^|\s|q)›[^\r\n›]*?gpt-[\w.-]+\s+\w+\s+·\s+~?\/ is a broad heuristic. It only avoids a false "ready" on a damaged working frame because the busy patterns are checked first — and those only scan the last 500 chars (AGENT_BLOCKER_TAIL_CHARS) while ready matching runs over 1000. If a redraw also mangles the esc to interrupt / Working( markers, a busy Codex could read as ready. Low risk given the fixture coverage, just a known watch-point.

  • coordinator.test.ts hand-copies the production regex into its prompt-detect mock, so those tests can silently drift from prompt-detect.ts. The real regex is separately exercised against the new fixtures in prompt-detect.test.ts, so coverage exists — just a maintenance smell (pre-existing).

Nice

  • New readiness patterns are tested against the real classifier via recorded frame fixtures, not just mocks.
  • The normalizePreambleFileContent extraction + normalizing both sides of the landing diff is a clean fix for the spurious committed-AGENTS.md diffs.
  • getAgentByBackend deep-copies args, avoiding mutation of the shared DEFAULT_AGENTS.

Overall: good to merge once the antigravity preamble routing is confirmed or fixed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants