Skip to content
Open
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
109 changes: 101 additions & 8 deletions .github/workflows/initiative-driver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# is pure-bash (no claude-code-action), so this stub dispatches the central
# workflow_dispatch DIRECTLY with `gh workflow run`. No LLM runs here.
# • You MUST NOT change: the dispatch target
# (-R combsmith/.github-private -f target_repo=${{ github.repository }}),
# (-R combsmith/.github-private -f target_repo=<this repo>),
# the `initiative:auto` label filter, or the PAT guard.
# • If you need different release behaviour, open a PR against the central
# driver in combsmith/.github-private — never by editing callers.
Expand All @@ -27,14 +27,32 @@
# 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 (combsmith/.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) and reads every threshold from standards/agent-rate-limits.json.
# It throttles dispatches that DO start (cooldown / daily budget / breaker); it
# does NOT pre-empt the cancel-in-progress concurrency group below — that group
# cancels a superseded run before any step (gate included) executes (#443/#402).
# A `defer` simply skips the dispatch step — never a cancel, never a job failure.
#
# Gate tooling is fetched at a pinned commit SHA of combsmith/.github (not
# a moving tag — the PAT is handed to that code). If the tooling is unavailable
# or the gate errors, the gate step FAILS LOUDLY (::error:: annotation + step
# summary, step marked failed) but the dispatch still runs (fail-open — an
# outage of the gate must never stop the fleet; standards/agent-rate-limits.md).
#
# 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.
# 3. Confirm the org-level secret GH_PAT_WORKFLOWS is accessible **and its
# owner has write access to combsmith/.github-private** (to dispatch
# the central workflow) **and to this repo** (the central driver applies the
# `dev-lead` label cross-repo with that PAT; a label applied with
# GITHUB_TOKEN would not trigger dev-lead).
# 3. Confirm the org-level secret GH_PAT_DON_PETRY (or the legacy fallback
# GH_PAT_WORKFLOWS) is accessible **and its owner has write access to
# combsmith/.github-private** (to dispatch the central workflow) **and
# to this repo** (the central driver applies the `dev-lead` label
# cross-repo with that PAT; a label applied with GITHUB_TOKEN would not
# trigger dev-lead).
#
# Standard: https://github.com/combsmith/.github/blob/main/standards/ci-standards.md
name: Initiative Driver — Dispatch Central
Expand Down Expand Up @@ -76,14 +94,89 @@ 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

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Checkout agent-rate-limit gate tooling
# Phase-4 wiring (#640): the gate library + orchestrator live in
# combsmith/.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, reports an ::error:: (fail loudly),
# emits no decision, and the dispatch step's `!= 'defer'` guard falls
# through to dispatching (fail-open).
# ref: pinned to an immutable commit SHA of combsmith/.github (#1232)
# — a moving tag silently lagged the gate script (v1 predates it) and
# would hand the PAT to whatever the tag next points at. Bump it in a
# reviewed PR (see standards/agent-rate-limits.md §3.1).
continue-on-error: true
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: combsmith/.github
ref: cd0b16751454d2eb3486ec04477d7ee9cc96c425 # main @ 2026-10-02 (#1232)
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 loud, fail open: a missing gate script
# or a gate error marks THIS step failed with an ::error:: (visible in the
# run), but continue-on-error keeps the job — and the dispatch — going.
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 || '' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the configured tracking issue for issue-triggered runs

On every issues trigger, the event issue number wins over INITIATIVE_DRIVER_TRACKING_ISSUE, so a breaker opened while processing a close event posts its escalation comment and needs-human-review label on the just-closed issue rather than the configured operations issue. Different close events also select different issues, preventing a single durable breaker record and scattering human-clearance markers across unrelated or closed work items. Prefer the configured tracking issue when present instead of restricting it to scheduled/manual runs.

Useful? React with 👍 / 👎.

@don-petry don-petry Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — change the template instead: this stub is synced verbatim from https://github.com/combsmith/.github/blob/main/standards/workflows/initiative-driver.yml, so a change here drifts from the template and the next sync reverts it. (The gate-side points, e.g. history source, failure-streak handling and escalation dedup, belong in the pinned gate script / template in combsmith/.github.)

run: |
set -euo pipefail
ARL_GATE_SCRIPT=.arl-gate-tooling/scripts/agent-rate-limit-gate.sh
if ! [ -f "$ARL_GATE_SCRIPT" ]; then
msg="Agent rate-limit gate NOT ENFORCED: ${ARL_GATE_SCRIPT} is missing (tooling checkout failed or the pinned ref lacks the script). Dispatching ungated (fail-open)."
echo "::error::${msg}"
echo "### :warning: ${msg}" >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
bash "$ARL_GATE_SCRIPT" initiative-driver \
--repo "$ARL_TRACKING_REPO" \
--mode enforce \
--workflow initiative-driver.yml \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Count actual dispatches instead of caller runs

Passing this workflow as the history source makes the pinned gate count every invocation— including cancelled runs and successful runs where the dispatch step was skipped—as a prior dispatch for both cooldown and the 20-per-day budget. For example, a burst of 20 issue events can exhaust the daily budget even if only one central dispatch occurred, after which later dependency-unblocking events are deferred for up to 24 hours. The history used for admission needs to distinguish runs that reached the central dispatch from gate-only attempts.

Useful? React with 👍 / 👎.

@don-petry don-petry Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — change the template instead: this stub is synced verbatim from https://github.com/combsmith/.github/blob/main/standards/workflows/initiative-driver.yml, so a change here drifts from the template and the next sync reverts it. (The gate-side points, e.g. history source, failure-streak handling and escalation dedup, belong in the pinned gate script / template in combsmith/.github.)

--actor "$ARL_ACTOR" \
--tracking-repo "$ARL_TRACKING_REPO" \
--tracking-issue "$ARL_TRACKING_ISSUE" || {
Comment on lines +157 to +160

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Forward triggering issue labels to the admission gate

For a close event on a security-labeled issue, or when initiative:auto is added to an issue that already has the security label, this invocation passes the actor but not the event issue's labels. The pinned gate therefore cannot apply its configured security-label exemption and may defer a run that its policy says must never be blocked. Pass the triggering issue labels through the gate's --labels option.

Useful? React with 👍 / 👎.

@don-petry don-petry Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — change the template instead: this stub is synced verbatim from https://github.com/combsmith/.github/blob/main/standards/workflows/initiative-driver.yml, so a change here drifts from the template and the next sync reverts it. (The gate-side points, e.g. history source, failure-streak handling and escalation dedup, belong in the pinned gate script / template in combsmith/.github.)

Comment on lines +159 to +160

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent duplicate circuit-breaker escalation comments

Enabling --tracking-issue activates the pinned gate's per-agent escalation path, but that implementation checks only the issue body for its deduplication marker and then writes the marker into a comment. Consequently the marker is never found on a later breaker opening, so each opening posts another identical comment even if the prior escalation has not been cleared. The pinned gate should inspect existing comments, as its token-budget escalation path already does, before this caller enables issue escalation.

Useful? React with 👍 / 👎.

@don-petry don-petry Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — change the template instead: this stub is synced verbatim from https://github.com/combsmith/.github/blob/main/standards/workflows/initiative-driver.yml, so a change here drifts from the template and the next sync reverts it. (The gate-side points, e.g. history source, failure-streak handling and escalation dedup, belong in the pinned gate script / template in combsmith/.github.)

rc=$?
echo "::error::Agent rate-limit gate errored (exit ${rc}) — dispatching ungated (fail-open)."
echo "### :warning: Agent rate-limit gate errored (exit ${rc}) — dispatching ungated (fail-open)." >> "$GITHUB_STEP_SUMMARY"
exit "$rc"
}

- 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'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the failure streak when a dispatch is deferred

When the circuit breaker opens after consecutive failures, this condition skips the dispatch but leaves the workflow run successful. The pinned gate computes its next failure streak from this workflow's conclusions and stops at the most recent success, so that successful no-op immediately clears the breaker; the following attempt can dispatch after the shorter cooldown instead of respecting the configured 30-minute breaker backoff. Deferred runs need a conclusion or history marker that does not reset the dispatch failure streak.

Useful? React with 👍 / 👎.

@don-petry don-petry Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — change the template instead: this stub is synced verbatim from https://github.com/combsmith/.github/blob/main/standards/workflows/initiative-driver.yml, so a change here drifts from the template and the next sync reverts it. (The gate-side points, e.g. history source, failure-streak handling and escalation dedup, belong in the pinned gate script / template in combsmith/.github.)

env:
GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }}
# Pass github.repository via env (not inline template expansion) to keep
# the workflow expression out of shell text (zizmor template-injection).
# The dispatch target value is unchanged — target_repo is still this repo.
TARGET_REPO: ${{ github.repository }}
run: |
gh workflow run initiative-driver.yml \
-R combsmith/.github-private \
-f target_repo=${{ github.repository }}
-f target_repo="${TARGET_REPO}"
Loading