fix: show Command Bank in main pos menu; fix pos bank run crash
gates / consistency-and-conventions (push) Successful in 27s
gates / consistency-and-conventions (push) Successful in 27s
- bin/pos: _pos_category_list now emits category-less tools (pos-bank, pos-config, pos-tree) as sorted menu entries with an empty subcommand column, deduped against real categories (pos-ai). bank previously never appeared in the bare 'pos' menu. - bin/pos-bank: fixed invalid 'local name="" -a cli_params=()' at cmd_run (line 150) — bash rejected '-a' after an assignment, crashing every 'pos bank run' with 'local: -a: not a valid identifier'. Split into 'local name=""' + 'local -a cli_params=()'. - tests/t-bank.sh: added B12-B14 covering cmd_run (no-params, missing-command, param substitution) — would have caught the crash. - AGENT_TODO.md: bank feature moved to Done.
This commit is contained in:
@@ -42,6 +42,8 @@ summary (newest last).
|
|||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- **`pos bank` command bank** — feature (41efc91) + lib registration fix (73d15a2) + main-menu visibility & `run` crash fix. Done 2026-09-12.
|
||||||
|
|
||||||
- **2026-09-09** — New `pos system alias` tool (Architect→Builder→Reviewer→Writer): persistent command aliases via wrapper scripts in `~/.local/bin/`. Interactive menu (create/edit/remove/list/show), storage at `~/.config/linux_post_install/aliases.env` (pipe-delimited `name|command`), wrapper sync on every invocation, name validation (`^[a-zA-Z][a-zA-Z0-9_-]*$`), ownership markers, collision checks. Docs: POS.md system category + detail block, howto/system.md recipes section. Verified: `bash -n`, `make gen` byte-idempotent, `make check` OK, `make lint` 0 FAIL / 0 WARN.
|
- **2026-09-09** — New `pos system alias` tool (Architect→Builder→Reviewer→Writer): persistent command aliases via wrapper scripts in `~/.local/bin/`. Interactive menu (create/edit/remove/list/show), storage at `~/.config/linux_post_install/aliases.env` (pipe-delimited `name|command`), wrapper sync on every invocation, name validation (`^[a-zA-Z][a-zA-Z0-9_-]*$`), ownership markers, collision checks. Docs: POS.md system category + detail block, howto/system.md recipes section. Verified: `bash -n`, `make gen` byte-idempotent, `make check` OK, `make lint` 0 FAIL / 0 WARN.
|
||||||
|
|
||||||
- **2026-09-09** — Telegram listener single-instance guard (Toolsmith): `bin/pos-communication-telegram-listener --run` now takes a `flock(1)` on `${XDG_RUNTIME_DIR:-/tmp}/pos-telegram-listener.lock` inside `run_daemon()` (before config load/sync/poll loop) — a second `--run` on the same token fails fast (exit 1, `ERROR: listener already running (single instance) — check: systemctl --user status pos-telegram-listener`), never racing getUpdates (Telegram 409/command stealing). Kernel auto-release → no stale-lock bookkeeping, systemd `Restart=always` restarts clean. `--status` first line now reports `listener: running (single instance lock held)` / `listener: not running` via the same `lock_held()` probe. `flock` dep guard added (`util-linux`). New regression `tests/t-telegram-listener-singleton.sh` (7 checks: first acquires+loops, second exits 1 with exact message, lock releases → third starts clean, status reports both states; stubbed curl/systemctl, sandboxed XDG_RUNTIME_DIR — hermetic, no network). Verified: `bash -n`, `make gen` ×2 byte-idempotent, `make check` OK, `make lint` 0 FAIL / 0 WARN, `make test` green, `git diff --check` clean.
|
- **2026-09-09** — Telegram listener single-instance guard (Toolsmith): `bin/pos-communication-telegram-listener --run` now takes a `flock(1)` on `${XDG_RUNTIME_DIR:-/tmp}/pos-telegram-listener.lock` inside `run_daemon()` (before config load/sync/poll loop) — a second `--run` on the same token fails fast (exit 1, `ERROR: listener already running (single instance) — check: systemctl --user status pos-telegram-listener`), never racing getUpdates (Telegram 409/command stealing). Kernel auto-release → no stale-lock bookkeeping, systemd `Restart=always` restarts clean. `--status` first line now reports `listener: running (single instance lock held)` / `listener: not running` via the same `lock_held()` probe. `flock` dep guard added (`util-linux`). New regression `tests/t-telegram-listener-singleton.sh` (7 checks: first acquires+loops, second exits 1 with exact message, lock releases → third starts clean, status reports both states; stubbed curl/systemctl, sandboxed XDG_RUNTIME_DIR — hermetic, no network). Verified: `bash -n`, `make gen` ×2 byte-idempotent, `make check` OK, `make lint` 0 FAIL / 0 WARN, `make test` green, `git diff --check` clean.
|
||||||
|
|||||||
@@ -635,7 +635,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `features/autostart.sh` | 50 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
| `features/autostart.sh` | 50 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
||||||
| `features/usb-automount.sh` | 138 | USB automount feature (udev rule + flag-gated service) |
|
| `features/usb-automount.sh` | 138 | USB automount feature (udev rule + flag-gated service) |
|
||||||
<!-- GEN:START filetable -->
|
<!-- GEN:START filetable -->
|
||||||
| `bin/pos` | 302 | CLI dispatcher with smart arg matching + logging + category help |
|
| `bin/pos` | 310 | CLI dispatcher with smart arg matching + logging + category help |
|
||||||
| `bin/pos-ai-alias` | 760 | manage AI agent aliases |
|
| `bin/pos-ai-alias` | 760 | manage AI agent aliases |
|
||||||
| `bin/pos-ai-gemini` | 7 | Forward to pos ai --provider gemini (backward compat) |
|
| `bin/pos-ai-gemini` | 7 | Forward to pos ai --provider gemini (backward compat) |
|
||||||
| `bin/pos-ai-hf` | 993 | Download AI models from Hugging Face (search, download, manage) |
|
| `bin/pos-ai-hf` | 993 | Download AI models from Hugging Face (search, download, manage) |
|
||||||
@@ -686,7 +686,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/pos-system-schedule` | 151 | Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently |
|
| `bin/pos-system-schedule` | 151 | Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently |
|
||||||
| `bin/pos-system-uninstall` | 518 | Remove pos toolkit binaries, services, shell integration, config, and data |
|
| `bin/pos-system-uninstall` | 518 | Remove pos toolkit binaries, services, shell integration, config, and data |
|
||||||
| `bin/pos-ai` | 714 | AI assistant: ask, chat, sessions, capture, models, providers |
|
| `bin/pos-ai` | 714 | AI assistant: ask, chat, sessions, capture, models, providers |
|
||||||
| `bin/pos-bank` | 313 | Persistent command bank for saving and running shell commands |
|
| `bin/pos-bank` | 314 | Persistent command bank for saving and running shell commands |
|
||||||
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
|
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
|
||||||
| `bin/pos-tree` | 118 | Show the pos CLI command tree: categories, commands, and subcommands |
|
| `bin/pos-tree` | 118 | Show the pos CLI command tree: categories, commands, and subcommands |
|
||||||
| `completions/pos.bash` | 318 | Dynamic bash completion |
|
| `completions/pos.bash` | 318 | Dynamic bash completion |
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ _pos_commands() {
|
|||||||
# ── Category list (sorted, filename-derived) ─────────────────────
|
# ── Category list (sorted, filename-derived) ─────────────────────
|
||||||
# Nested sub-tools (pos-<cat>-<a>-<b> where pos-<cat>-<a> exists) are
|
# Nested sub-tools (pos-<cat>-<a>-<b> where pos-<cat>-<a> exists) are
|
||||||
# omitted from the cheat-sheet line — they are shown under their parent tool.
|
# omitted from the cheat-sheet line — they are shown under their parent tool.
|
||||||
|
# Category-less tools (pos-bank, pos-config, pos-tree) are emitted as their
|
||||||
|
# own line with an empty subcommand column; a name already present as a
|
||||||
|
# category (pos-ai vs the ai category built from pos-ai-*) is NOT duplicated.
|
||||||
_pos_category_list() {
|
_pos_category_list() {
|
||||||
local -A cats=()
|
local -A cats=()
|
||||||
local cmd cat f
|
local cmd cat f
|
||||||
@@ -35,7 +38,10 @@ _pos_category_list() {
|
|||||||
[ -x "$f" ] || continue
|
[ -x "$f" ] || continue
|
||||||
cmd="${f##*/pos-}"
|
cmd="${f##*/pos-}"
|
||||||
cat="${cmd%%-*}"
|
cat="${cmd%%-*}"
|
||||||
[ "$cat" = "$cmd" ] && continue
|
if [ "$cat" = "$cmd" ]; then
|
||||||
|
cats["$cmd"]="${cats[$cmd]:-}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
cats["$cat"]+="${cmd#*-} "
|
cats["$cat"]+="${cmd#*-} "
|
||||||
done
|
done
|
||||||
local c subs joined s s2 top=() is_nested
|
local c subs joined s s2 top=() is_nested
|
||||||
@@ -208,6 +214,8 @@ EXAMPLES
|
|||||||
|
|
||||||
pos tree Show the command tree (categories + subcommands)
|
pos tree Show the command tree (categories + subcommands)
|
||||||
|
|
||||||
|
pos bank run <name> Run a saved command from the bank
|
||||||
|
|
||||||
pos docker vbox create lab1 Create disposable Docker VM
|
pos docker vbox create lab1 Create disposable Docker VM
|
||||||
pos docker vbox create lab1 --dir . Create VM using current directory
|
pos docker vbox create lab1 --dir . Create VM using current directory
|
||||||
pos docker vbox enter lab1 Shell into a Docker VM
|
pos docker vbox enter lab1 Shell into a Docker VM
|
||||||
|
|||||||
+2
-1
@@ -147,7 +147,8 @@ cmd_show() {
|
|||||||
|
|
||||||
# ── cmd_run ──────────────────────────────────────────────────────
|
# ── cmd_run ──────────────────────────────────────────────────────
|
||||||
cmd_run() {
|
cmd_run() {
|
||||||
local name="" -a cli_params=()
|
local name=""
|
||||||
|
local -a cli_params=()
|
||||||
if [ $# -eq 0 ]; then
|
if [ $# -eq 0 ]; then
|
||||||
name="$(_pick_command)" || return 0
|
name="$(_pick_command)" || return 0
|
||||||
else
|
else
|
||||||
|
|||||||
+1
-1
@@ -57,4 +57,4 @@ silently.
|
|||||||
| `t-share-mountpoint.sh` | share-client `ask_mountpoint` UX: existing/new/declined/rejected paths, confirm gate, mkdir side effects, non-TTY stdin contract, static `n`→`t` guards |
|
| `t-share-mountpoint.sh` | share-client `ask_mountpoint` UX: existing/new/declined/rejected paths, confirm gate, mkdir side effects, non-TTY stdin contract, static `n`→`t` guards |
|
||||||
| `t-pos-media-yt.sh` | unified `pos media yt` suite: dispatcher + forwarder resolution, shared yt-lib helpers, yt-mp3/mp4/grab/subtitles flags, dry-run deps, `YT_OUT_DIR` seam, `GRAB_DEFAULT` config, negative controls (unsafe-URL no-expansion, `--lang en,ar` single arg, txt timestamp-stripping) |
|
| `t-pos-media-yt.sh` | unified `pos media yt` suite: dispatcher + forwarder resolution, shared yt-lib helpers, yt-mp3/mp4/grab/subtitles flags, dry-run deps, `YT_OUT_DIR` seam, `GRAB_DEFAULT` config, negative controls (unsafe-URL no-expansion, `--lang en,ar` single arg, txt timestamp-stripping) |
|
||||||
| `t-telegram-listener-singleton.sh` | Telegram listener single-instance guard: first `--run` acquires the flock, second `--run` fails fast with the exact message, lock auto-releases so the next start is clean, `--status` reports the lock state |
|
| `t-telegram-listener-singleton.sh` | Telegram listener single-instance guard: first `--run` acquires the flock, second `--run` fails fast with the exact message, lock auto-releases so the next start is clean, `--status` reports the lock state |
|
||||||
| `t-bank.sh` | Command Bank: bank-lib.sh unit tests (add/remove/update/find/get/list/count/valid/extract_params/substitute_params) + pos-bank CLI integration (help, list, add, show, remove, params, invalid name) |
|
| `t-bank.sh` | Command Bank: bank-lib.sh unit tests (add/remove/update/find/get/list/count/valid/extract_params/substitute_params) + pos-bank CLI integration (help, list, add, show, run, remove, params, invalid name) |
|
||||||
@@ -334,4 +334,29 @@ BANK
|
|||||||
test_run env BANK_FILE="$sandbox/b11.bank.env" "$pos_bank" add "1bad" "desc" "cmd"
|
test_run env BANK_FILE="$sandbox/b11.bank.env" "$pos_bank" add "1bad" "desc" "cmd"
|
||||||
check_not_contains "pos bank add invalid name exits non-zero" "0" "$TR_RC"
|
check_not_contains "pos bank add invalid name exits non-zero" "0" "$TR_RC"
|
||||||
check_contains "pos bank add invalid name message" "Invalid name" "$TR_OUT"
|
check_contains "pos bank add invalid name message" "Invalid name" "$TR_OUT"
|
||||||
|
|
||||||
|
# B12: pos bank run — executes a saved command (no params)
|
||||||
|
# Negative control: the old `local name="" -a cli_params=()` declaration
|
||||||
|
# crashed at line 150 before any output (rc != 0, no "Running:" line).
|
||||||
|
: > "$sandbox/b12.bank.env"
|
||||||
|
test_run env BANK_FILE="$sandbox/b12.bank.env" "$pos_bank" add "greet" "Greet" "echo bank-run-ok"
|
||||||
|
check_rc "pos bank add for run exits 0" 0 "$TR_RC"
|
||||||
|
test_run env BANK_FILE="$sandbox/b12.bank.env" "$pos_bank" run "greet"
|
||||||
|
check_rc "pos bank run executes saved command" 0 "$TR_RC"
|
||||||
|
check_contains "pos bank run logs the command" "Running: echo bank-run-ok" "$TR_OUT"
|
||||||
|
check_contains "pos bank run executes output" "bank-run-ok" "$TR_OUT"
|
||||||
|
|
||||||
|
# B13: pos bank run missing command — fails
|
||||||
|
test_run env BANK_FILE="$sandbox/b12.bank.env" "$pos_bank" run "ghost"
|
||||||
|
check_not_contains "pos bank run missing exits non-zero" "0" "$TR_RC"
|
||||||
|
check_contains "pos bank run missing message" "Command not found" "$TR_OUT"
|
||||||
|
|
||||||
|
# B14: pos bank run with params — CLI key=val substitution, no interactive prompt
|
||||||
|
: > "$sandbox/b14.bank.env"
|
||||||
|
test_run env BANK_FILE="$sandbox/b14.bank.env" "$pos_bank" add "echo-param" "Echo param" "echo hi {who}"
|
||||||
|
check_rc "pos bank add param exits 0" 0 "$TR_RC"
|
||||||
|
test_run env BANK_FILE="$sandbox/b14.bank.env" "$pos_bank" run "echo-param" "who=there"
|
||||||
|
check_rc "pos bank run with params exits 0" 0 "$TR_RC"
|
||||||
|
check_contains "pos bank run substitutes param" 'Running: echo hi "there"' "$TR_OUT"
|
||||||
|
check_contains "pos bank run executes substituted command" "hi there" "$TR_OUT"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user