fix: stabilization pass — fail-closed auth, ai flag validation, lint/config/security hardening, regression tests
gates / consistency-and-conventions (push) Successful in 26s
gates / consistency-and-conventions (push) Successful in 26s
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.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# Tester Report — Regression Test Infrastructure + First Suite (2026-09-06)
|
||||
|
||||
## TL;DR (updated continuously)
|
||||
|
||||
- **Status:** TESTS_READY — 12/12 test files pass, 177 checks, runtime ~46s (`make test`).
|
||||
- **Deliverables:** `tests/run-tests.sh` (zero-dep runner), `make test` target, 12 `tests/t-*.sh` files, `tests/README.md`.
|
||||
- **Findings (production bugs discovered):** none — no production bug surfaced; all defects found during test iteration were in the test framework/stubs/test assertions themselves (see Step 4).
|
||||
- **Suite timing / counts:** `make test` (2026-09-06): files **12 pass / 0 fail / 0 skip**, checks **177 pass / 0 fail / 0 skip**, runtime **46s** (44s on rerun); exit 0.
|
||||
- **Gates:** `make lint` still `0 FAIL, 0 WARN`; `make check` now PASS (parallel-track gen drift resolved upstream during this session); tests/ has zero lint/check surface.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Environment baseline (before adding tests)
|
||||
|
||||
- `make check` at start: **FAILED** — `doc/code drift` (expected: parallel Builder tracks have uncommitted changes; gen output in the working tree not yet refreshed). Now resolves to PASS after upstream sync.
|
||||
- `make lint` at start: **PASS** — `0 FAIL, 0 WARN` (3.5s).
|
||||
- `make gen` idempotence on a pristine temp copy: **PASS** (2× ~1.4–1.8s; `git status --porcelain` empty after 2nd gen).
|
||||
- `systemd-analyze verify` prototype: passes (rc 0) when ExecStart binary exists and model path is quoted.
|
||||
- Config-loader migration (D-D): **landed in the working tree** — `load_env_file` present in `lib/config-ui.sh:336`; all 9 tools call it. Config-precedence tests target the final contract.
|
||||
|
||||
## Step 2: Framework + suite files (status below)
|
||||
|
||||
- [x] `tests/run-tests.sh`
|
||||
- [x] `tests/test-lib.sh`
|
||||
- [x] `tests/t-ai-server-flags.sh`
|
||||
- [x] `tests/t-ai-hf-download.sh`
|
||||
- [x] `tests/t-ai-llama-detect.sh`
|
||||
- [x] `tests/t-unsupported-flags.sh`
|
||||
- [x] `tests/t-systemd-unit.sh`
|
||||
- [x] `tests/t-telegram-auth.sh`
|
||||
- [x] `tests/t-matrix-auth.sh`
|
||||
- [x] `tests/t-gpg-password.sh`
|
||||
- [x] `tests/t-config-precedence.sh`
|
||||
- [x] `tests/t-uninstall-manifest.sh`
|
||||
- [x] `tests/t-gen-docs-drift.sh`
|
||||
- [x] `tests/t-lint-gate.sh`
|
||||
- [x] `Makefile` `test:` target
|
||||
- [x] `tests/README.md`
|
||||
|
||||
## Step 3: Full suite run (final)
|
||||
|
||||
Command: `make test` (target: `./tests/run-tests.sh`) — 2026-09-06.
|
||||
|
||||
```
|
||||
Running 12 test file(s) — strict mode: no network, no sudo, no system changes.
|
||||
|
||||
PASS t-ai-hf-download.sh (10 checks)
|
||||
PASS t-ai-llama-detect.sh (9 checks)
|
||||
PASS t-ai-server-flags.sh (28 checks)
|
||||
PASS t-config-precedence.sh (43 checks)
|
||||
PASS t-gen-docs-drift.sh (4 checks)
|
||||
PASS t-gpg-password.sh (14 checks)
|
||||
PASS t-lint-gate.sh (5 checks)
|
||||
PASS t-matrix-auth.sh (8 checks)
|
||||
PASS t-systemd-unit.sh (11 checks)
|
||||
PASS t-telegram-auth.sh (8 checks)
|
||||
PASS t-uninstall-manifest.sh (18 checks)
|
||||
PASS t-unsupported-flags.sh (19 checks)
|
||||
|
||||
──────────────────────────────────────────────
|
||||
Summary: files 12 pass / 0 fail / 0 skip (of 12)
|
||||
Checks : 177 pass / 0 fail / 0 skip
|
||||
Runtime: 46s
|
||||
```
|
||||
|
||||
Exit code 0. Rerun via `make test`: files 12/12 pass, 44s. `make lint` unaffected (`0 FAIL, 0 WARN`), `make check` passes (parallel drift resolved upstream, not by this track).
|
||||
|
||||
[PASS]
|
||||
|
||||
## Step 4: Defects found and fixed during test iteration (all in test artifacts, none in production)
|
||||
|
||||
1. `tests/test-lib.sh` `check_rc` — `$desc` read before `local desc="$1"` declaration → `set -u` crash on first use. Fixed.
|
||||
2. `tests/run-tests.sh` — `set -e` in the runner killed the PARENT when a test subshell exited nonzero (e.g. test 4 aborted after 3 passing tests). Fixed: subshell wrapped in `if (…); then rc=0; else rc=$?; fi`; verified a failing test now records FAIL and continues. Also: bare-name args (`run-tests.sh t-gpg-password`) now resolve `$TEST_DIR/<name>.sh`.
|
||||
3. `tests/t-ai-hf-download.sh` stub — embedded JSON via `$(cat "$tree_resp")` broke stub quoting → replaced with `cat "$TREE_RESP"` env passthrough; `for (( ; i<=$#; i++ ))` expanded `$#` at stub-write time → escaped `\$#`; `base_env` typo → `env_base`; `return 1` at stub top level → `exit 1` (see #6).
|
||||
4. `tests/t-ai-llama-detect.sh` — asserted literal `cpu`; tool emits `gpu: CPU` (case differs) → assertions corrected to actual token shape.
|
||||
5. `tests/t-config-precedence.sh` — Part A env-wins probe `FOO=envval load_env_file …` evaluated in the PARENT shell (no persistence) → rewrote as explicit subprocess with `export` + captured output; Part B needed llama-server + nvidia-smi stubs for the deps guard; Part D legacy guard was a false positive — exactly 3 documented `load_system_env` callers (pos-media-sync, pos-system-backup, pos-system-health) → whitelist those and assert count == 3.
|
||||
6. **Stub scripts: `return` at top level of a non-sourced script is an ERROR in bash and falls through** (`return: can only 'return' from a function or sourced script`), so every stub response silently gained a trailing `{"ok":true}` → corrupt JSON → listeners slept in a 5s retry loop and never processed (`jq -r '.ok'` returned `true\ntrue`). Fixed all stub heredocs to `exit 0` (telegram/matrix curl stubs; ai-hf already used `exit`).
|
||||
7. `tests/t-telegram-auth.sh` / `tests/t-matrix-auth.sh` — two line-continuation bugs in `test_run_env` invocations: a missing trailing `\` meant the env-var list became a separate command and `test_run_env` ran bare `env` (prints the whole environment — the mysterious `SHELL=/bin/bash` output) with rc 0. Fixed by single-line invocation. Matrix reply count needle `m.room.message` also matched the URL-encoded sync filter on every `/sync` line → narrowed to `/send/m.room.message`.
|
||||
8. `tests/t-gpg-password.sh` — artifact-leftover checks false-failed because run 1's `.gpg` remained on disk for runs 2/3 → now `rm -rf "$work"; mkdir` between runs; bare `--passphrase` guard now token-exact (`grep -c '^--passphrase$'`) since `--passphrase-fd` legitimately contains the substring.
|
||||
9. `tests/t-lint-gate.sh` — negative case invoked the REAL lint (absolute path); `lint-conventions.sh` computes `ROOT="$(dirname "$0")/.."` and `cd`s THERE, so it linted the real repo (clean), not the planted copy. Fixed: run the copy's own `scripts/lint-conventions.sh` (relative path) from inside the copy.
|
||||
10. `tests/t-uninstall-manifest.sh` — POS_LIBS extraction awk `<^POS_LIBS=( … {getline; while(1)…}` never matched a lone `^)` line because the block is `POS_LIBS=(… \⏎ …registry.sh)` (two lines, `)` on the second) → getline at EOF returns 0, loop spins forever at EOF → the whole test hung (this was the full-suite 300s hang). Replaced with a sed range `/^POS_LIBS=(/,/)$/p` + normalization; also the leftover-gap whitespace made the sorted diff fail (collapsed with `tr -s`), and plugin-removal marker check now greps `POS_PLUGIN` (the marker `installed_plugins()` scans for) instead of a literal `^# POS_PLUGIN:` in the uninstall script.
|
||||
11. `tests/t-systemd-unit.sh` — systemd unit uses double quotes (not backslash escaping) for the model path → assertion corrected; `EnvironmentFile` check compared against the unit PATH instead of its content → `$(cat "$unit")`.
|
||||
12. `tests/t-unsupported-flags.sh` — real error text is `installed llama.cpp <v> does not expose <flag> — remove it or upgrade llama.cpp`, not "does not support" → assertions updated.
|
||||
|
||||
None of the above touched production code. `make check` / `make lint` / `make gen` results are unchanged by this track (verify with `make check && make lint` — both currently green).
|
||||
|
||||
## Step 5: Coverage notes & handoff
|
||||
|
||||
- **Behavior covered per area:** ai-server flag seam (CLI/config/env/default precedence + unsupported-flag hard error + dedupe) 28; config file precedence + legacy loaders 43; gpg password hygiene (fd-only, no bare token, no secret in argv, artifact cleanup on enc/verify failure) 14; systemd unit generation (ExecStart quoting, environment/deps/secrets lines, `systemd-analyze verify`) 11; telegram/matrix authz fail-closed gates 8+8; ai hf download stub network behavior 10; llama detection stub 9; gen/lint gates (positive + planted-violation negative) 4+5; uninstall manifest symmetry + XDG scan tier + POS_PLUGIN marker 18; unsupported-flag matrix 19.
|
||||
- **What is not covered (deliberately):** real network/sudo/docker paths (stubbed only); `pos entertainment send` live-plugin e2e (requires Telegram token); anything requiring root. These are outside the sandbox contract of this suite and remain manual checks.
|
||||
- **Suite hygiene:** deterministic sorted order, per-test sandbox auto-clean, per-file logs, no network/sudo/system mutations, skip contract, total < 90s.
|
||||
|
||||
[PASS]
|
||||
Reference in New Issue
Block a user