Critical Bug
Pulse fails to detect commits in worktrees, causing adversarial-developer to never spawn. Pipeline hangs in "reviewing" forever with infinite developer respawns.
Correct Workflow (Verified by Code Analysis)
Intended flow:
- Developer writes code → commits in worktree (git add -A && git commit)
- Developer session ends → Pulse heartbeat detects this → Task transitions to "reviewing"
- Pulse schedules adversarial → checks hasCommittedChanges() → If true, spawn adversarial
- Adversarial reviews committed work → Records verdict via
taskctl verdict
- If APPROVED → @ops commits and pushes
- If ISSUES_FOUND → Respawn developer for fixes
Evidence from code:
developer-pipeline.txt:17 - ✅ git add + git commit in your worktree
developer-pipeline.txt:51 - When all checks pass: commit your changes
pulse-utils.ts:53 - git diff ${base_commit}..HEAD --stat (checks COMMITTED changes)
pulse-scheduler.ts:349 - hasChanges = await hasCommittedChanges(...) (must be true to spawn adversarial)
Bug: hasCommittedChanges Not Detecting Commits
Symptoms:
- Developer commits work (verified by
git log in worktree)
- Pulse reports: "No committed changes found. Developer wrote code but did not commit."
- Adversarial never spawns → Pipeline stuck forever
Root Cause (Per Investigation):
spawnDeveloper in pulse-scheduler.ts:177 calculates base_commit incorrectly:
const res = await $`git merge-base ${base} HEAD`.cwd(worktreeInfo.directory)
Problem: HEAD in a worktree is relative to that worktree's current state, which may not align with how hasCommittedChanges checks for commits.
Evidence:
- Worktree has commit
9c13ebf21 (verified by git log)
- hasCommittedChanges returns false despite commits existing
- Base commit calculation is wrong for worktrees
Fix Required
-
Base commit calculation: Use worktree branch name instead of HEAD for merge-base:
const res = await $`git merge-base ${base} ${worktreeInfo.branch}`.cwd(worktreeInfo.directory)
-
Alternative: Check for uncommitted changes instead:
git diff --cached for staged changes
git diff HEAD for all changes (committed + staged)
git log -1 to check if any commits exist since branch creation
Files Affected
packages/opencode/src/tasks/pulse-utils.ts - hasCommittedChanges (line 43-61)
packages/opencode/src/tasks/pulse-scheduler.ts - spawnDeveloper base_commit calculation (line 174-201)
Quality Gates
Acceptance Criteria
- Pulse detects commits correctly in worktrees
- Adversarial spawns after developer commits
- No false "No committed changes found" messages
- Pipeline progresses: developing → reviewing → adversarial-running → done
Critical Bug
Pulse fails to detect commits in worktrees, causing adversarial-developer to never spawn. Pipeline hangs in "reviewing" forever with infinite developer respawns.
Correct Workflow (Verified by Code Analysis)
Intended flow:
taskctl verdictEvidence from code:
developer-pipeline.txt:17- ✅ git add + git commit in your worktreedeveloper-pipeline.txt:51- When all checks pass: commit your changespulse-utils.ts:53-git diff ${base_commit}..HEAD --stat(checks COMMITTED changes)pulse-scheduler.ts:349-hasChanges = await hasCommittedChanges(...)(must be true to spawn adversarial)Bug: hasCommittedChanges Not Detecting Commits
Symptoms:
git login worktree)Root Cause (Per Investigation):
spawnDeveloperinpulse-scheduler.ts:177calculates base_commit incorrectly:Problem:
HEADin a worktree is relative to that worktree's current state, which may not align with howhasCommittedChangeschecks for commits.Evidence:
9c13ebf21(verified bygit log)Fix Required
Base commit calculation: Use worktree branch name instead of HEAD for merge-base:
Alternative: Check for uncommitted changes instead:
git diff --cachedfor staged changesgit diff HEADfor all changes (committed + staged)git log -1to check if any commits exist since branch creationFiles Affected
packages/opencode/src/tasks/pulse-utils.ts- hasCommittedChanges (line 43-61)packages/opencode/src/tasks/pulse-scheduler.ts- spawnDeveloper base_commit calculation (line 174-201)Quality Gates
Acceptance Criteria