I3118 — The edit guard's contract names every case it lets through, and each row has a test
Write the guard's decision table into docs (server unanswered, policy off, path outside the checkout, local state, no-file tool, own claim, task scope, another session's claim). Make guard.rs tests table-driven over it. Public text calls the guard blocking only for the rows that block.
READY wave 0 · p1 · implementation profile · parallel safe
Ready. Every dependency is done, so majordomus plan start I3118 will be accepted.
Objective
Write the guard's decision table into docs (server unanswered, policy off, path outside the checkout, local state, no-file tool, own claim, task scope, another session's claim). Make guard.rs tests table-driven over it. Public text calls the guard blocking only for the rows that block.
Why
On 2026-10-08 (c199#27) the owner's audit asked for an explicit fail-open versus fail-closed policy; the PR that wired the guard admits that writes pass when the server does not answer. On 2026-10-16 (c280#2) an audit found it described as if every unauthorised edit were blocked. This is a public-text-true fix about master's guard and does not wait on I2735 or I2289 (both BLOCKED); I2735 adds rows to the table when it lands. It extends milestone failure-is-visible. Sources: chatgpt-majordomus:c199#27, chatgpt-majordomus:c280#2.
Current state
I2735 desired_state lists the let-through cases. apps/majordomus-cli/src/guard.rs implements them. A search of docs/ for fail-open finds nothing about the guard.
Desired state
One table in the docs; the guard's unit tests iterate it; the mesh guarantee text cites it.
Scope
- apps/majordomus-cli/src/guard.rs
- docs/MESH.md
- docs/CLAIMS.yaml
- .ai/repo/rules/project/work-is-claimed-before-it-is-built.v1.md
Out of scope
- Changing fail-open to fail-closed (open question for the owner)
Dependencies
None. This issue is a root of the graph.
Acceptance criteria
- Every row of the table has a test of the same name
- No public sentence says every unclaimed edit is refused
- The table states the decisions guard.rs makes on master at the commit the issue starts from; I2735 adds rows when it lands
Validation
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --lib guard
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --test guard_hook
- MJ_TEST_JOBS=4 bash test/run.sh 3069_an_edit_no_claim_covers_is_refused
Evidence required
- guard_contract_table_tested
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3118.yaml. Read it back with majordomus plan show I3118.