d817c37652
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.
101 lines
10 KiB
Markdown
101 lines
10 KiB
Markdown
# Builder Report — 2026-09-06 — Stabilization: Tooling track (lint perf, D-E uninstall, H-002/H-003)
|
||
|
||
**Scope (per brief):** `scripts/lint-conventions.sh`, `bin/pos-system-uninstall`, `DOC/POS.md` (system uninstall row only if factual); NOT touched: other files listed in the brief. `lib/install-manifest.sh` is **NOT** created — see D-E.
|
||
|
||
**TL;DR**
|
||
- Status: **DONE** — all 3 steps implemented, probed, gated.
|
||
- Files in scope changed by me: `scripts/lint-conventions.sh` (rewrite), `bin/pos-system-uninstall` (D-E/H-002/H-003), `DOC/POS.md` (system-uninstall row only), plus gen output in `DOC/AGENT_Context_Project.md` + `completions/pos.bash` (reflecting the whole shared tree, incl. parallel tracks).
|
||
- D-E explicitly says **do NOT** create `lib/install-manifest.sh` — the brief's manifest is conditional ("if D-E specifies it"); it does not, so I implement D-E's actual decision (extend `bin/pos-system-uninstall` directly, no manifest file).
|
||
- Baseline `make lint` = **145.9 s** (measured, `time`); final = **4.38 s**, `0 FAIL, 0 WARN`, output byte-identical to original (differential test). `make check` OK; `make gen` idempotent.
|
||
- H-002/H-003 probes pass: exact-literal + anchored `awk` removal removes only pos-owned lines; comments, user PATH/MY_POS_REPO lines, `repos`/`dispose`/`compose` completion, and `unrelated.service` all survive.
|
||
- Remaining risk: real-machine removal path validated via fixtures only (no live uninstall run) — see Step 3.
|
||
|
||
## Step plan
|
||
1. Lint performance rewrite (Task 1).
|
||
2. D-E uninstall extensions + H-002/H-003 + surviving-artifacts docs (Tasks 2, 3).
|
||
3. Probes + full gates.
|
||
|
||
---
|
||
|
||
## Step 1: Lint performance rewrite
|
||
|
||
Refactored `scripts/lint-conventions.sh` hot paths to bash-native parsing:
|
||
- Merged per-line `uses_stdin` + top-level-`local` scans (was `printf | sed | tail` × 3 forks per line) into ONE single-pass per-file read with heredoc-delimiter state via `[[ =~ ]]`.
|
||
- Folded `# POS:` header / em-dash / posline / first `-h|--help` line into the same loop.
|
||
- Shebang via `read -r first < "$f"`; POS.md coverage via one preloaded `cat` + `[[ ]]`; secret-literal + system-path scans → bash `[[ =~ ]]` with cheap string gates; deleted dead `last_line()`.
|
||
- System-path outer filter (`(\btee\b|>>?)[^#]*?(path)`) reimplemented faithfully (`_syspath_outer` — no fork, global `_SI`), preserving the no-`#`-between-operator-and-path semantics that bash `=~` cannot replicate.
|
||
|
||
**Verification:**
|
||
- `bash -n` OK.
|
||
- Differential test vs `git show HEAD:scripts/lint-conventions.sh`: **outputs byte-identical** (both exit 0, `0 FAIL, 0 WARN`).
|
||
- Negative test (broken tool): all expected FAIL/WARNs fire; skipped per-file checks on missing POS header match original `continue`.
|
||
- Timings (`time bash scripts/lint-conventions.sh`): **before 145.9 s → after 4.79 s (~30x)**. `time make lint` before: >120 s (timed out at 145.9 s for the bare script); after: see gates below.
|
||
|
||
[DONE]
|
||
|
||
---
|
||
|
||
## Step 2: D-E install/uninstall + H-002/H-003
|
||
|
||
### D-E reconciliation — NO `lib/install-manifest.sh`
|
||
D-E (architect decision `stabilization-design.md:399-401`) explicitly says: *"Do NOT introduce a full manifest abstraction (like `lib/install-manifest.sh`) — that would be a larger refactor inconsistent with the current 'list-based' approach"*. The brief's manifest requirement was conditional ("If D-E specifies `lib/install-manifest.sh`"); it does not. Per the scope rule (necessary-to-complete vs better-design), I implemented D-E's actual decision: **one** source of truth inside `bin/pos-system-uninstall` (singleton `POS_LIBS` array + `PATH_LINE`/`COMPLETION_LINE`/`HOOK_PATTERN` constants + `installed_plugins()` helper) used by both scan and remove — the removal list is no longer two hardcoded places. Nothing else in the codebase was introduced.
|
||
|
||
### Changes to `bin/pos-system-uninstall`
|
||
- **Libs (D-E 1):** `POS_LIBS` = all 12 libs from install.sh phase 2 (`common.sh flags.sh notify.sh entertainment-lib.sh scheduler-lib.sh config-ui.sh user-timers-lib.sh entertainment-plugin-lib.sh usb-lib.sh share-lib.sh menu-lib.sh registry.sh`); scan + remove loops both read the single array. Verified **byte-identical** to install.sh:143.
|
||
- **ScaleTail + flags store (D-E 2):** scan + remove for `/usr/local/share/linux_post_install/scale-tail/` and `/flags/`, then `rmdir` the parent if empty.
|
||
- **User systemd units (D-E 3):** scan + remove `$XDG_CONFIG_HOME/$HOME/.config/systemd/user/pos-*` (`disable --now` + `rm`, `|| true` wrapped; `daemon-reload` at end). `unrelated.service` probe survives.
|
||
- **De-hardcoded entertainment plugins (D-E 4):** `installed_plugins()` discovers installed plugins by `# POS_PLUGIN:` marker (matching install.sh's directory-driven install), used by scan + remove.
|
||
- **H-002 (D-E 5):** `.bash_completion` `sed -i '/pos/d'` replaced with anchored `awk '/^[[:space:]]*source[[:space:]].*pos\.bash/ { next } { print }'` + mktemp + `chmod --reference` + count.
|
||
- **H-003 (D-E 6):** `.bashrc` sed removals replaced with exact-literal `awk` removal of postinstall.sh's `PATH_LINE` + `COMPLETION_LINE` and anchored `HOOK_PATTERN='^[[:space:]]*source[[:space:]].*pos-ai-hook\.sh'` (comment-safe per D-E acceptance criterion 5). Note: the old `/linux_post_install.*PATH/d` never removed the real PATH_LINE anyway (that literal has no `linux_post_install` substring); the new code removes the installer's actual line.
|
||
- **Surviving artifacts (D-E 7):** usage() documents deliberately NOT removed: apt packages, `/usr/local/bin/yt-dlp`, `~/.config/rclone/`, `~/.ssh/authorized_keys` additions, config/data tiers.
|
||
- **DOC/POS.md:** system-uninstall row Tier 1 description updated (factual): adds user units + ScaleTail + flags store.
|
||
|
||
### Probes (all pass)
|
||
1. **H-002/H-003 fixture `.bashrc` (15 lines incl. unrelated `pos` lines + comments) → 3 lines removed** (PATH_LINE, COMPLETION_LINE, hook source); custom `MY_POS_REPO`, user PATH, `# source pos.bash` comments survive.
|
||
2. **Fixture `.bash_completion` (7 lines incl. `repos`/`dispose`/`compose`) → 1 line removed** (source pos.bash); `repos`/`dispose`/`compose` and comment survive.
|
||
3. **scan_tier1 (HOME fixture):** finds exact bashrc/bash_completion lines + `pos-aria2.service`, `pos-entertainment-weather.timer` user units; does NOT find `unrelated.service` or unrelated completion lines.
|
||
4. **remove block replication:** REMOVED_COUNT=6 (3 bashrc + 1 completion + 2 user units); unrelated content + `unrelated.service` survive; `systemctl --user` fails gracefully (`|| true`, no session).
|
||
5. **Inventory: POS_LIBS == install.sh lib list** (12 names identical); 13th `lib/pos-ai-hook.sh` is not installed by install.sh phase 2 (correctly not in POS_LIBS).
|
||
|
||
[DONE]
|
||
|
||
---
|
||
|
||
## Step 3: Gates + hygiene
|
||
|
||
### Gate results (final state)
|
||
- `bash -n scripts/lint-conventions.sh bin/pos-system-uninstall` → OK.
|
||
- `make gen` ×2 → idempotent (`gen-docs: write OK` both runs; second run produces the same diff, no drift).
|
||
- `make check` → `check-sync: OK` (exit 0).
|
||
- `time make lint` → `0 FAIL, 0 WARN (convention lint)`, **4.38 s** (second run 6.26 s; final measured 4.38 s). Baseline was **145.9 s** for the bare script and >120 s (timeout) for `make lint` → ~30x speedup. Rapid repeat runs no longer leave the shell spinning (no more per-line fork storms).
|
||
- **Gen output note:** `make gen` regenerated `DOC/AGENT_Context_Project.md` + `completions/pos.bash` from the **shared** working tree. The diff includes my expected `bin/pos-system-uninstall` row-count update (435→517 lines) **plus** the other parallel tracks' already-uncommitted changes (`bin/pos-ai-server`, `bin/pos-ai`, `bin/pos-system-backup`, communication listeners, etc.). No POS headers/dirs were touched by me; gen is byte-order deterministic (`LC_ALL=C`), CI's `git diff --exit-code` will see the whole tree's refresh.
|
||
|
||
### Hybrid conflict check (shared working tree)
|
||
Final `git status` shows many files modified by **parallel Builder tracks** (stab-ai, stab-security: `bin/pos-ai*`, `bin/pos-communication-*`, `bin/pos-network-checkport`, `bin/pos-share-smb-client`, `bin/pos-system-backup`, `lib/share-lib.sh`, `lib/ai-providers/llamacpp.sh`, `apps/install.sh`, `templates/app.sh`, `DOC/howto/*`, `DOC/APPS.md`, `AGENT_TODO.md`, `config/*.env`). These were NOT edited by me — my changed-file set is exactly:
|
||
1. `scripts/lint-conventions.sh` (rewritten; 213 changed lines vs HEAD)
|
||
2. `bin/pos-system-uninstall` (D-E + H-002/H-003; 150 changed lines vs HEAD)
|
||
3. `DOC/POS.md` — only the `pos system uninstall` row (all other rows in the file diff belong to other tracks)
|
||
4. `DOC/AGENT_Context_Project.md` + `completions/pos.bash` — gen output including, among others, my uninstall row count
|
||
5. `AgentsReport/builder/2026-09-06_stab-tooling.md` (this report)
|
||
|
||
No protected/brief-excluded file was touched by me; no out-of-scope change made.
|
||
|
||
### DOC/SCRIPTS.md + DOC/DEV.md
|
||
Not touched: no manifest was created (D-E rejected it), so the brief's "only if the manifest needs documenting" condition does not apply. No new documentation needed.
|
||
|
||
[DONE]
|
||
|
||
---
|
||
|
||
## Final status
|
||
|
||
- **Scope:** lint perf (Task 1) + D-E uninstall coverage (Task 2) + H-002/H-003 safe removal (Task 3) + surviving-artifacts docs (D-E 7). All implemented; no scope expansion.
|
||
- **Timings:** `make lint` 145.9 s → 4.38 s (~30x). Differential: output byte-identical to original.
|
||
- **Probes:** all pass (H-002/H-003 fixture removal, scan_tier1 with HOME override, remove-block replication, POS_LIBS==install.sh inventory).
|
||
- **Gates:** `bash -n` OK, `make gen` idempotent, `make check` OK, `make lint` `0 FAIL, 0 WARN`.
|
||
- **Deferred/risks:**
|
||
1. The real-machine removal path (removing live `/usr/local/bin`, `/etc/systemd`, ScaleTail dirs) was NOT executed here — validated via fixture/sandbox probes only. A dry-run pass on a real install is doable via the tool's own scan display (`pos system uninstall` interactive scan shows Tier 1 entries before any removal).
|
||
2. `lib/pos-ai-hook.sh` (13th lib file) is intentionally not in `POS_LIBS` because install.sh phase 2 doesn't install it; the uninstaller already removes `~/.local/bin/pos-ai-hook.sh` separately — no action.
|
||
3. Other parallel tracks' edits are interleaved in the shared tree; my in-scope files are `scripts/lint-conventions.sh`, `bin/pos-system-uninstall`, DOC/POS.md (one row).
|
||
- **Recommended next agent:** Reviewer (independent adversarial review of the uninstall diff + lint rewrite), then Orchestrator to coordinate the shared-tree commit once the parallel tracks land.
|