Skip to content

Add the kb-gate verifier, its pinned bundle and workflow - #209

Merged
tzhouam merged 1 commit into
mainfrom
kb/gate-verifier
Sep 28, 2026
Merged

tzhouam merged 1 commit into
mainfrom
kb/gate-verifier

Conversation

@tzhouam

@tzhouam tzhouam commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

PR 6 of the knowledge-service redesign: the repository-side required check kb-gate.

  • Verifier (knowledge_service/gate_verifier.py, vendored into .github/kb-gate/):
    • reads PRs only as git objects;
    • passes non-knowledge changes;
    • a knowledge change needs:
      • a valid Ed25519 verdict bound to the repository, PR and head, inside its window;
      • a base-independent manifest match;
      • L1 on the change and on the landing tree (including dangling references to retired rules);
      • for auto: the block table and consistency hashes, plus context-base invalidation;
      • for human-approved: a live maintainer approval on the current head plus the label (this replaces the whitelist, not the rest of L1);
      • no kb:hold, and a fresh signed hold list that doesn't hold the PR or its scope.
  • Two stages, one name:
    • PR precheck (pull_request_target / verdict comments / dispatch): posts the kb-gate status on the verified head.
    • merge_group job kb-gate: verifies every first-parent segment against its own first parent.
  • Bundle: tools/build_kb_gate_bundle.py generates it; requirements.lock is hash-pinned (verified to install with --require-hashes on 3.12); MANIFEST.sha256 is checked before the verifier runs; CI --check is a non-blocking reminder.
  • .github/CODEOWNERS: maintainers own .github/, knowledge/{tools,skills,.claude}; governed pages have no code owner on purpose.
  • test.yml gains merge_group.

Effect once merged: every PR gets a kb-gate status. Code PRs pass. Knowledge PRs fail closed until the owner commits .github/kb-gate.pub, sets holds_url in .github/kb-gate/config.json, and adds a second maintainer to CODEOWNERS. The check is not required until the ruleset is configured.

Not in this PR: the service does not yet issue human-approved verdicts.

Commit hook approved; full suite, SPEC freshness and doc linters pass locally.

🤖 Generated with Claude Code

The repository-side required check for knowledge PRs.

- knowledge_service/gate_verifier: verifies a knowledge change from git
  objects only (the PR is never checked out or executed). A change that does
  not touch knowledge/ passes. A knowledge change needs a valid Ed25519
  verdict bound to this repository, PR and exact head, inside its issue
  window; a signed manifest equal to the change as applied (base
  independent); L1 on the change and on the tree that would land. Rules it
  retires or purges must not be cited anywhere in that landing tree. For auto:
  a block table equal to the L1 blocks, all passing, and consistency
  judgements covering the same owner directories whose page hashes match the
  landing tree. The context set must not have changed between the judged base
  and the effective base. For human-approved: the bound reviews are still
  APPROVED on this head, one of them by a knowledge maintainer (CODEOWNERS of
  .github/kb-gate/), and the label is present; the approval replaces the
  auto-merge whitelist (knowledge/tools, skills, scripts, mixed PRs) but not
  the rest of L1. In both cases: no kb:hold, and
  the signed hold list is fresh and holds neither the PR nor its scope
  (repository name, or "general" for knowledge/general/). It fails closed
  without a public key, a hold-list URL, an attributable merge group, or with
  upstream fact attestations it cannot re-check.
- Two stages under one name: the PR precheck (pull_request_target, verdict
  comments, dispatch) posts the kb-gate status on the head it verified; the
  merge_group job verifies every first-parent segment (two-parent merge
  commits, PR looked up by its head) against its own first parent.
- tools/build_kb_gate_bundle.py vendors the verifier and its L1/lifecycle/ops/
  signing/verdict siblings into .github/kb-gate/, with a hash-pinned
  requirements.lock and MANIFEST.sha256; the workflow installs with
  --require-hashes and runs only from there. The CI --check is a reminder
  and does not block.
- .github/CODEOWNERS makes knowledge maintainers own .github/, knowledge/tools,
  knowledge/skills and knowledge/.claude; governed pages have no code owner.
- test.yml also runs on merge_group (a merge-queue prerequisite).

Not in this change: the service does not yet issue human-approved verdicts
(polling kb:human-approved and checking the approval); until then only auto
verdicts exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T12:57:29.109855Z 182a8c1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@tzhouam
tzhouam merged commit 1671a31 into main Sep 28, 2026
2 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 182a8c15eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for review_id in verdict.get("review_ids") or []:
review = ctx.github.get(f"/repos/{ctx.repository}/pulls/{number}/reviews/{int(review_id)}")
login = str((review.get("user") or {}).get("login") or "").lower()
if review.get("state") != "APPROVED":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject approvals superseded by a later review

Fetching only each signed review ID does not establish the reviewer's current decision: when a maintainer approves and later submits a new CHANGES_REQUESTED review, GitHub creates another review while the earlier review object can remain APPROVED. The old signed ID therefore still adds that maintainer to approvers, allowing a human-approved verdict—which bypasses L2 and the automatic path whitelist—to pass after its approval was withdrawn. Evaluate the latest effective review state for each bound reviewer (or the PR's aggregate review decision), not only the historical review objects named in the verdict.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant