git¶
A trusted clauz3 layer for running local git from a proved program, with
subcommand, location, and push-target policies an agent can prove before any
command runs.
These effects are real, not mocks: git shells out to the git binary and
git_push actually pushes. The prover never runs their bodies — it records each
call as a fact and proves the contract. The bodies run only under clauz3 run,
after a program is proved and approved. Arguments are passed as an explicit
vector (never a shell string), so a subcommand and its arguments cannot smuggle
extra commands.
Install¶
This copies tools/git/ into your project. Then prove a program against it:
Effects¶
Import with from tools.git.trusted.effects import git, git_push:
git(subcommand: str, args: list[str], cwd: str) -> str— rungit <subcommand> <args...>incwdand return its stdout. Precondition:subcommandandcwdnon-empty.git_push(remote: str, branch: str, cwd: str) -> str— pushbranchtoremotefrom the repo atcwd. Precondition: all three non-empty.
Contracts¶
Import with from tools.git.trusted import contracts as git_rules:
git_rules.no_guarantees()— explicit null contract.git_rules.no_git()— the program runs no local git subcommands (does not by itself forbidgit_push; stackno_push()).git_rules.read_only()— every subcommand is a read-only inspection command (READ_ONLY_SUBCOMMANDS:status,log,diff,show,branch, ...).git_rules.only_subcommands(allowlist)— every subcommand is inallowlist.git_rules.never_subcommands(blocklist)— no subcommand is inblocklist.git_rules.only_in(root)— every subcommand runs in a directory underroot.git_rules.runs_at_most(count)— at mostcountsubcommands run.git_rules.no_push()— the program performs no pushes.git_rules.only_push_to_remote(remote)— every push targetsremote.git_rules.only_push_to_branch(branch)— every push targetsbranch.
read_only, only_subcommands, and never_subcommands are subcommand-name
policies; only_in is a path-prefix policy compiled to str.startswith.
Example¶
import clauz3
from tools.git.trusted import contracts as git_rules
from tools.git.trusted.effects import git, git_push
@clauz3.guarantee(git_rules.never_subcommands(["reset", "clean"]))
@clauz3.guarantee(git_rules.only_in("/repo"))
@clauz3.guarantee(git_rules.only_push_to_branch("main"))
def main() -> None:
git("add", ["-A"], "/repo")
git("commit", ["-m", "automated update"], "/repo")
git_push("origin", "main", "/repo")
Stacking guarantees confines the program to a single working tree, forbids
destructive subcommands, and pins the push target to main. A git("clean", ...)
or a git_push("origin", "release", ...) would fail the proof.
Tests¶
tests/cases/*_pass.py must prove; tests/cases/*_fail.py must not.
Source¶
src/clauz3/stdlib/git/tools/git/trusted/effects.py
"""Trusted git effects: real (non-mock) local ``git`` subprocesses.
The workhorse ``git`` effect runs any git subcommand in a working directory and
returns its stdout. It is recorded by name so the contracts in
``contracts.py`` can scope *which* subcommands an agent may run (the headline
``read_only`` guard), *where* they run, and *how many* times.
``git_push`` is split out as its own effect: pushing is the one
local-git operation that mutates a remote and touches the network, so its
remote and branch target deserve their own policy surface rather than being
folded into an opaque argument list.
The bodies shell out with an explicit argument vector (never a shell string),
so a subcommand and its arguments cannot smuggle extra commands. Each body uses
``subprocess.run``, so ``syscall`` is declared among their deal markers. The
prover never runs these bodies — it records each call as a fact and proves
the declared contracts. The bodies run only under ``clauz3 run``.
"""
import subprocess
import deal
import clauz3
from clauz3._path_safety import has_no_parent_segments
DEFAULT_TIMEOUT_SECONDS = 120
@clauz3.requires(
lambda subcommand, args, cwd: has_no_parent_segments(cwd),
message="cwd must not contain parent-directory segments",
)
@clauz3.requires(
lambda subcommand, args, cwd: len(subcommand) > 0 and len(cwd) > 0,
message="subcommand and cwd must be non-empty",
)
@deal.has("io", "syscall")
@clauz3.trusted
def git(subcommand: str, args: list[str], cwd: str) -> str:
"""Run ``git <subcommand> <args...>`` in ``cwd`` and return its stdout.
Arguments are passed as an explicit vector, so neither ``subcommand`` nor
any entry of ``args`` is interpreted by a shell. Which subcommands may run
(e.g. ``read_only``) and where they may run (``only_in``) are agent-stated
guarantees over the ``git`` effect.
"""
completed = subprocess.run( # noqa: S603
["git", "-C", cwd, subcommand, *args],
capture_output=True,
text=True,
timeout=DEFAULT_TIMEOUT_SECONDS,
check=True,
)
return completed.stdout
@clauz3.requires(
lambda remote, branch, cwd: has_no_parent_segments(cwd),
message="cwd must not contain parent-directory segments",
)
@clauz3.requires(
lambda remote, branch, cwd: len(remote) > 0 and len(branch) > 0 and len(cwd) > 0,
message="remote, branch, and cwd must be non-empty",
)
@deal.has("network", "io", "syscall")
@clauz3.trusted
def git_push(remote: str, branch: str, cwd: str) -> str:
"""Push ``branch`` to ``remote`` from the repository at ``cwd``.
Recorded as its own effect so ``contracts.no_push()`` can forbid
pushing entirely, while ``only_push_to_remote`` / ``only_push_to_branch``
pin the destination an agent is allowed to publish to.
"""
completed = subprocess.run( # noqa: S603
["git", "-C", cwd, "push", remote, branch],
capture_output=True,
text=True,
timeout=DEFAULT_TIMEOUT_SECONDS,
check=True,
)
return completed.stdout
src/clauz3/stdlib/git/tools/git/trusted/contracts.py
"""Git subcommand and push policies built from generic trusted effect facts.
Local git subcommands are recorded as the ``git`` effect and pushes as
``git_push`` (see ``effects.py``). These contracts let an agent state which
subcommands it may run, where they run, how many run, and — for pushes — which
remote and branch it is allowed to publish to.
``read_only`` is the headline guard: it pins every subcommand to a fixed set of
inspection commands that cannot mutate the working tree, the index, or any
remote, which is exactly what you want when handing a repository to an agent
that should only look.
"""
from tools.git.trusted.effects import git, git_push
from clauz3.spec import ContractSpec, contract, effect
from clauz3.spec import no_guarantees as core_no_guarantees
Git = effect(git)
Push = effect(git_push)
#: Subcommands that only read repository state — they touch neither the working
#: tree, the index, nor any remote. ``read_only`` pins every subcommand to this
#: set. Deliberately excludes network commands like ``fetch``/``pull`` and any
#: mutation (``commit``, ``checkout``, ``reset``, ``clean``, ``rebase``, ...).
READ_ONLY_SUBCOMMANDS = [
"status",
"log",
"diff",
"show",
"branch",
"remote",
"rev-parse",
"ls-files",
"ls-tree",
"blame",
"describe",
"tag",
"shortlog",
"reflog",
"cat-file",
"config",
]
@contract
def no_guarantees() -> ContractSpec:
"""Make no guarantees about git effects."""
return core_no_guarantees()
@contract
def no_git() -> ContractSpec:
"""Guarantee the program runs no local git subcommands.
Does not by itself forbid ``git_push``; stack ``no_push()`` for that.
"""
return Git.empty()
@contract
def read_only() -> ContractSpec:
"""Guarantee every git subcommand is a read-only inspection command.
Pins each subcommand to ``READ_ONLY_SUBCOMMANDS``, so the program cannot
mutate the working tree, index, or any remote via the ``git`` effect.
"""
return Git.all(lambda e: e.subcommand in READ_ONLY_SUBCOMMANDS)
@contract
def only_subcommands(allowlist: list[str]) -> ContractSpec:
"""Guarantee every git subcommand is in ``allowlist``."""
return Git.all(lambda e: e.subcommand in allowlist)
@contract
def never_subcommands(blocklist: list[str]) -> ContractSpec:
"""Guarantee no git subcommand is in ``blocklist``.
Useful to veto specific destructive subcommands (``reset``, ``clean``,
``rebase``) while leaving the rest of git available.
"""
return Git.all(lambda e: e.subcommand not in blocklist)
@contract
def only_in(root: str) -> ContractSpec:
"""Guarantee every git subcommand runs in a directory under ``root``."""
return Git.all(lambda e: e.cwd.startswith(root))
@contract
def runs_at_most(count: int) -> ContractSpec:
"""Guarantee at most ``count`` git subcommands run."""
return Git.count() <= count
@contract
def no_push() -> ContractSpec:
"""Guarantee the program performs no git pushes."""
return Push.empty()
@contract
def only_push_to_remote(remote: str) -> ContractSpec:
"""Guarantee every push targets the remote named ``remote``."""
return Push.all(lambda e: e.remote == remote)
@contract
def only_push_to_branch(branch: str) -> ContractSpec:
"""Guarantee every push targets the branch named ``branch``."""
return Push.all(lambda e: e.branch == branch)
All cases¶
Browse the full set on the all-cases page.