8 KiB
8 KiB
Shared Helpers (lib/)
All agents source lib/env.sh as their first action. Additional helpers are
sourced as needed.
| File | What it provides | Sourced by |
|---|---|---|
lib/env.sh |
Loads .env, sets FACTORY_ROOT, exports project config (FORGE_REPO, PROJECT_NAME, etc.), defines log(), forge_api(), forge_api_all() (accepts optional second TOKEN parameter, defaults to $FORGE_TOKEN), woodpecker_api(), wpdb(), matrix_send(), matrix_send_ctx(). Auto-loads project TOML if PROJECT_TOML is set. Auto-detects MATRIX_HOMESERVER: defaults to http://dendrite:8008 inside a container (DISINTO_CONTAINER=1) or http://localhost:8008 on bare metal; can be overridden via .env. |
Every agent |
lib/ci-helpers.sh |
ci_passed() — returns 0 if CI state is "success" (or no CI configured). ci_required_for_pr() — returns 0 if PR has code files (CI required), 1 if non-code only (CI not required). is_infra_step() — returns 0 if a single CI step failure matches infra heuristics (clone/git exit 128, any exit 137, log timeout patterns). classify_pipeline_failure() — returns "infra <reason>" if any failed Woodpecker step matches infra heuristics via is_infra_step(), else "code". ensure_priority_label() — looks up (or creates) the priority label and returns its ID; caches in _PRIORITY_LABEL_ID. ci_commit_status <sha> — queries Woodpecker directly for CI state, falls back to forge commit status API. ci_pipeline_number <sha> — returns the Woodpecker pipeline number for a commit, falls back to parsing forge status target_url. |
dev-poll, review-poll, review-pr, supervisor-poll |
lib/ci-debug.sh |
CLI tool for Woodpecker CI: list, status, logs, failures subcommands. Not sourced — run directly. |
Humans / dev-agent (tool access) |
lib/load-project.sh |
Parses a projects/*.toml file into env vars (PROJECT_NAME, FORGE_REPO, WOODPECKER_REPO_ID, monitoring toggles, Matrix config, etc.). |
env.sh (when PROJECT_TOML is set), supervisor-poll (per-project iteration) |
lib/parse-deps.sh |
Extracts dependency issue numbers from an issue body (stdin → stdout, one number per line). Matches ## Dependencies / ## Depends on / ## Blocked by sections and inline depends on #N / blocked by #N patterns. Inline scan skips fenced code blocks to prevent false positives from code examples in issue bodies. Not sourced — executed via bash lib/parse-deps.sh. |
dev-poll, supervisor-poll |
lib/matrix_listener.sh |
Long-poll Matrix sync daemon. Dispatches thread replies to the correct agent via tmux session injection (dev, action, vault, review) or well-known files (/tmp/{agent}-escalation-reply for supervisor/gardener). Handles all agent reply routing. In compose mode, started as a background process by docker/agents/entrypoint.sh; on bare metal, run as systemd service (see matrix_listener.service). |
Standalone daemon |
lib/formula-session.sh |
acquire_cron_lock(), check_memory(), load_formula(), build_context_block(), consume_escalation_reply(), start_formula_session(), formula_phase_callback(), build_prompt_footer(), run_formula_and_monitor(AGENT [TIMEOUT] [CALLBACK]) — shared helpers for formula-driven cron agents (lock, memory guard, formula loading, prompt assembly, tmux session, monitor loop, crash recovery). formula_phase_callback() handles PHASE:escalate (unified escalation path — kills the session; callers may follow up via Matrix). run_formula_and_monitor accepts an optional CALLBACK (default: formula_phase_callback) so callers can install custom merge-through or escalation handlers. |
planner-run.sh, predictor-run.sh, gardener-run.sh, supervisor-run.sh, dev-agent.sh, action-agent.sh |
lib/guard.sh |
check_active(agent_name) — reads $FACTORY_ROOT/state/.{agent_name}-active; exits 0 (skip) if the file is absent. Factory is off by default — state files must be created to enable each agent. Sourced by dev-poll.sh, review-poll.sh, action-poll.sh, predictor-run.sh, supervisor-run.sh. |
cron entry points |
lib/mirrors.sh |
mirror_push() — pushes $PRIMARY_BRANCH + tags to all configured mirror remotes (fire-and-forget background pushes). Reads MIRROR_NAMES and MIRROR_* vars exported by load-project.sh from the [mirrors] TOML section. Failures are logged but never block the pipeline. Sourced by dev-poll.sh and dev/phase-handler.sh — called after every successful merge. |
dev-poll.sh, phase-handler.sh |
lib/build-graph.py |
Python tool: parses VISION.md, prerequisite-tree.md, AGENTS.md, formulas/*.toml, evidence/, and forge issues/labels into a NetworkX DiGraph. Runs structural analyses (orphaned objectives, stale prerequisites, thin evidence, circular deps) and outputs a JSON report. Used by review-pr.sh (per-PR changed-file analysis) and predictor-run.sh (full-project analysis) to provide structural context to Claude. |
review-pr.sh, predictor-run.sh |
lib/secret-scan.sh |
scan_for_secrets() — detects potential secrets (API keys, bearer tokens, private keys, URLs with embedded credentials) in text; returns 1 if secrets found. redact_secrets() — replaces detected secret patterns with [REDACTED]. |
file-action-issue.sh, phase-handler.sh |
lib/file-action-issue.sh |
file_action_issue() — dedup check, secret scan, label lookup, and issue creation for formula-driven cron wrappers. Sets FILED_ISSUE_NUM on success. Returns 4 if secrets detected in body. |
(available for future use) |
lib/agent-session.sh |
Shared tmux + Claude session helpers: create_agent_session(), inject_formula(), agent_wait_for_claude_ready(), agent_inject_into_session(), agent_kill_session(), monitor_phase_loop(), read_phase(), write_compact_context(). create_agent_session(session, workdir, [phase_file]) optionally installs a PostToolUse hook (matcher Bash|Write) that detects phase file writes in real-time — when Claude writes to the phase file, the hook writes a marker so monitor_phase_loop reacts on the next poll instead of waiting for mtime changes. Also installs a StopFailure hook (matcher rate_limit|server_error|authentication_failed|billing_error) that writes PHASE:failed with an api_error reason to the phase file and touches the phase-changed marker, so the orchestrator discovers API errors within one poll cycle instead of waiting for idle timeout. Also installs a SessionStart hook (matcher compact) that re-injects phase protocol instructions after context compaction — callers write the context file via write_compact_context(phase_file, content), and the hook (on-compact-reinject.sh) outputs the file content to stdout so Claude retains critical instructions. When MATRIX_THREAD_ID is exported, also installs a Stop hook (on-stop-matrix.sh) that streams each Claude response to the Matrix thread. When phase_file is set, passes it to the idle stop hook (on-idle-stop.sh) so the hook can nudge Claude (up to 2 times) if Claude returns to the prompt without writing to the phase file — the hook injects a tmux reminder asking Claude to signal PHASE:done or PHASE:awaiting_ci. The PreToolUse guard hook (on-pretooluse-guard.sh) receives the session name as a third argument — formula agents (gardener-*, planner-*, predictor-*, supervisor-*) are identified this way and allowed to access FACTORY_ROOT from worktrees (they need env.sh, AGENTS.md, formulas/, lib/). monitor_phase_loop sets _MONITOR_LOOP_EXIT to one of: done, idle_timeout, idle_prompt (Claude returned to > for 3 consecutive polls without writing any phase — callback invoked with PHASE:failed, session already dead), crashed, or PHASE:escalate / other PHASE:* string. Unified escalation: PHASE:escalate is the signal that a session needs human input (renamed from PHASE:needs_human). Callers must handle idle_prompt in both their callback and their post-loop exit handler — see docs/PHASE-PROTOCOL.md idle_prompt for the full contract. |
dev-agent.sh, action-agent.sh |