fix(guard): refuse every asked-about call where no one can be asked

In the permission mode that shows no prompts, pre-bash-executor refused only a
merge into main and a push. A tag, a package publish and destructive git still
went through unattended, which is what the approval guard exists to stop. Now
every call it would ask about, and a command it could not read, is refused
there with the way forward (operator decision 2026-10-09). No new exemption:
the mode is still read in one place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-09 19:36:21 +02:00
commit bb0fb361a5
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
5 changed files with 19 additions and 11 deletions

View file

@ -319,6 +319,13 @@ test('P12: the guard asks before a merge into main; in the mode with no prompts
assert.match(blocked.stderr, /no one to ask/);
assert.match(blocked.stderr, /Way forward/);
assert.equal(guard(dir, 'git push origin feature', NO_PROMPT_MODE).status, 2, 'a push is refused too');
// Operator 2026-10-09, second decision: the other two classes as well.
for (const cmd of ['git tag v1.0', 'npm publish', 'git reset --hard HEAD~1', 'git push --force origin feature']) {
assert.match(guard(dir, cmd, 'default').stdout, /"permissionDecision":"ask"/, `the control: ${cmd} is asked where someone can answer`);
const r = guard(dir, cmd, NO_PROMPT_MODE);
assert.equal(r.status, 2, `${cmd}: refused where no one is asked`);
assert.match(r.stderr, /no one to ask/);
}
const plain = guard(dir, 'git status', NO_PROMPT_MODE);
assert.equal(plain.status, 0, 'an ordinary command still runs');
assert.equal(plain.stdout, '');

View file

@ -67,7 +67,7 @@ const EXEMPT = new Map([
['.gitignore', ['operator-instrument', 1, 'ignores the output of that same operator-run eval']],
['hooks/scripts/post-approval-log.mjs', ['mode-read', 3, "reads the session's permission_mode from hook input so an approval is never logged when no person was asked; starts nothing - operator decision 2026-10-06"]],
['tests/hooks/guards-review-regressions.test.mjs', ['mode-read', 1, 'feeds that same permission_mode value to the hook under test; starts nothing']],
['hooks/scripts/pre-bash-executor.mjs', ['mode-read', 1, "reads the session's permission_mode from hook input so a merge into main or a push is refused when no person can be asked; starts nothing - operator decision 2026-10-09"]],
['hooks/scripts/pre-bash-executor.mjs', ['mode-read', 1, "reads the session's permission_mode from hook input so every call the guard would ask about (merge into main, push, tag/release, destructive git) is refused when no person can be asked; starts nothing - operator decision 2026-10-09"]],
['tests/commands/trekexecute-coupling.test.mjs', ['mode-read', 1, 'feeds that same permission_mode value to the guard under test; starts nothing - operator decision 2026-10-09']],
]);