Commit graph

182 commits

Author SHA1 Message Date
openhands
9445e36a1e fix: auto-close issues when dev-agent detects already_done
Previously the agent unclaimed the issue but left it open, causing
an infinite claim/refuse/unclaim loop on every poll cycle.
2026-03-17 09:38:08 +00:00
openhands
1b3559bba7 fix: enforce single-threaded pipeline per project
Don't start new issues while open PRs are waiting for review/CI.
This prevents dev-agent from churning through backlog issues
without reviews landing first.
2026-03-17 09:17:02 +00:00
openhands
ea033d3f04 fix: TMPDIR unbound variable crashes already_done handler
TMPDIR is not guaranteed to be set. Replaced with /tmp/ directly.
This caused harb dev-agent to crash when posting refusal comments,
leaving issues stuck in a retry loop.
2026-03-17 09:00:43 +00:00
openhands
b376fbc25e fix: dev-agent.sh also needs per-project lock file
dev-poll.sh was fixed but dev-agent.sh still used hardcoded
/tmp/dev-agent.lock. The disinto agent locked out harb's agent.
2026-03-17 08:41:15 +00:00
openhands
249eef86c1 fix: per-project lock and log files for dev-poll
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.
2026-03-17 08:18:24 +00:00
johba
9050413994 refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes

Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project

New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env

Backwards compatible: scripts without a TOML arg fall back to .env config.

Closes #26, Closes #27

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
openhands
5aa0b42481 fix: dev-agent preflight treats ## Related refs as dependencies
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().
2026-03-17 05:58:54 +00:00
johba
98f0c40106 refactor: rewrite parse-deps.py as pure bash, remove only Python from repo
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>
2026-03-16 21:22:53 +01:00
johba
6cf580c010 refactor: extract shared dep parser to lib/parse-deps.py (Closes #20)
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>
2026-03-16 21:16:49 +01:00
johba
77cb4c4643 refactor: rename factory/ → supervisor/, factory-poll → supervisor-poll
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>
2026-03-15 18:06:25 +01:00
openhands
0a0d5e8e24 fix: inline merge+rebase in recovery path (do_merge not yet defined)
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.
2026-03-15 14:10:21 +00:00
openhands
2c527cef4a fix: dev-agent handles approved+stuck PRs in recovery mode
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.
2026-03-15 14:09:33 +00:00
openhands
c5fdd8ac50 fix: always rebase on merge failure, don't trust mergeable field
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.
2026-03-15 10:51:09 +00:00
johba
9b0c1e6c30 feat: add planner-agent, remove STATE.md append from dev-agent
- 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>
2026-03-15 11:45:16 +01:00
openhands
c22f1acbdf fix: add matrix notifications for silent failure paths
dev-poll.sh:
- Merge conflicts (rebase attempt + outcome)
- Non-conflict merge failures (HTTP code)
- Low memory skip
- New issue launch

review-poll.sh:
- Review script failure
2026-03-15 10:27:23 +00:00
openhands
b4d14c4c98 fix: auto-rebase on merge conflict (mergeable=false)
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.
2026-03-15 10:21:40 +00:00
johba
f215fbe3cf feat: add Matrix coordination channel, replace openclaw (Closes #8)
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>
2026-03-14 16:25:33 +01:00
johba
90ef03a304 refactor: make all scripts multi-project via env vars
Replace hardcoded harb references across the entire codebase:
- HARB_REPO_ROOT → PROJECT_REPO_ROOT (with deprecated alias)
- Derive PROJECT_NAME from CODEBERG_REPO slug
- Add PRIMARY_BRANCH (master/main), WOODPECKER_REPO_ID env vars
- Parameterize worktree prefixes, docker container names, branch refs
- Genericize agent prompts (gardener, factory supervisor)
- Update best-practices docs to use $-vars, prefix harb lessons

All project-specific values now flow from .env → lib/env.sh → scripts.
Backward-compatible: existing harb setups work without .env changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:49:09 +01:00
openhands
2b3c488f1c fix: STATE.md entries without status prefix — reads as done once merged 2026-03-14 12:14:42 +00:00
openhands
a3f0f7f6f3 fix: stuck PR issue extraction — check title, body (Closes #N), log skip
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).
2026-03-14 12:01:36 +00:00
openhands
30b31c76aa fix: stuck PR detection only matched fix/issue-NNN branches
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.
2026-03-14 11:12:27 +00:00
openhands
7fd913596b fix: write_state_entry defined after call site — crashes dev-agent
Function was defined at line 867 but called at line 550. Bash requires
functions to be defined before invocation. Moved to top with other
helpers. Also removed duplicate definition.
2026-03-14 11:01:05 +00:00
openhands
0f979fd6c9 fix: stuck PRs priority + STATE.md in first commit + 405 bug in dev-poll
1. PRIORITY 1.5 in dev-poll: scan ALL open PRs for REQUEST_CHANGES or CI
   failure before picking new backlog issues. Stuck PRs get fixed first
   to avoid complex rebases piling up.

2. STATE.md written in worktree before claude starts (included in first
   commit, not a separate push that dismisses stale approvals).

3. Removed HTTP 405 from merge success check in dev-poll.sh (was fixed
   in dev-agent.sh but not here — 2 occurrences).
2026-03-14 07:34:47 +00:00
openhands
8e3b72d13f feat: dev-agent auto-rebase before merge
When PR has merge conflicts (mergeable=false), attempt git rebase
before merge. If rebase fails, abort and escalate via notify.

Flow: approval → check mergeable → rebase if needed → wait CI → merge

Resolves the serial seed PR bottleneck where append-only files
(manifest.jsonl) create trivial conflicts that block the pipeline.
2026-03-13 19:56:12 +00:00
openhands
0132c7acc4 fix: 405 treated as merge success + STATE.md push dismissed approvals
Root cause: Two bugs combined to silently close PRs without merging.

1. HTTP 405 ('not allowed to merge') was in the success condition
   alongside 200/204. Codeberg returns 405 when branch protection
   blocks the merge (e.g., stale approvals).

2. append_state_log pushed a new commit AFTER review_bot approved,
   but BEFORE the merge attempt. With dismiss_stale_approvals=true,
   the new commit automatically dismissed the approval → 405.

Impact: 6 PRs (#683, #688, #692, #695, #696, #699) were 'merged'
(logged as success, branch deleted, issue closed) but never actually
merged into master. All work was lost.

Fixes:
- Remove 405 from merge success check
- Move STATE.md append out of pre-merge path
2026-03-13 17:41:10 +00:00
openhands
98210cc302 fix: dep check — trust closed state, drop merged-PR search
The merged-PR search was over-engineered and caused false negatives
(couldn't match PR to issue when title/body didn't contain #NNN).
Issue closed = dep satisfied. Factory only closes after merging.
2026-03-13 11:25:35 +00:00
openhands
d61dead3f1 fix: dep check fallback — also check PR with same number as issue
Codeberg uses shared issue/PR numbering. When a PR IS the dep issue
(e.g. PR #665 fixes issue #665), the title search misses it.
Fallback checks if pulls/{dep_num} is merged.
2026-03-13 11:24:14 +00:00
openhands
499f6d8828 feat: STATE.md append before merge, lives in harb repo
Moved from dark-factory to harb. Dev-agent appends one line to
STATE.md on the PR branch right before merge — goes through
review like any other change.
2026-03-13 10:27:10 +00:00
openhands
ed58874890 feat: STATE.md append on merge (dark-factory#5)
After each successful PR merge, dev-agent appends one line to
STATE.md: - [date] what now exists (#PR)

Lives in dark-factory repo (harb master is protected).
Planner will collapse this into a compact snapshot later.
2026-03-13 10:25:00 +00:00
openhands
64b464b01b feat: dev-agent → supervisor escalation via escalations.jsonl
When dev-agent exhausts CI fix budget, writes escalation marker.
Supervisor picks it up next poll and invokes claude -p to diagnose
(flaky test? rate limit? real bug?) and decide: fix, close PR, or
escalate to human.
2026-03-13 06:51:53 +00:00
openhands
4895ad1989 refactor: ci-debug to lib, rewrite README
- Moved ci-debug.sh from dev/ to lib/ (shared utility)
- README: fixed supervisor description (all alerts go to claude)
- README: replaced implementation details with actual design principles
2026-03-12 18:10:25 +00:00
openhands
cb24968d9b feat: dark factory — autonomous CI/CD agents for harb
Three agents extracted from ~/scripts/harb-{dev,review}/:

- dev/ — pull-based dev agent (find ready issues → implement → PR → merge)
- review/ — AI code review (structured verdicts, follow-up issues)
- factory/ — supervisor (bash health checks, auto-fix, escalation)

All secrets externalized to .env (see .env.example).
Shared env/helpers in lib/env.sh.
2026-03-12 12:44:15 +00:00