Commit Graph

45 Commits

Author SHA1 Message Date
he 16bda822ff feat: pos media sync — incremental Music→USB sync (mp3/mp4) + shared lib/usb-lib.sh
gates / consistency-and-conventions (push) Successful in 46s
2026-08-14 18:02:03 -04:00
he 03dd92370c feat: pos system backup -- optional --no-encrypt (BACKUP_ENCRYPT=0) 2026-08-14 17:19:17 -04:00
he 28fae8a684 feat: pos system backup — smart USB detection with mount offer for unmounted sticks
gates / consistency-and-conventions (push) Successful in 45s
2026-08-14 16:58:47 -04:00
he 5ef38dc46f fix: resolve all 23 MAINTENANCE audit tickets
- deps guards before -h|--help in docker-health/ps, network-scan,
  usb-server, media-mp3/mp4 (--dry-run pre-scan kept); system-firewall
  gains usage()/--help; autostart/usb-automount get flags.sh + template
- install.sh: normalize N-M range syntax in --steps
- bin/pos: INTERACTIVE_CMDS += docker-compose docker-vbox network-hotspot
- common.sh: canonical XDG-aware CONFIG_DIR + DIM color var; notify.sh
  stderr fallback; ent_plugin_* registry renames (runtime plugin API kept)
- docker-compose SCALE_DIR/CONFIG_ENV env seams; ffmpeg in PACKAGES;
  scrcpy.sh exec bit
- docs: health is console-only (--send/--markdown removed), POS.md file
  refs for config/tree/entertainment, DEV.md no-guard exception, docmap/
  filetable regenerated (make gen), hand-maintained line rows bumped
- add scripts/lint-conventions.sh gate + Makefile lint target; record
  all VERIFIED outcomes in MAINTENANCE.md; AGENT_TODO Done entry
  (2026-08-14)
- gates: make gen/check/lint all green (0 FAIL, 0 WARN); bash -n sweep
  clean; restricted-PATH dep tests + step-matrix dry-runs verified
2026-08-14 12:57:00 -04:00
he 93fb6b6b37 fix: share smb client persist — write a real .automount unit
x-systemd.automount in a unit file's Options= is only honored when read
from /etc/fstab, so persisted mounts never armed an automount; the unit was
also static (no [Install]) so enable was a no-op. Result: after a reboot the
share sat inactive and the disk never mounted on access.

persist now writes both <name>.mount and <name>.automount units (the
automount with WantedBy=multi-user.target) and enables/starts the automount;
unpersist stops/disables/removes both units.
2026-08-14 10:31:45 -04:00
he 1724096ea7 fix: share smb client list — show persistent automount units
persist uses x-systemd.automount, so the CIFS share is never actually
mounted until first access and findmnt -t cifs stays empty — list reported
'No SMB mounts' despite configured persistent units. list now also scans
$UNIT_DIR/*.mount for Type=cifs and reports them under 'Persistent
(automount)' (where, what). Empty output still prints 'No SMB mounts'.
2026-08-14 10:24:02 -04:00
Your Name 2d6d49258e feat: communication scrcpy — add SCRCPY_AUDIO config (audio to desktop on by default, false adds --no-audio) 2026-08-13 19:15:18 +00:00
Your Name 999a325422 feat: communication scrcpy — add SCRCPY_NEW_DISPLAY config for scrcpy --new-display (virtual display mirror) 2026-08-13 19:05:14 +00:00
Your Name 7d600ade7e fix: communication scrcpy — drop scrcpy from apt PACKAGES (not in Debian/Ubuntu repos by default), install via apps/media/scrcpy.sh 2026-08-13 14:32:09 +00:00
Your Name 261e4114e2 feat: communication scrcpy — Android mirror/control wrapper over scrcpy+adb (devices, record, tcpip, connect, push, pull, screenshot, info) 2026-08-13 14:29:09 +00:00
Your Name a4c025d236 feat: entertainment hardening — notify_send delivery, plugin lib, last-run state, config edit; shared user-timers lib 2026-08-13 14:13:06 +00:00
Your Name d9316ec7f7 fix: pos systemd units stop fast — TimeoutStopSec=5s everywhere, listener TERM traps; drop dead pos-health/pos-entertainment unit docs 2026-08-13 13:16:58 +00:00
Your Name d4d38ad901 feat: pos system backup copies to USB after verification — sha256-proven 100%
Once the archive verifies, USB detection runs (so a stick plugged in while
the backup ran is found): mounted removable storage is auto-detected via
lsblk -J + a recursive jq filter (rm, mounted, type part|disk — JSON makes
spacey mountpoints safe), or BACKUP_USB_ROOT pins a fixed stick and skips
detection. None mounted → one re-scan prompt ('s' skips, EOF from cron
skips silently, rc stays 0); one stick → y/N confirm; several → numbered
pick (0 = skip). The copy lands in <usb>/backups/ (mkdir -p, chmod 600
best-effort — a vfat chmod failure warns, never fails the copy) and the
transfer is proven 100% by sha256 source-vs-copy before any success is
announced; a mismatch warns with both hashes, notifies 'USB copy FAILED',
and exits 1. The ERR trap is re-armed before the USB phase so a copy
failure no longer notifies 'Backup FAILED'. Docs: usage() Environment,
POS.md backup row, howto/system.md (USB section + env table + mismatch
troubleshooting), DEV.md system.env list. Stub suite
(/tmp/opencode/backup-test, HOME-isolated, sudo/gpg/lsblk/sender stubs,
corrupting-cp + vfat-chmod overrides, per-test lsblk JSON fixtures):
40/40 green.
2026-08-13 03:23:30 -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 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 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 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 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 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 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 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 b9edd07801 feat: pos communication telegram listener — /command to bash map + owner-only daemon 2026-08-06 03:48:08 -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 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
Your Name 070524bafb feat: add tsui app installer and pos communication telegram sender 2026-08-05 02:42:35 -04:00
ciya e7c8c176ed feat: add pos system backup — encrypted folder snapshots with --service picker 2026-08-03 08:58:38 -04:00
Your Name 60718b360e feat: integrate precompiled hotspot binaries from x64_bin/ via pos network hotspot 2026-08-03 03:48:33 -04:00
Your Name 54592a5839 docs: reorganize into DOC/ and simplify README
- Move all docs (DEV, AGENT_Context, algorithm) into DOC/ via git mv
- Rewrite root README as short intro + quick start + links into DOC/
- Add per-area reference docs: SCRIPTS (core scripts + libs + features),
  POS (pos CLI + compose config), APPS (picker + catalog), SYSTEMD (units)
- Add DOC/README.md index; fix all cross-references
2026-08-03 02:50:38 -04:00