RHDH Forge
One home for reading a forge and constructing its write payloads. Issue parsing,
issue fetch, workspace resolution, check and pipeline reads, repository content
reads, and the gh and glab behaviours that mislead a caller who has not met
them before all live here. Otherwise, every skill that touches a forge keeps its
own drifting copy.
This skill reads. It never executes a write.
GitHub work runs through gh. GitLab work — rhidp/rhdh and
rhidp/rhdh-plugin-catalog on gitlab.cee.redhat.com — runs through glab,
which is only needed when a GitLab host is in play.
Route by outcome
| Outcome |
Load and follow |
| Turn a GitHub issue reference into structured context |
Run uv run scripts/fetch_issue_context.py <reference> |
| Parse a GitHub or GitLab reference without a network call |
references/issue-context.md |
| Resolve the plugin workspace an issue belongs to |
references/issue-context.md |
| Read PR state, labels, assignees, files, or check status |
references/gh-cli.md |
| Explain a failing, stale, or missing check |
references/gh-cli.md |
| Read a file from a repository or a PR branch |
references/gh-cli.md |
| Read a GitLab issue, MR state, pipeline status, or file |
references/glab-cli.md |
| Prepare a GitHub pull-request creation payload |
references/gh-cli.md, then the caller's mutation gate |
| Prepare a GitLab merge-request creation payload |
references/glab-cli.md, then the caller's mutation gate |
Prepare a comment, label, assignee, or /publish payload |
references/issue-context.md, then the caller's mutation gate |
| Prepare a GitLab comment, label, or approval payload |
references/glab-cli.md, then the caller's mutation gate |
Callers invoke this skill by name and consume what it returns. Do not load its
files from another skill.
Invariants
- Every route here is read-only. A caller that needs a write gets a payload, not
an execution.
- Construct an issue, PR, or MR URL from the resolved namespace, repository, and
number. Never retain the user's raw URL; it may carry a fragment or a query
string.
- A Jira key is not this skill's work. Extract it, hand it back, and let the
caller invoke
/rhdh-jira-api for the detail.
gh pr checks and statusCheckRollup are cached views and go stale. Confirm
a check verdict against gh run list --branch before acting on it.
- A GitLab pipeline verdict belongs to a commit, not to a merge request. Compare
the pipeline's SHA against the MR head SHA before reporting it.
- Report an unresolved workspace as unresolved. Guessing one sends a caller into
the wrong repository.
- Never read a credential file. If
gh auth status or glab auth status fails,
stop and report the missing capability.
Mutation boundary
The command patterns in the references are payloads, not authorization. This
skill builds the command and hands it back unexecuted, which is what leaves the
decision with the user rather than with the module that knows the syntax.
Before any pull request, merge request, comment, label, assignee, review,
approval, or /publish write, the calling skill invokes /mutation-gate and
follows it. This skill returns the exact argument vector and a shell-safe
rendering, the canonical host and repository, the target object or base and head
branches, the title when applicable, and the absolute body-file path. It also
returns the body-file contents for preview and a read-only verification command.
It never runs the write command.
For PR and MR creation, reject a missing or multiline title, a relative or
unreadable body file, an unresolved repository, or an empty base or head branch.
Treat each value as one argument. Do not interpolate a title or body into shell
syntax, use eval, or replace the body file with a heredoc.
A request to fetch, triage, or analyze is intent to read. It approves no write.
Issue context output
scripts/fetch_issue_context.py prints one JSON object and nothing else. There
is no envelope: the issue fields are the whole document.
{
"key": "owner/repo#607",
"summary": "issue title",
"source": "github",
"url": "https://github.com/owner/repo/issues/607",
"repository": "owner/repo",
"number": 607,
"state": "OPEN",
"labels": [],
"description": "full issue body",
"workspace": {"name": null, "strategy": "label"},
"comments": []
}
key is owner/repo#number, summary is the issue title, state is OPEN or
CLOSED, and workspace.strategy is one of label, body, title,
package, or unresolved.
/rhdh-jira-api returns the same issue shape with source: jira, and a GitLab
issue read through references/glab-cli.md fills the same fields with
source: gitlab, so a caller consumes any of the three without branching on
shape.
Keep an unresolved workspace null with strategy: unresolved rather than
inventing a name.
Scripts and references
scripts/fetch_issue_context.py deterministically builds that document from a
GitHub issue URL, a bare #number, or owner/repo#number. A GitLab issue is
read with glab instead.
references/issue-context.md covers reference parsing for both forges, field
extraction, workspace resolution, and the gated interaction payloads.
references/gh-cli.md covers gh and jq read patterns, pull-request
creation payloads, check and workflow-run reads, repository content reads,
the failure table, and the overlay repository's /publish rules.
references/glab-cli.md covers glab reads for merge requests, pipelines,
and repository content, GitLab merge-request creation payloads, the GitLab
field names that differ from GitHub's, and the other commands it constructs
but never runs.
Completion
A fetch is complete when the JSON carries key, summary, and source, url
was rebuilt from the resolved namespace, repository, and number rather than
copied from the request, and workspace.strategy names the rule that resolved
it or reads unresolved with name: null. A check verdict is complete only
once gh run list --branch confirmed it on GitHub, or the pipeline for the MR
head SHA confirmed it on GitLab; a gh pr checks or statusCheckRollup value
alone is a cached view, not a verdict. A write payload is complete when it
is handed back unexecuted for the caller's mutation gate. An interaction payload
states the exact command, repository, issue, PR, or MR number, head SHA, and body
or label. A PR or MR creation payload carries the canonical repository, exact
base and head branches, one-line title, absolute body-file path, body preview,
argument vector, shell-safe command, and read-only verification command. A Jira
key found in the issue is reported to the caller, never resolved here.
1---2name: rhdh-forge3description: Reads GitHub and GitLab and constructs unexecuted forge payloads for the other RHDH skills: parse an issue, pull request, or merge request reference, fetch issue detail, resolve a plugin workspace, inspect checks or pipelines, read repository files, or build the exact command for a GitHub pull request, GitLab merge request, comment, label, assignee, approval, or /publish write. Use for a forge URL, a bare #number, a !number merge request, "which workspace is this issue in", a stale statusCheckRollup, "why did that check fail", or safe gh, glab, and jq command construction.4---56# RHDH Forge78One home for reading a forge and constructing its write payloads. Issue parsing,9issue fetch, workspace resolution, check and pipeline reads, repository content10reads, and the `gh` and `glab` behaviours that mislead a caller who has not met11them before all live here. Otherwise, every skill that touches a forge keeps its12own drifting copy.1314This skill reads. It never executes a write.1516GitHub work runs through `gh`. GitLab work — `rhidp/rhdh` and17`rhidp/rhdh-plugin-catalog` on `gitlab.cee.redhat.com` — runs through `glab`,18which is only needed when a GitLab host is in play.1920## Route by outcome2122| Outcome | Load and follow |23|---|---|24| Turn a GitHub issue reference into structured context | Run `uv run scripts/fetch_issue_context.py <reference>` |25| Parse a GitHub or GitLab reference without a network call | `references/issue-context.md` |26| Resolve the plugin workspace an issue belongs to | `references/issue-context.md` |27| Read PR state, labels, assignees, files, or check status | `references/gh-cli.md` |28| Explain a failing, stale, or missing check | `references/gh-cli.md` |29| Read a file from a repository or a PR branch | `references/gh-cli.md` |30| Read a GitLab issue, MR state, pipeline status, or file | `references/glab-cli.md` |31| Prepare a GitHub pull-request creation payload | `references/gh-cli.md`, then the caller's mutation gate |32| Prepare a GitLab merge-request creation payload | `references/glab-cli.md`, then the caller's mutation gate |33| Prepare a comment, label, assignee, or `/publish` payload | `references/issue-context.md`, then the caller's mutation gate |34| Prepare a GitLab comment, label, or approval payload | `references/glab-cli.md`, then the caller's mutation gate |3536Callers invoke this skill by name and consume what it returns. Do not load its37files from another skill.3839## Invariants4041- Every route here is read-only. A caller that needs a write gets a payload, not42 an execution.43- Construct an issue, PR, or MR URL from the resolved namespace, repository, and44 number. Never retain the user's raw URL; it may carry a fragment or a query45 string.46- A Jira key is not this skill's work. Extract it, hand it back, and let the47 caller invoke `/rhdh-jira-api` for the detail.48- `gh pr checks` and `statusCheckRollup` are cached views and go stale. Confirm49 a check verdict against `gh run list --branch` before acting on it.50- A GitLab pipeline verdict belongs to a commit, not to a merge request. Compare51 the pipeline's SHA against the MR head SHA before reporting it.52- Report an unresolved workspace as unresolved. Guessing one sends a caller into53 the wrong repository.54- Never read a credential file. If `gh auth status` or `glab auth status` fails,55 stop and report the missing capability.5657## Mutation boundary5859The command patterns in the references are payloads, not authorization. This60skill builds the command and hands it back unexecuted, which is what leaves the61decision with the user rather than with the module that knows the syntax.6263Before any pull request, merge request, comment, label, assignee, review,64approval, or `/publish` write, the calling skill invokes `/mutation-gate` and65follows it. This skill returns the exact argument vector and a shell-safe66rendering, the canonical host and repository, the target object or base and head67branches, the title when applicable, and the absolute body-file path. It also68returns the body-file contents for preview and a read-only verification command.69It never runs the write command.7071For PR and MR creation, reject a missing or multiline title, a relative or72unreadable body file, an unresolved repository, or an empty base or head branch.73Treat each value as one argument. Do not interpolate a title or body into shell74syntax, use `eval`, or replace the body file with a heredoc.7576A request to fetch, triage, or analyze is intent to read. It approves no write.7778## Issue context output7980`scripts/fetch_issue_context.py` prints one JSON object and nothing else. There81is no envelope: the issue fields are the whole document.8283```json84{85 "key": "owner/repo#607",86 "summary": "issue title",87 "source": "github",88 "url": "https://github.com/owner/repo/issues/607",89 "repository": "owner/repo",90 "number": 607,91 "state": "OPEN",92 "labels": [],93 "description": "full issue body",94 "workspace": {"name": null, "strategy": "label"},95 "comments": []96}97```9899`key` is `owner/repo#number`, `summary` is the issue title, `state` is `OPEN` or100`CLOSED`, and `workspace.strategy` is one of `label`, `body`, `title`,101`package`, or `unresolved`.102103`/rhdh-jira-api` returns the same issue shape with `source: jira`, and a GitLab104issue read through `references/glab-cli.md` fills the same fields with105`source: gitlab`, so a caller consumes any of the three without branching on106shape.107108Keep an unresolved workspace `null` with `strategy: unresolved` rather than109inventing a name.110111## Scripts and references112113- `scripts/fetch_issue_context.py` deterministically builds that document from a114 GitHub issue URL, a bare `#number`, or `owner/repo#number`. A GitLab issue is115 read with `glab` instead.116- `references/issue-context.md` covers reference parsing for both forges, field117 extraction, workspace resolution, and the gated interaction payloads.118- `references/gh-cli.md` covers `gh` and `jq` read patterns, pull-request119 creation payloads, check and workflow-run reads, repository content reads,120 the failure table, and the overlay repository's `/publish` rules.121- `references/glab-cli.md` covers `glab` reads for merge requests, pipelines,122 and repository content, GitLab merge-request creation payloads, the GitLab123 field names that differ from GitHub's, and the other commands it constructs124 but never runs.125126## Completion127128A fetch is complete when the JSON carries `key`, `summary`, and `source`, `url`129was rebuilt from the resolved namespace, repository, and number rather than130copied from the request, and `workspace.strategy` names the rule that resolved131it or reads `unresolved` with `name: null`. A check verdict is complete only132once `gh run list --branch` confirmed it on GitHub, or the pipeline for the MR133head SHA confirmed it on GitLab; a `gh pr checks` or `statusCheckRollup` value134alone is a cached view, not a verdict. A write payload is complete when it135is handed back unexecuted for the caller's mutation gate. An interaction payload136states the exact command, repository, issue, PR, or MR number, head SHA, and body137or label. A PR or MR creation payload carries the canonical repository, exact138base and head branches, one-line title, absolute body-file path, body preview,139argument vector, shell-safe command, and read-only verification command. A Jira140key found in the issue is reported to the caller, never resolved here.