AUTOMATION.md — the autonomous dev loop¶
How daari develops itself with minimal human involvement. Agent contract: AGENTS.md.
The loop¶
flowchart LR
subgraph cloudLoop [Cloud loop]
Sched[Scheduled agent run] --> Drain[Drain stuck autodev PRs: update-branch / resolve / merge]
Drain --> Pick[Pick top auto-dev issue]
Pick -->|empty| Refill[PRD refill 3-5 issues]
Refill --> Pick
Pick --> Impl[Implement TDD per AGENTS.md]
Impl --> PR[Open PR + enable auto-merge]
PR --> CI[CI test check]
CI -->|green| MergeStep[Auto-merge to main]
CI -->|red| Fix[Agent comments or fixes]
MergeStep --> Clock{Under 10 min left?}
Clock -->|no| Pick
Clock -->|yes| Done[Exit 0: time box reached]
end
subgraph macLoop [Local runner on Mac]
Watch[launchd watchdog every 2h] --> Pull[Pull main + redeploy daari serve]
Pull --> Live[Live Ollama tests + Cursor smoke]
Live -->|fail| Issue[File regression issue auto-dev]
end
MergeStep --> Pull
Issue --> Pick
Components¶
| Piece | Where | State |
|---|---|---|
| Backlog | GitHub issues labeled auto-dev (+P1/P2/P3) |
seeded #1–#8 |
| Agent contract | AGENTS.md | active |
| Merge gate | branch protection on main (requires CI check test, strict, no force-push) + repo auto-merge |
active |
| Dev-cycle agent | Cursor Automation draft: automations/dev-cycle.md; CI fallback: .github/workflows/autodev.yml — drains issues back-to-back for 50 min (AUTODEV_DEADLINE_EPOCH), exits 0 before timeout-minutes: 60 |
fallback committed; needs CURSOR_API_KEY secret or Automation creation |
| PR review agent | automations/pr-review.md or enable Bugbot on cursor.com | draft |
| PRD cycle (backlog replenishment) | automations/prd-cycle.md; CI fallback: .github/workflows/prd-cycle.yml — daily scan + never-empty 3–5 issue refill (features or tech debt) | fallback committed; same CURSOR_API_KEY as autodev |
| Issue labeler | .github/workflows/issue-labeler.yml + scripts/apply_intended_labels.py — applies the **Intended labels:** first line of new/edited issues (#330) |
active |
| Local watchdog | scripts/autodev-local.sh + launchd (com.daari.serve, com.daari.autodev) |
installed and validated |
| GTM measure | .github/workflows/gtm-scoreboard.yml — weekly scripts/gtm_scoreboard.py --report --check-drought, auto-merging PR for docs/gtm/SCOREBOARD.md + REPORT.md, gtm,regression issue on 0 unique viewers / 14d (#1223). Never posts outside the repo; see gtm/PLAN.md |
active |
Local watchdog (Mac)¶
Every 2h (com.daari.autodev): pull main → reinstall if pyproject.toml changed → restart daari serve (kept alive by com.daari.serve) → run pytest -m integration against live Ollama → Cursor-shaped streaming smoke (18 tools + input_text) → on failure, file a deduped GitHub issue labeled auto-dev,regression.
com.daari.serve is this dev-machine watchdog plist (scripts/launchd/), not the user service daari service install writes — that one is com.daari.gateway and is restarted with daari service restart.
scripts/autodev-local.sh # run one cycle now
scripts/autodev-local.sh --install # install + start launchd agents
scripts/autodev-local.sh --uninstall # stop everything
tail -f ~/.daari/autodev/watchdog.out.log
One-time activations (human, ~5 min total)¶
- Cloud dev cycle — either:
- Add repo secret:
gh secret set CURSOR_API_KEY(key from cursor.com/settings) → the scheduled workflow starts working, or - Create the Cursor Automation from automations/dev-cycle.md in the Agents Window.
- Also
gh secret set AUTODEV_GH_TOKEN(fine-grained PAT, this repo: contents/PRs/issues/actions write, administration read) so bot-opened PRs are not held for Actions approval. Without Issues write the stall-watch cannot close resolvedregressionissues or sweepagent:working; it logs awarning:per issue and keeps going (#983, #1207). Without Administration read,gtm-scoreboard.ymlcannot read GitHub traffic and exits 1 with the fix (#1226). - PR review — enable Bugbot for the repo on cursor.com/dashboard, or create the automation from automations/pr-review.md.
- PRD cycle — the scheduled workflow
.github/workflows/prd-cycle.ymlruns daily at 14:00 UTC onceCURSOR_API_KEYis set (same secret as autodev). Optional: also create the Cursor Automation from automations/prd-cycle.md. A run that files zero issues is a failed run.
Pausing / stopping¶
| What | How |
|---|---|
| Local watchdog | scripts/autodev-local.sh --uninstall |
| CI dev cycle | gh secret delete CURSOR_API_KEY or gh workflow disable autodev-cycle |
| CI PRD cycle | gh workflow disable prd-cycle (same CURSOR_API_KEY gate) |
| Cursor Automations | disable in cursor.com dashboard |
| Everything merge-related | branch protection stays; nothing lands without green CI |
Escalation / notifications¶
- Agent-blocked work → comment on the issue,
agent:workinglabel removed. - Local regressions → issues labeled
regression(deduped by title per commit). - You only need to look at GitHub notifications for: blocked PRs,
regressionissues, red CI on main. - Stalled auto-merge (
DIRTY/ no checks):scripts/autodev_pr_watch.pycomments on the PR and filesauto-dev,regression(#200). Runs inautodev-cyclewithoutCURSOR_API_KEY. BEHINDauto-merge PRs: the same watcher mergesorigin/main(keeps bothdocs/TRACKING.md###sections) and approves first-partyaction_requiredruns so a park drains without a human Update branch click (#368).- Drain-first (#983): the watcher's rebase alone loses the up-to-date race while a run is merging every few minutes, so the dev-cycle agent starts each run by draining open
autodev/*PRs itself — update-branch, wait fortest,gh pr merge --squash;DIRTYPRs get conflicts resolved and the suite re-run — in issue priority order, before it picks new work. - Bot-PR approval gate (GitHub 2026-06-11): PRs opened with
GITHUB_TOKEN(github-actions[bot]) need Approve and run on every synchronize. Set repo secretAUTODEV_GH_TOKENto a fine-grained PAT (contents + issues + PRs + actions, this repo only; without Issues: write the agent cannot manageagent:workingand the watcher logs a warning instead of failing) so autodev opens PRs as a write-access user and CI starts on its own. Until that secret exists the workflow falls back toGITHUB_TOKEN.
Issue labels¶
The prd-cycle automation's token cannot apply labels (addLabelsToLabelable
returns FORBIDDEN), so every issue it files opens with a line like
**Intended labels: \auto-dev`, `P2`**. Since #330 theissue-labelerworkflow applies that line automatically onopened/edited, using the
repository's ownGITHUB_TOKENwithissues: writeas its only permission.
Keep writing the line — it is the contract. Rules: only the first non-empty
body line is read; onlyauto-dev,P1–P3,bug,regression,documentation,enhancementare applied; unknown names are skipped (never
created);agent:workingis never pre-applied because it is the agent's own
claim marker. Re-run by hand withpython scripts/apply_intended_labels.py --issue
Safety rails¶
- Agents touch only
auto-devissues; human-only actions (tags, releases, force-push, dep bumps, workflow edits) are enumerated in AGENTS.md. mainis protected: CItestcheck required, strict up-to-date, force-pushes and deletions blocked.- Local watchdog is read-only on the repo except
gh issue create.