Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/pr-review-fix-scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ on:
retry_hours:
description: Minimum hours before redispatching autofix for the same head
required: false
default: "24"
default: "1"
type: string
autofix_workflow:
description: Autofix workflow file to dispatch
Expand All @@ -51,7 +51,10 @@ on:
repository_dispatch:
types: [pr-review-fix-scheduler]
schedule:
- cron: "23 */2 * * *"
# One bounded repair dispatch per hourly sweep. The head-scoped marker and
# single-flight concurrency contract prevent duplicate work while allowing
# a failed or incomplete repair to be retried on the next hourly cycle.
- cron: "23 * * * *"

concurrency:
group: central-pr-review-fix-scheduler-${{ github.event.client_payload.target_repository || inputs.target_repository || vars.PR_REVIEW_FIX_TARGET_REPOSITORY || github.repository }}
Expand Down Expand Up @@ -80,7 +83,7 @@ jobs:
DRY_RUN: ${{ github.event.client_payload.dry_run == true || github.event.client_payload.dry_run == 'true' || inputs.dry_run == true }}
MAX_PRS: ${{ github.event.client_payload.max_prs || inputs.max_prs || '50' }}
MAX_DISPATCHES: ${{ github.event.client_payload.max_dispatches || inputs.max_dispatches || '1' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '24' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '1' }}
AUTOFIX_WORKFLOW: pr-review-autofix.yml
AUTOFIX_REPOSITORY: ContextualWisdomLab/.github
CANONICAL_REF: main
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Semantic Versioning where the repository publishes a release.

### Fixed

- Changed the bounded review-feedback repair scheduler from every two hours to every hour and made its exact-head redispatch default one hour, while retaining one-dispatch limits, head-scoped markers, and single-flight concurrency.
- Bounded the Strix quality self-test's deterministic timeout fixtures to 3-second process and 5-second fake-sleep budgets so exact-head policy evidence completes inside the existing job limit without changing production Strix scanner timeouts, providers, credentials, or review semantics.
- Allowed commas and ASCII parentheses in the bounded Strix changed-file path policy so legal tracked Packrat fixtures can receive exact-head security analysis, while rejecting raw `..` components before normalization and keeping controls, backslashes, whitespace ambiguity, and shell punctuation fail-closed.
- Bound each review-agent invocation key to the wrapper's complete canonical payload, including the base branch and requesting actor; altered fields with a valid-format key now fail before durable-leader election or forwarding, and wrapper write permission is job-scoped.
Expand Down
31 changes: 31 additions & 0 deletions tests/test_pr_review_fix_scheduler_workflow_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Workflow-level contract for the bounded PR review repair scheduler."""

from pathlib import Path


WORKFLOW = Path(".github/workflows/pr-review-fix-scheduler.yml")


def workflow_text() -> str:
"""Return the canonical workflow source used by the scheduler."""

return WORKFLOW.read_text(encoding="utf-8")


def test_review_fix_scheduler_runs_once_per_hour() -> None:
"""Every open-PR queue receives a fixed hourly repair opportunity."""

text = workflow_text()
assert 'cron: "23 * * * *"' in text
assert 'cron: "23 */2 * * *"' not in text


def test_same_head_autofix_retry_default_is_one_hour() -> None:
"""A failed or incomplete repair can be retried on the next hourly sweep."""

text = workflow_text()
retry_block = text.split("retry_hours:", maxsplit=1)[1].split(
"autofix_workflow:", maxsplit=1
)[0]
assert 'default: "1"' in retry_block
assert "inputs.retry_hours || '1'" in text
Loading