Repository navigation
Govern pushes by the content Git actually receives - #23
Merged
Merged
Conversation
Recover the Codex_Kernel idea that governance should be derived from the pushed objects, not from what an agent said it would modify: - git_objects: derive changed paths from commits new to the repository (combined diff for merges, empty tree for roots), shared by the hook and the offline planner so both produce identical operation hashes. - Pre-receive enforces claimed scopes: changes outside the claim's scopes need an out_of_scope_push approval bound to the claim and paths. - Protected paths (repo protect-path / repo add --protected-path) need a protected_path_update approval on any ref. - Allowed ref namespaces: repositories accept refs/heads/ only until an operator opts other namespaces in with repo allow-ref. - approve prepare: plan a push from a clone, listing changed paths and every required operation with the hook's exact hash; --request opens them. - Multiple approvals for one push are all-or-nothing. - docs/agent-guide.md: agent operating and secret-handling guidance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
Deep-Sixed
marked this pull request as ready for review
September 29, 2026 22:34
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c261e064f0
ℹ️ 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".
…rned scopes main now carries #19, which rejects pushes that touch paths outside the claim's scopes. This branch makes those pushes approval-governed instead. Resolution keeps both: - #19's scope normalization/validation, case-insensitive overlap, and path_in_scopes matcher replace this branch's duplicate glob matcher. - This branch's git_objects path derivation (shared with approve prepare) replaces #19's _pushed_paths, so the hook and the planner agree on hashes. - Out-of-scope pushes are still rejected by default, with #19's wording, but can now proceed with an out_of_scope_push approval. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
- Refuse to plan from a clone that lacks a commit any hub ref points at; otherwise commits already governed in the hub look new locally and the derived paths and hashes differ from the hook's. - Derive the null OID from the other revision's length, so planned new refs and deletions match the hook in SHA-256 repositories. - Render non-UTF-8 path bytes as \xNN escapes so operations containing them can be hashed and stored instead of crashing the hook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
Deep-Sixed
pushed a commit
that referenced
this pull request
Sep 29, 2026
#23 added 005_content_governance.sql, so the quorum migration moves to 006_approval_quorum.sql. Conflicts were only in the migration lists (tests and README) and the repo policy command reference, resolved by keeping both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mc44WsAZx9hzZdWEihDk5a
This was referenced Sep 29, 2026
Deep-Sixed
pushed a commit
that referenced
this pull request
Sep 29, 2026
…e ref-transaction binding main's content governance (#23) can require several approvals for one ref update, where this branch recorded one operation and one approval. Resolved by keeping main's derivation (governed_operations over git_objects.changed_paths) and binding all of it to the transaction: - pre-receive derives the update's paths from the received objects, records them with the update, and consumes nothing. - The reference-transaction `prepared` stage re-derives the operations from those recorded paths against current governance state and consumes one approval per operation. Recording the paths matters in a non-atomic multi-ref push: by `prepared`, earlier refs have moved, which would change which commits look new and so the hashes. - Every consumed approval is linked in ref_update_approvals, so an abort (or `doctor --repair` of an aborted update) restores all of them. This branch's own scope enforcement and path helpers are dropped in favour of main's (#19, #23). The ref_updates migration is renumbered from 003 to 006: main already ships 004 and 005, and a gap-filling 003 would apply after them on existing stores but before them on new ones. The README now requires Git 2.28 (for the reference-transaction hook) instead of #18's 2.17. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014R4wfmENrMnt36KN1Kj6Fx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This brings back the most useful Codex_Kernel idea: governance should be based on what Git actually receives, not on what an agent said it planned to change.
What changes
git_objects.py: works out which paths a push changes, using only Git objects. It inspects only commits that are new to the hub (reachable from the pushed revision and from no existing ref). Merges use Git's combined diff, and root commits are compared with the empty tree. So mergingmaininto a feature branch doesn't countmain's changes against the pusher. The hook and the offline planner share this code, so they produce the same operation hashes.out_of_scope_pushapproval. That approval is tied to the claim ID and to exactly those paths. Branches with no claim get no scope check.repo protect-pathandrepo add --protected-path. Any push that changes a matching path needs aprotected_path_updateapproval, on any ref.refs/heads/only. An operator can allow more withrepo allow-ref <repo> refs/tags/. Migration005applies this to existing repositories too.approve prepare. Plans a push from a clone. It lists the changed paths, the claim, anything that would refuse the push outright, and every approval needed, with the exact hash the hook will ask for.--requestopens those approvals and--jsonprints the plan as JSON.docs/agent-guide.md: how agents should work day to day, plus guidance on keeping secrets out of the permanent audit, handoff and approval records.mainvia migration004. It is not changed here.Upgrade impact
out_of_scope_pushapprovals.Both are documented in the README.
Testing
tests/test_content_governance.py(26 tests) uses real pushes through the hook. It covers:preparehash matching the hook's hashprepare005.pyteston the final head (75f73ee, after mergingmainwith Normalize claim scopes and enforce them at push time #19): 180 passed.ruff checkandpyrightare clean.🤖 Generated with Claude Code
https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m