Files
Linux_post_install/AgentsReport/builder/2026-09-06_f1-f3-fixes.md
T
Your Name d817c37652
gates / consistency-and-conventions (push) Successful in 26s
fix: stabilization pass — fail-closed auth, ai flag validation, lint/config/security hardening, regression tests
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.
2026-09-06 07:25:44 -04:00

7.8 KiB
Raw Blame History

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/, no bin/pos-system-uninstall, no bin/pos-network-download.
  • F1: --no-command-execution added to both bridge pos ai gemini ask invocations (telegram bin/pos-communication-telegram-listener:731, matrix bin/pos-communication-matrix-listener:466). Parse-order validated with probes.
  • F3: _prompt_run_command in bin/pos-ai now checks NO_EXEC BEFORE the "Command detected:" print and returns 0 with zero output (probe-verified). Kept the existing return 0 rc.
  • 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-execution usage text in bin/pos-ai — "still printed" → "neither printed nor run".
  • Gates: bash -n OK (4 files), make gen rc=0 + byte-identical output across runs, make check OK, make lint 0 FAIL, 0 WARN, git diff --check OK. 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 matches pos ai gemini ask ... to bin/pos-ai-gemini (exists, forwarder), which execs pos ai --provider gemini ask --no-command-execution ....
  • bin/pos-ai parse loop (bin/pos-ai:647-678) handles flags at ANY position in the while [ $# -gt 0 ] case (lines 668-669 set NO_EXEC=1; TRUST_MODE=0; non-flag tokens become cmd/args). So the flag is accepted after the subcommand.
  • Last-wins semantics vs --trust unchanged; 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 ask invocation command strings contain --no-command-execution (one occurrence each, in the executed timeout ... 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): prints Command 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 disabled string remains in bin/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-ai usage() --no-command-execution block: "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-263 and :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 -n on 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,790 and bin/pos-communication-matrix-listener:511 still 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 :num format; the rest of the lint rewrite (other message classes, FAIL rules) was not touched.
  • Note: DOC/howto/ai.md:262 non-tty bullet claim ("the code block is neither printed nor run") is now accurate for current code AND for the bridges with the flag.

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.