Night Agent — Implementation¶
Current State¶
The night agent is an autonomous Claude Code session that runs unattended, typically overnight (KST). It works through a fixed 4-stage pipeline — bug triage, code review, feature development, and QA — then stops. It never pushes to remote.
The agent's operating instructions live in .claude/agent-prompt.md. This doc explains how it works from a human perspective; that file is the authoritative source of truth.
How It Works¶
Entry point¶
The agent is invoked by running Claude Code with .claude/agent-prompt.md as its system prompt. On startup it:
- Checks out
mainand runsgit status - Reads
BACKLOG.mdfor full context - Checks the current KST time — if 06:00 or later, it commits any in-progress work, appends an "auto-stopped" note to
agent-log.html, and exits immediately
Stage 1 — Bug Triage¶
Runs pytest tests/ -x -q. If tests fail (or BACKLOG.md has items under ## Bugs), it:
- Identifies the domain from the stack trace
- Delegates the fix to the appropriate sub-agent (see Sub-agents below)
- Reviews the diff, commits on
main(or afix/<slug>branch for larger changes) - Skips directly to Stage 4
Stage 2 — Code Review¶
Lists all agent/feat-* branches and reviews any that don't yet have a ## Review section in their agent-log.md. For each:
- Reads the log and changed files
- Checks correctness, convention compliance, edge cases, and test coverage
- Appends a verdict (
approve/request-changes/needs-discussion) to the branch'sagent-log.md - If
request-changes: adds the issues to## Bugsin BACKLOG.md on main
Stage 3 — Feature Development¶
Picks the first unchecked [ ] item from BACKLOG.md ## Queue, moves it to ## In Progress, and creates a branch agent/feat-<slug>. Before delegating, it writes a pre-delegation plan covering which files change, key logic, and any spec gotchas. It then spawns the appropriate sub-agent, reviews the diff, writes agent-log.md to the branch, and commits.
If blocked (missing dependency, unclear spec, API key needed), it writes a Status: blocked log, moves the item back to Queue, and stops.
Stage 4 — QA¶
After any session that produced code changes, a test-engineer sub-agent runs the full test suite plus targeted checks (e.g. FEATURE_ORDER consistency for ML changes, dry-run fetch for scrapers). If QA fails, the agent spawns a fix sub-agent and re-runs QA before finishing.
Update main¶
After completing any stage, the agent:
- Updates
BACKLOG.md(moves item to## Completedwith branch, date, SHA) - Rebuilds
agent-log.htmlwith a new session card (stage run, changes, QA result, review verdicts) - Commits:
docs(agent): update log after <session-summary>
Sub-agents¶
The agent routes work to domain specialists based on the area touched:
| Domain | Sub-agent |
|---|---|
| Data / scraper / scheduler / news ingestion | data-engineer |
| ML / sentiment / predictions / feature engineering | ml-analyst |
| Dashboard / React / frontend / UI | frontend-engineer |
| CI/CD / Makefile / Docker / deployment | devops-engineer |
| Security / auth / API keys / permissions / RLS | security-reviewer |
| Stack trace / crash / hard-to-reproduce bug | debugger |
| Unclear | claude (general) |
Sub-agent definitions live in .claude/agents/.
Artifacts¶
| File | Purpose |
|---|---|
BACKLOG.md |
Queue, in-progress, completed items; bug list |
agent-log.html |
Human-readable session history with QA results and review verdicts |
agent/feat-<slug>/agent-log.md |
Per-feature log written to the feature branch |
Gotchas¶
- One stage per session — if Stage 1 or Stage 2 produced real work, the agent stops after Stage 4 rather than continuing to Stage 3.
- 06:00 KST hard stop — the agent checks the time at multiple points and aborts if it's past 06:00 KST.
- Sub-agents don't touch git — all git operations (commit, branch creation, BACKLOG.md edits) are done by the orchestrating agent, not the sub-agents.
- Never
git add .— files are staged explicitly to avoid accidentally committing.env,.pkl, or.dbfiles.
Constraints¶
- Never pushes to remote
- Never modifies
.env - Never commits
model_cache/*.pklor*.dbfiles - Commits are atomic — one logical change per commit