This repository is the GitHub notification → OpenClaw agent bridge used by Pilipilis.
- Default to
--mode shadowfor local runs. Use--mode liveonly when the operator explicitly asks. - Never enable
--mark-seenin development fixtures or shadow tests. It mutates the mailbox. - Never commit secrets, app passwords, tokens, local DBs, logs, or
~/.config/*files. - Treat
enabledReposas the canary guardrail. If it is set, jobs outside that repo set must be denied. - Do not remove the per-
work_keylock/coalescing behavior without replacing it with an equivalent concurrency guard. - Prefer adding tests around parser/policy/queue/dispatch behavior before changing production flow.
python -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[test]'
pytest -q# Initialize an isolated DB
DB=/tmp/github-agent-bridge-dev.sqlite3
gab --db "$DB" init-db
# Replay a saved .eml without external side effects
gab --db "$DB" --policy ./policy.example.json replay ./fixtures/example.eml --verbose
# Enqueue a real GitHub issue/PR comment URL as a synthetic trusted notification
gab --db "$DB" --policy ./policy.example.json enqueue-comment-url \
'https://github.com/gisce/erp/pull/27675#issuecomment-4419572864'
# Process queued jobs without touching GitHub/OpenClaw
gab --db "$DB" --policy ./policy.example.json run --mode shadow --once
# Inspect health
gab --db "$DB" --policy ./policy.example.json status
gab --db "$DB" --policy ./policy.example.json monitor --no-systemdPipeline:
IMAP/eml/manual URL -> Notification -> Policy decision -> SQLite jobs -> executor -> GitHub 👀 + OpenClaw agent
Important invariants:
- Reader must persist or explicitly handle a notification before advancing high-water state.
message_idis globally unique; duplicates must not create duplicate jobs.- Active jobs with the same
work_key(owner/repo#number) must coalesce instead of running concurrently. - Different
work_keys may run in parallel. shadowanddry-runmodes must not call GitHub or OpenClaw.review_onlywork uses a shorter timeout and must not ask agents to modify code.enabledReposis a hard allowlist when non-empty.
parser.py: classify GitHub notification text and extract repo/thread/comment context.policy.py: trust, canary scope, actions and routing decisions.queue.py: durable jobs, coalescing, locking and retry state.sql/schema.sql: packaged SQLite schema loaded byqueue.py.dispatch.py: GitHub reactions and OpenClaw agent command construction/execution.prompt_rules/*.md: packaged Markdown rules appended to agent prompts. Keep these readable; they are loaded withimportlib.resourcesso they work from wheels/sdists.prompt_rules/roles/*.md: packaged repository-role postures selected bypolicy.jsonrepoRoles/orgRoles.reader.py: IMAP polling and mailbox mutation.monitor.py: operational health checks.cli.py: operational entrypoints and developer tooling.autoupdate.py: safe release update planning. When changing runtime structure, reload boundaries, schema layout, dashboard packaging, queue semantics, or process/service topology, update the autoupdate classification and tests so the planner still knows whether a release can reload the dashboard, must defer executor work, or needs a migration window.
- Do not put substantial LLM prompt text inline in Python. Prompt text belongs in
src/github_agent_bridge/prompt_rules/*.mdorsrc/github_agent_bridge/prompt_rules/roles/*.md. - If a new prompt can reasonably vary by deployment, add a
policy.jsonpromptOverrideskey for it instead of hardcoding a resource path as the only source. - Packaged prompt resources are defaults. Operator override files are first-class configuration and must be honored wherever prompts are built, including background learning commands such as
feedback-learn. - Add or update tests for both the packaged default and the override path whenever prompt loading changes.
Run before handing off or pushing:
pytest -qFor changes that touch CLI behavior, also run the relevant command against a temporary DB. Never test live mode against production unless explicitly requested.