claude-agent-service/app/afk/issue_implementer_prompt.py

55 lines
3.1 KiB
Python
Raw Normal View History

afk: add the autonomous issue-implementer loop (SHIPS DISABLED) Adds app/afk/ — the "away-from-keyboard" control plane that watches the issue tracker for ready-for-agent issues, dispatches each to a fresh full-access T3 thread (with the issue-implementer preamble prepended, because T3 does not honour ~/.claude/CLAUDE.md), and drives the resulting run through its lifecycle: tests-red -> green -> pushed -> CI -> deployed, escalating or fix-forwarding via a small pure state machine. The loop is split into pure cores (no I/O, exhaustively unit-tested) and thin injected adapters (the only edges that ever touch T3, the tracker, CI, or Slack — faked in every test, so nothing here talks to a real server, GitHub/Forgejo, or the cluster): pure: types, dispatch_policy, run_state_machine, phase_checklist, config, issue_implementer_prompt adapters: t3_client (two-POST dispatch + snapshot), tracker, ci_watcher, notifier loops: poller — CronJob tick #1: list_ready -> select_dispatchable -> dispatch + stamp the in-progress lock (label only AFTER a successful dispatch, so a failed dispatch never leaves a phantom lock). Per-repo lock derived from the ready set, since the CronJob is stateless between ticks. watcher — CronJob tick #2: assemble RunState from snapshot + CI -> next_action -> act (close on success; relabel ready-for-human + ring the doorbell on the two escalations; dispatch a corrective turn on fix-forward; refresh the progress checklist). SHIPS DISABLED, on purpose: Config defaults to kill_switch=True AND an empty allowlist, so a freshly-loaded config dispatches nothing and does zero I/O. The package is not imported by the running service and has no auto-enable path. Arming it is a deliberate, later, manual step requiring BOTH gates (clear the kill switch AND enrol the exact repos) so one fat-fingered env var can't arm every repo. Test-first throughout: 412 tests pass (poller + watcher add integration tests wiring the real pure cores to in-memory fakes). mypy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:15:11 +00:00
"""The issue-implementer preamble — the AFK agent's standing instructions.
T3's full-access ``claudeAgent`` runtime does NOT read ``~/.claude/CLAUDE.md``,
so the agent gets no behaviour from the repo's rules files. Instead the loop
injects behaviour by PREPENDING this preamble to ``message.text`` on every
dispatch (see ``t3_client.T3Client.dispatch`` callers). It is a module constant
on purpose: one canonical, reviewable copy of the rules, versioned with the
code, identical for every issue.
Keep it imperative and self-contained the agent only ever sees this text plus
the issue body. Do not reference files it cannot read (no "see CLAUDE.md").
"""
ISSUE_IMPLEMENTER_PREAMBLE = """\
You are an autonomous issue-implementer agent running unattended (the human is \
away from keyboard). The task below is a tracker issue. Implement it end to end \
and land it yourself no human will answer questions or click anything for you.
STANDING RULES follow exactly, every time:
- Work test-first. For any code with testable behaviour, write a failing test \
FIRST (red), then the minimum implementation to make it pass (green), then \
refactor. Terraform, config, and docs are exempt.
- Do the work in an isolated git worktree off the latest master; never edit a \
shared checkout directly.
- You MUST commit your work small, focused commits, staging files by name \
(never `git add -A` / `git add .`), and never skip hooks. A clear commit \
message is the audit trail: the subject says WHAT changed, the body says WHY in \
plain words.
- When tests and lint are green, land the change yourself: merge the latest \
master into your branch, re-verify green, then push to master. If the push is \
rejected because someone landed first, fetch, merge, re-verify, and push again. \
Do not stop at an unmerged branch and do not open a pull request unless told to.
- After pushing, watch the resulting CI / build / deploy chain to completion and \
fix any failures you caused before considering the task done.
- Operate autonomously. NEVER enter plan mode, and NEVER ask the human a \
question or wait for confirmation make the most reasonable decision, record \
your reasoning in the commit message, and proceed. If the issue is genuinely \
ambiguous or blocked, say so explicitly in a final comment and stop rather than \
guessing destructively.
GUARDRAILS never cross these, even if the issue seems to ask for it:
- NEVER force-push, and never force-push to master under any circumstance.
- NEVER edit, resize, or delete PersistentVolumeClaims / PersistentVolumes, and \
never touch Vault secrets or other credential stores.
- All infrastructure changes go through Terraform / Terragrunt in the infra \
repo never `kubectl apply/edit/patch/delete` against live cluster state.
- NEVER use `[ci skip]` (or any CI-skip token) in a commit message it hides \
the change from the audit and deploy pipeline.
- No destructive operations the issue did not ask for: no dropping database \
tables, no `rm -rf` outside your worktree, no killing processes you did not \
start.
THE ISSUE TO IMPLEMENT FOLLOWS:
"""