Files
Linux_post_install/AgentsReport/builder/2026-09-06_r1r2-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

76 lines
5.7 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 — R1/R2 fixes (re-review findings)
Date: 2026-09-06
Builder: implementation pass on top of the re-review (`AgentsReport/reviewer/2026-09-06_pos_ai_rereview.md`)
Approved scope: fix R1 (`bin/pos-ai-server` ExecStart quoting) and R2 (`bin/pos-ai-hf` partial-failure honesty). Files modified: only `bin/pos-ai-server`, `bin/pos-ai-hf`. Generated docs were refreshed by the mandated `make gen` gate.
## TL;DR
- **Status: IMPLEMENTED** — both REQUIRED findings fixed; all gates green; both targeted probes pass.
- Files changed: `bin/pos-ai-server` (systemd_quote helper + quoted ExecStart tokens), `bin/pos-ai-hf` (honest failure count, `.hf-meta` gating, non-zero exit, honest progress labels).
- Verification: `bash -n` clean; `make gen` idempotent (sha256-identical across runs); `make check``check-sync: OK` (rc 0); `make lint``0 FAIL, 0 WARN`.
- R1 probe: dry-run ExecStart with a spaced model path → `systemd-analyze verify` rc 0; systemd word-split == exactly [binary, --model, <spaced path>, each flag, each value] (16 tokens, asserted programmatically).
- R2 probe: stub-curl 2-file parallel download with 1 failure → summary `📥 Downloaded: org/probe (1 of 2 files, 1 failed: model-fail.bin)`, NO `.hf-meta` written, `list` shows nothing, exit code 1.
- AGENT_TODO.md intentionally NOT updated: the brief constrains modifications to the two files only ("Do not touch other files").
## Step 1: R1 — systemd ExecStart quoting (`bin/pos-ai-server`)
Added `systemd_quote()` (bin/pos-ai-server:388-392): wraps a value in systemd double quotes and escapes embedded `"` as `\"` (verified: `${value//\"/\\\"}` produces `\"`). `cmd_start` now builds the base line as:
```bash
exec_cmd="$(systemd_quote "$llamacpp_full") -m $(systemd_quote "$model") --port $PORT --host $HOST"
```
(bin/pos-ai-server:445). Only the executable path and the model path — the tokens that may legally contain spaces per the brief — are quoted; numeric/flag tokens (`--port 8088`, `--n-gpu-layers 10`, …) stay unquoted, so no over-quoting. The unit heredoc still writes `ExecStart=$exec_cmd` (bin/pos-ai-server:508) and the dry-run prints the same `$exec_cmd` (bin/pos-ai-server:491), so dry-run output is byte-identical to the unit by construction.
Probe (run with fake `llama-server` from `/tmp/opencode/ai-probe/bin`, model at `/tmp/opencode/ai-probe/models/My Model/ggml-model-Q4_K_M.gguf`, flags `--port 9090 --gpu-layers 10 --ctx-size 2048 --temperature 0.7 --mmap`):
```
[+] (dry-run) ExecStart: "/tmp/opencode/ai-probe/bin/llama-server" -m "/tmp/opencode/ai-probe/models/My Model/ggml-model-Q4_K_M.gguf" --port 9090 --host 127.0.0.1 --n-gpu-layers 10 --ctx-size 2048 --threads 4 --temperature 0.7 --mmap
rc=0
systemd-analyze verify → rc=0
word-split == [binary, --model, <spaced path>, each flag, each value] → True (16 tokens)
```
[DONE]
## Step 2: R2 — partial-failure honesty (`bin/pos-ai-hf`)
Changes inside `cmd_download` only; the sequential single-file path (else branch) is byte-for-byte unchanged:
- `failed_files` is now function-scoped (bin/pos-ai-hf:632), populated only by the parallel branch, so the sequential path is unaffected (empty array there).
- Progress labels are honest: a reaped job that failed prints `[n/m] Failed: <file>` instead of `Completed:` (bin/pos-ai-hf:672, 686).
- `.hf-meta` is written only when `failed_files` is empty; on partial failure a warn explains the skip (bin/pos-ai-hf:727-744). Consumers `list`/`cache` only discover models with `.hf-meta` (cmd_list/hf_cache_models), so an incomplete model is not advertised.
- Summary is honest for the parallel path: `📥 Downloaded: <repo> (X of Y files, N failed: <f1> <f2>)` where X = Y N (bin/pos-ai-hf:760-761). The all-success multi-file summary and the single-file summary are unchanged.
- Exit: `return 1` when `failed_files` is non-empty (bin/pos-ai-hf:773-775) — only reachable from the parallel path.
Probe (stub curl in `/tmp/opencode/ai-probe/r2bin`, canned 2-file listing, target containing `fail` exits 1; `download org/probe --branch main` with both files in one parallel batch):
```
[1/2] Completed: model-ok.bin
[2/2] Failed: model-fail.bin
[!] Failed to download model-fail.bin
[!] Not writing .hf-meta — org/probe is incomplete (1 file(s) failed)
📥 Downloaded: org/probe (1 of 2 files, 1 failed: model-fail.bin)
📁 /tmp/opencode/ai-probe/dl/org-probe/
rc=1
```
Post-checks: dir contains only `model-ok.bin` (no `.hf-meta`); `pos ai hf list``No models downloaded yet`; single-file sequential success → meta written, rc 0 (unchanged); single-file sequential failure → warn-and-continue, rc 0 (unchanged, pre-existing behavior preserved per constraint).
[DONE]
## Step 3: Gates
- `bash -n bin/pos-ai-server bin/pos-ai-hf` → clean.
- `make gen` ×2 → `gen-docs: write OK`; sha256 of `DOC/AGENT_Context_Project.md` + `completions/pos.bash` identical across runs → idempotent. Filetable row counts now match `wc -l` exactly (pos-ai-hf 1004, pos-ai-server 659).
- `make check``check-sync: OK` (rc 0).
- `make lint``0 FAIL, 0 WARN (convention lint)`.
[DONE]
## Scope compliance / residual notes
- Only `bin/pos-ai-server` and `bin/pos-ai-hf` were edited by this pass; `DOC/AGENT_Context_Project.md`/`completions/pos.bash` were refreshed only by the mandated `make gen` gate (line counts/examples columns). No new flags/subcommands/config keys. AGENT_TODO.md not touched (brief forbids other files).
- Residual risk (pre-existing, explicitly out of scope by the "keep sequential path unchanged" constraint): the single-file sequential failure path still warns-and-continues with rc 0 and writes `.hf-meta` including the failed file. Flagged for a future decision; not changed here.
- Probes ran in this environment (real `systemd-analyze`, `bash`, `make` available); nothing was blocked.