Commit graph

1038 commits

Author SHA1 Message Date
openhands
26d6e1ae52 fix: feat: RESOURCES.md — infrastructure manifest for planner resource awareness (#23)
- 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>
2026-03-17 08:48:47 +00:00
johba
211ccb0445 Merge pull request 'fix: dev-agent.sh per-project lock file' (#31) from fix/agent-per-project-lock into main
Reviewed-on: https://codeberg.org/johba/disinto/pulls/31
2026-03-17 09:41:57 +01: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
johba
d971f6d9da Merge pull request 'fix: per-project lock and log files for dev-poll' (#29) from fix/per-project-locks into main
Reviewed-on: https://codeberg.org/johba/disinto/pulls/29
2026-03-17 09:19:09 +01: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
bd6424fca5 Merge pull request 'feat: register disinto as its own project' (#28) from chore/disinto-self-project into main
Reviewed-on: https://codeberg.org/johba/disinto/pulls/28
2026-03-17 09:06:06 +01:00
openhands
5608c252e0 feat: register disinto as its own project — the factory builds itself
Adds projects/disinto.toml so dev-poll, review-poll, gardener, and
supervisor all monitor johba/disinto issues and PRs alongside harb.
2026-03-17 08:04:46 +00:00
openhands
fce5e66b90 Merge feat/multi-project: split supervisor + project-agnostic poll scripts (#26, #27) 2026-03-17 08:03:45 +00:00
openhands
5152cdb8e5 feat: add projects/harb.toml for multi-project supervisor 2026-03-17 08:00:32 +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
johba
e503273fba feat: vault — publishing gate for external-facing agent actions (#19)
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>
2026-03-17 08:07:02 +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
openhands
2fd18b086d feat: gardener prioritizes blocker issues that starve the factory
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.
2026-03-16 21:06:01 +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
acab6c95c8 feat: supervisor detects dep deadlocks, stale deps, and dev-agent blocked states
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>
2026-03-16 21:07:02 +01:00
openhands
27373a16f3 docs: add hero image and Asimov quote to README
- Generated retro pulp sci-fi artwork of AL-76's Disinto
- Aligned slogan with disinto.ai landing page
- Added centered header with image, tagline, and origin quote
2026-03-15 18:08:52 +00: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
johba
8d73c2f8f9 refactor: rebrand dark-factory → disinto (Closes #15)
- README: rename, add disinto.ai link
- BOOTSTRAP.md: update all path references
- lib/matrix_listener.service: update paths to /home/admin/disinto
- factory scripts: update comments and prompt references
- .env.example: update header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:57:12 +01:00
johba
1675e17502 fix: replace PRODUCT-TRUTH.md/ARCHITECTURE.md refs with AGENTS.md
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>
2026-03-15 17:41:10 +01:00
johba
71aa49afbb docs: add AGENTS.md seeding instructions to BOOTSTRAP.md
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>
2026-03-15 17:01:04 +01:00
johba
7f41048aea fix: remove dead STATE.md code, restore matrix notify, targeted git add (Closes #13, Closes #14)
- 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>
2026-03-15 16:53:33 +01:00
johba
3bb75f18be feat: planner uses Claude tool access to navigate AGENTS.md tree (Closes #12)
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>
2026-03-15 16:33:47 +01:00
openhands
679c62e7cb refactor: planner maintains AGENTS.md instead of STATE.md
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.
2026-03-15 15:13:41 +00:00
johba
e1101894d6 fix: clean stale git worktrees in P4 housekeeping (Closes #11)
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>
2026-03-15 16:05:38 +01:00
openhands
5c6293fdab fix: strip non-bullet preamble from planner output
Sonnet prepends narration before the actual bullets. Strip everything
before the first '- ' line instead of rejecting the whole output.
2026-03-15 15:02:53 +00:00
openhands
af75c0eccf fix: even stronger output-only instruction for Sonnet
Sonnet keeps narrating. Made the constraint explicitly say 'starts
with - on the very first character' and 'will be rejected'.
2026-03-15 14:59:42 +00:00
openhands
ff50d28645 feat: planner reads project docs for architectural understanding
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.
2026-03-15 14:58:10 +00:00
openhands
240ba62b28 factory: learned — False Positive: 'Waiting for CI + Review' Alert 2026-03-15 14:52:58 +00: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
a114f638ef fix: planner validates bullet output, rejects meta-commentary
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.
2026-03-15 12:51:59 +00:00
openhands
4b95d32a0c fix: planner PR lookup filters by head.ref client-side
Codeberg head= query param is unreliable — filter with jq instead.
2026-03-15 12:49:22 +00:00
openhands
17053f8559 fix: planner creates PR instead of direct push to protected master
Also removes local keyword from top-level scope.
2026-03-15 12:47:50 +00:00
openhands
335ea0d48d fix: remove local keyword outside function in planner 2026-03-15 12:42:12 +00:00
openhands
efa6eab352 fix: planner GIT_RANGE newline bug from pipefail + head -1
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.
2026-03-15 12:41:50 +00:00
johba
1a9afa9f9c Merge pull request 'docs: add BOOTSTRAP.md for onboarding new projects' (#9) from docs/bootstrap into main
Reviewed-on: https://codeberg.org/johba/dark-factory/pulls/9
2026-03-15 13:34:44 +01:00
johba
70dddc3162 docs: add BOOTSTRAP.md for onboarding new projects
Project-agnostic guide covering .env config, target repo prep,
issue conventions, cron setup, verification, and troubleshooting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:34:35 +01: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
996d197401 fix: supervisor only kills factory-spawned claude, not interactive sessions
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>
2026-03-15 10:39:40 +01:00
johba
7bba97b0d6 fix: add ~/.local/bin to PATH for claude binary
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>
2026-03-14 17:18:15 +01: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
johba
f16df6c53e docs: update README for multi-project vision, add gardener, expand setup
- Remove harb-specific framing — describe as project-agnostic factory
- Add gardener agent (was missing from docs entirely)
- New Prerequisites section with required vs optional dependencies
- Expand Setup with full annotated .env example
- Add Agents summary table
- Add "project-agnostic" design principle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:38:38 +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