Files
Linux_post_install/AgentsReport/builder/2026-09-06_review-fixes.md
T
Your Name 528b16676e
gates / consistency-and-conventions (push) Successful in 2m16s
fix: review-driven hardening of pos ai hf/server + llamacpp provider
Adversarial review of the AI tools (commits 387f23f/0856b25) found 2
BLOCKING + 5 REQUIRED defects; all fixed:

- pos-ai-hf --include/--exclude: bash-case glob filtering (array-safe,
  no jq regex interpolation, composes gguf->filename->include->exclude)
- pos-ai-server: ExecStart rebuilt as single-line properly-quoted command
  (systemd_quote for executable + model path; systemd-analyze verify rc=0)
- --branch/--revision aliased (last wins), dead BRANCH variable removed
- parallel download drains all jobs: per-pid wait, honest
  'X of Y files, N failed' summary, rc=1 on partial failure, no .hf-meta
  for half-downloaded models, EXIT-trap temp cleanup
- detect_llama_version guarded; validate_requested_flags errors on
  unsupported explicit flags with version-aware message
- pos ai hf cache [status|clear]: real implementation, fail-closed confirm
- new bin/pos-ai-llamacpp thin forwarder + llamacpp shorthand in bin/pos-ai
  (pos ai llamacpp <subcmd> = pos ai --provider llamacpp <subcmd>)
- docs synced: bin/pos-ai usage(), DOC/POS.md AI_PROVIDER row, howto/ai.md
  (adapter list, --provider backends, shorthand, providers table); gen
  regenerated (tree/dispatch/completions)

Verified: bash -n all bin/pos*; make gen idempotent; make check green;
make lint 0 FAIL, 0 WARN. Reviewer acceptance: APPROVE_WITH_NOTES
(0 REQUIRED). Audit deliverables + agent reports included for context.
2026-09-06 03:45:53 -04:00

105 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Builder Report — POS AI review fixes (F1F6)
Date: 2026-09-06
Builder: big-pickle
## TL;DR
- Status: IMPLEMENTED
- Fixes F1F6 from `AgentsReport/reviewer/2026-09-06_pos_ai_full_review.md` implemented in `bin/pos-ai-hf`, `bin/pos-ai-server`, `DOC/POS.md` (hf + server detail), generated docs via `make gen`.
- Scope: exactly the approved fixes; no changes to `bin/pos-ai`, `bin/pos-ai-llamacpp`, `bin/pos`, README.md, AGENT_TODO.md, lib/ (AGENT_TODO.md not updated on purpose — out of scope, has pre-existing worktree edits).
- Verification: `bash -n` clean; `make gen` idempotent (3rd run md5-identical); `make check` → check-sync: OK; `make lint``0 FAIL, 0 WARN`; targeted probe matrix below (all passed).
- Deviation from reviewer wording: destroy-confirmation for `cache clear` reads `/dev/tty` (same pattern as `pos-ai-server pick_model`) instead of sourcing `lib/common.sh confirm()``pos-ai-hf` is NOT in `bin/pos` `INTERACTIVE_CMDS` and `bin/pos` is off-limits, so a plain stdin `read`/`confirm` would hang-or-trip the `uses_stdin` lint rule. Fail-closed default `n`, EOF/invalid denies (verified via `setsid`/pty probes).
## Step 1: F1 — include/exclude glob filtering (pos-ai-hf)
[DONE]
- Removed the `--include/--exclude` + `--gguf` erroring pre-check (`bin/pos-ai-hf` cmd_download) — patterns now compose, not conflict.
- Removed the old jq `match()` regex branch (regex semantics despite "supports glob" docs) from the `elif` chain; single composition point after gguf/filename filter, order: gguf/filename → include → exclude.
- New `hf_apply_patterns()` (`bin/pos-ai-hf:422-447`): bash `case` glob semantics, always yields a JSON array (`[]` when no match) preserving `{"rfilename","size"}` shape.
- Added error path `No files match include/exclude patterns in <repo> (branch: <branch>)` (rc 1) when patterns filter everything out.
Probes (fake curl serving canned repo):
- `--include "model.gguf"` (single file, sequential): rc 0, only model.gguf fetched, `.hf-meta` files array is a JSON array of 1.
- `--include "*.gguf"` (parallel): rc 0, model.gguf + Q8_0/model-q8.gguf fetched, meta files array length 2.
- `--include "*.bin"``ERROR: No files match include/exclude patterns in org/model (branch: main)`, rc 1.
- `--gguf --include "*.gguf"` composes: rc 0, same 2 gguf files.
- exclude-only `--exclude "*.safetensors"` → rc 0, 3 files remain.
## Step 2: F2 — systemd unit single-line ExecStart (pos-ai-server)
[DONE]
- `cmd_start` now builds ONE `exec_cmd` string with binary + model + all resolved flags (`bin/pos-ai-server:431-477`); unit written via heredoc with `ExecStart=$exec_cmd` on a single line (`bin/pos-ai-server:488-504`) — no more multi-line `echo >>` appends that systemd rejects.
- Dry-run prints the same `$exec_cmd` it would write into the unit (previously the dry-run line missed all optional flags).
- Real (non-dry) start: unit written, then `systemctl --user daemon-reload` (container has no systemd user session → fails after write, expected; unit itself verified).
Probes:
- dry-run with all flags: single ExecStart line containing every flag, rc 0.
- real run wrote the unit; `systemd-analyze verify <unit>`**RC=0, no warnings** (executable path resolves, `EnvironmentFile=-%h/...` accepted).
## Step 3: F3 — --branch/--revision alias (pos-ai-hf)
[DONE]
- Removed the separate `BRANCH` variable; `--branch` and `--revision` both set `REVISION` (`bin/pos-ai-hf:127-148`), last flag wins (usage documents the alias).
- `hf_resolve_branch` unchanged: explicit revision or API default branch, falls back `main`.
Probes:
- `--branch main`, `--revision v1.0`, and `--revision v2.0 --branch main` (later wins → main) all rc 0.
## Step 4: F4 — parallel download failure handling (pos-ai-hf)
[DONE]
- Rewrote the parallel path (`bin/pos-ai-hf:638-692`): per-pid `wait` with `! wait` failure capture, parallel `job_pids`/`job_names` arrays, `failed_files` collection, per-job log files under `mktemp -d` temp dir (no interleaved output), individual job reaped as batch limit reached AND full drain at the end, per-file `Failed to download <file>` warns after the batch (same style as sequential path), `trap 'rm -rf "$temp_dir"' EXIT` + explicit `rm -rf` + `trap - EXIT` so temp dirs never survive.
- Removed dead helpers `err_with_context`, `hf_download_file`, `run_parallel_download`.
Probes (poisoned fake curl failing only `Q8_0/model-q8.gguf`):
- 2-file parallel download: 1 success + 1 failure — batch rc 0, `[!] Failed to download Q8_0/model-q8.gguf` reported at end, successful file on disk, **zero stray `/tmp/tmp.*` dirs** after exit.
- Known limit (pre-existing, noted not in review scope): summary line counts *attempted* files (`2 files, 40 B`) even when one fails — same optimistic counting as the sequential path.
## Step 5: F5 — version/feature validation guard (pos-ai-server)
[DONE]
- `detect_llama_version <binary>` guarded: missing binary or unreadable `--version``unknown`, never errexit (previously called `llama-server --version` directly → crash when binary absent).
- Replaced no-op `validate_server_features` with `validate_requested_flags <binary> <version> <flag...>`: greps the binary's actual `--help` output for each **explicitly requested** flag token; first unsupported one errors `installed llama.cpp <version> does not expose <flag> — remove it or upgrade llama.cpp`; unreadable `--help` → warn once and proceed (no hard-fail). Alias-mapped requests dedupe (`--gpu`/`--gpu-layers`/`--n-gpu-layers` all validate `--n-gpu-layers`).
- Parse loop records canonical request tokens in `REQUESTED_FLAGS` (defaults/config-derived values NOT validated — only what the user typed).
- `cmd_status`: binary guard with actionable error before version probe; version printed via the *resolved* binary path.
Probes (fake llama-server v0.1.0 whose `--help` omits `--kv-cache` and `--slots`):
- `start --model fake.gguf --slots 4``ERROR: installed llama.cpp 0.1.0 does not expose --slots — remove it or upgrade llama.cpp`, rc 1 (also proves validation runs before dry-run return).
- `status` without llama-server on PATH → `ERROR: llama-server not found — install llama.cpp (...)`, rc 1, no crash.
- `status` with shim → `service: stopped`, `version: 0.1.0`, rc 0.
## Step 6: F6 — hf cache real implementation (pos-ai-hf)
[DONE]
- `cmd_cache {status|clear}` with default `status` (`bin/pos-ai-hf:887-894`); bad action → usage error. Top-level indent of `cmd_cache()` fixed (reviewer style nit).
- `cmd_cache_status`: cache dir + model count + total on-disk size (excludes `.hf-meta` — same discovery as `list`/`remove`); empty dir → `Models: 0 (nothing downloaded yet)`, rc 0.
- `cmd_cache_clear`: lists models to be removed, then confirm `Remove all downloaded models? [y/N]: ` read from `/dev/tty` (see TL;DR deviation), fail-closed — anything but `y`/`Y` (including EOF) → `Aborted — nothing removed`, rc 0; on `y` removes all model dirs and prints freed size.
Probes:
- `cache status` empty cache: rc 0, `Models: 0 (nothing downloaded yet)`.
- `cache status` 2 fake models: `Models: 2 / Size: 5 B`, rc 0.
- `cache clear` under `setsid` (EOF, no tty): prompt shown, `Aborted — nothing removed`, rc 0, **models intact**; clean stderr (the `/dev/tty` open error is suppressed: `read -r yn 2>/dev/null </dev/tty` — redirection order matters).
- `cache clear` via pty (`script -qec` feeding `y`): list shown, prompt, `Cache cleared (freed 9 B)`, rc 0, model dirs **gone**.
## Step 7: Docs (DOC/POS.md) + make gen/check/lint
[DONE]
- `DOC/POS.md`: hf download row updated (`--revision` alias, include/exclude glob composition order, example), new `pos ai hf cache [status|clear]` row, server flags+validation detail extended.
- `make gen` after touching bin files: tree/dispatch/filetable/completions regenerated (also repairs the pre-existing stale `_pos_flags` for ai-hf/ai-server and picks up the maintainer's untracked `pos-ai-llamacpp` forwarder).
- Gates (final state): `bash -n bin/pos-ai-hf bin/pos-ai-server` → OK; `make gen` twice after edits → second run byte-identical (idempotent); `make check` → check-sync: OK; `make lint``0 FAIL, 0 WARN`.
## Files changed (this task)
- `bin/pos-ai-hf` — F1/F3/F4/F6 (+ dead code removal, style fix)
- `bin/pos-ai-server` — F2/F5
- `DOC/POS.md` — hf download row, cache row, server flags/validation
- `DOC/AGENT_Context_Project.md`, `completions/pos.bash` — generated by `make gen` (auto-rows, flags, subcmd completion)
Pre-existing worktree drift NOT touched (confirmed untouched in final diff): `AGENT_TODO.md`, `DOC/howto/ai.md`, `bin/pos`, `bin/pos-ai`, untracked `bin/pos-ai-llamacpp`, `AUDIT.md` etc.
## Remaining risks / deferrals
- `systemctl --user daemon-reload`/`enable --now` cannot complete inside this container (no systemd user session) — real start verified only up to unit write + `systemd-analyze verify` RC 0; the systemctl calls themselves are otherwise standard.
- Summary line after a partially failed parallel download counts attempted files, not successes (pre-existing, matches sequential path; not flagged in review).
- `validate_requested_flags` warns-and-proceeds if `--help` cannot be read (deliberate: silent-basic-defaults behavior lost, actionable warning kept).