Commit Graph
4 Commits
Author SHA1 Message Date
asepharyana c48adea6c3 feat(worker): upstream fork auto-sync — pull+merge fork repos hourly
Merge new upstream (parent) commits into every fork in the App installation,
gated by a per-repo interval (default 1h), inside the existing 5-minute tick
(STEP 0, max 2 forks/tick, oldest-first).

- Conflicted merges are resolved by Claude Code (merge-reconciler rules:
  never wholesale --ours/--theirs, verify with the repo's own
  typecheck+tests, commit --no-edit; Claude never pushes — harness does).
- Clean merges get a single Claude Code quality pass commit.
- Push path: owner PAT (gh CLI) first — the App lacks workflows:write and a
  workflows-touching merge is rejected for the App token; App token fallback.
- Protected default branch: detected from the push result (GH006 /
  required-status-check) → upstream-sync-<ts> branch + PR through the normal
  pipeline; duplicate open sync PRs are skipped.
- CI safety: after a direct push, ticks verify the fork CI at our merge sha;
  red CI at OUR merge (still the tip) → sha-guarded force-revert to
  pre-merge sha + Discord notify; never reverts foreign commits.
- Discord: synced / PR opened / reverted / skipped-once on pr-agent-ops.
- merge_pr gains the same PAT fallback (a PR merge touching workflows is a
  workflow-file push).
- CLI: --sync-status, --sync-only <repo> [--dry].
- Tests: scripts/test_pr_queue_sync.py (46 assertions, monkeypatched, no
  network); py_compile clean.
- Plan: .hermes/plans/2026-09-21-upstream-auto-sync.md
2026-09-21 17:04:39 +07:00
asepharyana 1dc4d098fa feat(worker): skip-on-error no loop + conflict auto-fix + deduped notif
1. Skip ONCE on infra errors (Claude Code CLI missing/timeout/unreachable):
   - run_ai_fix returns '[INFRA] ...' reasons; worker marks the PR permanently
     skipped at that head SHA in fix-state (no more retry every 5 min)
   - skip is recorded per {repo,pr,sha}; cleared when head SHA changes
2. Merge conflict auto-fix via Claude Code:
   - mergeable=False or merge HTTP 409 now trigger run_ai_fix (prompt already
     merges base + resolves conflicts) once per head SHA
   - success → next tick re-checks mergeable and merges; failure → skip once
3. Discord skip notification dedupe:
   - notify_skip_once(): posts '⏭️ Skipped: <reason>' exactly once per
     PR+head_sha (state.notified flag); no repeated spam every cron tick
   - skip reason + which PR is visible in the notification
4. State migration: legacy {repo:{pr:'sha'}} → dict form handled in _pr_entry
Verified: py_compile clean, state-helper unit tests pass (skip/fixed/notify
dedupe/legacy migration). Cron wrapper execs repo copy — no manual sync.
2026-09-21 15:58:52 +07:00
asepharyana bc69998d8e feat(server): production cut-over to Bun — notify_review, setup/callback, key resolution
- index.ts: add POST /api/v1/notify_review (queue-worker Discord bridge),
  /setup/callback (GitHub App manifest conversion), error logging on review
  failure, PR_AGENT_APP_DIR-based private key resolution
- config.ts: API key falls back to on-disk omniroute_key (same source as
  run_server.py) when no env key present — fixes 401 in systemd context
- markdown.ts: don't hyperlink non-URL ticket values (N/A)
- secrets.ts: fallback private key from ~/.hermes/keys + omni key ~/.hermes
- pr-queue-worker.py / auto_merge_bot.py: notify_review default port 4002→4023

Deploy: pr-agent-bun.service (Bun binary, port 4023) replaces
pr-agent-server.service (Python, port 4002, disabled). Caddy route updated in
asepharyana/infra (proxy 4023). Verified live: webhook → review → claude-opus-5
→ persistent GitHub comment published after Python shutdown.
2026-09-21 13:47:47 +07:00
asepharyana 835552c5ca feat(ops): add PR queue worker with toolchain pin guard
- pr-queue-worker.py: cron orchestrator (review trigger → AI fix → safety →
  CI gate → approve/merge) now versioned in-repo
- TOOLCHAIN_PINS: close dependabot PRs bumping pinned majors
  (typescript/eslint/@tsparticles/eslint-config-next/eslint-plugin-react)
- STALE_CI_CLOSE_DAYS=2: close dependabot PRs stuck failing CI
- Secrets externalized to env (PR_AGENT_*), hydrated from ~/.hermes/.env —
  file is safe for the public repo; no inline secrets
2026-09-21 11:36:14 +07:00