Repository navigation
Add kb accept-unknown: judge an unknown knowledge commit through the gate (design v8 8.3) - #233
Conversation
…gate (design v8 8.3)
Until now an unknown commit (knowledge that reached main without passing
the gate) could only be disposed of by an exact revert. The design also
allows keeping it, but only when its governed content fully passes the
gate. This adds that path.
- `kb accept-unknown SHA` takes a unique prefix of 7+ hex characters. It
only validates the request and records it as accept_request:<sha>. It
exits 2 for something that is not an unknown commit, is ambiguous, or is
already disposed of. `kb serve` holds the ledger lease, so the scheduler
judges the request on its next tick (accept.accept_pending).
- The commit's own change (first parent to commit) goes through the full
gate as a change set of kind "accept": L1, L2, consistency and upstream
facts, with a current judge calibration required. It must lie inside one
enabled public repository scope, touch only governed pages, and not be a
root commit. While the service's revert PR is still being opened, the
request waits for the next tick.
- Only a pass disposes of the commit. disposed:<sha> is set to the commit
itself, so it is trusted wherever it is part of the history, and the
record is marked accepted. Its "unrecorded" intake candidate is dropped.
An open revert PR goes to superseding and gets a close item. The pause
is not lifted: `kb resume` stays a person's call.
- Acceptance can be resumed. After a pass, the record is first written as
"accepting". The disposal and "accepted" are written only after the
cleanup; the cleanup finds the candidate event directly (new
ledger.event_by_external_id, no scan) and closes the revert. A crash in
between is finished by the next tick without calling the judge again.
- Like external PRs, the rules L1 finds the commit retiring or purging are
kept on the accept change set. The cleanup records them in the
retirement ledger (idempotent upserts), so the next release sweep purges
them.
- Any other result leaves the commit undisposed, tells people why, and is
kept on the request record.
- `kb status` now lists open unknown commits with their accept request.
- Also: a stale comment in the scheduler ("human approvals") and the help
line for `kb control` (there is no hold list any more).
Tests (test_kb_accept_unknown.py):
- an accepted commit is disposed of; its revert PR is closed and its
candidate dropped; activation and the audit pass it; it is decided once;
- a request waits while its revert PR is being opened;
- a commit the gate rejects stays unknown, with its revert kept and people
told;
- no acceptance without a current calibration;
- a non-governed change cannot be accepted;
- requests are validated when recorded;
- nothing is judged without the lease;
- an interrupted acceptance is finished without judging again;
- the candidate is found behind more than 1000 pending events;
- an accepted retirement becomes purgeable at the next release;
- `kb status` lists open unknown commits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3359d7a450
ℹ️ 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".
| rt.ledger.stage_intake(rt.lease_owner, lifecycle.repo, changeset_id, kind=KIND, | ||
| status="accepted" if passed else "failed", verdicts=[], human_reason="", |
There was a problem hiding this comment.
Persist the acceptance recovery marker atomically
If the process stops after stage_intake commits here but before the unknown cursor is changed to accepting at lines 126–127, the request and unknown record still appear unprocessed. The next scheduler tick therefore runs the full gate again and creates another accept change set; a nondeterministic second judgment can even refuse a commit whose first judgment passed. Persist the recovery marker in the same transaction as the staged decision, or detect and reuse the existing accept change set by SHA.
Useful? React with 👍 / 👎.
Design v8 §8.3. This is the second way to dispose of an unknown knowledge commit, one that reached main without passing the gate. Instead of merging the exact revert, keep the commit, but only if it passes the full gate itself.
kb accept-unknown SHAtakes a unique 7+ hex prefix, validates the request and records it.kb serveholds the ledger lease, so the scheduler judges the request on its next tick.acceptchange set: L1, L2, consistency and upstream facts, with a current calibration required.kb resume.kb statuslists open unknown commits with their accept requests.Tests:
test_kb_accept_unknown.pyhas 10 cases:Commit hook (gpt-6-astra-high): APPROVE at iteration 3. Iterations 1–2 found the crash window, the event scan limit and the missing retirement bookkeeping; all are fixed and tested. The full kb suite is green.
🤖 Generated with Claude Code