원클릭으로
prj-discover
// PR Jangler GitHub-to-queue sync. Use when the orchestrator dispatches the discovery sweep (on cadence or empty queue) or when the user runs 'prj-discover' for manual debug.
// PR Jangler GitHub-to-queue sync. Use when the orchestrator dispatches the discovery sweep (on cadence or empty queue) or when the user runs 'prj-discover' for manual debug.
PR Jangler hub. Cron-driven autonomous workflow for triaging, verifying, reviewing, fix-planning, adversarially validating, fix-implementing, deciding, and daily-reporting on a GitHub PR backlog. Use when the user mentions "PR jangler", "pr-jangler", "PR backlog workflow", "PR triage", "autonomous PR review", "fix-plan", "fix-PR", "adversarial validator", "PleaseAdvise", or wants to install, configure, or extend the PR Jangler BMad module. Routes to 12 phase skills, owns the cross-cutting state-file conventions, idempotency rules, GitHub-label vocabulary, and 1Password/SMTP/`gh`/`op` dependency map shared by every phase. Triggers on prj-setup, prj-orchestrator, prj-discover, prj-triage, prj-verify-claim, prj-review, prj-detect-overlap, prj-plan-fix, prj-validate-adversarial, prj-implement-fix, prj-decision, prj-report-daily.
PR Jangler final-call workflow. Use when the orchestrator dispatches the decision phase for a reviewed PR or when the user runs 'prj-decision' to label, comment, and log a ready-to-merge / request-changes / close-as-not-now verdict.
PR Jangler duplicate and overlap detector. Use when the orchestrator dispatches the overlap check after triage marked a PR as possible-duplicate, or when the user runs 'prj-detect-overlap' for manual debug.
PR Jangler Tier-2 implementer. Use when prj-validate-adversarial passed for a PR and the orchestrator dispatches FixImpl. Pushes a fix branch and opens a fix-PR into the contributor's branch; falls back to a comment if the contributor's branch refuses PRs.
PR Jangler cron heartbeat dispatcher. Use when cron invokes one heartbeat of the PR backlog workflow or when the user runs 'prj-orchestrator' for manual debug.
PR Jangler fix-planning workflow. Use when a Trello-like comment claim on a PR has been verified by prj-verify-claim and a fix plus failing-test plan must be designed before any implementation. Activated by prj-orchestrator when a PR's phase is FixPlan.
| name | prj-discover |
| description | PR Jangler GitHub-to-queue sync. Use when the orchestrator dispatches the discovery sweep (on cadence or empty queue) or when the user runs 'prj-discover' for manual debug. |
This skill is the GitHub-state synchronizer for the PR Jangler module. One invocation reads the configured prj_repo via gh, diffs its open-PR set against the persisted queue at {project-root}/_bmad-output/pr-workflow/state.json, and writes back additive changes: new PRs land at phase Discovered, closed PRs flip to Archived, fresh comments bump new_comments_since_triage and queue a prj-triage --mode comment follow-up, and PRs idle longer than 14 days get needs_retriage: true. Per-PR cache directories are created on first discovery with a meta.json snapshot. Rate-limit aware: defers cleanly if GitHub's core quota dips below 100 remaining.
Act as a careful diffing librarian. Never silently drop a PR or a comment. Treat additive writes as the contract: existing phases are only flipped to Archived (closed upstream) or annotated with needs_retriage (idle); the rest of the state machine is owned by the phase skills.
scripts/run.py) resolve from the skill root.{project-root}/... resolves from the project working directory.[modules.prj] in {project-root}/_bmad/config.toml.prj-orchestrator's state_io module (imported via sys.path); this skill never touches state.json directly.Load configuration from {project-root}/_bmad/config.toml (the [modules.prj] block). The required key is prj_repo (owner/name). If absent, exit early with status misconfigured and a clear run-log entry; do not call gh.
Execute the sweep:
python3 scripts/run.py
That single script handles the full sweep: rate-limit check, gh calls, reconciliation, atomic state save, per-PR cache creation, run-log append. Flags:
--dry-run compute the diff and log the would-be changes, do not write state or cache--verbose emit progress diagnostics to stderr--project-root <path> override autodetectSee python3 scripts/run.py --help for full detail.
Three Python modules, each with a single concern. Determinism lives in the scripts; the LLM activation context exists so the orchestrator's Skill-tool dispatch resolves cleanly when the cadence fires.
| Concern | Lives in |
|---|---|
| Shared state I/O (atomic load, validate, save, runlog) | state_io (imported from prj-orchestrator/scripts) |
gh CLI wrapping: list, view, diff-stats, rate-limit | scripts/gh_client.py |
| Pure-function reconciliation (state-vs-GitHub diff) | scripts/reconcile.py |
| Orchestration: config, sweep, cache writes, runlog | scripts/run.py |
The sibling import is intentional: state ownership belongs to prj-orchestrator, and rewriting it here would fork the contract.
This skill writes to:
{project-root}/_bmad-output/pr-workflow/state.json (via state_io.save_state, atomic){project-root}/_bmad-output/pr-workflow/prs/{pr_number}/meta.json (created on first discovery; never overwritten silently after that){project-root}/_bmad-output/pr-workflow/logs/{YYYY-MM-DD}.jsonl (append-only run-log)This skill reads from:
{project-root}/_bmad/config.toml (config){project-root}/_bmad-output/pr-workflow/state.json (prior queue state)gh (open PRs, comment payloads, diff stats, rate-limit)Codified in scripts/reconcile.py; summarized here for activation review.
phase: "Discovered", contributor_login from author.login, next_action: {skill: "prj-triage", mode: "pr"}, seen_comment_ids set to whatever ids the PR already carries.new_comments_since_triage is bumped by the delta count; last_action_at advances. If the PR's phase is past initial triage (anything other than Discovered or Triaged), next_action flips to {skill: "prj-triage", mode: "comment"}. Otherwise the existing prj-triage --mode pr action wins.Archived, next_action → null. Skill skips PRs already at Archived.last_action_at older than 14 days) — needs_retriage: true set. The orchestrator picks up the flag on the next heartbeat via its existing priority bump.Before any other gh call, the script invokes gh api rate_limit and reads resources.core.remaining. If remaining < 100, the sweep is deferred: a run-log entry with status: "deferred-rate-limit" is appended, state is left untouched, and the script exits 0. The orchestrator's next cadence fire will retry.
state_io.save_state. Direct file writes to state.json are forbidden.Smoke-test against a configured project (requires gh auth):
python3 scripts/run.py --dry-run --verbose
Expected on a fresh project with PRs open: exit 0, run-log entry with status: "dry-run", report.new_prs listing every open PR number. No state changes on disk.
Run the unit tests (no gh calls; all subprocess invocations mocked):
python3 -m unittest discover scripts/tests