agent-guard 0.7 🚀 AI Test Security: Tampering Stop
Discover agent-guard 0.7 for AI agent test security: prevents test tampering, automates code review, and records developer audit logs. Review before shipping.

How agent-guard 0.7 Handles Legitimate Test Changes
A test-tampering guard has to walk a tight line. It should stop an AI coding agent from weakening tests, but it also shouldn't block normal maintenance every time a test file changes. If you update a snapshot after an API rename, add a fixture, or fix a flaky timing test, a blunt "tests changed" rule can trigger the same alarm as removing an assertion.
That's more than annoying. If the guard trips too often, developers will either route around it or disable it entirely. You can end up with something that looks strict on paper and doesn't help much in the real workflow.
agent-guard 0.7 changes that trade-off. Instead of treating every test edit as equally suspicious, its Stop hook compares changed test files against copies captured at session start. It then labels each edit as legitimate, malicious, or ambiguous. Clearly harmful changes stay blocked. When the classifier can't make a confident call, the change is also blocked. And if an ambiguous change is truly needed, the release adds an explicit escape hatch that's logged.
This article walks through what changed, how the review and bypass workflows fit together, and what the heuristic approach does - and doesn't - guarantee.
Why test-change detection needs more than a binary rule
A test suite is part of the system's safety net. If an agent changes application code and also weakens the tests that are supposed to catch regressions, you can get a "green" test run that's really just false confidence. That's the problem a test-tampering guard is meant to catch.
But test files aren't static. They change constantly during ordinary development. A team may add a new test, move shared setup into a helper, update expected output after a deliberate behavior change, or repair a flaky timing test. Those changes can look a lot like suspicious edits in a diff - assertions can disappear, expected values can shift, and tests can be rearranged.
The false-positive problem
A binary rule - "any test file changed, therefore block" - is simple to describe and hard to live with. It catches suspicious edits, but it also stops legitimate work. When teams hit that kind of friction repeatedly, they tend to respond in familiar ways: disable the guard, build an informal workaround, or approve changes without looking too closely.
None of that improves security. The point of a guardrail isn't to maximize blocks. It's to help people make the right call while staying usable during day-to-day development.
There's also a second issue: intent doesn't always come through in a diff. If an expected value changes, it might be a valid snapshot refresh after an API change - or it might be an attempt to make a failing test pass without fixing the underlying regression. The edit text alone often can't settle that.
The v0.7 change in approach
The release stops pretending there's only one outcome. It classifies changes into three categories, then handles each differently:
- Legit: Recognized structural or non-behavioral additions and edits are allowed, and the pass is recorded in the audit log.
- Malicious: Changes like weakened assertions or newly skipped tests are blocked.
- Ambiguous: The classifier can't tell whether the edit is justified, so it's blocked unless an operator explicitly allows it.
That third bucket matters because it avoids the fantasy that a heuristic can "read" intent. It also avoids a blanket ban on all test maintenance. In practice, the decision becomes visible: either the guard has a reason to allow the change, or someone supplies that reason through the escape hatch.
How agent-guard 0.7 classifies test edits
The Stop hook compares each changed test file with its SessionStart copy. So the guard isn't judging only the final version - it has a before-and-after view within the current session.
Then it evaluates what changed. This is still a heuristic, not a full understanding of what the test is supposed to do in the wider product. Teams should treat the verdict as a control signal, not as a substitute for reviewing the change.
Changes classified as legitimate
Per the v0.7 release notes, the classifier treats a number of common edits as legitimate, including:
- Adding new test functions
- Adding fixtures or helper code
- Adding imports
- Renaming items
- Comment-only edits
These are typical maintenance moves that don't, by themselves, indicate an existing check was weakened. When the change is classified as legitimate, the session continues and the pass is written to the audit log.
Even when nothing suspicious happens, that audit entry still helps. It shows that the guard saw a test-file change and let it through for a normal reason, instead of silently doing nothing whenever tests get touched.
Changes classified as malicious
Some patterns are treated as blocked:
- Assertions that have been weakened, removed, or inverted
- Tests that have newly been skipped
- A
try/exceptchange that swallows a removed assertion - Deletion of an entire test file
The block message includes the verdict label, which gives the person dealing with the failure more context than a generic "operation denied" reply. It doesn't remove the need to inspect the diff, but it makes the guard's decision easier to understand and troubleshoot.
A blocked verdict is about the edit, not a complete explanation of why someone made it. There can be unusual but legitimate reasons for a change that matches a suspicious pattern. The right response is to review the diff and, when it's truly justified, use the documented bypass with a reason - not to assume every block automatically means malicious intent.
Changes classified as ambiguous
Some edits are inherently harder to judge. Changing an expected value while keeping the assertion at the same strictness might be a valid snapshot update, or it might be a way to bless incorrect behavior. The classifier can't know the product intent behind that new value just by looking at the diff.
In v0.7, ambiguous changes are blocked by default. This matches the earlier protective behavior and keeps uncertainty from turning into automatic approval. If the edit is valid, the developer can review the diff and explicitly allow it through the escape hatch.
"Malicious" vs "ambiguous" is still useful operationally. A malicious verdict points to a recognized weakening pattern. An ambiguous verdict means the guard doesn't have enough confidence to decide either way. Both result in a block, but the next step differs: investigate the suspicious pattern in the first case; gather context and document the decision in the second.
How to review or allow an ambiguous change
A bypass is only helpful if it fits the workflow without becoming invisible. agent-guard 0.7 adds two related commands: one to inspect the diff without stopping the session, and one to explicitly allow a test change with a reason.
Preview the classifier's decision
Use test-review to classify the current diff without blocking:
agent-guard test-review --session <id>
This is handy when you want to see what the guard is reacting to before you decide what to do. For example, if an agent updated snapshots, run the review, check the files and verdicts it lists, and then compare them to the behavior change you actually intended. This command doesn't approve anything - it just gives information for a human or a workflow step.
Keeping that separation matters. Previewing a verdict and authorizing an exception are different actions. If they blur together, it becomes too easy for a diagnostic command to accidentally behave like a bypass.
Allow a justified change with a reason
If you've reviewed an ambiguous edit and think it's legitimate, pass a reason when invoking the hook:
agent-guard hook-test --allow-test-change "updating snapshots after the API rename"
If your agents can't pass flags, you can also use an environment variable:
export AGENT_GUARD_ALLOW_TEST_CHANGE=1
The flag makes the exception and its reason explicit in the command. The environment variable is more of a compatibility path for agents that can't supply the flag - but it doesn't carry a reason the same way. Teams should think about how they'll capture context when using it, rather than assuming it will show up as complete audit practice.
Every time the escape hatch is used, it's appended to the audit log along with the reason, session, files, and verdicts. The decision is recorded as allowed-escape-hatch and can be inspected with agent-guard log. The key point isn't that bypasses should never happen - real work sometimes needs an exception. The key point is that an exception should be visible and leave a record.
A practical review sequence
When a test change triggers the guard, a disciplined workflow looks like this:
- Read the verdict. Decide whether the guard called the edit malicious or ambiguous.
- Inspect the diff. Compare the changed test file with what you intended to do (test maintenance and/or product behavior).
- Run the review command if needed. Use
agent-guard test-review --session <id>to see the current classification without blocking. - Verify behavior. Run the relevant tests and make sure you preserved the intended behavior - not just that the run went green.
- Use the escape hatch only when justified. Provide a concise, specific reason for an ambiguous change.
- Check the audit record. Confirm the exception shows up in
agent-guard logwith the expected session, files, and verdicts.
This isn't a replacement for code review. It just makes the exception path explicit and gives reviewers an audit trail they can follow.
Trade-offs and practical limits
The main design choice in v0.7 is conservative classification. Legitimate patterns can pass; recognized weakening patterns are blocked; uncertain cases stay blocked unless someone explicitly allows them. That's a reasonable default for a tool meant to protect tests from tampering, because silently approving an unclear diff undermines why the guard exists.
There's a real cost: developers still have to step in for valid edits that the heuristic can't classify confidently. That's not something you can fix just by making the classifier more permissive. A more permissive classifier may reduce friction, but it also creates a bigger path for harmful edits. Strict by default is safer, even if it means more review work.
What the audit trail changes
An escape hatch without logging is easy to misuse because the approval disappears into the workflow. An escape hatch with a reason and file-level context is easier to review later. The audit record helps a team answer questions like: which session allowed the change, which files were involved, and what verdicts did the guard produce?
The audit record doesn't prove the change was correct. A weak reason can still be entered, and an approved change can still introduce a bug. Auditability supports accountability, but it doesn't replace judgment, test execution, or review.
What the heuristic does not know
The classifier compares file changes and recognizes patterns. It can't independently tell whether an updated expected value reflects an approved product decision, whether a fixture matches a real-world scenario, or whether the updated test still covers the right behavior. Those questions depend on context outside the diff.
Treat the verdict as one layer in a broader development process. Keep normal code review going, run the relevant tests, and make it clear in the pull request or commit what behavior you changed and why. The guard is most useful when it catches risky edits early and makes ambiguous exceptions reviewable - rather than when teams expect it to prove correctness by itself.
The source also describes the tool as standard-library-only and mentions the phrase "fail-open everywhere," while specifically saying ambiguous test edits remain blocked as in v0.6. Those statements cover different aspects of the tool and shouldn't be merged into a claim that ambiguous test changes are automatically allowed. For the test-change workflow described here, the documented behavior is clear: ambiguous changes block unless you use the explicit escape hatch.
Install and inspect the project
The project's stated installation steps are:
pip install agent-guard-hooks
agent-guard install
For source and implementation details, see the agent-guard GitHub repository. The release package is available on PyPI. Check the project documentation for setup and behavior relevant to your environment before enabling it in a production workflow.
Conclusion
agent-guard 0.7 tackles a real usability problem in test-tampering prevention: if a guard blocks every test edit, people will eventually treat it as an obstacle. The response isn't to quietly approve uncertain changes. It separates recognizable legitimate edits from suspicious ones, keeps ambiguous cases blocked, and makes justified exceptions explicit and auditable.
It's a workable balance, with one clear limitation: the classifier can't infer intent from every diff. Use the review command to understand what it flagged, inspect the change yourself, and reserve the escape hatch for exceptions you can explain.
To try it, install agent-guard-hooks, run agent-guard install, and review the project's GitHub repository before adding it to your workflow. The real test is whether it catches risky edits without turning normal test maintenance into an invisible workaround.