17-point code-level audit executed via Explorer->Architect->Builder->Tester->Reviewer;
Reviewer accepted (APPROVE_WITH_NOTES; 3 block-list items resolved):
- security: telegram sender-owner AND-gate + TELEGRAM_OWNER_ID, matrix
MATRIX_ROOM_ID fail-closed, gpg --passphrase-fd 3 (no argv secret),
/dev/tcp positional-arg form (checkport/smb-client/share-lib/NET_PROBE),
eval deny-by-default + --no-command-execution carried by both chat bridges,
tty-gated --trust; config/{telegram,matrix}.env reference templates
- ai: all ExecStart flags validated against installed llama.cpp
(requested->error, default->omit+warn, CONFIG_REQUESTED_FLAGS); single-file
hf download failure rc=1 + no .hf-meta; LLAMACPP_HOST coherent;
POS_SUBCMDS + metadata gaps closed
- tooling: lint-conventions Bash-native rewrite (~24-30x faster, rules and
output byte-identical, :num restored); pos system uninstall covers all 12
libs + scale-tail + flags dir + systemd user units (|| true) + plugin
markers; anchored .bash_completion/.bashrc removal replaces sed -i '/pos/d'
- config: canonical load_env_file in lib/config-ui.sh (CRLF strip, env-wins,
XDG, LOADED_ENV_KEYS); 9 tools migrated; entertainment-lib collapsed to
wrappers; docker-compose deliberately unmigrated (source semantics)
- tests: first committed regression suite — tests/run-tests.sh zero-dep
runner + make test; 12 files / 179 checks / 0 skip / ~52s; hard skip
contract; systemd-analyze verify on generated unit PASS
Verified: make gen idempotent; make check green; make lint 0 FAIL, 0 WARN;
make test green; bash -n clean; git diff --check clean. Audit deliverables +
agent reports + AGENT_TODO Done entry included.
7.8 KiB
Builder report — Reviewer F1/F3/F4 fixes — 2026-09-06
TL;DR
- Status: IMPLEMENTED
- Scope: Reviewer block-list fixes F1 (BLOCKING), F3 (REQUIRED), F4 (SUGGESTED). No D-A/decision-pending behavior touched, no
tests/, nobin/pos-system-uninstall, nobin/pos-network-download. - F1:
--no-command-executionadded to both bridgepos ai gemini askinvocations (telegrambin/pos-communication-telegram-listener:731, matrixbin/pos-communication-matrix-listener:466). Parse-order validated with probes. - F3:
_prompt_run_commandinbin/pos-ainow checksNO_EXECBEFORE the "Command detected:" print and returns 0 with zero output (probe-verified). Kept the existingreturn 0rc. - F4: Restored
$f:$num:format in the two lint WARN messages (byte-identical to HEAD's strings; functional probe shows correct line numbers). - Docs: minimal alignment (only literal contradictions of the fixed behavior):
DOC/POS.md:103,DOC/howto/ai.md:261-273, plus the--no-command-executionusage text inbin/pos-ai— "still printed" → "neither printed nor run". - Gates: bash -n OK (4 files),
make genrc=0 + byte-identical output across runs,make checkOK,make lint0 FAIL, 0 WARN,git diff --checkOK. Not committed (per brief).
Step 1: F1 — add --no-command-execution to both bridge ask invocations
[DONE]
Change (the running subprocess now carries the flag):
bin/pos-communication-telegram-listener:731:timeout 120 pos ai gemini ask --no-command-execution --session "$session" --system "$AI_SYSTEM" "$prompt"bin/pos-communication-matrix-listener:466: identical change.
Why that position is valid (read bin/pos-ai arg parsing first):
- Dispatcher (
bin/pos:271-298) longest-prefix matchespos ai gemini ask ...tobin/pos-ai-gemini(exists, forwarder), which execspos ai --provider gemini ask --no-command-execution .... bin/pos-aiparse loop (bin/pos-ai:647-678) handles flags at ANY position in thewhile [ $# -gt 0 ]case (lines 668-669 setNO_EXEC=1; TRUST_MODE=0; non-flag tokens becomecmd/args). So the flag is accepted after the subcommand.- Last-wins semantics vs
--trustunchanged; bridges never pass--trust.
Probes:
- PROBE-C:
bin/pos-ai --provider gemini ask --no-command-execution --help→ rc=0, usage shows the flag. - PROBE-D (full chain):
PATH="$PWD/bin:$PATH" bin/pos ai gemini ask --no-command-execution --help→ rc=0, usage shows the flag (2 mentions). - PROBE-E negative control:
bin/pos-ai --provider gemini ask --definitely-not-a-flag --help→ rc=1 (parser genuinely rejects unknown options, so C/D are not vacuously passing). - grep: both bridge
askinvocation command strings contain--no-command-execution(one occurrence each, in the executedtimeout ... pos ai gemini ask ...line).
Step 2: F3 — _prompt_run_command NO_EXEC returns before printing
[DONE]
Change (bin/pos-ai:369-384): the NO_EXEC check now sits immediately after the tty guard, BEFORE the print block:
[ -w /dev/tty ] || return 0
if [ "${NO_EXEC:-0}" -eq 1 ]; then
return 0
fi
printf '\n%s\n' "Command detected:" >&2
printf ' %s\n\n' "$cmd" >&2
The old printf 'command execution disabled (--no-command-execution)\n' >&2 + printf '%s\n' "$cmd" lines are removed. rc semantics preserved: current NO_EXEC path returned 0 → still returns 0.
Probe (function extracted from production bin/pos-ai, run in tty-writable environment):
- PROBE-A (
NO_EXEC=1): rc=0, stdout_bytes=0, stderr_bytes=0 —[ -n check ]on captured output fails as required (no output). - PROBE-B (
NO_EXEC=0, same environment): printsCommand detected:+ the command to stderr — proves the tty guard passed and the NO_EXEC branch is what silenced PROBE-A (differential, not vacuous). - grep: no
command execution disabledstring remains inbin/pos-ai.
Step 3: Doc alignment for the fixed NO_EXEC behavior (literal contradictions only)
[DONE]
The brief permits doc edits only where a doc "literally contradicts the fixed behavior". After F3 the fixed behavior is: under --no-command-execution nothing is printed. These claims said "still printed" — fixed with minimal wording:
bin/pos-aiusage()--no-command-executionblock: "The proposed command is still printed but never executed" → "The proposed command is neither printed nor executed".DOC/POS.md:103: "the block is printed but not run" → "the block is neither printed nor run"; "the detected command is still printed but never run" → "the detected command is neither printed nor run".DOC/howto/ai.md:261-263and:270-271: same two claims → "neither printed nor run".
The F1-related claim (bridges rely on the flag as the structural guard) was already accurate after the F1 fix and was NOT rewritten. No other doc touched (DOC/howto/communication.md, config/*.env unchanged).
Step 4: F4 — restore :num in lint WARN messages
[DONE]
Change (scripts/lint-conventions.sh): added a per-file line counter (num=0 before each inner while IFS= read -r line loop; num=$((num + 1)) as the FIRST statement of the loop body — before every continue gate, so skipped lines still get correct numbers). The two WARN messages now emit "$f:$num: ...", byte-identical to HEAD's format:
warn_ "$f:$num: secret-like literal assignment (manual review for hardcoded credentials)"(line 247)warn_ "$f:$num: writes to a system path (verify a VAR=\"\${VAR:-path}\" test seam exists)"(line 297)
No other lint behavior changed (only the two emit paths and the counters).
Probe (real script run from a scratch tree with planted violations):
WARN lib/violation.sh:3: secret-like literal assignment (manual review for hardcoded credentials)
WARN lib/violation.sh:4: writes to a system path (verify a VAR="${VAR:-path}" test seam exists)
0 FAIL, 2 WARN (convention lint)
:3 / :4 are the exact line numbers of the planted SECRET_API_KEY="abc123" and echo "x" > /etc/example lines.
Step 5: Gates & probes
[DONE]
bash -non the 4 touched shell scripts: OK.make gen×2: rc=0 both runs; generated-output hash identical before/after (711d6379...) → no gen drift from my edits.make check(scripts/check-sync.sh): OK.make lint(scripts/lint-conventions.sh): 0 FAIL, 0 WARN (rc=0).git diff --check: OK.- Executable bits unchanged (all 4 scripts still
-rwxrwxr-x). - Out-of-scope D-A behavior confirmed untouched:
bin/pos-communication-telegram-listener:761,790andbin/pos-communication-matrix-listener:511still warn-based soft-fail (pending Architect decision); no edits in that region. - Not committed (per brief).
Files changed
bin/pos-communication-telegram-listener(F1, line 731)bin/pos-communication-matrix-listener(F1, line 466)bin/pos-ai(F3_prompt_run_command; usage text for--no-command-execution)scripts/lint-conventions.sh(F4, two WARN emit paths + counters)DOC/POS.md(1 sentence, literal contradiction only)DOC/howto/ai.md(2 sentences, literal contradiction only)AgentsReport/builder/2026-09-06_f1-f3-fixes.md(this report)
Remaining risks
- None in-scope. The two lint WARN messages now match HEAD's
:numformat; the rest of the lint rewrite (other message classes, FAIL rules) was not touched. - Note:
DOC/howto/ai.md:262non-tty bullet claim ("the code block is neither printed nor run") is now accurate for current code AND for the bridges with the flag.
Recommended next agent
Orchestrator — reviewer block-list F1/F3/F4 implemented and gate-verified; reviewer should re-run make test (untouched, per parallel track) and confirm F2 via the parallel D-A Architect decision before merge.
Changes made by Builder
In-scope implementation only (F1, F3, F4 + literal-contradiction doc alignment). No out-of-scope modifications.