Skip to content

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)

  1. Cloud dev cycle — either:
  2. Add repo secret: gh secret set CURSOR_API_KEY (key from cursor.com/settings) → the scheduled workflow starts working, or
  3. Create the Cursor Automation from automations/dev-cycle.md in the Agents Window.
  4. 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 resolved regression issues or sweep agent:working; it logs a warning: per issue and keeps going (#983, #1207). Without Administration read, gtm-scoreboard.yml cannot read GitHub traffic and exits 1 with the fix (#1226).
  5. PR review — enable Bugbot for the repo on cursor.com/dashboard, or create the automation from automations/pr-review.md.
  6. PRD cycle — the scheduled workflow .github/workflows/prd-cycle.yml runs daily at 14:00 UTC once CURSOR_API_KEY is 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:working label removed.
  • Local regressions → issues labeled regression (deduped by title per commit).
  • You only need to look at GitHub notifications for: blocked PRs, regression issues, red CI on main.
  • Stalled auto-merge (DIRTY / no checks): scripts/autodev_pr_watch.py comments on the PR and files auto-dev,regression (#200). Runs in autodev-cycle without CURSOR_API_KEY.
  • BEHIND auto-merge PRs: the same watcher merges origin/main (keeps both docs/TRACKING.md ### sections) and approves first-party action_required runs 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 for test, gh pr merge --squash; DIRTY PRs 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 secret AUTODEV_GH_TOKEN to a fine-grained PAT (contents + issues + PRs + actions, this repo only; without Issues: write the agent cannot manage agent:working and 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 to GITHUB_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-dev issues; human-only actions (tags, releases, force-push, dep bumps, workflow edits) are enumerated in AGENTS.md.
  • main is protected: CI test check required, strict up-to-date, force-pushes and deletions blocked.
  • Local watchdog is read-only on the repo except gh issue create.