Org-level repo holding:
- Org profile (
profile/README.md) - what GitHub renders on the org page. - Org-default issue templates (
.github/ISSUE_TEMPLATE/) - applied to any repo without local templates. - Cross-repo orchestrators - workflows that fan out across downstream repos listed in
repos.yaml. Every orchestrator resolves its target set through the shared.github/actions/resolve-targetscomposite action (oneyqread + a jqselect+ an optional single-targetrepositoryinput), and every fan-out workflow defaults todry_run: trueon manual dispatch. The families:- Sync orchestrators - audit downstream repos and file structured drift issues for human review:
sync-sdks.ymlaudits each SDK and the docs site against the canonical OpenAPI spec ininference-gateway/schemas.sync-adks.ymlaudits each ADK against the canonical A2A JSON-RPC schema ininference-gateway/schemas.
- Agent orchestrators - mechanical fan-out across
kind: agenttargets:bump-adl.ymlbumps every agent's ADL CLI pin to a given version, regenerates, and opens one PR per agent.refresh-agent-manifest.ymladditively merges newadl initdefaults into each agent'sagent.yaml(one PR per agent).trigger-cd.ymldispatches each agent's owncd.ymlto cut releases (fire-and-forget).
- Lifecycle orchestrators - cross-repo maintenance across
repos.yamltargets (stale.ymlsweeps every target except thekind: noneinfra repos,select(.kind != "none");cleanup-runs.ymlandbackfill-roadmap.ymlsweep every registered target,select(true), includingkind: none):stale.ymlmarks issues with no activity for 30 days asstaleand closes them 7 days later.cleanup-runs.ymlprunes completed workflow runs by conclusion (defaultskipped- the noiseinfer-action/claude-code-actionleave on every issue event;skipped,failurealso drops failed-run logs), with an optionalkeep_lastper-repo retention floor, from each target's Actions tab, daily.backfill-roadmap.ymladds open issues that are on no project board to the org Roadmap 2026 board (project #7) at StatusTodo, so issues filed outside the@claude/@inferflow are not lost off the roadmap.
- Migration (one-shot) -
migrate-claude.ymlrewrites each repo's.github/workflows/claude.ymlinto a thin caller of the org reusableclaude.yml, reading its inputs from that entry'sorchestrators.claudeblock (select(.orchestrators.claude != null)), and in the same PR also bumps the target's own Floxclaude-codepin (.flox/env/manifest.toml) to the latest flox catalog version, isolatesclaude-codein its ownpkg-group = "claude-code"(so the bumped floor resolves independently ofcodex- a sharedaigroup made the constraints unsatisfiable), and refreshes the lock - noteclaude-codeis a flox catalog package (claude-code.version = "^X.Y.Z"), not a GitHub release, so the latest comes fromflox show claude-code(never npm, which can be ahead of the catalog), and there is no config-regen step - soflox activate -- trueruns explicitly afterflox upgrade claude-codepurely to writemanifest.lockin its canonical form. Its PR title names the moves -chore(deps): bump claude-code X -> Y, claude-code-action vA -> vB(claude-code-action read from the reusableclaude.ymlat the caller's old vs. new ref) - falling back toci: centralize claude.yml via reusable workflow.migrate-infer.ymldoes the same for.github/workflows/infer.ymlagainst the org reusableinfer.yml, reading that entry'sorchestrators.inferblock (select(.orchestrators.infer != null)), and in the same PR also bumps the target's own Floxinferpin (.flox/env/manifest.toml) to the latestinference-gateway/clirelease, refreshes the lock, and regenerates the committed.infer/config withinfer init --overwriteusing that CLI (preserving.infer/agents.yamland.infer/mcp.yaml) - mirroring howbump-adl.ymlbumps each agent's adl-cli pin. The migrate-infer PR title names the actual version moves -chore(deps): bump infer CLI vX -> vY, infer-action vA -> vB- listing only the component(s) that changed (infer-action is read from the reusableinfer.ymlat the caller's old vs. new ref), and falls back toci(infer): centralize infer.yml + sync .infer configwhen no version moved. Both operate on every repo that defines the matching block. - Dependency bumps (standalone) -
bump-codex.ymlbumps every codex-bearing target's Floxcodexpin (.flox/env/manifest.toml) to the latest flox catalog version, isolatescodexin its ownpkg-group = "codex", and refreshes the lock - one PR per repo. It selectsselect(.kind != "agent"):codexis a local-authoring CLI present in every non-agent repo but absent from the adl-generated agent envs. Likebump-adl.ymlit opens PRs (mechanical, reviewable); likemigrate-claude.yml'sclaude-codebump the latest comes fromflox show codex(a catalog package, not a GitHub release) and it runsflox upgrade codex+flox activate -- trueto canonicalizemanifest.lock. Unlike the migrations there is no thin caller to write and no config to regenerate - it touches only.flox/env/*. PR titlechore(deps): bump codex X -> Y, orci: isolate codex in its own flox pkg-groupwhen only the group moves.
- Sync orchestrators - audit downstream repos and file structured drift issues for human review:
schemas (openapi.yaml)
│ push to main → repository_dispatch (event_type: spec-updated)
▼
.github/workflows/sync-sdks.yml
│ reads repos.yaml (kind: sdk | docs), fans out matrix
▼
claude-code-action (one per target)
│ reads spec + target tree, detects drift,
│ files structured [FEATURE] / [TASK] issues
▼
issues on python-sdk / typescript-sdk / rust-sdk / sdk / docs
│
▼
maintainer reviews each issue and decides next steps
schemas (a2a/a2a-schema.yaml)
│ push to main → repository_dispatch (event_type: a2a-spec-updated)
▼
.github/workflows/sync-adks.yml
│ reads repos.yaml (kind: adk), fans out matrix
▼
claude-code-action (one per target)
│ reads schema + target tree, detects drift,
│ files structured [FEATURE] / [TASK] issues
▼
issues on adk / rust-adk (typescript-adk added once the repo exists)
│
▼
maintainer reviews each issue and decides next steps
Key invariants for the sync orchestrators (do not apply to the agent orchestrators below):
- Each sync orchestrator inlines the org's issue-filing mechanics directly in its prompt - the stable drift titles and labels, the Bug/Feature/Task Issue Type id table, and the
updateIssueIssueTypemutation. No skill is installed; the prompt is self-contained. - The orchestrator only files issues. It never opens PRs, never mentions
@claude, and never modifies any code on the target repos. - Issues are notifications. A human reviews each and decides whether to implement, defer, or close.
- One GitHub App (
inference-gateway-maintainer-bot) provides cross-repo auth -issues:writeon the target +contents:readon the target andschemas. No PATs. - Adding or removing a target is one PR to
repos.yaml(a singletargetslist). Thekindfield (sdk,docs,adk,agent,none) routes the row to the right workflow; an optional nestedorchestrators:block carries the reusable-workflow inputs -orchestrators.claudemarks the repo formigrate-claude.yml,orchestrators.inferformigrate-infer.yml.
maintainer runs: gh workflow run bump-adl.yml -f adl_version=vX.Y.Z
│
▼
.github/workflows/bump-adl.yml
│ reads repos.yaml (kind: agent), fans out matrix
▼
per-agent job (one per agent):
│ mints scoped App token, checks out target into ./target/,
│ installs Flox + go-task, edits .flox/env/manifest.toml,
│ runs `flox upgrade adl` + `flox activate -- task generate`,
│ patches headers in .adl-ignore'd files, asserts agent.yaml is unchanged
▼
peter-evans/create-pull-request opens (or updates) a PR titled
`chore(deps): bump ADL CLI to vX.Y.Z` on branch `bot/bump-adl-cli-vX.Y.Z`
│
▼
maintainer reviews each PR and merges
Deliberate deviation from the sync orchestrators: this workflow opens PRs, because ADL CLI bumps are mechanical and reviewable, not judgment calls.
maintainer runs: gh workflow run trigger-cd.yml [-f ref=main]
│
▼
.github/workflows/trigger-cd.yml
│ reads repos.yaml (kind: agent), fans out matrix
▼
per-agent job: gh workflow run cd.yml --repo inference-gateway/<agent> --ref <ref>
│
▼
each agent's own cd.yml runs semantic-release independently
Fire-and-forget: this orchestrator does not wait for the dispatched releases to finish or report their outcomes back. Watch each agent's Actions tab for outcomes.
cron: '15 3 * * *' (daily, manual via workflow_dispatch with -f dry_run=true)
│
▼
.github/workflows/stale.yml
│ reads repos.yaml (select(.kind != "none")), fans out matrix
▼
per-target job:
│ mints a per-target scoped App token
│ step 1: gh issue list updated:<30d -label:stale (minus exempt) → add `stale` label + warning comment
│ step 2: gh issue list label:stale updated:<7d → close with comment
▼
issues across every target in repos.yaml
Distinct from the sync/agent orchestrators:
- Filter is
select(.kind != "none"). Every product target (sdk/docs/adk/agent) is swept; the infra/tooling repos (kind: none-cli,operator,registry,inference-gateway,adl, ...) are intentionally excluded so their issues are not auto-staled. Adding or removing a product target from the sweep = the same single PR torepos.yamlthat already routes it to its sync or agent workflow. - Cannot use
actions/staledirectly - that action is hard-coded to operate ongithub.context.repo(the runner's own repo) and has no foreign-repo input. The orchestrator does the equivalent withgh issuecalls against the matrix target. - Exempt labels:
pinned,security(human override), andsdk-drift,adk-drift,docs-coverage(long-lived drift trackers filed by the sync orchestrators - they may legitimately sit open while a maintainer triages). - Dry-run support: defaults to
dry_run: trueon manual dispatch (prints the planned mark/close set per repo without modifying anything); the daily cron sweeps for real.-f repository=<name>narrows to one target. - Issues only. PRs are intentionally left alone.
Out-of-scope repos (kind: none entries, plus anything not in repos.yaml such as awesome-a2a) are not swept by this workflow.
cron: '0 6 * * *' (daily, disabled until validated; manual via workflow_dispatch, dry_run previews)
│
▼
.github/workflows/cleanup-runs.yml
│ reads repos.yaml (select(true) - all registered targets, incl. kind: none), fans out matrix
▼
per-target job:
│ mints a per-target scoped App token (actions: write)
│ list: gh api 'repos/inference-gateway/<target>/actions/runs?status=completed' --paginate
│ rank: jq protect newest keep_last repo-wide (live wfs) -> prune dead wfs in full -> filter conclusions
│ delete: gh api -X DELETE 'repos/inference-gateway/<target>/actions/runs/<id>' (re-checked)
▼
each target's Actions tab is pruned per the active filters
Why these runs exist: inference-gateway/infer-action (@infer) and anthropics/claude-code-action (@claude) trigger on every issues / issue_comment event, then their job hits a job-level if: guard and skips when the trigger phrase is absent. GitHub records each as status: completed, conclusion: skipped and has no native auto-prune, so they pile up and bury meaningful runs in every Actions tab.
Distinct from stale.yml (the other lifecycle orchestrator):
- Acts on workflow runs, not issues. Deletes completed runs whose
conclusionis in theconclusionsinput (defaultskipped; e.g.skipped,failureto also drop failed-run logs and shrink the secret-leak surface;allfor any conclusion).keep_lastprotects the newest N runs across the repo (regardless of workflow), so a recent tail survives while the rest is pruned. Lists?status=completedsokeep_lastcan rank every run, then filters in jq; a per-run re-check re-confirmsstatus: completedandconclusion ∈ setbefore each delete. keep_lastonly protects live workflows. The step first listsactions/workflows(the IDs whose file still exists) and applies the retention floor only to those. Runs of a deleted or renamed workflow (aworkflow_idno longer backed by a file) are pruned in full - otherwise a retired pipeline's history would sit behindkeep_lastforever.- Fails loud, resumes idempotently. All matrix jobs mint from one App installation (a single 5,000-req/hr bucket), so a large
conclusions=allpurge across many repos can exhaust it mid-sweep. A rate-limit 403 on the run/workflow listing used to surface as a falsefound 0and a green check (themapfile < <(...)process substitution hid the non-zero exit fromset -e); it now fails the job with an::error::and the leftover count. Because deletes are idempotent, just rerun (or wait for the daily cron) to continue - and prefer-f repository=<name>to purge one repo at a time within the shared budget. - Broader matrix than
stale.yml. Resolvesselect(true)- every registeredrepos.yamltarget, including thekind: noneinfra repos (inference-gateway,cli,operator,registry, ...), which accumulate the same skipped@claude/@inferruns. This intentionally diverges fromstale.yml(which exemptskind: noneso infra issue trackers are not auto-staled). Private repos are never registered inrepos.yaml, so they are excluded by construction; repos absent fromrepos.yaml(.github,agents,awesome-a2a,tools) are untouched. - Destructive, so
dry_rundefaults totrueon manual dispatch.gh workflow run cleanup-runs.yml -f dry_run=falseactually deletes; the daily cron deletes by design. A per-targetMAX_DELETEScap bounds one run and logs a::warning::with the leftover count when reached (leftovers handled on the next run). - Schedule disabled on landing. The
schedule:block ships commented out (asstale.ymldid); enable it once validated on one repo.
Testing on one repo (AC#3): the repository input narrows the matrix to a single target so the sweep can be validated on one Actions tab first:
# preview one repo (default: skipped-only, no retention)
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f dry_run=true -f repository=docs
# preview pruning skipped + failed runs while keeping the newest 5 in the repo
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f dry_run=true -f repository=docs -f conclusions=skipped,failure -f keep_last=5
# delete on that one repo, then check its Actions tab
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f dry_run=false -f repository=docscron: '30 4 * * *' (daily, disabled until validated; manual via workflow_dispatch, dry_run previews)
│
▼
.github/workflows/backfill-roadmap.yml
│ reads repos.yaml (select(true) - all registered targets, incl. kind: none and kind: agent), fans out matrix
▼
per-target job:
│ mints a per-target scoped App token (org Projects: read & write rides along)
│ list: gh issue list --state open --json projectItems -> keep issues whose projectItems == [] (on no board)
│ add: gh project item-add 7 --owner inference-gateway --url <issue> (idempotent)
│ status: gh project item-edit ... --single-select-option-id <Todo>
▼
every open issue that was on no project board is now on Roadmap 2026 (project #7) at Status Todo
Why this exists: an issue lands on the org Roadmap 2026 board (project #7) only when an @claude / @infer run touches it (claude.yml / infer.yml add the worked issue and advance its Status). Issues filed directly by a human, or before board tracking existed, never reach the board and are invisible to anyone planning off it. This sweep reconciles that gap so planned work spread across repos is never lost off the roadmap.
Distinct from the other lifecycle orchestrators:
- Adds issues to a board; never edits or closes them. For each target it lists open issues on no project board and adds them to project #7 at Status
Todofor a human to triage. It does not touch issues already tracked anywhere and never setsIn progress/QA/Done(those stay owned by the@claude/@inferflow and by merges). - "On no board" = empty
projectItems, not "not on #7". The filter is the issue's ProjectsV2 membership (gh issue list --json projectItems, keep length 0). The maintainer App's org-level Projects: read grant letsprojectItemssee every org board, so an issue already on #7 or any other org board is left alone. There is deliberately no prefetch of #7's items (that would answer the narrower "not on #7" and re-add issues tracked elsewhere). Classic Projects (projectCards, shut down 2024-2025) is always empty now and is not checked. - Broad matrix, like
cleanup-runs.yml. Resolvesselect(true)- every registeredrepos.yamltarget, including thekind: noneinfra andkind: agentrepos (orphan issues can live anywhere). Private repos and repos absent fromrepos.yaml(.github,agents,awesome-a2a,tools) are untouched. Issues only (gh issue listexcludes PRs); open only. - Idempotent, so safe to rerun.
gh project item-add 7on an issue already on #7 returns the existing item id (exit 0); re-runs are no-ops and theprojectItemsfilter shrinks the candidate set each run. A per-targetMAX_ADDScap bounds one run and logs a::warning::with the leftover count (next run continues). The issue listing is rate-limit aware and fails the job on a 403 rather than reporting a falsefound 0. dry_rundefaults totrueon manual dispatch.-f dry_run=falseadds for real; theschedule:block (cron30 4 * * *, staggered offstale.ymlandcleanup-runs.ymlto share the 5,000-req/hr bucket) ships commented out until validated on one repo.
Testing on one repo: the repository input narrows the matrix to a single target so the backfill can be validated before it runs fleet-wide:
# preview one repo (lists the orphan open issues it would add)
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github -f dry_run=true -f repository=cli
# add that one repo's orphans to project #7 at Status Todo, then check the board
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github -f dry_run=false -f repository=clicodex is a local-authoring CLI (like claude-code and infer), not a bot or an adl-generated dependency, so its bump is a standalone fan-out that touches only .flox/env/* - no thin caller, no config regen.
maintainer runs: gh workflow run bump-codex.yml [-f codex_version=X.Y.Z] -f dry_run=false
│
▼
.github/workflows/bump-codex.yml
│ matrix job: `flox show codex` -> latest catalog version,
│ reads repos.yaml (select(.kind != "agent")), fans out matrix
▼
per-target job (one per codex-bearing repo):
│ mints scoped App token, checks out target into ./target/,
│ installs Flox, sed's codex.version floor to ^X.Y.Z and isolates
│ codex in its own pkg-group "codex",
│ runs `flox upgrade codex` + `flox activate -- true`
▼
peter-evans/create-pull-request opens (or updates) a PR titled
`chore(deps): bump codex X -> Y` on branch `bot/bump-codex-X.Y.Z`
│
▼
maintainer reviews each PR and merges
Mirrors migrate-claude.yml's claude-code flox bump - catalog package, latest from flox show, pkg-group isolation so the raised floor resolves independently of co-resident packages, flox activate -- true to write manifest.lock in canonical form - minus the thin-caller render. Matrix is select(.kind != "agent"): codex ships in every non-agent repo but is absent from the adl-generated kind: agent envs. Idempotent: a repo already at the latest caret floor in its own group produces no diff and opens no PR; a repo already at the latest version but still in the shared ai group gets a group-only PR titled ci: isolate codex in its own flox pkg-group. Like bump-adl.yml it opens PRs (mechanical, reviewable) and defaults dry_run: true.
.github/
actions/
resolve-targets/ # composite action: repos.yaml + jq select -> matrix
ISSUE_TEMPLATE/ # org-default issue templates (feature, refactor, bug, documentation)
workflows/
sync-sdks.yml # SDK + docs audit against OpenAPI (kind: sdk | docs)
sync-adks.yml # ADK audit against A2A schema (kind: adk)
bump-adl.yml # ADL CLI version bump fan-out (kind: agent)
refresh-agent-manifest.yml # additive agent.yaml defaults refresh (kind: agent)
trigger-cd.yml # release fan-out (kind: agent)
migrate-claude.yml # write claude.yml thin caller + bump claude-code Flox pin (select(.orchestrators.claude != null))
migrate-infer.yml # write infer.yml thin caller + regenerate .infer config (select(.orchestrators.infer != null))
bump-codex.yml # codex CLI Flox-pin bump fan-out (select(.kind != "agent"))
stale.yml # stale-issue sweep (select(.kind != "none"))
cleanup-runs.yml # prune completed runs by conclusion/retention (select(true) - all registered targets, incl. kind: none)
backfill-roadmap.yml # add orphan open issues to Roadmap 2026 / project #7 at Status Todo (select(true))
claude.yml # reusable @claude workflow (workflow_call)
infer.yml # reusable @infer workflow (workflow_call)
repos.yaml # single downstream registry - drives every matrix
profile/ # GitHub-rendered org profile
Once the GitHub App secrets (INFERENCE_GATEWAY_MAINTAINER_APP_ID, INFERENCE_GATEWAY_MAINTAINER_APP_PRIVATE_KEY) and the org-standard CLAUDE_CODE_OAUTH_TOKEN are provisioned:
Every fan-out workflow below defaults to dry_run: true on manual dispatch (safe preview). Add -f dry_run=false to act for real and -f repository=<name> to run on a single target first.
# Sync orchestrators (audit against current schemas main HEAD; spec-updated events file for real):
gh workflow run sync-sdks.yml --repo inference-gateway/.github # dry, all sdk/docs
gh workflow run sync-sdks.yml --repo inference-gateway/.github -f dry_run=false -f repository=python-sdk # file for real, one repo
gh workflow run sync-adks.yml --repo inference-gateway/.github
# Agent orchestrators:
gh workflow run bump-adl.yml --repo inference-gateway/.github -f adl_version=vX.Y.Z # dry preview
gh workflow run bump-adl.yml --repo inference-gateway/.github -f adl_version=vX.Y.Z -f dry_run=false # open PRs
gh workflow run refresh-agent-manifest.yml --repo inference-gateway/.github -f adl_version=vX.Y.Z
gh workflow run trigger-cd.yml --repo inference-gateway/.github -f dry_run=false # dispatch cd.yml on all agents
# Migration (one-shot):
gh workflow run migrate-claude.yml --repo inference-gateway/.github -f repository=cli # dry, one repo
gh workflow run migrate-claude.yml --repo inference-gateway/.github -f dry_run=false # open PRs for all
# (also bumps each target's own .flox/env/manifest.toml claude-code pin to the latest flox catalog version)
gh workflow run migrate-infer.yml --repo inference-gateway/.github -f repository=cli # dry, one repo
gh workflow run migrate-infer.yml --repo inference-gateway/.github -f dry_run=false # open PRs for all
# (bumps each target's own .flox/env/manifest.toml infer pin to the latest inference-gateway/cli release)
# Dependency bumps (codex CLI Flox pin across non-agent repos):
gh workflow run bump-codex.yml --repo inference-gateway/.github -f repository=cli # dry, one repo
gh workflow run bump-codex.yml --repo inference-gateway/.github # dry, all codex-bearing targets
gh workflow run bump-codex.yml --repo inference-gateway/.github -f dry_run=false # open PRs for all (latest codex)
# Lifecycle orchestrators (cron runs for real; manual previews by default):
gh workflow run stale.yml --repo inference-gateway/.github -f dry_run=false # sweep for real
gh workflow run cleanup-runs.yml --repo inference-gateway/.github # dry, all targets, skipped-only
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f dry_run=false -f repository=docs # delete skipped on one target
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f conclusions=skipped,failure -f keep_last=5 # dry: prune skipped+failed, keep newest 5 repo-wide
gh workflow run cleanup-runs.yml --repo inference-gateway/.github -f conclusions=all -f keep_last=5 # dry: keep only newest 5 in the repo, prune the rest
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github -f repository=cli # dry, one repo: list orphan open issues
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github # dry, all targets
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github -f dry_run=false -f repository=cli # add one repo's orphans to project #7 (Status=Todo)
gh workflow run backfill-roadmap.yml --repo inference-gateway/.github -f dry_run=false # backfill all targets for realFor SDK targets the workflow uses each SDK's own task oas-download to pull the canonical openapi.yaml. For docs it fetches raw from inference-gateway/schemas. For ADK targets the workflow uses each ADK's own task a2a:download-schema to pull the canonical a2a/a2a-schema.yaml. Both sync workflows always audit against current main of schemas.
Before the orchestrators can run end-to-end, the following pieces need to land separately:
- GitHub App
inference-gateway-maintainer-botprovisioned and installed on every target listed inrepos.yaml. ItsINFERENCE_GATEWAY_MAINTAINER_APP_ID(client ID) andINFERENCE_GATEWAY_MAINTAINER_APP_PRIVATE_KEYsaved as repo or org secrets, plusCLAUDE_CODE_OAUTH_TOKENfor the Claude Code Max subscription auth. The reusable@claudeand@inferworkflows (claude.yml,infer.yml) both mint a maintainer-App token from theINFERENCE_GATEWAY_MAINTAINER_APP_ID/INFERENCE_GATEWAY_MAINTAINER_APP_PRIVATE_KEYsecret pair (the identity the agent'sghruns as; the App needsissues: write,contents: write,pull-requests: writeon every target it runs on, plus org-level Projects: Read and write - see the per-workflow bullets below).infer.ymladditionally forwards the provider API-key secrets toinfer-action(DEEPSEEK_API_KEYcovers the defaultdeepseek/deepseek-v4-flashmodel;ANTHROPIC_API_KEY,OPENAI_API_KEY,GOOGLE_API_KEY,GROQ_API_KEY,MISTRAL_API_KEY,CLOUDFLARE_API_KEY,COHERE_API_KEY,OLLAMA_API_KEY,OLLAMA_CLOUD_API_KEY,MOONSHOT_API_KEYenable the others). All reach the reusable workflow viasecrets: inherit. - App installation permissions must cover what every orchestrator needs:
- Sync workflows:
issues: writeon the target +contents: readon the target andschemas. - Reusable
claude.yml(the@claudebot):contents: write,pull-requests: write,issues: writeon every target it runs on, plus Organization permissions -> Projects: Read and write (org-level, not per-repo) so the bot can add the issue it works on to the Roadmap 2026 board (org project #7) and advance its Status (In progress at start, QA at PR open). The agent'sghalready runs as the maintainer App (claude-code-action exports thegithub_tokeninput to it asGH_TOKEN/GITHUB_TOKEN), so only the App's org-Projects grant is needed - no extra token wiring. On a permission failure it files a best-effort, idempotent tracking issue ininference-gateway/.github(title[bot] Missing GitHub permission: <capability>, labelbot, deduped org-wide) and continues without aborting the task - so abotlabel must exist oninference-gateway/.github. - Reusable
infer.yml(the@inferbot): the samecontents: write,pull-requests: write,issues: writeon every target plus the org-level Projects: Read and write grant - and because both bots now mint from the sameINFERENCE_GATEWAY_MAINTAINER_APP_*maintainer App, that single grant already covers@infer. Board tracking + permission-escalation matchclaude.yml, injected via infer-action'scustom-instructions. One difference: infer's App token is repo-scoped, so itsrepositories:list is widened to the current repo +.githubso the escalation issue can reach the control repo (board writes ride the org-level grant and need no repo in the list). bump-adl.yml/refresh-agent-manifest.yml:contents: write,pull-requests: write, andworkflows: write(because regeneration rewrites.github/workflows/{ci,cd}.yml) on everykind: agenttarget.trigger-cd.yml:actions: writeon everykind: agenttarget (to callgh workflow run cd.yml).migrate-claude.yml:contents: write,pull-requests: write, andworkflows: write(it writes.github/workflows/claude.yml) on every target with anorchestrators.claudeblock. Bumping the Floxclaude-codepin needs onlycontents: write- already covered, no new scope.migrate-infer.yml:contents: write,pull-requests: write, andworkflows: write(it writes.github/workflows/infer.yml) on every target with anorchestrators.inferblock. Regenerating.infer/needs onlycontents: write- already covered, no new scope.bump-codex.yml:contents: writeandpull-requests: writeon everyselect(.kind != "agent")target (it edits only.flox/env/*; noworkflows: write). The maintainer App is already installed on these repos - themigrate-*workflows mint tokens for the same set - so no new scope.stale.yml:issues: write(label, comment, close) on every swept target (select(.kind != "none")). No new scope beyond what the sync workflows already require.cleanup-runs.yml:actions: writeon every swept target (select(true)- every registered target, including thekind: noneinfra reposcli,operator,inference-gateway,registry,schemas,skills,adl,adl-cli,a2a-debugger,infer-action) to delete workflow runs (deleting skipped, failed, or any conclusion needs no broader scope). The maintainer App is already installed on these repos (themigrate-*workflows mint tokens for them) and itsactions: writepermission is installation-wide;trigger-cd.ymlrelies on the same scope on agent targets.backfill-roadmap.yml:issues: readon every swept target (select(true)- every registered target, incl.kind: noneandkind: agent) to list issues and read theirprojectItems, plus the org-level Projects: Read and write grant to add issues to project #7 and set Status. Both are already provisioned -issuesaccess is installation-wide (the sync/stale workflows use it) and the org-Projects grant is the same oneclaude.yml/infer.ymluse - so no new scope and no new secret.
- Sync workflows:
- Dispatch workflows in
inference-gateway/schemasthat firerepository_dispatchto this repo:event_type: spec-updatedwheneveropenapi.yamlchanges onmain(drivessync-sdks.yml).event_type: a2a-spec-updatedwhenevera2a/a2a-schema.yamlchanges onmain(drivessync-adks.yml). Until these land, the sync orchestrators only run on manual trigger.
- Drift labels must exist on each sync target before issues file cleanly:
sdk-drifton everykind: sdk/kind: docsrepo andadk-drifton everykind: adkrepo.stale.ymlalso exempts adocs-coveragelabel (legacy, kept so any historical coverage tickets stay long-lived). - PR labels
dependenciesandadl-clishould exist on everykind: agentrepo for the bump-adl PRs, anddependenciesandcodexon everyselect(.kind != "agent")repo for the bump-codex PRs (the action will create them if the App has permission, but pre-existing is cleaner).
Until these are in place, workflow_dispatch lets a maintainer kick any workflow off manually for testing.
- A. Operation coverage -
operationIds without a corresponding public method. - B. Generated models / types - top-level schemas missing from the committed generated-types file.
- C. README / examples - operations not demonstrated in
README.mdorexamples/. - D. Vendored spec staleness - SDK's checked-in
openapi.yamldiverging from the canonical one.
Note: the five
proxy*operations (proxyGet/Post/Put/Delete/Patch) under/proxy/{provider}/{path}are gateway-internal endpoints and are exempt from classes A, C, and E across all targets.
- E. Docs coverage -
operationIds or schemas not mentioned inmarkdown/**orapp/**. Filed as[DOCS] …withtype: documentation.
- A. JSON-RPC method coverage - A2A methods (
message/send,message/stream,tasks/get,tasks/list,tasks/cancel,tasks/pushNotificationConfig/*, …) without a corresponding public method on the ADK's server / client surface. - B. Generated A2A types - top-level schemas missing from the committed generated-types file (
types/generated_types.gofor the Go ADK,src/a2a_types.rsfor the Rust ADK). - C. README / examples - JSON-RPC methods not demonstrated in
README.mdorexamples/. - D. Vendored schema staleness - ADK's checked-in
schema.yamldiverging from the canonicala2a/a2a-schema.yaml.
Each class maps to one stable issue title and a matching Issue Type (feature for sync-sdks/sync-adks A/C, task for B/D, documentation for sync-sdks class E); re-runs refresh in place.