Skip to content

feedback: add run-feedback supervisor (stable docker env + auto-resume) - #241

Open
zardus wants to merge 2 commits into
mainfrom
feature/feedback-supervisor
Open

feedback: add run-feedback supervisor (stable docker env + auto-resume)#241
zardus wants to merge 2 commits into
mainfrom
feature/feedback-supervisor

Conversation

@zardus

@zardus zardus commented Jun 25, 2026

Copy link
Copy Markdown
Member

Why

The discord-feedback bot's screen window has repeatedly ended up dead, each time for a different reason. Two root causes dominate:

  1. Wrong docker environment. The bot was launched from a plain shell (not nix develop), so DOCKER_HOST was unset and pwnshop fell through to the host docker — whose docker0 bridge is broken on this box. Result: every challenge "fails" to build with adding interface veth... to bridge docker0 failed: Device does not exist, even though the challenges are fine. (Confirmed: the same challenges build instantly inside nix develop, against the project dockerd.)
  2. No auto-recovery. A transient hiccup (docker, a GitHub blip, an OOM) killed the bot mid-run, and it stayed dead until someone hand-typed the resume command.

What

tools/feedback/run-feedback wraps the bot so neither can leave the window dead:

  • One persistent nix develop session. It re-execs itself into nix develop if not already inside one. The shellHook starts the project-local dockerd and exports DOCKER_HOST once, and it stays up for the entire run — the bot always has a correct, stable docker and can never fall through to the broken host daemon.
  • Auto-resume loop. On any nonzero exit it waits (capped 30→300s backoff) and resumes from the last checkpoint with --resume-latest. Transient failures self-heal on the next iteration. It stops only on a clean exit (work done) or Ctrl-C.

Builds on the resume machinery already merged (#237/#239/#240): per-phase checkpointing, --resume-latest skipping empty runs, and tokenless watch-resume.

Usage

tools/feedback/run-feedback --apply --create-pr --directions "..." --resume-latest

🤖 Generated with Claude Code

Two failure modes have repeatedly left the discord-feedback bot's screen window
dead at a prompt:

  1. Launched from a plain shell (not `nix develop`), DOCKER_HOST is unset and
     pwnshop falls through to the host docker -- whose docker0 bridge is broken --
     so every challenge "fails" to build ("adding interface veth... to bridge
     docker0 failed: Device does not exist") though nothing is actually wrong.
  2. A transient hiccup (docker, GitHub blip, OOM) kills the bot mid-run and it
     stays dead until someone hand-types the resume command.

run-feedback makes both impossible:

  * Runs the bot inside ONE persistent `nix develop` session (re-execs itself in
    if needed). The shellHook starts the project dockerd and exports DOCKER_HOST
    once, and it stays up for the whole run -- so the bot always has a correct,
    stable docker and never falls through to the broken host daemon.
  * Loops: on any nonzero exit it waits (capped 30..300s backoff) and resumes
    from the last checkpoint with --resume-latest, so a transient failure
    self-heals next iteration. Stops only on a clean exit or Ctrl-C.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc47172e5a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

*) retry_args+=("$arg") ;;
esac
done
retry_args+=(--resume-latest)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the selected run id on retries

When the first iteration was started with --resume <old-id> (or a fresh run dies before it writes any checkpoint), forcing the retry to --resume-latest can attach the next loop to a different artifact directory. The bot's latest_run_id() prefers the newest run with progress (tools/feedback/discord-feedback:3208-3212), so a retry can start watching/fixing an unrelated PR instead of the run that just failed; keep the explicit run id once known rather than converting every retry to latest.

Useful? React with 👍 / 👎.

# --command` runs the shellHook first (starting dockerd + exporting DOCKER_HOST), then this
# same script with IN_NIX_SHELL set, so the branch below runs the supervised loop with a
# stable docker for its entire lifetime.
if [ -z "${IN_NIX_SHELL:-}" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require the project Docker env before skipping nix develop

If this wrapper is launched from another Nix shell, or from a shell where DOCKER_HOST was unset, IN_NIX_SHELL is still nonempty and this check skips the repository nix develop; the bot then runs with DOCKER_HOST=<unset> and pwnshop can fall back to the host Docker daemon, which is the failure mode this supervisor is meant to prevent. Gate on the repo dev-shell Docker environment (for example DOCKER_HOST/PWN_WORKSPACE) rather than IN_NIX_SHELL alone.

Useful? React with 👍 / 👎.

…done

The scrape only feeds the analysis agent. A resume whose analysis phase is
already checkpointed re-ran the entire scrape anyway (minutes of Discord API
calls, a Discord token requirement, and a misleading "Resuming from merged PR
#N / scraping from ..." banner) before discarding it all at the analysis phase
guard. Under the supervisor's auto-resume loop that waste repeats on every
retry.

Extract the scrape into scrape_feedback_sources() and call it only when analysis
isn't done yet; otherwise reuse the run's recorded transcript/PR-feedback
artifacts. Watch-only resumes already short-circuit earlier via the create-pr
fast path; this covers resumes that died between analysis and create-pr.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant