From cb82acb155e0cbf38c4bf7051d8db9683b636bc9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 9 Aug 2026 04:31:07 -0400 Subject: [PATCH] fix: cache pos config scopes for completion; stop per-TAB registry scan pos config re-scanned every tool's '# POS_CONFIG:' header per keypress (dozens of subshells, greps, seds). On the loaded homelab box a stuck completion wedged interactive shells at 69% CPU for ~an hour. make gen now emits a static _pos_config_scopes array into completions/pos.bash (no runtime scan; live-scan fallback if the cache is missing). --- AGENT_TODO.md | 4 +++- DOC/AGENT_Context_Project.md | 2 +- completions/pos.bash | 34 +++++++++++++++++++++++----------- scripts/gen-docs.sh | 18 ++++++++++++++++++ 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/AGENT_TODO.md b/AGENT_TODO.md index f76047e..c0b0557 100644 --- a/AGENT_TODO.md +++ b/AGENT_TODO.md @@ -16,7 +16,9 @@ summary (newest last). ## Done -- **2026-08-09** — `pos config ` interactive config editor: reads the `# POS_CONFIG:` registry across tools into a single runtime config (`~/.config/linux_post_install/*.env`, one file per scope, chmod 600); secret masking with show/hide toggle, `digits:`/`num:`/`url:` validation, `-` to clear, blank keeps; `*plugins` marker expands plugin vars (entertainment) from `entertainment-lib.sh`; gen-docs now handles category-less tools (`pos-config`), fixed a `set -e`+`pipefail` bug that truncated the header registry. +- **2026-08-09** — `pos config ` scope completion is now cached at gen time (`_pos_config_scopes` array emitted by `make gen` from the `# POS_CONFIG:` registry) instead of scanning ~40 tools per TAB — a per-keypress subshell storm that wedged interactive shells for minutes on the loaded homelab box. Two stuck `-bash` sessions (69%/38% CPU) killed. `plugin_marker`/`plugin_keys` hardened with `|| true` so `config_keys` no longer aborts mid-scan under `set -euo pipefail` on mixed lib/plugin dirs (installed layout) — fixes missing plugin keys in `pos config entertainment`. + +- **2026-08-09** — `pos config ` interactive config editor: reads the `# POS_CONFIG:` registry across tools into a single runtime config (`~/.config/linux_post_install/*.env`, one file per scope, chmod 600); secret masking with show/hide toggle, `digits:`/`num:`/`url:` validation, `-` to clear, blank keeps; `*plugins` marker expands plugin vars (entertainment) from `entertainment-lib.sh`; `desc::example` value-format hints shown in the editor; gen-docs now handles category-less tools (`pos-config`), fixed a `set -e`+`pipefail` bug that truncated the header registry. - **2026-08-09** — `pos-communication-telegram` → `pos-communication-telegram-sender`: one canonical `send` (dropped the legacy `--send` flag, which duplicated the `send` subcommand in completion). `pos communication telegram ` now completes to just `sender listener`. `lib/notify.sh` maps platform `telegram` → `telegram-sender` via `notify_sender_name()`; entertainment-send + health `--send` check updated. Removed phantom subcommands from howto/communication.md (webhook/logs/broadcast/file never existed). diff --git a/DOC/AGENT_Context_Project.md b/DOC/AGENT_Context_Project.md index 350ac73..0139958 100644 --- a/DOC/AGENT_Context_Project.md +++ b/DOC/AGENT_Context_Project.md @@ -578,7 +578,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/pos-system-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) | | `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) | | `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) | -| `completions/pos.bash` | 267 | Dynamic bash completion | +| `completions/pos.bash` | 279 | Dynamic bash completion | | `apps/install.sh` | 171 | App install/uninstall picker/orchestrator | diff --git a/completions/pos.bash b/completions/pos.bash index 31de706..6a54897 100644 --- a/completions/pos.bash +++ b/completions/pos.bash @@ -17,6 +17,9 @@ _pos_subcmds[communication-telegram-sender]="send test config" _pos_subcmds[docker-compose]="ls installed up down restart logs update config" _pos_subcmds[docker-vbox]="create enter stop start rm ls" # GEN:END possubcmds +# GEN:START posconfigscopes +declare -a _pos_config_scopes=(compose entertainment notify system telegram) +# GEN:END posconfigscopes _pos() { local cur prev words cword @@ -158,18 +161,27 @@ _pos() { COMPREPLY=($(compgen -W "${out[*]}" -- "$cur")) } - # Dynamic scope completion for `pos config ` — greps the - # "# POS_CONFIG:" headers in the tools dir (the config registry). + # Config scope completion for `pos config ` — cached at gen time from + # the "# POS_CONFIG:" registry (scanning all tools per TAB is too heavy). + # Falls back to a live scan only if the cache is missing. _pos_config_scopes() { - local scopes=() f line scope - for f in "$pos_dir"/pos-*; do - [ -x "$f" ] || continue - while IFS= read -r line; do - scope="$(sed 's/^# POS_CONFIG:[[:space:]]*//' <<<"$line" | cut -d'|' -f1 | tr -d ' ')" - [ -n "$scope" ] && scopes+=("$scope") - done < <(grep '^# POS_CONFIG:' "$f" 2>/dev/null) - done - COMPREPLY=($(compgen -W "$(printf '%s\n' "${scopes[@]}" | sort -u | tr '\n' ' ') --help" -- "$cur")) + local scopes=() + if declare -p _pos_config_scopes &>/dev/null; then + scopes=("${_pos_config_scopes[@]}") + else + local f line scope + for f in "$pos_dir"/pos-*; do + [ -x "$f" ] || continue + while IFS= read -r line; do + line="${line#*POS_CONFIG:}" + scope="${line%%|*}" + scope="${scope// }" + [ -n "$scope" ] && scopes+=("$scope") + done < <(grep '^# POS_CONFIG:' "$f" 2>/dev/null || true) + done + mapfile -t scopes < <(printf '%s\n' "${scopes[@]}" | sort -u) + fi + COMPREPLY=($(compgen -W "${scopes[*]} --help" -- "$cur")) } # ── Dispatch ─────────────────────────────────────────────── diff --git a/scripts/gen-docs.sh b/scripts/gen-docs.sh index dd5222a..3cda987 100755 --- a/scripts/gen-docs.sh +++ b/scripts/gen-docs.sh @@ -120,6 +120,23 @@ gen_possubcmds() { done } +# Config scopes: the "# POS_CONFIG:" registry (first field = scope), cached so +# `pos config ` doesn't re-scan every tool per completion. +gen_posconfigscopes() { + local f line scope scopes=() + for f in "$root"/bin/pos-*; do + [ -x "$f" ] || continue + while IFS= read -r line; do + line="${line#*POS_CONFIG:}" + scope="${line%%|*}" + scope="${scope// }" + [ -n "$scope" ] && scopes+=("$scope") + done < <(grep '^# POS_CONFIG:' "$f" 2>/dev/null || true) + done + mapfile -t scopes < <(printf '%s\n' "${scopes[@]}" | sort -u) + echo "declare -a _pos_config_scopes=(${scopes[*]:-})" +} + # Section index of AGENT_Context itself: maps each "## " heading to its # line range. Excludes the "Document Map" heading (this block). gen_docmap() { @@ -189,6 +206,7 @@ regen_block "$ctx" dispatch regen_block "$ctx" selfcontained regen_block "$comp" posflags regen_block "$comp" possubcmds +regen_block "$comp" posconfigscopes regen_block "$ctx" filetable # docmap is self-referential: its own block size shifts the section line