Skip to main content

Module guard

Module guard 

Source
Expand description

The edit guard (I2735): before a provider’s tool writes a file of this checkout, is the path claimed?

A session reaches the mesh at its start (I2734), a task’s scope is claimed there by start (I2288), and a task completed off the mesh is refused (I2289). None of that stops a worker from editing a file nobody claimed: the claim was a convention until the edit itself asked for one. This is the asking. It answers one question — may this session write this path now — from four facts, each read without building the index, because it runs before every edit a provider makes:

  1. the policy switch session.edits_require_claim, off unless a repository turns it on;
  2. whether the repository declares its mesh enabled — a repository without a mesh has no claims to be covered by;
  3. the active task’s scope, which start has claimed on the mesh as task-<id>;
  4. the live claims the mesh holds for the session doing the writing.

What it cannot decide it lets through and says why: an unreadable policy, no server to ask, a mesh state that does not parse. Refusing an edit because a probe failed would make a checkout nobody can serve a checkout nobody can edit, which is worse than the edit it would have stopped; I2289 still refuses the completion of such work.

One edit, from the path a provider names to the verdict it reads:

use std::path::Path;
use majordomus_cli::guard::{judge_facts, relative_to, ClaimSource, EditFacts};

// a provider is about to write this file of the checkout at /work/repo
let root = Path::new("/work/repo");
let asked = "/work/repo/docs/MESH.md";
let rel = relative_to(root, asked);
assert_eq!(rel.as_deref(), Some("docs/MESH.md"));

// the facts gathered for it: the policy asks for a claim, the mesh is on, a task claims lib
let scope = vec!["lib".to_string()];
let facts = EditFacts {
    required: Ok(true),
    mesh_enabled: true,
    task: Some(("t-1", &scope[..])),
    session: Some("claude-code-s1"),
    claims: ClaimSource::Claims(vec![]),
};
let verdict = judge_facts(asked, rel.as_deref(), facts);
assert!(!verdict.allowed, "neither the task nor a claim of the session covers docs");
assert!(verdict.remedy.unwrap().contains("majordomus start"));

Structs§

EditFacts
The facts one edit is judged from, gathered by the caller so that this function reads nothing and can be proved on every combination.
EditVerdict
The answer to one edit: whether it may proceed, the one word it was decided on, the sentence a person reads and, for a refusal, what would allow it. guard.edit returns it as it is; guard hook turns it into an exit code.

Enums§

ClaimSource
Where the guard reads the mesh’s live claims: the running server’s own state, or that server asked over HTTP, or nothing when no server answers.

Functions§

active_task
The active task of the checkout at root: its id and scope, while its outcome is active.
covers
Whether a claim on claim covers a write to path: the same path, an ancestor of it, or the whole repository (.).
edits_require_claim
session.edits_require_claim of the repository at root, or why its policy could not be read — which judge_facts answers by enforcing nothing.
from_payload
The path a provider’s pre-tool payload names, and the provider’s own session id: the fields Claude Code sends (tool_input.file_path, tool_input.notebook_path, session_id). None when the payload names no path — a tool that writes no file.
judge
Judge an edit of path by session in the checkout at root, reading every fact. claims is asked only when the cheaper facts have not already decided.
judge_facts
Judge one edit of rel (repository-relative, or None when outside the checkout).
mesh_declared_enabled
Whether the repository at root declares its mesh enabled: a declaration under .ai/repo/mesh/ whose top-level enabled is true. Read from the files, not the index: this runs before every edit.
relative_to
path relative to root, when it is inside it: absolute or relative to root, with . and .. resolved lexically, so a file that does not exist yet — the commonest thing a tool writes — is placed as surely as one that does. None outside the checkout.
server_claims
The live claims of the checkout’s shared server, asked over HTTP from outside it.