Blocking the write tool, not the prompt
The better AI coding agents get at designing, testing, and building software, the more convincingly they rationalize skipping the tests. Discipline for capable agents is the problem this whole deck is about.
So how does the superpowers bundle try to enforce it?
One commit, 26 files — markdown, agents, and scripts. Nine wrapper agents just ASK the model to comply: "Tests first, always: No production code without a failing test."
It ships the request. Not the guarantee.
"Refuse to write code without tests" is a natural-language instruction. A good-enough rationalizer treats it as a suggestion, not a hard limit — so the discipline it promises isn't guaranteed.
If asking can't hold the line, what can?
It lives in a separate module — microsoft/amplifier-module-tool-filesystem v1.0.0, by the Microsoft MADE:Explorations Team — pulled in transitively via amplifier-foundation.
Here's how that module actually stops a write.
write_file and edit_file call is_path_allowed first: deny-first, then allow, else default-DENY. An off-limits write returns failure before path.write_text ever runs.
Which means one config value can lock everything down.
Set allowed_write_paths to empty on the tool-filesystem module and every write path fails. It's configuration at the framework level — beneath the reach of any prompt.
And here's what that empty list actually does when you run it.
With an empty allow-list, is_path_allowed returns (False, 'Access denied') for every path. With the default ['.'], a local path is allowed. The model literally cannot write anywhere — and no rationalization changes that.
That's the difference between asked and enforced.
The honest posture: the empty allow-list is an operator hardening — an untracked, gitignored settings.local.yaml added later, not something the repo ships. The bundle hands you the ask; enforcement is the separate module you configure.
Make discipline structural, not merely requested.
Feature status: Enforcement code PRESENT & VERIFIED
Data as of: git/stat/cache-meta timestamps on this machine; module cache_meta cached 2026-07-02. Superpowers sole commit 073253a: Jan 6 2026. Local settings.local.yaml mtime: Apr 1 2026.
Research performed:
git rev-list --count HEAD && git show --stat HEAD — 1 commit, 26 filesls agents/*.md | wc -l && cat agents/tdd-enforcer.md — 9 agents; "Refuse to write code without tests"git ls-tree -r HEAD | grep -i settings; git check-ignore -v .amplifier/settings.local.yaml; stat .amplifier/settings.local.yaml — untracked, gitignored (.gitignore:67), 88 bytescat .amplifier/settings.local.yaml — allowed_write_paths: [] for module tool-filesystemgrep 'name|version|authors' pyproject.toml; cat .amplifier_cache_meta.json — amplifier-module-tool-filesystem v1.0.0, Microsoft MADE:Explorations Team, commit 355fa41cat path_validation.py; sed -n '140,160p' write.py; sed -n '170,185p' edit.py — is_path_allowed, deny-first, default-DENY, checked before writepython3 -c "...is_path_allowed(Path('/tmp/x'),[],[])..." — (False, 'Access denied'); ['.'] → (True, None)cat bundle-dev.md && grep -rn 'allowed_write|tool-filesystem' — filesystem pulled in transitively via microsoft/amplifier-foundationGaps: Module pytest suite not run (path_validation.py loaded directly via importlib and executed). Who/why created the local settings.local.yaml is unknown — only its content, mtime, and gitignored status are verified. obra/superpowers submodule internals not read in full. On-disk cache checkout drifted to commit 39af862 (whitespace fix); path_validation.py byte-identical to 355fa41, so behavior unchanged. Dates are local git/stat timestamps, not externally corroborated.
Primary contributors: Sam Schillace (superpowers bundle's single commit 073253a, co-authored with the Amplifier agent); Microsoft MADE:Explorations Team (the enforcing module); obra/superpowers (upstream skill library, git submodule).