The write path for an OCX package index.
An OCX index is a static sparse HTTP tree — package roots at
/p/<namespace>/<package>.json pointing at content-addressed OCI image
indices, no server and no database. indexbot is the process that maintains
one: it validates announced roots against registry truth, regenerates derived
fields, enforces the governance contracts that let untrusted fork PRs announce
safely, and renders the wire tree a static host serves.
The reference deployment is ocx-sh/index (https://index.ocx.sh). Nothing here is specific to it: an index is one format with many copies, and every per-deployment input — the registry-host allowlist, the owners, the namespace — is committed data in the index repository, never a constant in this package.
Pre-release. 0.1.0 is the extraction of this bot out of
ocx-sh/index, which remains the reference deployment. Breaking changes ship without migration shims until 1.0 — pin an exact version in CI.
uv tool install ocx-indexbotPin it in CI instead of installing it loose — the bot runs in privileged workflow jobs, so its version belongs in a committed lockfile where a bump is a reviewed pull request.
| Subcommand | Purpose |
|---|---|
announce |
Record an owner-curated tag, CI-verified against the physical registry |
reconcile |
Verify committed index state against registry truth; file anomalies, never auto-heal |
validate |
The unprivileged PR gate — semantic checks a JSON Schema cannot express |
validate-pr |
The same gate as one command: resolve the PR's changed roots, their base-ref bytes and its provenance, then validate |
render |
Emit the served wire tree (config.json, /p/**, /c/index.json) |
seed-import |
Bulk-import package roots from mirror metadata |
classify-pr |
Route a pull request to the machine lane or the human lane |
governance-check |
The privileged gate: ownership, review requirements, auto-merge disposition |
governance-gate |
The same gate for one pull request, in one process: classify, label, gate, arm or withdraw auto-merge |
governance-poll |
The whole governance lane as a scheduled sweep — GitLab, which has no privileged pull-request trigger |
label-failed-run |
Label the pull request whose head a failed pipeline ran on |
stale |
Close abandoned pull requests, either forge, no third-party action |
ci |
Render this index's pipeline files from its committed policy, or check them for drift |
schema |
Print the shipped deployment-policy JSON Schema |
workflows-check |
Assert the CI-tree security invariants over an index repo's hand-written workflows (GitHub) or pipeline (GitLab) |
schema |
Print the JSON Schema for .github/index-policy.json |
The toolchain is provisioned by OCX itself. Install it once:
curl -sSL https://setup.ocx.sh | shocx.toml pins task, uv, git-cliff, actionlint, lychee and
gitleaks. Either prefix commands with ocx run --, or activate the project
(direnv allow, using the tracked .envrc) and run them bare:
task verify # format, lint, types, bandit, tests at 100% branch coverage, lockfile
task test # pytest only
task format # apply the formatterCI reaches the same state through ocx-sh/setup-ocx, so its steps run the
identical task <name>.
Apache-2.0. See LICENSE.