Skip to content

Worklist-guard opt-out doesn't apply when phrase is in iterate-feedback draft #171

Description

@judell

Problem

The worklist-guard hook (.claude/hooks/worklist-guard.py for Claude, app/shell/worklist-guard-codex.py for Codex) detects user-typed opt-out phrases (just do it, commit this directly, skip the worklist, etc.) by reading the latest user message in the Claude session transcript via last_user_text(transcript_path). That works for plain-chat opt-outs but misses opt-outs typed into an iterate feedback draft.

Concrete repro

  1. Worklist has an applied (TO COMMIT) item.
  2. User clicks Iterate with feedback text containing just do it (e.g., make a test edit to README. just do it.).
  3. Bram drains the iterate via feedbackRef to resources/feedback-drafts/<id>.md. The actual conversation message in the Claude session JSONL is just the structured payload: iterate: {"items":[{...}]} — it does NOT contain the literal just do it text.
  4. Agent attempts a file edit outside the worklist's coverage.
  5. Hook's last_user_text reads the structured payload, finds no opt-out phrase, denies.

Observed live in #170 conversation: iterate feedback with explicit just do it ended up blocked by the guard; only retyping the phrase in plain chat unblocked the agent.

Proposed fix

When the latest user message in the transcript matches a structured iterate: payload shape, additionally read resources/feedback-drafts/<feedbackRef>.md for each item's feedbackRef and concatenate its content into the text the opt-out matcher sees.

The feedbackRef field is already part of the iterate payload shape (app/__shell/conventions.md); the hook just needs to parse it out of the JSON tail of the user message line, find each ref, and read the corresponding draft file from the project's resources/feedback-drafts/ directory.

Both hook scripts need the change:

  • app/__shell/worklist-guard.py (bundle template, installed at .claude/hooks/worklist-guard.py)
  • app/shell/worklist-guard-codex.py (Codex bundle template, installed at ~/.bram/codex-worklist-guard.py)

Same change pattern; share a helper if it factors cleanly.

Out of scope

  • Changing the iterate payload shape itself.
  • Reading approved: / drop: feedback for opt-out — those payloads are structured authorization, not opt-out triggers. The opt-out matcher should remain narrowly scoped to in-flight free-text user direction, which today is plain-chat or iterate-feedback.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions