Major changes:
- Task loop polls Under Review + New Bugs sections (was only checking empty sections)
- Smart project routing: keyword matching maps task names to correct codebase
(e.g. 'pledge' → legacy-donation-system-laravel)
- Pi executes in the project directory, not /opt/pi-worker
- Git pull before execution to get latest code
- Skips already-attempted tasks (checks Asana comments)
- Config now exposes projectsPath
First real bug fixed autonomously:
'Duplicate Pledges Detected with Same External Reference'
→ Fixed uniqid() causing duplicate Engage pledges on every sync
→ 1 file changed in app/N3O/Schema.php
Also: fix watchdog to use systemd-notify command (unix_dgram unsupported in Bun),
add debug logging to lock acquire failures
- Replaced Grammy bot.start() with manual fetch-based getUpdates loop
- Grammy used only for bot.handleUpdate() (middleware/handlers)
- 409 conflicts handled with 10s backoff + continue (no crash)
- Network errors handled with 3s retry
- Root cause of persistent 409: zombie bun process (PID 72407) from 3:23 AM
was holding Telegram long-poll lock all day
- Separate cleanupCompletedMyTasks (fast, no Pi) from sweepIncompleteTasks (with Pi verify)
- Cache verified-not-done tasks for 30min to avoid re-checking every cycle
- Cache project sections for 5min to reduce API calls
- Add rate limit (429) retry with Retry-After header
- Add server error (5xx) retry
- Remove assignee:null - only use assignee_status:later
- Keep tasks assigned to user always
- Before executing: verify if work is already done on server
- If already done: skip execution, comment evidence, mark complete
- After executing: run verification again to confirm work was applied
- Verification agent uses Pi with read-only investigation prompt
- Adds verification status (PASSED/COULD NOT CONFIRM) to Asana comments
- Prevents redundant work and catches false completions
Pi CLI exits with code 0 even when the Anthropic API returns errors
(e.g. insufficient credits). The error is only visible in the JSON
event stream as stopReason:"error" with an errorMessage field.
Now the executor parses message_end/turn_end events for errorMessage
and treats them as failures, preventing false "task completed" reports.
- SECTIONS now uses arrays of candidate names searched in priority order
- Maps Bug Intake sections: New Bugs→TODO, Under Review→IN_PROGRESS, Resolved→DONE
- Added findFirstSection helper for array-based section lookup
- Asana REST API client for task polling, section management, and commenting
- Pi CLI executor for running tasks with specialist agent teams
- Task loop: polls Asana To Do/Pi Worker sections, executes tasks, reports results
- Improvement loop: rotates through 8 improvement categories (code quality, security, docs, testing, etc)
- Health server on :8787
- File-based mutex locks with stale lock detection
- Docker + docker-compose deployment config
- deploy.sh for one-command deployment to cr-server-new via SSH/Incus
- Replaced direct Anthropic API with Pi CLI (uses platform auth, no API key needed)
- Model: claude-sonnet-4-6
- Streaming JSON mode with live progress updates in Telegram
- Per-user session files via Pi's --session/--continue
- Auto-recovery from corrupted sessions
- 5 min timeout, not-lazy system prompt