Skip to content

feat(wiki): Phase 4 — MaintenanceQueue + RepoWikiLoop opens PRs#8359

Merged
HydraOps-T-rav merged 2 commits intomainfrom
hydraflow/wiki-loop-prs
Apr 19, 2026
Merged

feat(wiki): Phase 4 — MaintenanceQueue + RepoWikiLoop opens PRs#8359
HydraOps-T-rav merged 2 commits intomainfrom
hydraflow/wiki-loop-prs

Conversation

@HydraOps-T-rav
Copy link
Copy Markdown
Collaborator

Summary

Phase 4 of the git-backed repo wiki. Adds the admin-action MaintenanceQueue and upgrades RepoWikiLoop to detect tracked-layout diffs and open an auto-merged maintenance PR via auto_pr.open_automated_pr_async. Stacked on #8358.

What's new

src/wiki_maint_queue.pyMaintenanceTask + MaintenanceQueue. Kind-validated dataclass, JSON-persisted FIFO, corrupt-file tolerant. Single-host Phase 4; multi-host remains an open question.

src/repo_wiki_loop.py — two new ctor params (credentials, maintenance_queue), two new state fields (_open_pr_branch, _open_pr_url), and two new hooks on _do_work:

  1. Queue drain up front — before list_repos() can early-return, so admin actions targeting freshly-migrated repos aren't stuck in the queue.
  2. _maybe_open_maintenance_pr(stats) — scans git status --porcelain <repo_wiki_path> for uncommitted changes. When present, opens an auto-merged PR titled chore(wiki): maintenance YYYY-MM-DD via the existing open_automated_pr_async helper. Respects config.repo_wiki_maintenance_auto_merge and config.repo_wiki_maintenance_pr_coalesce. Fail-soft: helper failures log, don't raise.

src/service_registry.py — threads credentials through the loop constructor so the loop can auth the eventual gh pr create.

What's out of scope (Phase 5)

  • Admin-task execution — drained tasks are logged but don't mutate the tracked layout yet. active_lint / compile_topic still write to the legacy gitignored path. The maintenance-PR path is plumbing; it stays dormant until those side effects target repo_root / repo_wiki/.
  • Coalesce actually pushing new commits — when a prior PR is open, Phase 4 reuses the URL but doesn't push new commits to the existing branch yet. That lands with Phase 5.

Tests

19 new tests pass locally:

  • tests/test_wiki_maint_queue.py (7): enqueue/drain ordering, idempotent drain, persistence across restart, corrupt-file recovery, kind validation, peek-doesn't-drain, drain clears persisted file.
  • tests/test_repo_wiki_loop_pr.py (12): _porcelain_paths behavior (empty, untracked, modified, ignores files outside prefix), PR body formatting with sorted files, _maybe_open_maintenance_pr (skip on missing creds / no diff, opens PR with correct kwargs, coalesces into open PR, force-opens when coalesce disabled, fail-soft on helper failure), _do_work queue drain (reports count even when list_repos empty).

make quality-lite clean; full phase-3.5 + repo_wiki test suite still passes.

Test plan

  • uv run pytest tests/test_wiki_maint_queue.py tests/test_repo_wiki_loop_pr.py tests/test_repo_wiki*.py tests/test_phase_wiki_wiring.py — 96 passed.
  • make quality-lite — clean.
  • CI make quality.
  • Phase 5 wires admin-task execution + actual coalesce push.

🤖 Generated with Claude Code

@HydraOps-T-rav HydraOps-T-rav force-pushed the hydraflow/wiki-phase-wiring branch from 186001a to 35fc358 Compare April 19, 2026 23:02
Base automatically changed from hydraflow/wiki-phase-wiring to main April 19, 2026 23:02
T-rav-Hydra-Ops and others added 2 commits April 19, 2026 17:03
Adds the PR-opening plumbing to `RepoWikiLoop` + the admin-action
`MaintenanceQueue` that console routes will enqueue into.  See
docs/git-backed-wiki-design.md Phase 4.

New module: `src/wiki_maint_queue.py`

- `MaintenanceTask` dataclass: `kind: Literal["force-compile",
  "mark-stale", "rebuild-index"]`, `repo_slug`, `params`.  Kind is
  validated in `__post_init__`.
- `MaintenanceQueue(path)`: in-memory FIFO with JSON persistence.
  `enqueue` / `peek` / `drain`.  Corrupt queue file → warn + empty
  queue so factory boot stays robust.  Single-host per Phase 4;
  multi-host coordination stays in open questions.

`RepoWikiLoop` upgrade (`src/repo_wiki_loop.py`)

- New ctor params: `credentials: Credentials | None = None`,
  `maintenance_queue: MaintenanceQueue | None = None`.  Queue defaults
  to `.hydraflow/wiki_maint_queue.json`.
- New state: `_open_pr_branch`, `_open_pr_url` for coalescing
  subsequent ticks into an already-open maintenance PR.
- `_do_work` now drains the queue up front (survives the `list_repos()`
  early-return) and reports `queue_drained` in stats.  Phase 4 logs
  the drain; Phase 5 wires actual mark-stale / force-compile /
  rebuild-index execution.
- New `_maybe_open_maintenance_pr(stats)` method:
  * Silent no-op when credentials are missing, repo_root is not a
    git repo, or the tracked `repo_wiki/` has no uncommitted changes.
  * Uses `_porcelain_paths(repo_root, path_prefix)` to scope
    `git status --porcelain` to the configured `repo_wiki_path`.
  * Routes through `auto_pr.open_automated_pr_async` with
    `auto_merge=config.repo_wiki_maintenance_auto_merge`,
    `raise_on_failure=False` so PR-opening failures log + return
    cleanly rather than crashing the loop tick.
  * When coalesce is enabled and a prior PR is still open, the method
    reuses the recorded URL instead of opening a new one.  Phase 5
    will actually push the new commits to the same branch.

`src/service_registry.py` wires `credentials` through the loop ctor.

Tests (`tests/test_wiki_maint_queue.py`, `tests/test_repo_wiki_loop_pr.py`)

- 7 queue tests: enqueue/drain ordering, idempotent drain, persistence
  across restart, corrupt-file recovery, unknown-kind rejection,
  peek-doesn't-drain, drain clears persisted file.
- 12 loop tests: `_porcelain_paths` (empty, untracked, modified,
  respects prefix); `_maintenance_pr_body` (formatting + sorted files);
  `_maybe_open_maintenance_pr` (skip on missing creds, skip on no
  diff, opens PR with correct kwargs, coalesces into open PR,
  force-opens when coalesce disabled, fail-soft on helper error);
  `_do_work` queue-drain integration (reports count even when
  list_repos is empty).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… on CI green

Auto-merge is off on HydraFlow's branch protection, so Phase 4 now
handles review + merge itself after opening each maintenance PR.

auto_pr.open_automated_pr / open_automated_pr_async accept a new
`labels: list[str] | None = None` kwarg; each value is appended as
`--label <name>` on the `gh pr create` call.

RepoWikiLoop:
- opens the PR with `labels=["hydraflow-wiki-maintenance"]` and
  `auto_merge=False`
- adds `_poll_and_merge_open_pr(stats)` — runs every tick when an open
  PR is tracked:
    * `gh pr view --json state,reviewDecision,statusCheckRollup`
    * state MERGED/CLOSED → clear tracked state
    * CI pending → skip (next tick will retry)
    * CI failure → leave for human triage, log
    * CI success + not approved → `gh pr review --approve` with
      automation comment
    * CI success + approved → `gh pr merge --squash`, then clear state
  Every branch fails-soft so a transient gh error doesn't strand the
  PR; the next tick re-polls from GitHub's authoritative state.
- `_do_work` calls the poller before attempting to open a new PR, so
  one tick can both merge the previous cycle and emit the next.
- Module-level `_ci_rollup_state` helper collapses the statusCheckRollup
  entries to success/pending/failure.

Tests:
- `TestMaintenancePrLabeling` — asserts `hydraflow-wiki-maintenance`
  label is passed and auto_merge is False.
- `TestPollAndMergeOpenPR` — 6 new cases covering every state machine
  branch (no-op when nothing tracked, clears on already-merged, skips
  on CI pending, approve-then-merge on CI green, skip approve when
  already approved, CI failure keeps PR for human triage).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HydraOps-T-rav HydraOps-T-rav force-pushed the hydraflow/wiki-loop-prs branch from 50236e4 to 9024dd7 Compare April 19, 2026 23:03
@HydraOps-T-rav HydraOps-T-rav merged commit 4bcdf35 into main Apr 19, 2026
@HydraOps-T-rav HydraOps-T-rav deleted the hydraflow/wiki-loop-prs branch April 19, 2026 23:03
HydraOps-T-rav pushed a commit that referenced this pull request Apr 20, 2026
Phase 4 (RepoWikiLoop maintenance PR) added ``queue_drained`` to the
zero-repos early-return so admin tasks targeting freshly-migrated
repos don't pile up in the queue.  This scenario test still asserted
the pre-Phase-4 shape and broke CI on #8362 even though its source
change was from PR #8359 that already merged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HydraOps-T-rav pushed a commit that referenced this pull request Apr 20, 2026
Phase 4 (RepoWikiLoop maintenance PR) added ``queue_drained`` to the
zero-repos early-return so admin tasks targeting freshly-migrated
repos don't pile up in the queue.  This scenario test still asserted
the pre-Phase-4 shape and broke CI on #8362 even though its source
change was from PR #8359 that already merged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant