- Add RESOURCES.example.md: committed template showing Compute/Domains/Accounts/Budget structure
- Gitignore RESOURCES.md so local infrastructure data is never committed
- Planner phase 2 reads RESOURCES.md from factory root when present
- Planner prompt instructs Claude to reference specific resource aliases in operational issues
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hardcoded /tmp/dev-agent.lock meant harb and disinto dev-polls shared
a lock — one project's running agent blocked the other. Now uses
/tmp/dev-agent-{project}.lock and dev-agent-{project}.log.
Implements the vault subsystem: a JSONL queue and gate agent that sits
between agent output and irreversible external actions (emails, posts,
API calls, charges).
New files:
- vault/vault-poll.sh: cron entry (*/30), three phases: retry approved,
timeout escalations (48h), invoke vault-agent for new pending actions
- vault/vault-agent.sh: claude -p wrapper that classifies and routes
actions based on risk × reversibility routing table
- vault/vault-fire.sh: two-phase dispatcher (pending→approved→fired)
with per-action locking and webhook-call handler
- vault/vault-reject.sh: moves actions to rejected/ with reason + timestamp
- vault/PROMPT.md: vault-agent system prompt with routing table
Modified:
- lib/matrix_listener.sh: new vault dispatch branch for APPROVE/REJECT
replies to escalation threads
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The broad regex `(?:^|\n)\s*-\s*#\K[0-9]+` matched ANY bullet with #NNN,
including ## Related sections. This caused #893 (and likely others) to be
permanently blocked by sibling issues that aren't actual dependencies.
Now only extracts deps from:
- Inline 'depends on #NNN' / 'blocked by #NNN' phrases
- ## Dependencies / ## Depends on / ## Blocked by sections
This matches the same logic used by dev-poll.sh get_deps().
Adds PRIORITY_blockers_starving_factory detection: scans backlog issues'
deps, finds any that are open but not labeled backlog, and puts them
at the top of the Claude prompt as highest priority for promotion.
Previously, gardener promoted random tech-debt issues while the actual
blockers (e.g. #650, #563, #714, #743) were ignored, leaving all
backlog items permanently stuck.
Replace lib/parse-deps.py with lib/parse-deps.sh to keep the toolchain
all-bash. Rewrite supervisor P3b cycle detection and P3c stale dep check
as pure bash using associative arrays and DFS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single source of truth for dependency parsing, replacing three copies:
- dev-poll.sh get_deps() now calls parse-deps.py
- supervisor P3b/P3c import parse_deps() via importlib
Supports stdin, argument, and --json modes for different callers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add three new supervisor checks:
- P2c: alert when dev-agent reports "no ready issues" for 6+ consecutive polls
- P3b: detect circular dependency deadlocks via DFS cycle detection
- P3c: flag backlog issues blocked by deps open >30 days
Update supervisor PROMPT.md with guidance for Claude to resolve circular deps
by reading code context, and handle stale deps by checking relevance.
Gardener prompt now forbids bidirectional deps between sibling issues and
requires ## Related (not ## Dependencies) for cross-references.
Closes#16, Closes#17
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The supervisor agent was confusingly named "factory" (same as the
project). Rename directory, script, log, lock, status, and escalation
files. Update all references across scripts and docs.
FACTORY_ROOT env var unchanged (refers to project root, not agent).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These docs never existed — gardener and review-pr referenced them
as if they did. AGENTS.md tree is now the single architecture
reference for all agents.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Explains how to seed the AGENTS.md tree with watermarks before the
first planner run to avoid the first-run flood. Also adds planner
to cron schedule and lifecycle diagram.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove STATE_FILE variable and all STATE.md references from phase 2
- Restore matrix_send for gap analysis issue creation
- Replace broad `git add -A "*.md"` with targeted `find -name AGENTS.md`
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1 rewritten:
- Claude gets --dangerously-skip-permissions to navigate code, read
diffs, and update AGENTS.md files directly
- Per-file <!-- last-reviewed: SHA --> watermarks replace global marker
- Sub-directory AGENTS.md files discovered and updated independently
- ~200 line convention enforced via prompt
- Changes committed on branch and PR'd
Phase 2 now reads AGENTS.md tree + STATE.md for gap analysis.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
STATE.md was a machine-generated system description that was always
worse than the human-curated AGENTS.md. Killed STATE.md entirely.
Phase 1: Reviews recent git history against AGENTS.md, suggests
updates via PR to keep the file tree, conventions, and architecture
descriptions current.
Phase 2: Gap analysis — compares AGENTS.md + VISION.md + open issues,
creates backlog issues for missing capabilities.
Add unconditional worktree cleanup to factory supervisor:
- Remove review + dev worktrees older than 2h with no active agent
- Use git worktree remove --force instead of rm -rf
- Run git worktree prune every poll to clear dangling refs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Feeds AGENTS.md, PRODUCT-TRUTH.md, ARCHITECTURE.md, UX-DECISIONS.md
into the prompt so the planner understands the system at a conceptual
level. Rewritten prompt emphasizes describing the system, not the
changes. Good/bad examples guide output style.
do_merge() is defined at line 876, but recovery mode calls it at
line ~498. Bash requires functions to be defined before use.
Inlined the merge→rebase→re-approve→retry logic directly.
1. Recovery mode: if PR already has approval + green CI, try merge
immediately instead of entering the review wait loop forever.
2. do_merge: on 405/merge failure, rebase → force push → wait CI →
re-approve via review_bot → retry merge. Covers the stale-approval
dismissal problem end-to-end.
3. Codeberg mergeable field is unreliable — rebase on any merge failure.
Sonnet sometimes narrates what it did instead of outputting the actual
STATE.md. Added validation that first line starts with '- ' and
strengthened the output-only instruction.
set -o pipefail causes head -1 to fail the pipeline when git log
is still producing output. The || fallback then appends a second
line. Fix: capture first SHA separately with || true.
Codeberg's mergeable field flickers between true/false — unreliable
for deciding whether to rebase. Just attempt rebase on any non-200/204.
Worst case it's a no-op. Also added git fetch before rebase.
- Remove write_state_entry/append_state_log from dev-agent (#10)
- Add planner-agent.sh: rebuilds STATE.md from git history + closed
issues, then gap-analyses against VISION.md to create backlog
issues (#6, #7)
- Add planner-poll.sh: cron wrapper with lock + memory guard
STATE.md is now solely owned by the planner — one compact snapshot
rebuilt each run, not an ever-growing append log.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When merge returns non-200, check mergeable flag. If false,
rebase the PR branch onto master via worktree. If rebase fails,
spawn dev-agent to resolve. Prevents infinite 405 retry loops.
Extracted try_merge_or_rebase() helper used at all 3 merge points.
pgrep matched all claude processes including manual screen sessions.
Narrow to "claude -p" so only non-interactive (factory-spawned) processes
get reaped by the stale-process cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dev-agent failed with exit 127 (command not found) because claude
is installed in ~/.local/bin which wasn't in the PATH set by env.sh.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add matrix_send() to lib/env.sh and matrix_listener.sh daemon for
real-time notifications, threaded escalations, and human-in-the-loop
replies. All agents now notify via Matrix instead of openclaw.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PRs #684 and #710 had no issue number in branch name or title.
Now also checks PR body for 'Closes #NNN'. If still no issue found,
logs a skip (dev-agent requires an issue number to work).
PRs with custom branch names (fix/fitness-factory-address,
chore/seed-consolidation) were invisible to priority 1.5.
Now also extracts issue number from PR title (#NNN) as fallback.