From aa68f1280e11c0a6edb71eec67bf5aaf7c9b4e0d Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:01:45 +0000 Subject: [PATCH 1/2] chore: sync 2 org-standard workflow stub(s) from petry-projects/.github --- .github/workflows/add-to-project.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index d5b20a58..1d031237 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -47,11 +47,11 @@ jobs: add-to-project: permissions: contents: read - uses: petry-projects/.github/.github/workflows/add-to-project-reusable.yml@add-to-project/v1-stable # NOSONAR(githubactions:S7637) first-party channel ref + uses: petry-projects/.github/.github/workflows/add-to-project-reusable.yml@add-to-project/v1-ring1 # NOSONAR(githubactions:S7637) first-party channel ref with: project_id: PVT_kwDOD2inqs4BZq3- project_url: https://github.com/orgs/petry-projects/projects/1 - agent_ref: add-to-project/v1-stable + agent_ref: add-to-project/v1-ring1 # Pass only the secrets the reusable declares (least privilege; avoids # `secrets: inherit` handing the reusable every org secret). secrets: From 0f7af869042e42a7d42a60dc5f566ecd8e10a624 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:01:46 +0000 Subject: [PATCH 2/2] chore: sync 2 org-standard workflow stub(s) from petry-projects/.github --- .github/workflows/initiative-driver.yml | 63 ++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/.github/workflows/initiative-driver.yml b/.github/workflows/initiative-driver.yml index b25ee1e5..5a58fa22 100644 --- a/.github/workflows/initiative-driver.yml +++ b/.github/workflows/initiative-driver.yml @@ -27,6 +27,16 @@ # sub-issues to dev-lead — so the central driver does not have to watch every # enrolled repo's events. # +# Rate-limit gate (#640): before dispatching, this stub asks the source-side +# agent-rate-limit gate (petry-projects/.github/scripts/agent-rate-limit-gate.sh) +# whether `initiative-driver` may dispatch right now. initiative-driver is the +# canary that ENFORCES: the gate derives concurrency / cooldown / daily-budget / +# consecutive-failure counters from this stub's own run history (no state +# backend), reads every threshold from standards/agent-rate-limits.json, and +# serializes a close-event + schedule burst AHEAD of the cancel-in-progress +# concurrency group so two dispatches cannot race into cancellation (#443/#402). +# A `defer` simply skips the dispatch step — never a cancel, never a job failure. +# # To adopt: # 1. Copy this file verbatim to .github/workflows/initiative-driver.yml in your repo. # 2. Ensure the `initiative:auto` label exists on the repo. @@ -76,11 +86,62 @@ jobs: GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN never starts a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN never starts a run." exit 1 fi + - name: Checkout agent-rate-limit gate tooling + # Phase-4 wiring (#640): the gate library + orchestrator live in + # petry-projects/.github; an enrolled caller stub does not carry them, so + # fetch them read-only into a scratch path. Uses the same PAT as the + # dispatch — the workflow's GITHUB_TOKEN cannot read another repo — so the + # stub's `permissions:` block is unchanged. + # continue-on-error: a tooling-checkout outage must not stop the fleet — + # the gate step then finds no script, emits no decision, and the dispatch + # step's `!= 'defer'` guard falls through to dispatching (fail-open). + continue-on-error: true + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: petry-projects/.github + ref: v1 + path: .arl-gate-tooling + fetch-depth: 1 + persist-credentials: false + token: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} + + - name: Agent rate-limit admission gate (enforcing) + # initiative-driver is the ONE canary agent type that ENFORCES (pure bash, + # no model spend, the direct #443 target — AC #5). Reads run history with + # the PAT (independent of the `permissions:` block) and emits + # decision=allow|defer to $GITHUB_OUTPUT; a defer is honoured by the `if:` + # on the dispatch step below. Fail-safe: the step can never fail the job. + continue-on-error: true + id: arl_gate + env: + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} + ARL_ACTOR: ${{ github.actor }} + ARL_TRACKING_REPO: ${{ github.repository }} + # For issue events use the event's issue number; for schedule/workflow_dispatch + # fall back to a configured repo variable so argate_escalate can post the + # breaker marker and apply the needs-human-review label (both are skipped when + # tracking_issue is empty). Set INITIATIVE_DRIVER_TRACKING_ISSUE to the epic + # or operations issue number for this repo to enable escalation on non-issue runs. + ARL_TRACKING_ISSUE: ${{ github.event.issue.number || vars.INITIATIVE_DRIVER_TRACKING_ISSUE || '' }} + run: | + set -euo pipefail + bash .arl-gate-tooling/scripts/agent-rate-limit-gate.sh initiative-driver \ + --mode enforce \ + --workflow initiative-driver.yml \ + --actor "$ARL_ACTOR" \ + --tracking-repo "$ARL_TRACKING_REPO" \ + --tracking-issue "$ARL_TRACKING_ISSUE" || true + - name: Dispatch central initiative-driver + # Skipped (clean no-op) ONLY on an explicit `defer` — never a cancel, never + # a job failure (#640, AC #1/#2). Fail-OPEN: an empty/missing decision (the + # gate step or its tooling checkout failed) still dispatches, because an + # outage of the gate must never stop the fleet (ADR §7 fail-safe direction). + if: steps.arl_gate.outputs.decision != 'defer' env: GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: |