gh Adapter Contract
gh Adapter Contract — The gh Surface BoB Depends On
Section titled “gh Adapter Contract — The gh Surface BoB Depends On”What a second forge backend behind
bin/ghwould have to reproduce (#1753). (Back to reference index.)
BoB talks to its forge through gh. A backend for another forge (#1746) does not
have to be all of gh: it has to be the part of gh BoB uses. This page names
that part, and the engine that reads it from the tree so it stays true.
The inventory
Section titled “The inventory”scripts/forge/gh-inventory.js reads every tracked file and lists each gh
call it finds, by command:
node scripts/forge/gh-inventory.js scan # one line per command: executable and prompt-text countsnode scripts/forge/gh-inventory.js scan --json # gh-inventory/1: totals, per-command flags / --json fields / files, every siteTwo kinds of call site are counted apart, and the split is the point:
| Kind | Where | Why it matters |
|---|---|---|
| executable | .sh / .js / .ts / workflow YAML, and extensionless scripts with a shell or node shebang |
Code that runs gh. It could be ported by editing a function. |
| prompt-text | .md under commands/, skills/, agents/, registry/, runbooks/, docs/, templates/, and the root guides |
Instructions an agent follows and then runs through Bash. They can only be ported by keeping gh working, which is why a gh-shaped shim beats a rewrite. |
Not read: tests/ (they stub gh), www/ (published pages), journal/,
story/, wiki/, evals/, CHANGELOG.md and app test files.
Two forms are recognised:
- shell —
gh issue list --json number,titleon a line. In code, comment lines are skipped.<N>placeholders are words, and the command ends at the first pipe,;,&&, redirect or closing backtick. - argv — a JS/TS array literal whose first element is a
ghcommand and the second its subcommand:gh(['issue', 'list', …]),execFileSync('gh', ['api', …]),const args = ['pr', 'merge', …]. A command that takes no subcommand (status,browse) only counts withghin sight, so git’s['status', '--porcelain']is not read asgh status.
A subcommand outside gh’s own command tree is prose (“the gh issue family”),
not a call. An argv array assembled piece by piece is not seen; the shim’s
runtime record (Forge Health → The shim) sees every
call that actually runs, and is the cross-check for those.
A call is keyed <command> <subcommand> — issue list, pr merge. For
gh api the key is the normalised endpoint: every interpolation (${x}, $X,
<N>, {owner}) and every numeric path segment becomes {}, and the repo is
always one {} whether it was written {owner}/{repo}, ${slug} or a literal
owner and name — so api repos/{}/issues/{} is one endpoint. api graphql is
its own key.
A --json field list held in a variable cannot be read statically; the command
is marked json_dynamic.
The contract
Section titled “The contract”scripts/forge/gh-contract.json (gh-contract/1) records one entry per command
the tree calls:
| Field | Meaning |
|---|---|
behavior |
What the command does for BoB — the part of gh’s behaviour a backend must reproduce. |
output |
The output shape callers read: a JSON array or object of the --json fields, a URL whose last segment is the new number, a REST body, or nothing but the exit code. |
portable |
true — a backend must reproduce it. false — known-unsupported: no forge-neutral equivalent. |
reason |
For an unsupported command, why. |
flags, json |
The flags and --json fields BoB calls it with. json_dynamic: true when a field list is held in a variable. |
The behavior, output, portable and reason text is written by hand. The flags
and fields are what the scan finds, recorded by record.
What every backend must also keep
Section titled “What every backend must also keep”- Transparency. Everything outside the contract passes through unchanged: stdin, stdout, stderr and the exit code (Forge Health → The shim).
- An honest failure. A read that cannot be answered exits non-zero; it is never an empty list. The cache, the queue and the callers rely on telling “nothing matched” from “the lookup failed”.
The drift gate
Section titled “The drift gate”make check-gh-contract # the gate, part of make checknode scripts/forge/gh-inventory.js check --json # gh-contract-check/1node scripts/forge/gh-inventory.js record # fold new usage into the contract, re-render this pagenode scripts/forge/gh-inventory.js write # re-render this page's block onlycheck fails, naming the call sites, when:
| Problem | Meaning | Fix |
|---|---|---|
unrecorded-command |
The tree calls a gh command the contract does not list. |
record, then write its behavior, output and portable. |
unrecorded-flag / unrecorded-json |
A known command is called with a new flag or --json field, or a field list in a variable. |
record — and know a backend must now support it. |
unused-command |
The contract lists a command nothing calls. | record drops it. |
undocumented |
An entry has no behavior, output or portable, or is unsupported with no reason. | Write the text. |
doc-drift / doc-missing |
The generated block below is not what the contract renders. | write. |
New coupling to the forge therefore cannot land silently: it lands with a contract edit in the same diff, where a reviewer sees it. Exit codes: 0 clean, 1 drift, 2 the tree or contract could not be read.
GraphQL
Section titled “GraphQL”The cap behind this contract (#1746) measures “zero GraphQL in executable
code”. Today there are four executable callers of gh api graphql, and each is
kept, and listed as known-unsupported, not ported:
| Caller | What one query reads |
|---|---|
scripts/brief/reconcile.js |
The state and labels of up to 60 issues across repos, for the brief reconciler (#3100). |
scripts/brief/brief.js |
The newest releases of every repo in the portfolio, for the briefing (#2243). |
scripts/forge/batch.js |
A repo’s issues 40 at a time, for the stale-todo sweep (#3219). |
scripts/release/notes.js |
40 issue titles, bodies and labels at a time, for the release notes. |
Each was batched on purpose: one query answers what dozens of REST calls (or
gh issue views) would, and that is what keeps these readers inside the quota.
A port would multiply quota spend by the batch size for no gain on GitHub, so a
backend refuses them instead; every caller already treats a failed read as
unknown, never as an empty answer. Each call site carries a one-line comment
naming this contract.
Nothing passes the metric silently. The generated block names every executable
file that calls an unsupported command, so a fifth GraphQL caller changes the
block, and make check-gh-contract fails with doc-drift until the block is
re-rendered in the same diff — where a reviewer sees the new row.
The surface
Section titled “The surface”85 commands: 51 a backend must reproduce, 34 known-unsupported. GraphQL in executable code: 7 call site(s) in 4 file(s), listed as unsupported below.
Commands a backend must reproduce
Section titled “Commands a backend must reproduce”| Command | Behavior | Output | Flags | --json fields |
|---|---|---|---|---|
api repos/{} |
Read one repository’s metadata (default branch, visibility, archived). | the REST response body as JSON (or the –jq projection of it) | --jq |
— |
api repos/{}/collaborators |
List the repo’s collaborators. | the REST response body as JSON (or the –jq projection of it) | — | — |
api repos/{}/collaborators/{} |
Add or remove one collaborator (-X PUT / DELETE). | the REST response body as JSON (or the –jq projection of it) | -X |
— |
api repos/{}/compare/{}...{} |
Compare two refs: ahead/behind counts and the commits between. | the REST response body as JSON (or the –jq projection of it) | — | — |
api repos/{}/contents/{} |
Read one file’s content at a ref. | the file’s content (raw with -H Accept: raw, else the contents object) | -H |
— |
api repos/{}/git/refs/heads/master |
Move master to a SHA (-X PATCH -f sha=…). | the REST response body as JSON (or the –jq projection of it) | -X -f |
— |
api repos/{}/git/refs/heads/{} |
Create, move or delete a branch ref — merge-on-green’s fast-forward (-X PATCH -f sha=… -F force=false). | the REST response body as JSON (or the –jq projection of it) | -F -X -f |
— |
api repos/{}/issues |
List or create issues through REST (–paginate; -X POST -f title=…). | the REST response body as JSON (or the –jq projection of it) | --jq --paginate -X -f |
— |
api repos/{}/issues/comments/{} |
Read, edit or delete one issue comment (-X PATCH –input). | the REST response body as JSON (or the –jq projection of it) | --input --jq -X |
— |
api repos/{}/issues/{} |
Read one issue, or patch its state, body or labels (-X PATCH –input). | the REST response body as JSON (or the –jq projection of it) | --input --jq -X |
— |
api repos/{}/issues/{}/comments |
List or add an issue’s comments (–paginate; -X POST -f body=…). | the REST response body as JSON (or the –jq projection of it) | --jq --paginate -X -f |
— |
api repos/{}/labels |
List the repo’s labels (–paginate). | the REST response body as JSON (or the –jq projection of it) | --jq --paginate |
— |
api repos/{}/pulls/{}/merge |
Merge one pull request (-X PUT). | the REST response body as JSON (or the –jq projection of it) | -X |
— |
api user |
Read the signed-in account (its login). | the REST response body as JSON (or the –jq projection of it) | -q |
— |
api user/keys |
List the account’s SSH keys. | the REST response body as JSON (or the –jq projection of it) | --jq |
— |
auth login |
Sign the machine in to the forge. | nothing callers parse; the exit code is the answer | --git-protocol --hostname --web |
— |
auth status |
Is this machine signed in? Exit 0 = yes. | nothing callers parse; the exit code is the answer | — | — |
auth token |
Print the current token, for a caller that talks HTTP itself. | the token on stdout | — | — |
issue close |
Close an issue, optionally with a comment and a reason (completed / not planned). | nothing callers parse; the exit code is the answer | --comment --reason --repo -R |
— |
issue comment |
Add a comment to an issue. | the comment URL on stdout (not parsed) | --body --body-file --repo -R |
— |
issue create |
File an issue with a title, body, labels and assignee. | the URL of the new object on stdout — callers read the number from its last path segment | --assignee --body --body-file --label --repo --title -R |
— |
issue edit |
Change an issue’s body, title or labels (–add-label / –remove-label). | the issue URL on stdout (not parsed) | --add-label --body --body-file --remove-label --repo |
— |
issue list |
List issues by state, label, assignee or a search string. –search takes GitHub query syntax, which a backend must translate or refuse. | a JSON array of objects carrying exactly the requested –json fields (or the –jq projection of it) | --assignee --jq --json --label --limit --repo --search --state -R -l -q -s |
assignees body closedAt comments createdAt labels number state stateReason title updatedAt url + dynamic |
issue reopen |
Reopen a closed issue. | nothing callers parse; the exit code is the answer | --comment --repo |
— |
issue view |
Read one issue: body, labels, state, comments. | one JSON object carrying the requested –json fields (or the –jq projection of it); without –json, human text callers do not parse | --comments --jq --json --repo -q |
assignees body closedAt comments createdAt labels number state stateReason title url + dynamic |
label create |
Create a label with a colour and description; –force updates one that exists. | nothing callers parse; the exit code is the answer | --color --description --force -R |
— |
label delete |
Delete a label. | nothing callers parse; the exit code is the answer | --repo --yes |
— |
label edit |
Rename a label or change its colour or description. | nothing callers parse; the exit code is the answer | --name --repo |
— |
label list |
List the repo’s labels. | a JSON array of objects carrying exactly the requested –json fields (or the –jq projection of it) | --jq --json --limit --search |
description name |
pr close |
Close a pull request, optionally deleting its branch. | nothing callers parse; the exit code is the answer | --comment --delete-branch |
— |
pr comment |
Add a comment to a pull request. | the comment URL on stdout (not parsed) | --body --repo |
— |
pr create |
Open a pull request from a head branch to a base. | the URL of the new object on stdout — callers read the number from its last path segment | --base --body --body-file --fill --head --label --title |
— |
pr diff |
Print a pull request’s diff. | a unified diff on stdout | — | — |
pr edit |
Change a pull request’s body or labels. | nothing callers parse; the exit code is the answer | --add-label --body |
— |
pr list |
List pull requests by state, base, head, author or label. statusCheckRollup is GitHub’s checks model; a backend must synthesise it from its own commit statuses. | a JSON array of objects carrying exactly the requested –json fields (or the –jq projection of it) | --author --base --head --jq --json --label --limit --search --state -R -q |
body createdAt headRefName isDraft labels mergedAt number state statusCheckRollup title url |
pr merge |
Merge a pull request (–squash, –delete-branch). –admin bypasses branch protection, which a backend may not offer. | nothing callers parse; the exit code is the answer | --delete-branch --squash |
— |
pr view |
Read one pull request: body, head branch, commits, check rollup. | one JSON object carrying the requested –json fields (or the –jq projection of it); without –json, human text callers do not parse | --jq --json --repo -q |
body commits headRefName number statusCheckRollup url + dynamic |
release create |
Publish a release for a tag, with notes from a file or generated. | the URL of the new object on stdout — callers read the number from its last path segment | --generate-notes --notes --notes-file --title --verify-tag |
— |
release download |
Download a release’s assets. | files written to the working directory | — | — |
release list |
List releases. | a JSON array of objects carrying exactly the requested –json fields (or the –jq projection of it) | --json --limit --repo |
isDraft name publishedAt tagName |
release view |
Read one release (tag, URL). | one JSON object carrying the requested –json fields (or the –jq projection of it); without –json, human text callers do not parse | --jq --json |
tagName url |
repo archive |
Archive a repository. | nothing callers parse; the exit code is the answer | --yes |
— |
repo clone |
Clone a repository by owner/name. | a git checkout on disk | — | — |
repo create |
Create a repository, optionally from a local source directory. | the repository URL on stdout | --private --source |
— |
repo edit |
Change repository settings (docs show --help). |
nothing callers parse; the exit code is the answer | --help |
— |
repo list |
List an owner’s repositories. | a JSON array of objects carrying exactly the requested –json fields (or the –jq projection of it) | --json --limit |
isArchived isPrivate nameWithOwner pushedAt |
repo unarchive |
Unarchive a repository. | nothing callers parse; the exit code is the answer | — | — |
repo view |
Read the current repository: name, owner, default branch, visibility, archived. | one JSON object carrying the requested –json fields (or the –jq projection of it); without –json, human text callers do not parse | --jq --json -q |
defaultBranchRef isArchived isPrivate name nameWithOwner + dynamic |
ssh-key add |
Register a public SSH key on the account. | nothing callers parse; the exit code is the answer | --title |
— |
ssh-key delete |
Remove an SSH key from the account. | nothing callers parse; the exit code is the answer | — | — |
ssh-key list |
List the account’s SSH keys. | human text | — | — |
Known-unsupported
Section titled “Known-unsupported”No portable equivalent: a backend refuses these, and the callers named here are what a port would have to change.
| Command | Behavior | Why it is unsupported | Executable call sites | Prompt-text call sites |
|---|---|---|---|---|
api graphql |
One GraphQL query that reads many objects at once: the state and labels of up to 60 cross-repo issues for the brief reconciler (scripts/brief/reconcile.js, #3100), the newest releases of every repo for the briefing (scripts/brief/brief.js, #2243), a repo’s issues in chunks for the stale-todo sweep (scripts/forge/batch.js, #3219) and 40 issue titles at a time for the release notes (scripts/release/notes.js). | GitHub’s GraphQL schema. Each of these reads is batched on purpose: one query answers what dozens of REST calls would, which is what keeps the briefing, the reconciler and the stale-todo sweep inside the quota (#3100, #3219). A port to REST or gh issue view would multiply quota spend by the batch size, so they stay GraphQL and a backend refuses them; every caller already treats a failed read as unknown, never as an empty answer. A new executable caller changes this row, so it cannot land silently. | scripts/brief/brief.js scripts/brief/reconcile.js scripts/forge/batch.js scripts/release/notes.js |
docs/reference/bob-asks.md docs/reference/briefing.md docs/reference/forge-health.md |
api rate_limit |
Read the token’s remaining quota per resource (the shim’s budget, #3190). | GitHub’s quota model; the shim’s pacing (scripts/forge/budget.js) is built on it. A backend reports its own limits or none. | scripts/bootstrap-labels.sh scripts/forge/budget.js scripts/forge/health.js |
docs/reference/forge-health.md |
api repos/{}/actions/permissions |
Read the repo’s Actions permission settings. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | — | registry/runbooks/bob-attack-surface-review.md |
api repos/{}/actions/runners |
List the repo’s self-hosted runners and their status. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/dashboard/server.js scripts/fleet/ci-locus.js scripts/fleet/ci-rollout.js scripts/fleet/runner.sh |
— |
api repos/{}/actions/runners/registration-token |
Mint a runner registration token. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/runner.sh |
— |
api repos/{}/actions/runners/remove-token |
Mint a runner removal token. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/runner.sh |
— |
api repos/{}/actions/runs |
List workflow runs. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/ci-locus.js |
— |
api repos/{}/actions/runs/{}/jobs |
List the jobs of one workflow run. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/dashboard/server.js scripts/fleet/ci-locus.js |
runbooks/self-hosted-runner.md |
api repos/{}/actions/variables/{} |
Read one Actions variable (CI_RUNNER_LABEL). | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/ci-locus.js scripts/fleet/ci-rollout.js scripts/fleet/runner.sh |
— |
api repos/{}/actions/workflows |
List the repo’s workflows. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/ci-rollout.js |
— |
api repos/{}/branches/master/protection |
Read master’s branch protection. | GitHub’s branch-protection model; a backend’s protected-branch settings do not share its shape. | — | registry/runbooks/bob-attack-surface-review.md |
api repos/{}/branches/{}/protection |
Read or replace a branch’s protection (-X PUT –input). | GitHub’s branch-protection model; a backend’s protected-branch settings do not share its shape. | scripts/fleet/branch-protection.js |
— |
api repos/{}/branches/{}/protection/required_status_checks |
Read a branch’s required status checks (merge-on-green’s base-side read). | GitHub’s branch-protection model; merge-on-green falls back to .github/required-checks.json when it cannot read this. | scripts/promotion/merge-on-green.sh |
— |
api repos/{}/commits/{}/check-runs |
List the check runs reported on one commit. | GitHub Checks: check runs come from GitHub Apps and Actions and have no forge-neutral model — a backend with its own CI needs its own mapping | — | docs/how-to/promotion-pipeline-setup.md |
api repos/{}/hooks |
List the repo’s webhooks. | GitHub’s webhook model and event names; a backend’s hooks carry different events and payloads. | — | skills/todo-writing/references/platform-recipes.md |
api repos/{}/pages |
Read the repo’s GitHub Pages site. | GitHub Pages; BoB publishes its sites through Cloudflare, and this read is a docs example. | — | skills/todo-writing/references/platform-recipes.md |
api repos/{}/rulesets |
List the repo’s rulesets. | GitHub rulesets have no forge-neutral equivalent. | — | skills/todo-writing/references/platform-recipes.md |
api user/installations |
List the GitHub App installations the token can see. | GitHub Apps. | — | registry/runbooks/bob-attack-surface-review.md registry/runbooks/drill-farm-compromise.md |
api {} |
A call whose endpoint is held in a variable (a docs example of gh api <path>). |
The endpoint cannot be read from the tree, so the contract cannot promise it. | — | docs/reference/forge-health.md |
api {}/{}/settings/billing/actions |
Read an owner’s Actions minutes against the included quota (#1695). | GitHub billing for Actions minutes. | scripts/fleet/actions-budget.js |
— |
api {}/{}/settings/billing/usage |
Read an owner’s billing usage (#1695). | GitHub billing. | scripts/fleet/actions-budget.js |
— |
auth refresh |
Add OAuth scopes to the token (-h host -s user,…). | GitHub OAuth scopes; a backend’s token permissions are named differently. | scripts/fleet/actions-budget.js |
commands/what-next.md docs/reference/actions-budget.md |
run list |
List workflow runs for a branch, commit or workflow. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | .github/workflows/auto-release.yml scripts/asks/done-check.js scripts/brief/completion.js scripts/dashboard/project-detail.js scripts/dashboard/series.js scripts/dashboard/server.js scripts/fleet/ci-health.js scripts/fleet/ci-locus.js scripts/fleet/ci-rollout.js scripts/release/release.sh scripts/rituals/evidence.js |
docs/explanation/bob-viz.md docs/explanation/warp-drive-internals.md docs/how-to/promotion-pipeline-setup.md docs/how-to/versioning.md docs/reference/ci-health.md docs/reference/project-detail.md docs/reference/series.md runbooks/local-delivery.md runbooks/self-hosted-runner.md |
run rerun |
Re-run a workflow run (–failed). | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/asks/done-check.js scripts/fleet/ci-locus.js |
docs/reference/ci-locus.md docs/reference/todo-format-contract.md runbooks/self-hosted-runner.md |
run view |
Read one workflow run, its jobs or its log. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/asks/done-check.js scripts/fleet/ci-locus.js |
docs/reference/ci-locus.md registry/runbooks/github-pat-rotation.md runbooks/self-hosted-runner.md |
run watch |
Wait for a workflow run to finish (–exit-status). | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | — | registry/runbooks/cloudflare-api-token-rotation.md registry/runbooks/github-pat-rotation.md |
search issues |
Search issues across an owner or repos with GitHub query syntax (the briefing’s sources). | GitHub’s search API and query syntax (is:, label:, repo:, owner-wide) — a backend has no equivalent; callers would have to move to per-repo issue/pr list filters | scripts/brief/brief.js scripts/dashboard/briefings.js scripts/dashboard/notices.js scripts/dashboard/reports.js scripts/dashboard/series.js scripts/forge/cache.js scripts/warp-drive/preflight-todo-cleanup.js |
docs/explanation/bob-viz.md docs/reference/briefing.md docs/reference/notices.md docs/reference/reports.md docs/reference/series.md |
search prs |
Search pull requests across an owner (the briefing’s merged and open PRs). | GitHub’s search API and query syntax (is:, label:, repo:, owner-wide) — a backend has no equivalent; callers would have to move to per-repo issue/pr list filters | scripts/brief/brief.js |
docs/reference/briefing.md |
secret list |
List a repo’s or org’s Actions secrets by name (never values). | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/asks/done-check.js scripts/docs-site/init.sh scripts/security/cred-check.js scripts/security/secrets.js |
docs/reference/bob-secrets.md docs/reference/secrets-inventory.md registry/runbooks/bob-attack-surface-review.md registry/runbooks/bridge-secret-rotation.md registry/runbooks/cloudflare-api-token-rotation.md registry/runbooks/drill-lost-laptop.md registry/runbooks/github-pat-rotation.md registry/skills/secrets-management/SKILL.md registry/skills/tailscale-remote-ops/SKILL.md skills/todo-writing/assets/todo-template.md skills/todo-writing/references/platform-recipes.md |
secret set |
Set an Actions secret. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/docs-site/init.sh scripts/fleet/distribute-secret.sh scripts/security/cred-check.js scripts/security/secrets.js |
docs/how-to/promotion-pipeline-setup.md docs/how-to/secrets-check.md docs/reference/bob-secrets.md docs/reference/branch-protection.md docs/reference/secrets-inventory.md registry/runbooks/bridge-secret-rotation.md registry/runbooks/cloudflare-api-token-rotation.md registry/runbooks/github-pat-rotation.md registry/skills/docs-site/SKILL.md registry/skills/secrets-management/SKILL.md skills/todo-writing/references/platform-recipes.md |
variable delete |
Delete an Actions variable. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/runner.sh |
— |
variable list |
List the repo’s Actions variables. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | — | registry/runbooks/bob-attack-surface-review.md skills/todo-writing/references/platform-recipes.md |
variable set |
Set an Actions variable (CI_RUNNER_LABEL, #1728). | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | scripts/fleet/runner.sh |
docs/reference/branch-protection.md skills/todo-writing/references/platform-recipes.md |
workflow run |
Dispatch a workflow. | GitHub Actions: runners, runs, workflows, secrets and variables have no forge-neutral model — a backend with its own CI needs its own mapping, and BoB’s CI locus (docs/reference/ci-locus.md) is GitHub-only today | — | docs/how-to/skill-authoring.md registry/runbooks/cloudflare-api-token-rotation.md registry/runbooks/github-pat-rotation.md |
Related
Section titled “Related”- Forge Health — the shim every call goes through, and the cache, queue and budget behind it.