Parent: #440
Part of epic: "Enforce leased filesystem write-roots against the worker's actual diff"
ONE mechanism: a pure function in sandbox/policy.py (or a new sandbox/enforce.py) write_root_violations(changed_paths: Iterable[str], policy: CapabilityPolicy, *, base: str) -> tuple[str, ...] returning the subset of changed paths that fall outside EVERY entry in policy.filesystem.write_roots. No I/O, no git, no clock — paths and roots are injected, so identical inputs yield an identical tuple (mirrors operational_entropy.snapshot's injected-core style).
Primary acceptance criterion (one sentence, test-provable): a changed path normalized under any write_roots entry yields no violation, and a path outside every write_root (including escapes via .. or an absolute path beyond the worktree) appears in the returned tuple. Fail-safe semantics: an empty write_roots set means the worker had no write grant, so every changed path is a violation. Normalization reuses os.path.normpath as in worktree_sweep._norm so /wt/loop-5/../../etc/x resolves before the prefix test. ~80 net LOC incl. tests.
Customer story
An operator dispatching workers on a real repository without trusting their context or code needs one authoritative predicate that says which of a worker's changed paths fall outside its leased write_roots, so the escape can be detected deterministically rather than eyeballed.
Parent: #440
Part of epic: "Enforce leased filesystem write-roots against the worker's actual diff"
ONE mechanism: a pure function in sandbox/policy.py (or a new sandbox/enforce.py)
write_root_violations(changed_paths: Iterable[str], policy: CapabilityPolicy, *, base: str) -> tuple[str, ...]returning the subset of changed paths that fall outside EVERY entry in policy.filesystem.write_roots. No I/O, no git, no clock — paths and roots are injected, so identical inputs yield an identical tuple (mirrors operational_entropy.snapshot's injected-core style).Primary acceptance criterion (one sentence, test-provable): a changed path normalized under any write_roots entry yields no violation, and a path outside every write_root (including escapes via
..or an absolute path beyond the worktree) appears in the returned tuple. Fail-safe semantics: an empty write_roots set means the worker had no write grant, so every changed path is a violation. Normalization reuses os.path.normpath as in worktree_sweep._norm so/wt/loop-5/../../etc/xresolves before the prefix test. ~80 net LOC incl. tests.Customer story
An operator dispatching workers on a real repository without trusting their context or code needs one authoritative predicate that says which of a worker's changed paths fall outside its leased write_roots, so the escape can be detected deterministically rather than eyeballed.