Skip to content

fix: fewer prompts — make tasks once checked, local git work, commands rules can read - #71

Merged
mauricios merged 9 commits into
mainfrom
fix/fewer-prompts-make-and-git
Oct 15, 2026
Merged

mauricios merged 9 commits into
mainfrom
fix/fewer-prompts-make-and-git

Conversation

@mauricios

@mauricios mauricios commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Why

Testing in an adopting project, agents asked the developer to approve commands all day, mostly make commands. Its session transcripts, about 2,200 commands, showed the project already allowed make *, so a plain make task never prompted. The prompts came from three places:

  • Commands no rule can read (~650): a leading VAR= assignment, paths in $VARs, git -C <path>, shell loops, and heredoc scripts into python3 or node.
  • make run cmd="yarn …" (~110): the project's own ask rule covers it. Agents used it because no task ran one test file, linted one file, formatted, or type-checked.
  • git add and git commit (~65): the skeleton allowed neither, so every commit prompted.

Claude Code's behavior here was checked against its permissions docs: an ask rule beats an allow rule, an allow rule doesn't match past a leading assignment, and a redirect outside the project prompts.

What changed

  • dev-env's specification:
    • C3: test takes t=<filter>, lint takes f=<files>, and each mode adds format and typecheck. The templates show both.
    • C9 — allow broadly, ask by name: every task runs without a prompt but the ones that delete data or run a command they're given, each of which gets an ask rule. No task waits for input or follows a log. (A first commit allowed each task by name after a make -n check, from the earlier fix/make-allow-rules work; the second commit replaces that with this simpler model.)
    • C10: a task that runs a command it's given is for people and asks. A command agents keep needing becomes a task of its own.
  • Docker module: it allows docker * and make *. Its ask rules name what must still prompt, and an ask rule beats any allow rule:
    • deletes data: compose down -v or --rmi, rm, rmi, prune, make reset;
    • leaves the machine: docker push;
    • prints secrets: docker inspect, a bare docker compose config, an exec or compose run that names env;
    • make run.
  • /dev-env: its audit flags missing filters, an unasked make run, a project task that deletes data under another name, and a task that follows a log. Set up proposes an ask rule for each such task. /adf:upgrade lists those tasks before it reruns the installer.
  • The module permission check in the evals accepts exactly docker * and make * for this module, and only while their ask rules are there. Every other module and rule is held to read-only, as before.
  • Skeleton:
    • .claude/settings.json allows git * and gh * in place of 24 narrow rules, and asks by name before what must still prompt:

      • switches off the hooks, or releases: git config (core.hooksPath), git push --tags;
      • changes a pull request's state or speaks for a reviewer: gh pr ready, merge, review;
      • can't be undone or exposes a credential: releases, gh repo delete, gh secret, gh auth, gh api writes.

      The list is short on purpose, chosen by the developer. Discarding local work (git reset --hard, clean, restore, branch -D) and issue writes run without a prompt; git-workflow.md gains "never discard work unless the developer asks", and AGENTS.md still says an agent posts only when asked. Rare commands that are easy to undo run too: gh pr close/reopen, labels, workflow runs, gists, extensions, docker stop/kill/login.

    • .claude/rules/claude-code.md gains § Commands that run without a prompt, and a guardrails row.

  • The mode is the developer's (M10, decision 0034 amended). In the adopting project, agents ran make test/build/e2e with DEV_MODE=native though the developer runs only Docker, partly because the framework showed that override as an example. An agent now runs every task in the configured mode and never sets DEV_MODE or SERVICES unasked. The docker module asks before any make command that sets either one. The claude-code.md example becomes make logs s=web, and deployment.md and /dev-env say the override is for people.
  • Docs: decision 0038 amends 0032 and 0033. The changelog entry carries the upgrade impact, and the onboarding guide's guardrails table gains a row.

For reviewers

  • Bash(make *) trusts the project's Makefile. It matches the command, not what the task runs. A task that deletes data under a new name runs without a prompt until its ask rule goes in, so review a Makefile change as code that runs without one.
  • docker compose run and exec run any command in the project's containers without a prompt (decided in conversation). The containers hold the project's code and data, not the host's.
  • docker run runs without a prompt (the developer's choice): with a host mount or --privileged, a container reaches the host's files.
  • A secret can still print through a form no ask rule names (docker compose config --format json). /dev-env's safety rules and the specification's V4 cover it; the rules catch the usual forms. The env rule is a little broad: an exec whose arguments contain env, such as a test file named environment.test.ts, asks too.
  • git and gh run without a prompt but for the named exceptions. Staging everything and --amend run too. The guard-git hook still blocks --no-verify, commits or pushes on protected branches, and a pull request that isn't a draft. A gh write added in a later gh version runs until the skeleton names it.
  • The command-writing section is instruction, not enforcement. A command no rule can read still prompts, which is the safe failure.

Verification

  • ./evals/run-evals.sh: all suites pass. New and changed tests:
    • C9 on the templates: every task but reset exists in both modes and deletes nothing, and logs never follows.
    • The filter: make test t=<file> passes the file to the test command.
    • Docker rules: make up, make test t=…, make up DEV_MODE=native, docker compose up/down/build/run/exec, docker images, and docker stats run without a prompt. make run, make reset, make up DEV_MODE=native, make up SERVICES=none, docker push, docker inspect, a bare compose config, and exec … printenv ask, while docker run, stop, kill, and login run. A leading DEV_MODE=native make up still prompts. The test's rule simulator now applies the documented rule that a trailing * also matches the bare command.
    • The module permission check: shown failing when the make reset ask is removed or another broad allow is added.
    • Settings: the check simulates Claude Code's matching against the expected verdict of about 40 git and gh commands, both sides of the line — gh pr close, workflow run, label create, and git stash clear run. It failed on the old settings and passes on the new ones.
    • Static checks: C9 and C10 in the specification, /dev-env and /upgrade naming the check, and the new claude-code.md section.
  • python3 scripts/build-committed.py --check: the round trip holds, with 65 files.
  • Not verified: a real adopting project after /dev-env set up, to measure the prompts that remain.

🤖 Generated with Claude Code

mauricios and others added 8 commits October 15, 2026 12:04
…s rules can read

An adopting project's agents were prompted all day, mostly on make commands.
Its transcripts showed the project already allowed make *: the prompts came
from commands no rule could read (a leading VAR= assignment, paths in
variables, git -C, shell loops, heredoc scripts), from make run cmd="…" doing
what no task did, and from every git add and commit.

- dev-env's specification: test takes t=<filter> and lint f=<files>, each
  mode adds format and typecheck (C3); a make task gets an allow rule only
  once this project's task exists in every mode, deletes nothing, and logs
  never follows (C9, brought across from the earlier fix/make-allow-rules
  work and widened to every task but reset); a task that runs a command it's
  given is for people and asks (C10).
- The docker module allows no make task itself, and asks before make run.
  /dev-env set up adds the rules after the check; /adf:upgrade removes old
  ones whose task fails it.
- The skeleton allows git add, commit, switch, fetch, and pull --ff-only, and
  asks before git add . / -A and commit --amend.
- claude-code.md gains § Commands that run without a prompt.

Decision 0038 amends 0032 and 0033.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… commands

The per-task check took a rule per task and a step that added them, and every
new task prompted until that step ran again. An ask rule beats any allow rule,
so naming the few exceptions is simpler.

- The docker module allows make *, docker compose run, and docker compose
  exec, beside its read-only Docker commands, and keeps asking before make
  reset, make run, and the destructive Docker commands.
- dev-env's C9 now says every task runs but the ones that delete data or run a
  command they're given, each with an ask rule; no task waits for input or
  follows a log. /dev-env set up proposes an ask rule for a project task that
  deletes data under another name, and /adf:upgrade lists them.
- The module permission check accepts exactly the three broad allows decision
  0038 names, and only while their ask rules are there; every other module and
  rule is held to read-only as before.
- Decision 0038 records the per-task check as tried and declined.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…still prompt

The developer asked for most docker commands to run without a prompt. The
module now allows docker * beside make *, and its ask rules name the
exceptions:

- what deletes data: compose down -v or --rmi, rm, rmi, prune, make reset;
- what reaches past this project: docker stop and kill, which can stop other
  projects' containers, and docker run, whose mounts reach the host's files
  (agents use docker compose run, which runs);
- what leaves the machine: docker push and login;
- what prints secrets: docker inspect, a bare docker compose config, and an
  exec or compose run that names env;
- make run.

The module permission check accepts exactly docker * and make * for this
module, and only while those ask rules are there. Decision 0038 records the
model and the cost: a secret printed through a form no rule names, such as
config --format json, is left to /dev-env's safety rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… must still prompt

The developer asked for git and gh to run more broadly. The skeleton's
settings allow git * and gh * in place of 24 narrow rules, and ask by name
before:

- what loses uncommitted work or rewrites history: reset --hard, clean,
  checkout -- and ., restore, stash drop and clear, branch -D, filter-branch;
- git config, which could switch off the git hooks, and push --tags;
- what changes a pull request's state or speaks for someone: pr ready, merge,
  review, close, reopen, and issue writes;
- what reaches past the pull request: releases, repository settings, secrets
  and variables, gh auth, workflow runs, gists, extensions, labels, and gh api
  writes.

Staging everything and --amend run now; the guard-git hook still blocks
--no-verify, protected branches, and a pull request that isn't a draft. The
settings check simulates Claude Code's matching against the expected verdict
of about 40 commands. Decision 0038 covers make, docker, git, and gh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…omeone, or reaches past the project

The developer wanted git, gh, and docker allowed more broadly. The ask lists
keep only:

- git: what loses work git can't bring back (reset --hard, clean, checkout --
  and ., restore, stash drop, branch -D), config, and push --tags;
- gh: pr ready, merge, review; issue writes; releases; repo delete; secrets;
  auth; api writes;
- docker: what deletes data, docker run, docker push, the secret-printing
  forms, and make run.

Rare commands that are easy to undo now run: gh pr close and reopen, issue
reopen, delete, and transfer, repo create, edit, rename, and archive,
variables, workflow runs, run cancel and delete, gists, extensions, labels,
git filter-branch and stash clear, docker stop, kill, and login. The tests
expect both sides of the line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t a prompt

The developer chose to drop two more groups from the ask list:

- git's work-discarding commands: reset --hard, clean, checkout -- and .,
  restore, stash drop, branch -D;
- issue writes: gh issue create, edit, comment, close.

The rules still hold: git-workflow gains "never discard work unless the
developer asks", since no prompt stops it now, and AGENTS.md still says an
agent posts only when asked. What keeps asking: git config and push --tags;
readying, merging, or reviewing a pull request; releases; repo delete;
secrets; gh auth; and gh api writes. The docs that listed issue writes as
confirmed by a person, and the expected verdicts, follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The developer chose to allow docker run too. Its ask rule goes; decision 0038
records the cost: a mount or --privileged reaches the host's files, and
Docker access is root-equivalent on Linux. The docker module now asks only
before what deletes data, docker push, the secret-printing forms, and make
run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e asks

Testing in an adopting project whose developer runs only Docker, agents ran
make test, build, and e2e with DEV_MODE=native — the framework showed that
override as an example, in claude-code.md among others — and the developer
had to save a memory to stop it.

- dev-env's specification gains M10: an agent runs every task in the mode
  the checkout is configured for, and sets DEV_MODE or SERVICES only when the
  developer asks for that mode in the task. A task that can't run in it is
  reported, and the developer decides.
- The docker module asks before any make command that sets DEV_MODE or
  SERVICES, so a requested override is approved and any other is seen.
- claude-code.md's example becomes make logs s=web, and gains "run them in the
  configured mode"; deployment.md and /dev-env say the override is for
  people; /dev-env gains a rationalization row and a red flag.
- Decision 0034 is amended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s entries

The conflicts were the two pull requests adding beside each other: the
changelog's Unreleased entries, and decisions 0038 and 0039 in the index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mauricios
mauricios marked this pull request as ready for review October 15, 2026 20:06
@mauricios
mauricios merged commit 0089378 into main Oct 15, 2026
1 check passed
@mauricios
mauricios deleted the fix/fewer-prompts-make-and-git branch October 15, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant