Docs
Guide

Publish requirement health

Publish the requirement-health report and badge on GitHub Pages so proof status is visible on every pull request.

Publish a continuously updated Kibi requirement-health report on GitHub Pages, with a clickable % tested badge in the repository README.

Badge and report are one feature. Someone who sees 87% tested needs to open the report to see what that percentage represents and which requirements are missing proof. Kibi does not host badges or reports; GitHub Pages is the expected publisher. Knowledge stays in the repository's .kb/ directory.

What the badge means

A badge such as kibi | 87% tested is the share of applicable current Kibi requirements that have current proof. Non-current (for example superseded) requirements are excluded, as are requirements marked not applicable to proof.

The published HTML report is the place to inspect:

  • which requirements are tested end to end
  • which are missing proof
  • contradictions
  • stale verification state
  • other requirement-health details already exposed by kibi report

The badge and index.html always come from one kibi report coverage snapshot. Do not compute a separate GitHub-only percentage.

1. Enable GitHub Pages

In GitHub:

text
Settings → Pages → Source → GitHub Actions

This is the only expected GitHub UI step. Kibi does not change repository settings for you.

2. Add the Kibi workflow

Copy the canonical workflow to:

text
.github/workflows/kibi-report.yml

The file to copy is docs/examples/github/kibi-report.yml. It is byte-identical to the template shipped in kibi-cli.

One build-report job generates the report. Pull requests validate that generation and upload the candidate site as an ordinary workflow artifact. Only the repository default branch (it does not assume the branch is named main) and workflow_dispatch may deploy GitHub Pages. A pull_request event never deploys Pages, never replaces the canonical report or badge, and never receives pages: write or id-token: write. The workflow uses pull_request, not pull_request_target, with repository-level contents: read. GitHub Actions checkouts are detached, so the workflow sets KIBI_BRANCH to the pull-request head ref or the pushed/dispatched branch name before kibi sync and kibi report.

The generate job:

  1. checks out the candidate GitHub Actions ref (the PR merge commit on pull requests, otherwise the pushed or dispatched commit)
  2. sets up Node.js
  3. installs project dependencies with npm (SWI-Prolog arrives with them as the bundled kibi-swipl-linux-x64-gnu package, so there is no separate install step)
  4. runs kibi sync
  5. runs kibi report --output kibi-report (the job fails if this fails)
  6. on pull_request, uploads the kibi-report/ directory as the kibi-pr-report artifact (HTML report plus badge)
  7. on the default branch or workflow_dispatch, copies that output under pages/kibi-report/ so the public path is /kibi-report/ and uploads it as a GitHub Pages artifact

The deploy-report job then deploys that Pages artifact. It does not run for pull requests. Pushes to non-default branches start the workflow and skip both jobs. The workflow does not build or test the rest of the application, does not commit generated files, and does not use an orphan gh-pages branch.

3. Add the clickable badge

markdown
[![Kibi requirement health](https://OWNER.github.io/REPOSITORY/kibi-report/badge.svg)](https://OWNER.github.io/REPOSITORY/kibi-report/)

Replace OWNER with the repository owner (lower case is fine, since the *.github.io host is case-insensitive) and REPOSITORY with the repository name exactly as GitHub spells it. The project-site path is case-sensitive, so MyRepo and myrepo are different URLs. Clicking the badge must open the report. Files are published under /kibi-report/ so Kibi does not occupy the Pages site root.

This workflow still replaces the GitHub Pages deployment. If the repository already publishes a site, copy kibi-report/ into that site's output instead of using this workflow as the only deploy.

Expected URLs

Repository Report Badge
OWNER/REPOSITORY https://OWNER.github.io/REPOSITORY/kibi-report/ https://OWNER.github.io/REPOSITORY/kibi-report/badge.svg
Owner/MyRepo (mixed case) https://owner.github.io/MyRepo/kibi-report/ https://owner.github.io/MyRepo/kibi-report/badge.svg
OWNER/OWNER.github.io (owner site) https://OWNER.github.io/kibi-report/ https://OWNER.github.io/kibi-report/badge.svg

The image URL must be anonymously reachable for GitHub to render it in a public README. For a private report, publish both files to an authenticated static host that your intended audience can access. GitHub Actions artifacts expire and are not a stable badge URL.

Do not commit generated kibi-report/ files.

CLI shortcut

kibi init --github performs normal kibi init behavior, then scaffolds the same documented integration:

bash
kibi init --github

It:

  • writes .github/workflows/kibi-report.yml from the packaged template
  • adds the clickable badge to an existing root README when a github.com remote can be determined
  • adds kibi-report/ to .gitignore when missing
  • prints the Pages enable instruction

It is safe to run more than once. Matching workflows are left as already configured. Customized workflows are not overwritten. An existing Kibi badge is not duplicated. If no README exists, the workflow is still written and the badge Markdown is printed. If owner/repository cannot be determined from a github.com remote, the workflow is still written and placeholder badge Markdown is printed instead of inventing a URL.

Package-manager adaptations

The canonical workflow uses npm because that matches the documented Kibi install (npm install --save-dev kibi-cli ... and npm exec -- kibi).

Change only the Node setup cache and the install/exec commands:

pnpm

yaml
- uses: actions/setup-node@v5
  with:
    node-version: 24
    cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec kibi sync
- run: pnpm exec kibi report --output kibi-report

Install the pnpm action (pnpm/action-setup) before setup-node if the runner does not already have pnpm.

Yarn

yaml
- uses: actions/setup-node@v5
  with:
    node-version: 24
    cache: yarn
- run: yarn install --frozen-lockfile
- run: yarn kibi sync
- run: yarn kibi report --output kibi-report

Bun

yaml
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bunx kibi sync
- run: bunx kibi report --output kibi-report

Keep kibi-cli as a project dependency so CI uses the version the repository pinned. Do not add application build or test steps just to generate the report.

Badge-only opt-out

Prefer the full report. To publish only the badge:

bash
kibi init --github --badge-only

Or copy docs/examples/github/kibi-badge.yml to .github/workflows/kibi-badge.yml.

That workflow still runs kibi report (same snapshot, same % tested). Pull requests upload the generated report directory as kibi-pr-report and still do not deploy Pages. Default-branch and workflow_dispatch publishes only badge.svg under /kibi-report/. The README link should point at this section rather than pretending a report exists:

markdown
[![Kibi requirement health](https://OWNER.github.io/REPOSITORY/kibi-report/badge.svg)](https://looted.github.io/kibi/guide/github-integration.html#what-the-badge-means)

--badge-only without --github is rejected. --github by itself always means badge + full report.

Merge conflicts in Kibi manifests

Two branches that each add symbols both append to the end of .kb/symbols.yaml (and sometimes to the same .kb/relationships/*.yaml shard), so Git reports a conflict even though the additions are independent. kibi merge-driver is a Git merge driver that merges these manifests by record id instead of by line:

  • records added on either side are kept (ours first, then theirs)
  • an edit made on only one side wins over the unchanged other side
  • a deletion on one side is kept when the other side left the record unchanged
  • relationships and links that both sides added to one symbol are unioned
  • anything else both sides changed differently (for example two different status values) is a real conflict: the driver names it, leaves ordinary conflict markers, and exits non-zero so the file stays unmerged

.kb/symbol-coordinates.yaml is a gitignored local cache derived by every kibi sync, so it never takes part in a merge.

Locally

Declare the driver in the repository's .gitattributes:

text
.kb/symbols.yaml merge=kibi
.kb/relationships/*.yaml merge=kibi

Then each clone opts in once (Git never runs a driver from repository content alone):

bash
git config merge.kibi.driver "npm exec --no -- kibi merge-driver %O %A %B"

Without that setting Git ignores the attribute and falls back to its normal line merge, so declaring it is safe for contributors who do not use Kibi.

In CI

Copy docs/examples/github/kibi-kb-merge.yml to .github/workflows/kibi-kb-merge.yml. On every push to the default branch it test-merges each open same-repository pull request with git merge-tree. When the only conflicts are Kibi manifests, it merges the default branch into the PR branch with kibi merge-driver and pushes the merge commit. A branch that still tracks .kb/symbol-coordinates.yaml from before schema 13 has it removed in that merge. Pull requests with any other conflict, or a real conflict inside a manifest, are left untouched for a person. Fork pull requests are skipped because the workflow cannot push to them.

The merge driver and kibi sync run from the default branch's install of kibi-cli, not the pull request's, so branches opened before the driver existed are still handled. The default branch therefore needs a kibi-cli version that includes kibi merge-driver.

Pushes made with the default GITHUB_TOKEN do not start other workflows, so the pull request's checks would not re-run on the merge commit. Add a repository secret named KIBI_MERGE_TOKEN and the workflow pushes with it instead. Use a fine-grained personal access token or GitHub App token limited to the repository, with Contents and Workflows set to read and write. Workflows access is needed because a merge that brings in changes under .github/workflows/ is rejected without it; the default GITHUB_TOKEN can never push those merges. An expired secret fails the job rather than falling back to GITHUB_TOKEN, so renew it or delete the secret. The same package-manager adaptations as the report workflow apply.

Troubleshooting

The workflow succeeds but https://OWNER.github.io/REPOSITORY/kibi-report/ is 404. Enable Settings → Pages → Source → GitHub Actions. Until that is set, Pages deployments do not go live. The report is not at the Pages site root.

The badge image is a broken picture in the README. The SVG URL must be anonymously reachable. Private Pages sites will not render in public READMEs. Confirm /kibi-report/badge.svg loads in a logged-out browser.

The workflow is skipped on every feature-branch push. Report generation runs on pull_request, workflow_dispatch, or a push to the repository default branch. Pushes to other branches start the workflow and then skip the jobs. Open a pull request to validate a candidate report, change the GitHub default branch, or use Run workflow for a one-off publish. GitHub Pages still deploys only from the default branch or workflow_dispatch.

kibi: command not found or npm exec -- kibi fails. Install kibi-cli as a project dependency and commit the lockfile. The workflow does not install Kibi globally.

Kibi could not find a usable SWI-Prolog. The workflow relies on the bundled runtime that npm ci installs on ubuntu-latest (Linux x64, glibc). It is missing when the install skipped optional dependencies (--omit=optional, --no-optional, pnpm supportedArchitectures that excludes the runner's platform) or the lockfile lacks the platform package. Install with the package manager's defaults, or add kibi-swipl-linux-x64-gnu explicitly. On a runner without a bundled build (Alpine/musl containers, self-hosted Windows), install SWI-Prolog 9.0+ from the SWI-Prolog PPA or your platform package manager and put swipl on PATH; see Installation.

Pages published the wrong site / two Kibi workflows. A repository can host one Pages site. Keep either kibi-report.yml or kibi-badge.yml, not both.

kibi init --github did not overwrite my workflow. If .github/workflows/kibi-report.yml already exists and differs from the template, Kibi leaves it in place. Compare it with docs/examples/github/kibi-report.yml.

Owner/repository could not be determined. kibi init --github only parses github.com remotes (HTTPS or SSH). GitHub Enterprise hosts are not auto-filled. The workflow is still written; paste the printed badge Markdown after replacing OWNER/REPOSITORY.