YugabyteDB Issue Creator
yugabyte/yugabyte-db
Creates a GitHub issue or JIRA ticket for a YugabyteDB change or bug, after scrubbing customer data, secrets and unreleased details from anything public.
Diagnose and fix jira/invalid-bug on PRs by running the same 7 checks as the jira-lifecycle-plugin
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install openshift-eng/ai-helpers validate-bug --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/jira/skills/validate-bug .claude/skills/validate-bug && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .claude/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bugType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install openshift-eng/ai-helpers validate-bug --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/jira/skills/validate-bug .agents/skills/validate-bug && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .agents/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install openshift-eng/ai-helpers validate-bug --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/jira/skills/validate-bug .cursor/skills/validate-bug && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .cursor/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/openshift-eng/ai-helpers.git --path plugins/jira/skills/validate-bug--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install openshift-eng/ai-helpers validate-bug --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/jira/skills/validate-bug .gemini/skills/validate-bug && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .gemini/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install openshift-eng/ai-helpers validate-bugInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/jira/skills/validate-bug .github/skills/validate-bug && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .github/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add openshift-eng/ai-helpers --skill validate-bug -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install openshift-eng/ai-helpers validate-bug --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/openshift-eng/ai-helpers.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/jira/skills/validate-bug .opencode/skills/validate-bug && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "validate-bug" agent skill from https://github.com/openshift-eng/ai-helpers/tree/main/plugins/jira/skills/validate-bug into .opencode/skills/validate-bug/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "validate-bug", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
validate-bugDiagnose and fix jira/invalid-bug on PRs by running the same 7 checks as the jira-lifecycle-plugin
Validate Bug is an agent skill from openshift-eng/ai-helpers. Diagnose and fix jira/invalid-bug on PRs by running the same 7 checks as the jira-lifecycle-plugin
Its SKILL.md is about 3.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development. It works with Jira. The repository describes itself as: Developer productivity tools for Claude Code & other AI assistants. The licence is Apache-2.0.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit a627176. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
ghFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
github.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
JIRA_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Validate Bug loads about 3.6k tokens when it runs. Until then it costs about 28 tokens; SKILL.md has 1,628 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from openshift-eng/ai-helpers at commit a627176, republished under its Apache-2.0 licence (© openshift-eng). 1,628 words, ~3,609 tokens.
.claude/skills/validate-bug/SKILL.md (or your agent's skills folder).IMPORTANT FOR AI: This is a procedural skill. Execute each phase in order. Do not skip steps. Do not invent field IDs — use only the documented custom field IDs below.
This skill replicates the validation logic of the jira-lifecycle-plugin (Prow external plugin) that applies the jira/invalid-bug label to PRs in OpenShift repositories.
| Field | Custom Field ID | JQL Name |
|---|---|---|
| Target Version | customfield_10855 | "Target Version" |
| Release Note Text | customfield_10783 | — |
| Release Note Type | customfield_10785 | — |
| Severity | customfield_10840 | — |
The jira-lifecycle-plugin runs these checks in order. A bug must pass ALL checks to get jira/valid-bug.
| # | Check | What it validates |
|---|---|---|
| 1 | Bug is open | Status is not "Closed" |
| 2 | Target version matches branch | Bug's Target Version matches the expected version for the PR's base branch |
| 3 | Bug in valid state | Status is one of: NEW, ASSIGNED, POST |
| 4 | Release notes set | Release note text is non-empty and doesn't match the default template, OR release note type is "Release Note Not Required" |
| 5 | Dependent bug states | Each dependent (linked via "Blocks") is in an allowed state |
| 6 | Dependent bug target versions | Each dependent targets an allowed version |
| 7 | Dependents exist | At least one "Blocks" link exists to a bug in the same project |
Checks 5-7 only apply to release branches (release-4.X), not main/master.
The plugin config follows a mechanical pattern:
Target version (what the bug on the PR's branch must target):
release-4.X → 4.X.z (prefix match — 4.X.0 also accepted)main / master → 5.0.0 (prefix match — 5.0 also accepted). Update when main targets a new major version — check openshift/release/core-services/jira-lifecycle-plugin/config.yaml for the current value.Dependent target version (what the "Blocks" linked bug must target):
release-4.X → 4.(X+1).0 or 4.(X+1).zValid states for the bug itself (all branches):
NEW, ASSIGNED, POSTValid states for dependent bugs (varies by branch — check openshift/release/core-services/jira-lifecycle-plugin/config.yaml for current boundaries):
release-4.22 and newer: MODIFIED, ON_QA, VERIFIEDrelease-4.6 through release-4.21: VERIFIED, RELEASE PENDING, CLOSED (ERRATA), CLOSED (CURRENT RELEASE), CLOSED (DONE), CLOSED (DONE-ERRATA)Dependent bug checks (checks 5-7):
release-4.X branchesmain / master (config sets exclude_defaults: true)Release notes:
require_release_notes: true)"Cause: What actions or circumstances cause this bug to present.\r\nConsequence: What happens when the bug presents.\r\nFix: What was done to fix the bug.\r\nResult: Bug doesn't present anymore."gh CLI authenticated with GitHubcloudId: use redhat.atlassian.netParse the argument to determine input type:
PR URL — matches https://github.com/{org}/{repo}/pull/{number}
gh pr view {number} --repo {org}/{repo} --json title,baseRefName,state[A-Z]+-[0-9]+ (e.g., OCPBUGS-85778)baseRefName (e.g., release-4.20, main)PR number — plain integer
gh repo view --json nameWithOwner -q .nameWithOwnerJIRA key — matches [A-Z]+-[0-9]+
--branch argument (no PR context to infer branch)--branch not provided, error: "JIRA key input requires --branch (e.g., --branch release-4.20)"Validate the JIRA key project:
OCPBUGS, DFBUGS, or PROJQUAYCompute expected values from branch:
expected_target_version, expected_dependent_versions, valid_states, dependent_valid_states, dependents_required using the mapping aboveFetch the primary bug:
Use mcp__atlassian__getJiraIssue:
cloudId: redhat.atlassian.netissueIdOrKey: the JIRA keyfields: ["summary", "status", "issuetype", "fixVersions", "issuelinks", "customfield_10855", "customfield_10783", "customfield_10785", "customfield_10840", "labels", "components"]responseContentFormat: markdownExtract key data from response:
status.name — bug status (e.g., "New", "Verified")customfield_10855 — Target Version array (each entry has .name)customfield_10783 — Release Note Text (string or ADF doc)customfield_10785 — Release Note Type (object with .value)issuelinks — array of issue linksFind dependent bugs:
Filter issuelinks for links where:
"Blocks" AND direction is outwardIssue (this bug blocks the dependent)OCPBUGS-*)For each dependent found:
getJiraIssue:fields: ["summary", "status", "customfield_10855", "fixVersions"]Run each check and record the result:
results = []Check 1: Bug is open
status.name is NOT "Closed"status.name is "Closed""bug is open, matching expected state (open)""bug is closed, expected it to be open"Check 2: Target version matches branch
customfield_10855 (array)"expected the bug to target the '{expected}' version, but no target version was set".name starts with the expected prefix (e.g., "4.20" for release-4.20)"expected the bug to target either version '{expected}' or 'openshift-{expected}', but it targets '{actual}' instead"Check 3: Bug in valid state
status.name (uppercased) is in ["NEW", "ASSIGNED", "POST"]"bug is in state {actual}, which is not one of the valid states (NEW, ASSIGNED, POST)"Check 4: Release notes
customfield_10783customfield_10785.value equals "Release Note Not Required""Cause: What actions or circumstances""release note text must be set and not match the template OR release note type must be set to 'Release Note Not Required'"Check 5: Dependent bug states (skip if dependents_required is false)
status.name (uppercased) is in the allowed dependent_valid_states list"expected dependent Jira Issue {key} to be in one of the following states: {allowed}, but it is {actual} instead"Check 6: Dependent bug target versions (skip if dependents_required is false)
customfield_10855expected_dependent_versions prefixes"expected dependent Jira Issue {key} to target a version in {allowed}, but it targets '{actual}' instead"Check 7: Dependents exist (skip if dependents_required is false)
"expected Jira Issue to depend on a bug targeting a version in {allowed} and in one of the following states: {allowed_states}, but no dependents were found"Render results as a markdown table:
## Validating {JIRA_KEY} against branch {BRANCH}
**Bug**: {summary}
**Status**: {status} | **Target Version**: {target_version} | **Project**: {project}
| # | Check | Expected | Actual | Result |
|---|--------------------------------|-------------------------|--------------------| -------|
| 1 | Bug is open | Open | {status} | {P/F} |
| 2 | Target version | {expected_tv} | {actual_tv} | {P/F} |
| 3 | Valid state | NEW/ASSIGNED/POST | {status} | {P/F} |
| 4 | Release notes | Set (not template) | {actual_rn} | {P/F} |
| 5 | Dependent bug states | {allowed_states} | {actual_dep_state} | {P/F} |
| 6 | Dependent bug target version | {allowed_dep_tv} | {actual_dep_tv} | {P/F} |
| 7 | Dependents exist | At least one | {count} found | {P/F} |
Result: {N} of 7 checks passedFor checks that were skipped (main branch, no dependents required), show SKIP in the Result column.
For each failure, list the specific fix instruction:
### Fixes needed
1. **Target version**: Set Target Version to `{expected}` (currently `{actual}`)
2. **Status**: Transition to NEW, ASSIGNED, or POST (currently `{actual}`)
3. **Release notes**: Set release note text or set Release Note Type to "Release Note Not Required"
4. **Dependents**: Create or link a bug in {PROJECT} targeting `{expected_dep_version}`If all checks pass:
All 7 checks passed. If the PR still shows `jira/invalid-bug`, comment `/jira refresh` on the PR.After reporting, offer to fix each failing check. List the fixes and ask for confirmation before proceeding.
Fix: Target version (checks 2, 6)
mcp__atlassian__getJiraIssueTypeMetaWithFields with projectIdOrKey: {PROJECT}, issueTypeId from the bug's issuetype.id, and requiredFieldsOnly: falsecustomfield_10855 in the response fields — its allowedValues array contains all available versions. Match the entry whose .name equals the expected version string (e.g., 4.20.z) and extract its .idmcp__atlassian__editJiraIssue with fields: {"customfield_10855": [{"id": "{version_id}"}]}Fix: Status (checks 1, 3)
mcp__atlassian__getTransitionsForJiraIssuemcp__atlassian__transitionJiraIssue with the transition IDFix: Release notes (check 4)
Cause: {what causes the bug}
Consequence: {what happens}
Fix: {what was done}
Result: {the fix resolves it}mcp__atlassian__editJiraIssue with fields: {"customfield_10783": "{text}"}fields: {"customfield_10785": {"value": "Release Note Not Required"}}Fix: Missing dependents (check 7)
issuelinks (same project, outward direction)mcp__atlassian__createIssueLink with type: "Blocks", inwardIssue: {original_bug}, outwardIssue: {new_bug} (original bug blocks the new dependent)mcp__atlassian__createJiraIssue then mcp__atlassian__createIssueLinkFix: Dependent bug state (check 5)
mcp__atlassian__getTransitionsForJiraIssue for the dependentmcp__atlassian__transitionJiraIssueAfter all fixes applied:
/jira refresh on the PR to have the bot re-validate."| Error | Handling |
|---|---|
| PR not found | Display error with PR URL, suggest checking the URL |
| No JIRA key in PR title | Display the PR title, explain the expected format: {JIRA-KEY}: description |
| JIRA issue not found | Check if key is correct, check project access |
| MCP tool unavailable | Fall back to gh CLI for GitHub data; for JIRA, display manual fix instructions |
| Branch not recognized | Warn that branch {name} doesn't match expected patterns, ask for --branch override |
| Version ID not found | Display the expected version string, instruct user to set it manually in JIRA |
| Transition not available | List available transitions, explain which one is needed and why it might be blocked |
openshift/release/core-services/jira-lifecycle-plugin/config.yaml. If validation rules change, update the mapping in this skill.jira/valid-bug, the bot will not remove it.main branch uses exclude_defaults: true, which disables dependent bug checks (5-7).© openshift-eng, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/jira/skills/validate-bug of openshift-eng/ai-helpers.
Open the folder on GitHubat commit a627176
Validate Bug next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Validate Bug this skillopenshift-eng/ai-helpers | 120 | — | ~3.6k | Automated safety check: Pass | Apache-2.0 | |
| YugabyteDB Issue Creatoryugabyte/yugabyte-db | 11k | — | ~2k | Automated safety check: Pass | Custom licence | |
| Code Reviewcroffasia/itsaplan | 895 | — | ~2k | Automated safety check: Pass | AGPL-3.0 | |
| PR BodySAP/spartacus | 784 | — | ~499 | Automated safety check: Pass | Apache-2.0 | |
| Link Ticket To SessionJayantDevkar/claude-code-karma | 329 | — | ~1.8k | Automated safety check: Notes | Apache-2.0 | |
| SDK Changelogbouffalolab/bouffalo_sdk | 501 | — | ~1.1k | Automated safety check: Pass | Apache-2.0 |
yugabyte/yugabyte-db
Creates a GitHub issue or JIRA ticket for a YugabyteDB change or bug, after scrubbing customer data, secrets and unreleased details from anything public.
croffasia/itsaplan
A skill your agent uses when reviewing code — a diff, a merge request, a file, a directory, or a feature.
SAP/spartacus
A skill your agent uses when the user asks to generate, write, or draft a pull request (PR) body or description for the current branch.
JayantDevkar/claude-code-karma
Link the current Claude Code session to a ticket (Linear, Jira, GitHub Issues, or GitHub Pull Requests) and cache its title/status in karma.
bouffalolab/bouffalo_sdk
A skill your agent uses when generating a customer-facing CHANGELOG between two SDK release tags.
cobusgreyling/loop-engineering
Scans open GitHub issues and discussions, flags duplicates, scores priority and proposes labels into issue-triage-state.md without ever labeling or closing.
openshift-eng/ai-helpers
Find and independently validate actionable reliability defects across OpenShift release jobs and presubmits, then export portable issue handoffs.
openshift-eng/ai-helpers
Fetch and address all PR review comments — categorize by priority, make code changes, post replies, and push.
openshift-eng/ai-helpers
Categorize Jira issues into Red Hat Sankey Activity Type categories using MCP Jira tools.
openshift-eng/ai-helpers
Decide whether a GitHub PR has unanswered authorized review comments or new required CI failures worth a follow-up agent.
openshift-eng/ai-helpers
Analyze OpenShift must-gather diagnostic data including cluster operators, pods, nodes, and network components.
openshift-eng/ai-helpers
Schema for the autodl JSON data file produced by payload-analysis for database ingestion — you must use this skill whenever generating the autodl JSON file
Works with
Categories
Diagnose and fix jira/invalid-bug on PRs by running the same 7 checks as the jira-lifecycle-plugin. Validate Bug is an agent skill from openshift-eng/ai-helpers.
Validate Bug fits situations like: development work in your project.
Run `npx skills add openshift-eng/ai-helpers --skill validate-bug -a claude-code`. Or copy the skill folder (plugins/jira/skills/validate-bug in openshift-eng/ai-helpers) into .claude/skills/validate-bug in your project. Claude Code loads it when a task matches its description.
Run `npx skills add openshift-eng/ai-helpers --skill validate-bug -a codex`. Or copy the skill folder (plugins/jira/skills/validate-bug in openshift-eng/ai-helpers) into .agents/skills/validate-bug in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add openshift-eng/ai-helpers --skill validate-bug -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/validate-bug, .gemini/skills/validate-bug, .github/skills/validate-bug and .opencode/skills/validate-bug in your project.
Going by SKILL.md and its folder, Validate Bug needs the command-line tools its instructions call (gh) and credentials named JIRA_KEY. Our summary lists: A credential in JIRA_KEY.
SKILL.md names 1 domain. In commands or code: github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Validate Bug is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.6k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Validate Bug: YugabyteDB Issue Creator (yugabyte/yugabyte-db, 11k stars), Code Review (croffasia/itsaplan, 895 stars), PR Body (SAP/spartacus, 784 stars) and Link Ticket To Session (JayantDevkar/claude-code-karma, 329 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
openshift-eng (a GitHub organization) maintains it in openshift-eng/ai-helpers, which has 120 GitHub stars. The repository holds 118 skills in this directory. The repository was last updated on October 6, 2026.
Source: openshift-eng/ai-helpers on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.