Skip to content

fix(taskctl): adversarial-developer feedback loop loses context between rounds, causing rewrite loops #384

@randomm

Description

@randomm

Critical Bug

After 3 rounds of adversarial review, the same critical issues keep appearing in different forms. The developer-adversarial loop fails to converge because developer does not receive context about previous implementation attempts.

Evidence

Round 1: CRITICAL - Branch regex allows command injection
Round 2: MEDIUM - Branch regex too restrictive, rejects valid names
Round 3: CRITICAL - Branch regex still has flaws (empty strings, invalid chars)

Same regex issue appears differently each round. Each "fix" introduces NEW bugs.

Root Cause Analysis

What IS passed between rounds:

  • verdict.summary - brief description
  • verdict.issues - list with location/severity/fix
  • verdict.tested_scenarios - what was tested
  • verdict.coverage_level - confidence
  • Attempt number: "This is retry X of Y"

What is MISSING (CRITICAL GAP):

  • Git diff showing previous implementation
  • No file list of what was already changed
  • No visibility into "what did I already try"

Why the loop didn't converge:

The prompt tells developer "codebase changes are already in worktree" but developer never sees WHAT changed. Each retry, developer works blind - rewrites code from scratch instead of fixing specific bugs. This introduces NEW issues in each round.

Source: packages/opencode/src/tasks/pulse-scheduler.ts:537-566 (respawnDeveloper)

How to Reproduce

  1. Run taskctl start on any issue
  2. Wait for developer to complete and adversarial to find issues
  3. Watch respawnDeveloper prompt - it lists issues but shows NO git diff
  4. Developer rewrites code instead of fixing bugs
  5. Adversarial finds NEW issues in round 2
  6. Repeat until max attempts exhausted

Recommended Fix

Add git diff output to respawnDeveloper prompt:

// In respawnDeveloper (pulse-scheduler.ts ~line 537-566)

const diffOutput = await $`git diff ${validatedBaseCommit}..HEAD`
  .cwd(worktreeInfo.directory)

const previousImplementation = `# PREVIOUS IMPLEMENTATION (for reference)

The following changes were previously committed in this worktree:

\`\`\`bash
${diffOutput}
\`\`\`

⚠️ CRITICAL: These changes already exist. Do NOT rewrite from scratch.
Read the changed files FIRST, then fix the specific issues listed below.
`

// Include this in the prompt before listing adversarial issues

Files Affected

  • packages/opencode/src/tasks/pulse-scheduler.ts - respawnDeveloper function

Quality Gates (Non-Negotiable)

  • TDD: Write test verifying git diff is included in respawn prompt
  • Coverage: 80%+ for modified code paths
  • Local verification: All tests pass

Acceptance Criteria

  • Developer receives git diff of previous implementation on retry
  • Adversarial feedback loop converges within 2 rounds for common issues
  • No NEW issues introduced in round 2 that stem from lack of context
  • Developer prompt explicitly shows what already exists before listing fixes

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