Commit Graph

58 Commits

Author SHA1 Message Date
Your Name 414a990801 refactor: pos system event-trigger → pos system schedule — per-job timers, notify policies, legacy migrate
The single-timer threshold monitor generalizes into a scheduler: each job is a
chmod-600 file in schedule.d/<name>.env (INTERVAL 5m..59m/1h..23h/hourly/daily/
weekly/OnCalendar=..., NOTIFY policy, optional MSG, RULE for threshold,
COMMAND = literal rest of line) with its own systemd user timer pair
(pos-schedule-<name>.timer + oneshot .service, Persistent, reconciled on
enable/disable — orphan units + the legacy pos-event-trigger timer
auto-removed). Policies: always (full output every run), onchange (diff vs
last run, first run sends), onerror (non-zero exit or empty output),
threshold (old event-trigger behavior: first numeric vs RULE, alert on
false→true + recovery, per-job firing state), never (silent side-effect jobs).
run [name|all], list, config (interactive add/edit/remove/enable/disable with
validation), enable/disable [name|all], status, migrate (converts legacy
event.env rules → rule-N.env threshold jobs, verbatim LHS as COMMAND, adopts
the legacy timer's OnCalendar or 5m, removes the old timer). Per-run logs +
state in ~/.local/share/linux_post_install/schedule/{logs,state}/.
config/event.env + event-rules.template → config/schedule.d/ starter jobs
(nvme-health, cpu-temp, disk-root, silent log-cleanup); postinstall installs
them no-clobber into an empty schedule.d/ (legacy event.env users get a
migrate hint instead). bin/pos EXAMPLES + INTERACTIVE_CMDS
(system-schedule config) updated; install.sh ships the renamed tool+lib.
2026-08-13 02:14:25 -04:00
Your Name 8b3435a8d5 feat: pos network download replace <gid> <url> + fresh-link status advisory
Give a dead single-file HTTP/FTP download a fresh URL: same dir + file name
(--continue=true resumes the partial), forgets the old source from
download.retry, verifies the new link (a dead replacement is diagnosed and
marked permanent instead of silently looping). status flags downloads needing
this with a 'needs fresh link' line. Torrents/active/multi-file rejected with
hints; --dir/--split/--tmux supported.
2026-08-13 02:14:14 -04:00
Your Name bd77a3949e feat: pos network download restart + smart retry + systemd healer — outage-resilient downloads
restart <gid>: re-queue from history — torrents via rebuilt magnet
(urn:btih: + &tr= trackers), HTTP via original URIs keeping dir/out;
--continue=true resumes partials, complete files verify instantly.

retry <gid|all>: waits out internet outages (NET_PROBE seam,
--interval/--max-wait), re-queues and re-verifies; aria2 error 3 = real
problem → diagnosed + marked permanent (url:/bt: ids in download.retry,
skipped by retry all, manual restart overrides); --once/--quiet for the
healer timer.

Healer: pos-aria2-retry.{service,timer} user units — arms on download
start (add/torrent/metalink/restart), disables when nothing left.
watch <gid> auto-restarts after an outage.

Fixes from stub-suite review: ensure_healer missing from submit paths;
RESTART_NAME lost across do_restart subshell (download_name helper);
restart exited 1 (tmux test as last statement).

Stub harness (/tmp/opencode/dl-test) 119/119 green; make gen && make check green.
Docs: POS.md rows, howto/network.md outage recipe, SYSTEMD.md user units.
2026-08-12 02:46:42 -04:00
Your Name c5dd6466ba feat: pos network download — aria2 RPC daemon + queue control (add/torrent/metalink, watch, limits)
Persistent aria2c as a systemd user service (pos-aria2.service, enable --now,
linger warning) on localhost:6800 with a generated RPC secret in
~/.config/linux_post_install/download.env (chmod 600, env override). 18
commands: start/stop/status, add/torrent/metalink (auto-start, --tmux live
view), list/info/files/peers, pause/resume/remove/purge/move, limit/set,
watch (2s live repoll). JSON built via jq -nc --arg, never string
interpolation. Deps: aria2 in preinstall PACKAGES, aria2c/jq/curl guards
before --help. Docs: POS.md + howto/network.md + indices + Common Tasks row.
2026-08-12 01:55:16 -04:00
Your Name a4849616d9 feat: pos share smb server + smb client — Samba share tools (samba/cifs-utils deps, systemd automount units) 2026-08-11 16:15:02 -04:00
Your Name 384ed4bf90 fix: matrix sender login — real error reporting + @ prefix auto-add 2026-08-11 15:33:48 -04:00
Your Name 32a69f09e9 feat: pos network checkport nmap engine overhaul — 2-pass scan, --versions probe, udp/v6 fixes 2026-08-11 15:33:46 -04:00
Your Name 3536f267c7 refactor: move usb/nfs tools into new 'share' category
- rename bin/pos-usb-server -> pos-share-usb-server, pos-system-nfs-{client,server} -> pos-share-nfs-{client,server}
- update # POS: headers, usage strings, INTERACTIVE_CMDS, usage() EXAMPLES, notify-scope comment
- docs: new DOC/howto/share.md (USB+NFS consolidated), drop usb.md + system.md NFS sections,
  POS.md ### share section, HOWTO/README/AGENT_Context/README/DEV/AGENTS updates
- make gen && make check green
2026-08-11 14:52:18 -04:00
Your Name b74dfffd0b feat: Matrix/Synapse sender + listener — second notify platform (telegram,matrix)
pos communication matrix sender: send (plain/--markdown/--room), login
(password->access token via m.login.password), test. Implements the
lib/notify.sh sender contract, so NOTIFY_PLATFORM=telegram,matrix now
fans out for real; matrix.env config scope registered for pos config.

pos communication matrix listener: systemd user daemon long-polling
/sync (since token, compact m.room.message filter); reacts to own user's
messages (/ and ! both resolve), threaded m.in_reply_to replies, @quiet
marker, ai bridge with per-room session, interactive editor. Added to
INTERACTIVE_CMDS.

Docs: POS.md, howto/communication.md, HOWTO.md, usage EXAMPLES.
Verified against a mock homeserver (send shape, login, owner filter,
replies, exit codes, editor). make gen && make check green.
2026-08-09 20:19:07 +00:00
Your Name 6e437cace8 fix: pos tree truncated when a category's last tool has no subcommands 2026-08-09 18:41:26 +00:00
Your Name 5f2c8fdcec feat: event-trigger run logs live value on no-change
Diagnosis aid: when a rule evaluates but doesn't fire, run now prints
'OK: <cmd> = <value> (no change)' so a rule that silently never crosses
its threshold (e.g. wrong sensor in the check command) is visible
instead of just 'evaluated N rule(s)'.
2026-08-09 18:11:51 +00:00
Your Name 577d49ac2d fix: report skipped rules in event-trigger run; add lm-sensors dep
- run now counts rules skipped because their check produced no number (or
  the line was unparseable) and reports both counts, so an all-skipped pass
  no longer reads as 'evaluated 0 rule(s)'.
- preinstall.sh installs lm-sensors — the sensor example rules in event.env
  need it; howto troubleshooting notes to check 'sensors -u' output for the
  real *_input key before adding a rule.
2026-08-09 17:31:59 +00:00
Your Name 030ec0b456 feat: pos system event-trigger — state-based threshold monitors (eventer)
Each line of event.env is an independent rule: ["msg" if ] <check> <op> <thr>.
Check runs on every pass; first numeric output compared float-safe; op is the
rightmost 'op threshold' pair so checks with their own >/< parse fine. Alerts
once on false->true + one recovery message on true->false (no repeats while
the condition holds); per-rule state keyed by rule-line hash in
~/.local/share/linux_post_install/eventer/state/.

Subcommands: run (timer entrypoint), config (interactive add/remove/edit with
check-validation), list (rules + live values), enable [interval] (systemd
user timer pos-event-trigger.timer; 5m..weekly or OnCalendar; graceful without
a user manager, loginctl enable-linger attempt), disable, status. --dry-run
honors the DEV.md convention. Alerts via lib/notify.sh (Telegram default).

New: bin/pos-system-event-trigger, lib/eventer-lib.sh, config/event.env
template (no-clobber via postinstall), install.sh lib install, INTERACTIVE_CMDS
entry. Docs: POS.md system row, HOWTO.md index, howto/event-trigger.md.
make gen && make check green; functional tests cover trigger/recovery/no-repeat,
float+unit parsing, editor add/remove/edit + validation + dry-run, timer
enable/disable/status, dispatcher routing.
2026-08-09 17:09:59 +00:00
Your Name 2e57634877 feat: harden pos media mp3/mp4 — smart format selection, metadata, dry-run
Both tools: yt-dlp calls via spawn (honor DRY_RUN; --dry-run prints the
command and skips dep checks), -o/--output, --no-playlist, --cookies (with
file check), clean ffmpeg/yt-dlp guards, POS_FLAGS for completion, full
embedded metadata (--embed-metadata --embed-chapters --embed-thumbnail
--no-overwrites; mp3 adds --convert-thumbnails jpg + artist-from-uploader
parse-metadata). mp3 gains --by-artist (~/Music/<artist>/<title>.mp3).

mp4: -f <id>/--best/--worst skip the prompt (mutual-exclusion validated),
and the interactive picker now shows a curated [audio]/[video]/[combo]
format table on stderr (stdout carries only the chosen id — ui_pick
lesson), validates the id against the real -F output, and defaults empty
input to best. Docs: howto/media.md rewritten.
2026-08-09 15:56:47 +00:00
Your Name 0146dbe5f9 feat: ai bridge answers about replied-to Telegram messages
Extract reply_to_message.text (fallback caption) from each getUpdates
result and pass it to handle_message; the ai bridge prefixes the prompt
with '[Reply context — the message you are replying to]', so replying to
a /status output and asking 'ai check this details' gives the model the
actual output. AI bridge only — mapped /commands unchanged; context rides
in the user turn so the session records what was analyzed. Docs:
howto/ai.md bridge section.
2026-08-09 15:43:06 +00:00
Your Name 310367f3b2 feat: ai sessions + Telegram-friendly replies (--system, markdown strip)
pos ai gemini: --session gives ask/chat persistent memory
(~/.local/share/linux_post_install/ai/<name>.json, capped 40 turns),
new 'sessions' subcommand to list/clear; --system injects a Gemini
systemInstruction on every turn without storing it in the session file.
Telegram listener keeps one session per chat (telegram-<chat_id>), clears
on 'ai /reset', passes a Telegram-voice system prompt (emojis welcome),
and strips markdown from replies before sendMessage since messages are
sent as plain text. Docs: howto/ai.md flags/sessions/bridge behavior.
2026-08-09 15:32:39 +00:00
Your Name 1832a88c71 fix: pos config secret values corrupted by stray newline in captured input
cfg_read_secret is invoked via $() inside _cfg_edit_one, so the echo that
advanced the cursor after hidden input landed on the capture pipe instead of
the terminal — every secret value stored with pos config on a real TTY got a
leading newline (e.g. AI_GEMINI_API_KEY="\n<key>"), which neither cfg_value
nor the ai/telegram load_config parsers could read back: the menu showed
'(not set)' and pos ai gemini kept demanding a key.

Fix: send that newline to stderr (>&2). Defense in depth: cfg_write and
write_config_key now strip CR and truncate multi-line pastes, and the readers
(cfg_value, ai + telegram load_config) strip CR. Reproduced and verified on a
pseudo-TTY; piped-stdin tests never caught it because non-TTY input skips the
stty/echo path.
2026-08-09 15:08:29 +00:00
Your Name 23eede637a feat: pos ai gemini — CLI + Telegram AI chat (ask, chat, models)
- bin/pos-ai-gemini: one-shot ask (stdout-only, pipe-friendly), interactive
  multi-turn chat REPL (q/Ctrl+C, /reset), models list; --model override,
  default gemini-2.5-flash; key via x-goog-api-key header, never printed.
- Config scope 'ai' (AI_GEMINI_API_KEY secret, AI_GEMINI_MODEL) in
  ~/.config/linux_post_install/ai.env via 'pos config ai'; config/ai.env
  template installed no-clobber by postinstall.
- Telegram listener: non-command text starting with 'ai ' (case-insensitive)
  is answered by Gemini via 'pos ai gemini ask'; owner-chat only, errors
  reply with the pos config ai hint. Future intents slot in as case arms.
- ai-gemini added to INTERACTIVE_CMDS (chat reads stdin).
- Docs: POS.md ai section + listener bridge, howto/ai.md, HOWTO/README
  index rows, bin/pos usage example; make gen refreshed context/completions.
2026-08-09 14:40:15 +00:00
Your Name 0acdf3b346 fix: listener daemon read config from wrong HOME
enable_service baked Environment=HOME=$HOME into the unit at enable
time; a stale/wrong shell HOME made the daemon read an empty
~/.config/linux_post_install/telegram_commands.env — commands showed in
the bot menu (synced from the editor's correct HOME) but replying said
"unknown command" and /help said none mapped. systemd user services
already set the correct HOME; stop pinning it.
2026-08-09 14:09:10 +00:00
Your Name 52413a6a68 feat: pos tree — print the CLI command tree
pos tree derives the hierarchy live from bin/pos-* filenames + # POS:
/# POS_SUBCMDS: headers, so it always matches what the dispatcher can
run. Category-less tool (like pos-config); --depth N limits nesting.

Also sharpen the agent-facing docs that the work exposed:
- AGENTS.md: drop the stale "one category-less exception" claim; document
  the category-less pattern (pos-config, pos-tree) and that gen only reads
  the text after the first em-dash in # POS: headers
- DEV.md: category-less vs categorized rule + header extraction note
- AGENT_Context "Adding a New Tool": new step 0 — pin the exact CLI verb
  and runtime context (dev/repo-only vs installed) before writing code
- POS.md: new config + tree sections; category-less tools get their own
  sections
- README: pos tree bullet following the pos X convention
2026-08-09 12:50:52 +00:00
Your Name 4d8f70d770 refactor: telegram config via pos config telegram; fix listener pipe + entertainment bugs
- Drop sender 'config'/'config set' subcommand — redundant with 'pos config
  telegram' (same POS_CONFIG registry: masked token input/display, chat-id
  validation, chmod 600); sender/listener error hints now point there.
- Listener: load_map now uses a \x1f delimiter, so mapped /commands
  containing '|' are no longer truncated at the first pipe.
- entertainment send: forward extra plugin args (previously dropped); pass
  '--' before the message so leading '-' plugin output isn't parsed as an
  option.
- write_config_key/cfg_write: replace unescaped sed writes with grep-v+append
  so values with &, |, \ round-trip safely.
- sync_systemd: daemon-reload after removing timer units.
- config-ui: 'digits' validation accepts negative group/supergroup chat ids.
2026-08-09 12:22:12 +00:00
Your Name 97e9d57f45 fix: telegram listener editor crashes on remove/edit/test
ui_pick printed its menu listing to stdout, so 'idx="$(ui_pick)"' captured
the menu plus the picked number; the array subscript MAP_CMDS[$idx] then
arithmetically evaluated the multi-line string and died with 'syntax error
in expression (error token is ...)'. Menu decoration now goes to stderr so
only the index reaches stdout. Pre-existing bug, exposed by the ::desc
description column.
2026-08-09 11:28:29 +00:00
Your Name 498979a78d feat: telegram listener pushes command list to bot menu via setMyCommands
Map entries may now carry a menu description (/cmd::desc=bash) shown in
the bot's "/" menu; it falls back to the bash command (~40 chars) when
omitted. The command list is pushed automatically after every map edit,
on --enable, and at daemon start, plus a manual --sync-commands flag
(wired into POS_FLAGS completion). Names are validated against Telegram's
lowercase [a-z0-9_] rule — invalid ones are skipped from the menu with a
warning but still resolve when typed; an empty map clears the menu.

Fixes found by unit-testing the sync path: map_has always returned false
(awk END{exit 1} overrode the match), map_set had a local cross-reference
that broke under set -u, and warn() leaked into the generated JSON (now
stderr). Docs + AGENT_TODO updated; make gen && make check pass.
2026-08-09 09:54:05 +00:00
Your Name fe7708f142 ai need continue 2026-08-09 04:57:28 -04:00
Your Name 494952369d fix: config editor example hints + plugin registry abort under pipefail
POS_CONFIG fields gain an optional 'desc::example' value-format hint shown
in the editor ('e.g. weather,5m joke,10m' under ENABLED). Harden
entertainment-lib's plugin_marker/plugin_keys grep|sed pipelines with
'|| true': under set -o pipefail a grep miss exited 1 and set -e aborted
config_keys mid-scan, so installed layouts (/usr/local/bin mixes libs and
plugins) silently lost all plugin keys in pos config.
2026-08-09 04:22:59 -04:00
Your Name d6a3f9c3b3 revert: drop TEST var from compose POS_CONFIG registry 2026-08-09 03:58:42 -04:00
Your Name 0b7fdb4954 feat: pos config — interactive config editor driven by the POS_CONFIG registry
Add bin/pos-config + lib/config-ui.sh: reads the '# POS_CONFIG:' headers
across tools into a unified runtime config (~/.config/linux_post_install/
<scope>.env, chmod 600). Secret masking with show/hide, digits:/num:/url:
validation, '-' clears, blank keeps; '*plugins' expands entertainment
plugin vars from entertainment-lib.sh. pos config with no scope opens a
picker (scope list when not a TTY); completion offers scopes from the
registry at runtime.

gen-docs.sh now handles category-less tools (pos-config) instead of
emitting pos-config-config; fix set -e/pipefail abort that truncated the
header registry mid-read. install.sh ships config-ui.sh.
2026-08-09 03:57:17 -04:00
Your Name 873ae84b49 refactor: rename telegram tool to pos-communication-telegram-sender; drop --send legacy alias
The --send flag duplicated the send subcommand — completion suggested both.
Now 'pos communication telegram <TAB>' completes to just 'sender' and
'listener'. send is the single canonical action.

- git mv bin/pos-communication-telegram bin/pos-communication-telegram-sender
- remove --send branch + POS_FLAGS entry; add --markdown to completion
- lib/notify.sh: notify_sender_name() maps platform telegram -> telegram-sender
  (notify_send otherwise looks for bin/pos-communication-telegram)
- pos-system-health --send 'sent:' check + pos-entertainment-send use the new
  name and the send subcommand
- completion: keys with nested tools but no direct tool complete to the group
  suffixes (sender/listener); --type/--parse-mode value completion moved to
  the new word positions
- docs updated (POS.md, AGENT_Context, DEV.md, SCRIPTS.md, notify.env,
  HOWTO.md, postinstall.sh); removed phantom webhook/log/broadcast subcommands
  from howto/communication.md
2026-08-09 03:28:30 -04:00
Your Name 16bc6685f8 fix: honor --dry-run across install phases; repair repo conventions and doc drift
- spawn() now respects DRY_RUN, install.sh exports it to child phases, and
  postinstall.sh wraps every user-home mutation in run() — '--dry-run' no
  longer runs apt/install/clone or edits dotfiles for real
- gen-docs.sh chmods regenerated files to 644 (mktemp mv left them at 0600)
- make check now syntax-checks apps/, entertainment/, features/, templates/
- .gitignore protects config/authorized_keys + config/rclone.conf; drop the
  tracked empty authorized_keys and the stray 6 MB session file
- pos-system-health --send prints 'sent:' only when a platform sender exists,
  otherwise warns on stderr (notify_send is silent-fail)
- standardize sourced libs (no shebang); refresh AGENT_Context/DEV/APPS/SCRIPTS
  doc drift: notify.sh in lib lists, pos-health systemd units, tsui, scripts/,
  INTERACTIVE_CMDS list, entertainment scheduler (systemd timers only)
2026-08-09 03:01:58 -04:00
Your Name 7dff27206b fix: health --send is notification-only; listener @quiet prefix kills double reply 2026-08-07 14:15:33 -04:00
Your Name 81ac553590 fix: entertainment 1h timer never fired (invalid OnCalendar); drop cron backend, systemd-only 2026-08-07 13:43:45 -04:00
Your Name f99acc36a2 feat: nested pos subcommands — POS_SUBCMDS header, nested category help + completion 2026-08-06 04:01:39 -04:00
Your Name b9edd07801 feat: pos communication telegram listener — /command to bash map + owner-only daemon 2026-08-06 03:48:08 -04:00
Your Name f01eb91299 fix: pos entertainment config set validates all pairs before writing (atomic) 2026-08-06 03:31:29 -04:00
Your Name e50434d62c fix: align plugin keys column in pos entertainment config help 2026-08-06 03:28:14 -04:00
Your Name 03e9d4c8e6 feat: add pos system nfs-server and nfs-client (systemd persistent mounts) 2026-08-06 03:19:42 -04:00
Your Name 025971ca1e feat: multi-platform alerting + shared system.env config with dynamic help values
- lib/notify.sh: route notify_send to every platform in NOTIFY_PLATFORM
  (notify.env, default telegram; comma-separated = send to all). New
  platforms need only a bin/pos-communication-<p> sender implementing
  'send <value> [--markdown]' (Matrix/Synapse ready)
- pos-communication-telegram: add --markdown as alias for --parse-mode
  markdown to match the sender contract
- lib/common.sh: load_system_env() — shared ~/.config/linux_post_install/
  system.env for pos-system-* tools (env exported > file > default)
- pos-system-health/backup: load system.env and show effective dynamic
  values (NOTIFY_PLATFORM, HEALTH_BACKUP_MAX_AGE_DAYS, BACKUP_SERVICE_ROOTS)
  in --help
- config/system.env + config/notify.env templates copied by postinstall
- systemd/pos-health.service: EnvironmentFile for both configs so the
  daily digest honors them
2026-08-06 02:37:56 -04:00
Your Name 9a94329dd0 feat: add pos system health, lib/notify.sh, and daily Telegram digest timer
- bin/pos-system-health: host dashboard (disk, RAM, failed units, backup age,
  fail2ban, docker); exits 1 on any FAIL; --send/--markdown via Telegram
- lib/notify.sh: self-contained opt-in alerting helper; silent-fails, wired
  into pos-system-backup (success + ERR trap) and pos-system-firewall
- systemd/pos-health.{service,timer}: 08:00 digest as installing user;
  postinstall enables timer once telegram.env exists, now copies *.timer
- AGENT_TODO.md: worklist with Now/Next/Later/Done history; linked from AGENTS.md
2026-08-06 02:25:23 -04:00
Your Name 7e28769ec5 add entetaiment features 2026-08-06 01:48:24 -04:00
Your Name d722842d20 add auto trig for api and send via telegram 2026-08-05 11:49:27 -04:00
Your Name bd92c7f899 feat: auto-install config/entertainment.env (default Al-Hasakah weather) on install 2026-08-05 14:59:50 +00:00
Your Name 2aaf5cff62 feat: add entertainment module — public-API plugins (weather, joke) sent via Telegram by default (pos entertainment send) 2026-08-05 14:45:51 +00:00
Your Name e3762f4074 feat: add --parse-mode (plain|markdown|html) to pos communication telegram 2026-08-05 14:45:10 +00:00
Your Name 330a3ba0b4 fix: add yt-dlp dep guard to pos-media-mp3/mp4 (clean error instead of raw command-not-found) 2026-08-05 14:23:03 +00:00
Your Name e62626b55c ai need to continue ... 2026-08-05 05:47:45 -04:00
Your Name 494eae2bdf feat: add pos usb server (USB Redirector control); fix doc/code drift
- new bin/pos-usb-server: flag-style control of usbsrv (--ls, --share,
  --unshare, --auto-share, --callback, --close-callback, --auto-connect,
  --disconnect, --nickname, --timeout, --port, --info, --version);
  interactive prompts fall back to args; command -v usbsrv guard
- wire into bin/pos: usb category, example, INTERACTIVE_CMDS
- completions: usb-server flag completion
- docs: POS.md usb section, AGENT_Context tree/dispatch/table, README
- fix: add pos-network-hotspot to no-common.sh list (was omitted)
- fix: stale pos-docker-compose line count 317 -> 363
- fix: DEV.md/AGENT_Context note non-apt deps (command -v guard, not PACKAGES)
- fix: document INTERACTIVE_CMDS all-or-nothing per-script trade-off
- fix: usage() shows docker health (was missing from cheat-sheet)
2026-08-05 04:38:03 -04:00
Your Name fe751bbc0c feat: add category help to pos dispatcher (pos <category> --help) 2026-08-05 04:09:19 -04:00
Your Name d591e71363 feat: show public IP location in pos network ip 2026-08-05 03:57:21 -04:00
Your Name 49fb248454 refactor: merge vbox into docker as pos docker vbox 2026-08-05 03:30:51 -04:00
Your Name 0c9d09c331 docs: add dev templates + clarify conventions; fix pos help for multi-word commands 2026-08-05 03:03:56 -04:00