Repository navigation
Commit 09303ec
Catch, block and revert knowledge changes that bypassed the gate (design v8)
Without GitHub-side enforcement, a person can still merge or push a
knowledge change the gate never saw. The service now catches it on the next
tick, keeps it from being served, and opens a revert.
- audit (provenance) runs every scheduler tick, no longer daily. Each
first-parent commit on main that touches knowledge/ is classified as:
- trusted: a recorded merge SHA, or a two-parent merge of a recorded head
carrying only that head's change;
- pending: a merge of a head whose merge item still waits for its receipt;
looked at again next tick;
- disposed: an exact revert of it was merged;
- unknown: anything else. An inexact revert merge is itself unknown.
- For an unknown commit the service:
- pauses the repositories it touched (everything outside a repository
scope);
- records unknown:<sha> and alerts people;
- sends its content back to intake as a new candidate (event source
"unrecorded");
- opens a revert PR that restores the governed paths to their first-parent
content. The publisher builds it and it is NEVER merged automatically;
open_revert_pr is always executable, since it is issued because the
repository was paused.
A path changed again since (the revert would conflict), or a non-governed
path, goes to people instead. Without the lease the revert is recorded as
revert_pending and issued by the next pass that holds it.
- A merged revert disposes of the unknown commit only if it is exact: the PR
merged the revert commit the publisher built, and on governed paths the
merge changed exactly the reverted paths back to their pre-images.
disposed:<sha> records the pair. A closed revert leaves it undisposed and
alerts people.
- Exactness compares tree entries (mode and content). A revert made by hand
is recognised the same way. The set is every undisposed unknown commit
sharing a knowledge path with the new commit, closed transitively (an
earlier partial revert is itself one of them). The new commit disposes of
the set when it changes only the set's paths and, after it, EVERY path the
set touched, governed or not, holds its tree entry from before the earliest
commit (ordered by ancestry): together they changed nothing. The unknown
record keeps the complete path list and the entries of all its knowledge
paths, uncapped, so conflict detection and exactness cover every path.
A disposed commit is trusted only while its disposing revert is part of
the history being checked, so main rewound past the revert brings it back.
A revert PR or intake candidate is created only when EVERY repository
scope the commit touches may publish; a commit touching a private upstream
goes to people. A merged
revert PR is settled only after fetching, so a fresh merge is never
mistaken for another unknown change.
- activate() itself, and so `kb activate`, refuses any SHA with an unknown or
pending knowledge commit between the active snapshot and it (the first
activation has no baseline). The scheduler checks the same before
activating and records activation_blocked, and nothing is activated while
an unknown commit is undisposed (the G5 exception in the design).
- The intake event for an unknown commit carries its diff, not just its
message and file names.
- The signed control record now carries provenance: the active snapshot and
the trusted list (merge SHAs plus disposal pairs). Before merging, the
publisher checks that every governed knowledge commit on main since the
active snapshot is trusted or one of its own merges; otherwise it refuses
(transient: the service pauses and reverts).
Not implemented yet: kb accept-unknown (accepting the unknown content instead
of reverting). For now a merged exact revert, the service's or one made by
hand, lifts the block.
Tests: an unknown change is paused, blocks activation, is reverted and sent
back to intake, and is handled once; an exact revert disposes of it and both
commits become trusted; a revert merged with other changes disposes of
nothing and is caught itself; a conflicting revert goes to people; nothing is
activated while an unknown change is open, and activation resumes after the
revert; the publisher refuses to merge on top of an unknown change; our own
merge waiting for its receipt is not unknown; a revert merged with a mode
change is not exact; a hand-made revert disposes of what it undoes;
activate() refuses a commit that passed no gate; the intake event carries
the diff; a revert is settled without the test pre-fetching; a revert must
restore non-governed paths too (a partial revert keeps the block, and a
second completes it); a hand revert of an AGENTS-only change clears it; a
later edit to the 54th of 55 paths makes the revert conflict; rewinding
main past a revert brings the unknown change back; a commit touching a
private scope is never reverted in public.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>1 parent cd48103 commit 09303ec
12 files changed
Lines changed: 738 additions & 87 deletions
File tree
- doc
- architecture/SPEC
- features
- src/infermatrix_copilot/kb_service
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
241 | 241 | | |
242 | 242 | | |
243 | 243 | | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
69 | 71 | | |
70 | 72 | | |
71 | 73 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | | - | |
139 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
140 | 143 | | |
141 | 144 | | |
142 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
143 | 152 | | |
144 | 153 | | |
145 | 154 | | |
| |||
0 commit comments