Commit Graph

93 Commits

Author SHA1 Message Date
Your Name 072a8e72c1 feat: pos media grab — smart URL classifier for auto-download
gates / consistency-and-conventions (push) Successful in 2m14s
New tool that classifies URLs by domain and delegates to pos media mp3
(audio) or pos media mp4 (video). Listener gains URL detection step
between prefix map and AI bridge — bare URLs auto-download.

Domain rules: music.youtube.com/soundcloud/bandcamp → mp3,
youtube/vimeo/twitch → mp4 --best, unknown → configurable default.

28 test cases / 70 assertions / 0 failed.
make gen && make check green, make lint 0 FAIL / 0 WARN.
2026-09-04 10:48:49 -04:00
Your Name a4761df3f6 feat: telegram listener text-prefix map — <word> <text> routes to a mapped app
gates / consistency-and-conventions (push) Successful in 2m3s
Generalizes the Telegram listener with a configurable text-prefix map
(telegram_prefixes.env): any non-command message '<word> <text>' runs
the mapped command with <text> appended as ONE quoted argument — e.g.
opencode=opencode turns 'opencode check cpu' into opencode "check cpu".

Routing order per message: text-prefix map → built-in Gemini ai bridge →
/command map → Unknown command. A mapped word shadows the Gemini bridge.

The prefix verb is reworked: bare = list map + bridge word; 'prefix
<word> <cmd...>' = map; 'prefix <word>' = show; 'prefix -r <word>' = remove.
The Gemini trigger word itself is now set via 'pos config telegram'
(TELEGRAM_AI_PREFIX).

Also extracted run_and_reply() to share the /command-map (60s) and
prefix (120s) execution semantics; fixed a latent set -e abort on
invalid templates in prefix_map_set's check_syntax call.

Verified: 27/27 routing-harness assertions, full CLI verb suite,
dispatch smoke, pos config telegram render, bash -n, make gen && make check,
make lint 0 FAIL / 0 WARN, shellcheck -S style (0 new findings).
2026-09-04 08:10:59 -04:00
Your Name e6fa0a4ee9 feat: configurable AI-bridge trigger word for telegram listener
gates / consistency-and-conventions (push) Successful in 1m50s
The listener's "ai " bridge prefix was hard-coded. Messages starting
with <prefix> + space (case-insensitive, literal match) are now
forwarded to Gemini; default stays "ai".

- TELEGRAM_AI_PREFIX in telegram.env (default ai), hot-reloaded per
  message like the command map — no daemon restart needed
- New 'prefix' verb: pos communication telegram listener prefix [word]
  (validated [A-Za-z0-9][A-Za-z0-9_-]*; writes telegram.env chmod 600)
- Field added to the telegram # POS_CONFIG: scope (sender header) so
  'pos config telegram' edits it too
- --status shows the current prefix; usage + POS_SUBCMDS: prefix
  (completions regenerated)
- Matching via scoped nocasematch + quoted-literal =~ prefix;
  ai_bridge_prefix() precedence: env file > env var > default ai

Verified: routing harness (default/custom/case-insensitive/reset/
fallback/unknown-command) green, CLI verb tests, dispatch smoke,
pos config render, gates 0 FAIL 0 WARN.
2026-08-27 11:04:37 -04:00
Your Name 4306a53fef fix: paste-safe multi-line value input in pos ai alias Insert Prompt
gates / consistency-and-conventions (push) Successful in 1m54s
menu_ask_value used line-oriented read -rp: a multiline Ctrl+V paste
flooded the tty queue, read consumed only the first line, and the rest
executed as commands later (or were eaten by a later prompt).

- lib/menu-lib.sh: new menu_read_value() raw-mode bracketed-paste
  reader (stty -icanon -echo -isig, \e[?2004h/l, literal newlines inside
  [200~..[201~, Enter submits outside paste, edit keys, cancel on
  Ctrl-D-empty/Ctrl-C/Z/\, terminal restored via trap). Bytes via
  dd|od|tr chunks, not bash read: read self-interrupts on ETX from a
  tty even with ISIG disabled.
- bin/pos-ai-alias: prompt encode/decode (backslash, newline) with
  load/save wiring; newline-safe truncate; edit wizard Enter keeps the
  full original prompt (no more silent >80-char truncation).

Verified via pty harnesses: multiline + single-line paste captured
verbatim with nothing executed, Ctrl-D/Ctrl-C cancel cleanly, full
create/list/show/edit E2E, round-trips byte-exact. Gates: make gen &&
make check, make lint 0 FAIL 0 WARN.
2026-08-27 04:44:13 -04:00
Your Name 300b742ac8 feat: alias trust flag — auto-execute agent commands without confirmation
gates / consistency-and-conventions (push) Successful in 1m29s
Add an optional5th 'trusted' field to aliases
(name|provider|session|prompt|trusted). Trusted aliases pass --trust to
pos ai, which makes _prompt_run_command auto-execute the agent's detected
commands without the Y/n confirmation (command still printed for audit).

- bin/pos-ai: new --trust global flag; _prompt_run_command takes trusted
  arg and skips the prompt when set; POS_FLAGS + usage updated
- bin/pos-ai-alias: _ALIAS_TRUSTED array, 5-field env format (backward
  compat: missing field defaults to untrusted), Trust column in table,
  trust row in show, trust step (5/5) in create wizard with security
  warning, trust toggle (4/4) with diff tag in edit wizard, wrapper
  scripts get --trust when alias is trusted
- completions/pos.bash + gen docs updated

Gates: make gen && make check && make lint = 0 FAIL, 0 WARN
2026-08-27 03:27:09 -04:00
Your Name e969234ca5 feat: command registry, alias wrapper scripts, config-ui readability
gates / consistency-and-conventions (push) Successful in 1m28s
- lib/registry.sh: shared query API over POS_* headers (reg_scan, reg_list,
  reg_lookup, reg_tools_in, reg_each, reg_config_scopes/keys). Replaces
  per-consumer sed/grep header parsing.

- bin/pos-tree + bin/pos _pos_category_help(): migrated to registry API.
  Category help now shows [deps: ...] annotations. Tree output preserved.

- New optional headers # POS_DEPS: and # POS_EXAMPLES: in tool metadata.
  Added to pos-network-download (aria2c jq curl), pos-media-sync (lsblk jq),
  pos-system-backup (tar), pos-docker-ps (docker) as initial adopters.

- scripts/gen-docs.sh: extended tools array with deps/examples fields;
  conditional column rendering in gen_dispatch; deps annotation in gen_tree.
  Fixed URL-unsafe // joiner (→ middle dot ·) and \x1f caption delimiter
  collision in config-ui.

- bin/pos-ai-alias: rewrote activation from bash aliases (source-time-frozen)
  to executable wrapper scripts at ~/.local/bin. Staleness eliminated:
  edits apply on next invocation with no shell reload. _alias_sync()
  reconciliation on every subcommand, marker-guarded lifecycle, collision
  refusal, legacy .sh retirement. Fixed dup-table bug (option 4 no-op).

- lib/config-ui.sh: @caption/@[KEY=alt] conditional captions, *providers=<tag>
  tagged wildcards, uniform typography tier (bold/cyan/dim), honest prompt.
  Active provider keys bold, inactive dimmed with reason. Backward-compatible.

- bin/pos-system-uninstall: marker-scan for wrapper script cleanup.

- Docs synced: AGENTS.md (new headers + registry), DOC/SCRIPTS.md (registry
  section + lib list), DOC/POS.md (alias wrapper activation), MAINTENANCE.md
  (M-024). Lint fixed: pos-ai-alias registered in INTERACTIVE_CMDS.

Gates: make gen && make check && make lint = 0 FAIL, 0 WARN
2026-08-27 02:30:27 -04:00
Your Name 4fd3c37c40 update docs
gates / consistency-and-conventions (push) Failing after 16s
2026-08-26 07:28:03 -04:00
Your Name 5d7407e30f chore: update docmap + filetable for registry.sh addition 2026-08-26 06:23:35 -04:00
Your Name 6566c8343d chore: re-gen docs for pos-ai-alias addition 2026-08-26 06:02:10 -04:00
Your Name a5c19e842d revert: remove e(dit) option from AI command prompt
gates / consistency-and-conventions (push) Successful in 1m40s
Keep only Y/n (run or skip). The edit feature was unreliable across
different terminal contexts (tee pipes, SSH, CLI). May revisit later.
2026-08-26 04:58:08 -04:00
Your Name 9564880ebf fix: AI command edit - flatten multi-line for readline
gates / consistency-and-conventions (push) Successful in 1m47s
read -e -i only handles single-line text. Multi-line commands (docker
install etc) broke it. Now flattens newlines to spaces before pre-filling
the readline buffer. User sees a single editable line.
2026-08-26 04:37:52 -04:00
Your Name d0299d3f98 feat: AI command edit via clipboard + xdotool fallback
gates / consistency-and-conventions (push) Successful in 2m14s
- _inject_command tries: xclip/wl-copy (clipboard) -> xdotool (typing) -> tmux -> history
- Clipboard is primary: user pastes with Ctrl+Shift+V
- preinstall.sh: add xdotool and xclip to PACKAGES
2026-08-26 04:13:36 -04:00
Your Name c1f1c4109f feat: AI command prompt adds e(dit) option with keyboard simulation
gates / consistency-and-conventions (push) Successful in 2m11s
- e: xdotool type (X11/Wayland) -> tmux send-keys -> history fallback
- Command appears on active terminal line for editing before Enter
- Y/Enter: execute, n: add to history
2026-08-26 03:51:16 -04:00
Your Name 710b626f47 feat: AI command prompt - run or edit detected shell commands
gates / consistency-and-conventions (push) Successful in 2m6s
- _extract_commands() parses bash/sh/shell fenced code blocks
- _prompt_run_command() prompts [Y/n] via /dev/tty after AI response
- Y/Enter: execute via run helper (respects DRY_RUN)
- n: command added to history (press up-arrow to recall, edit, run)
- Integrated in both cmd_ask() and cmd_chat()
- Skipped when output is piped/redirected
2026-08-26 03:26:11 -04:00
Your Name e0c9ba384a feat: dynamic provider config — pos config ai auto-discovers provider keys
gates / consistency-and-conventions (push) Successful in 1m30s
- lib/ai-providers/*.sh declare # PROVIDER_CONFIG: headers
- lib/config-ui.sh: _cfg_provider_keys() scans providers at runtime
- bin/pos-ai: POS_CONFIG uses *providers marker (no hardcoded keys)
- Adding a new provider auto-populates config UI — no main tool edits needed
2026-08-26 02:58:45 -04:00
Your Name 88ea660891 feat: system uninstall — safe interactive pos toolkit remover
gates / consistency-and-conventions (push) Successful in 2m4s
- Three tiers: binaries/services/shell (default), config (--config), data (--data)
- Interactive scan + numbered plan display, confirm per tier
- --yes skips prompts (tier 1 only); --yes --config --data = nuclear
- Shell integration cleanup: bashrc PATH/completion/hook entries
- Systemd services disabled and stopped
- Idempotent, never removes git repo
2026-08-25 11:00:05 -04:00
Your Name 4f79ce123f refactor: ai — merge gemini/openrouter into unified plugin architecture
gates / consistency-and-conventions (push) Successful in 1m59s
- bin/pos-ai: single provider-agnostic tool (ask/chat/sessions/capture/models/providers)
- lib/ai-providers/gemini.sh: Gemini adapter (59 ln)
- lib/ai-providers/openrouter.sh: OpenRouter adapter (59 ln)
- bin/pos-ai-gemini/openrouter: thin forwarders for backward compat
- Provider adapter interface: provider_name/default_model/generate/models_list
- Unified session format (OpenAI messages), auto-migrate old gemini contents
- Config: AI_PROVIDER/AI_API_KEY/AI_MODEL/AI_SYSTEM_PROMPT in ai.env
- Config fallback: AI_API_KEY → provider-specific env var → error
- Default system prompt configurable via AI_SYSTEM_PROMPT
- New subcommand: pos ai providers (lists providers + config status)
- Shell hook (pos-ai-hook.sh) for auto-capture
2026-08-25 09:57:10 -04:00
Your Name 4af097f5eb docs: sync POS/AGENT_Context/completions for share, vbox, ai features
gates / consistency-and-conventions (push) Successful in 2m28s
- POS.md: new openrouter rows, updated share/vbox entries
- AGENT_Context_Project.md: GEN tree/dispatch/filetable/docmap resync
- completions/pos.bash: new flags/subcommands for openrouter + capture
- bin/pos: INTERACTIVE_CMDS += ai-openrouter (stdin reader)
2026-08-25 08:40:05 -04:00
Your Name 692cb6b362 feat: menu doors for media-sync/backup/compose/schedule/vbox/download; firewall menu → stderr+/dev/tty mechanics
gates / consistency-and-conventions (push) Successful in 2m10s
2026-08-24 14:44:25 -04:00
Your Name 010e067935 fix: ytsync — classify youtu.be/<id> short links as videos; sync tools-docs thumbnail flag
gates / consistency-and-conventions (push) Successful in 2m34s
2026-08-23 07:46:51 -04:00
Your Name 5de7a331fe feat: pos media ytsync — incremental YouTube channel/playlist sync into ~/Videos 2026-08-23 07:39:36 -04:00
Your Name 364c5c3687 feat: pos docker stack — containers grouped by compose stack (project)
gates / consistency-and-conventions (push) Failing after 12s
New bin/pos-docker-stack: docker ps output grouped by Docker Compose
project (stack). Each stack is a sorted section (name, status, ports);
containers without a compose project land in a Standalone group at the
end. Running only by default, -a|--all includes stopped/exited. Status
colored on a terminal; summary line 'Stacks: N containers: N
standalone: N'; exit 0 when empty.

Data via docker ps --format with \x1f delimiters (project label
com.docker.compose.project from compose v2); parsed with awk -F'\x1f'
+ IFS=$'\x1f' read — tab/pipe delimiters are IFS whitespace or appear
in values (DEV.md:213). Dash padding via sed, not tr (multi-byte).
Deps guard (docker) before --help; no stdin.

Docs: POS.md docker row + detail, howto/docker.md table + section,
bin/pos usage EXAMPLES, AGENT_Context Common Tasks row. Verified:
stub suite 23/23, live daemon runs, dispatch, make gen && make check,
make lint 0 FAIL / 0 WARN.
2026-08-15 13:01:03 -04:00
Your Name a09f9cfafa fix: usb target picking excludes EFI partitions and pre-flights space
gates / consistency-and-conventions (push) Successful in 59s
usb_detect offered a Ventoy stick's 32M VTOYEFI ESP as a sync/backup
target: with the data partition unmounted it was the only mounted
candidate, and cp died mid-copy with 'No space left on device'.
Detection now reads FSTYPE/PARTTYPENAME and drops EFI system
partitions from both the mounted list and the mount-offer list;
USB_MOUNTED entries carry mp|label|size|model|fs and usb_pick_root
shows that in the single-stick confirm and the multi-stick/partition
picker (USB_ROOT stays a bare mountpoint). pos-media-sync pre-flights
the exact payload size vs df free space (err, or warn under --dry-run)
before any copy.
2026-08-15 04:21:10 -04:00
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 59e6c3530b docs: document the live Gitea Actions gate and deterministic-gen convention
gates / consistency-and-conventions (push) Successful in 43s
CI is now live (act_runner on the Gitea host), so the docs stop saying a
runner 'needs to be registered' and record how the gate works:
- AGENTS.md: CI bullet now notes the live runner, red run = merge-blocker,
  and the byte-order deterministic generator rule (LC_ALL=C, learned when the
  CI container's locale reordered the category-less pos-config/pos-tree keys
  and the gen-drift gate caught it).
- DEV.md: definition-of-done mentions the live CI re-run; new 'CI: Gitea
  Actions Gate' section (runner location, CONFIG_FILE run.sh gotcha,
  --add-host pin, one-time tokens, runnerv1 status enum 1=success/2=failure,
  deterministic-generator convention, static-only limits).
- AGENT_Context step 7: pushing re-runs the gates, red run blocks.
- AGENT_TODO: dropped a duplicated 'gate added' Done entry and fixed its
  stale 'runner pending' phrasing.
2026-08-14 16:08:09 -04:00
he 647699b4cc fix: make gen deterministic with LC_ALL=C byte-order sort
Plain sort in scripts/gen-docs.sh is locale-dependent: category-less tool
keys start with '|', which collates after letters under the CI container's
locale (pos-config/pos-tree moved to the end of the tree/dispatch/filetable
blocks). The new Gitea Actions gate caught this as a gen-drift failure on a
clean checkout. Force LC_ALL=C for byte-order sort and regenerate the doc
(config/tree now deterministically sort after the letter categories).
2026-08-14 15:59:21 -04:00
he 23ec322ef1 docs: document the convention lint gate (make lint) in AGENTS/DEV/AGENT_Context
- DEV.md: new 'Convention Lint Gate' section enumerating all check classes
  (shebang/strict-mode, exec bits, POS headers, -h|--help after deps guards,
  INTERACTIVE_CMDS, POS.md coverage, plugins/apps/units/wrappers/secrets/env
  seams) + 'refine never weaken' rule; test step and definition of done now
  include make lint (0 FAIL / 0 WARN)
- AGENTS.md: make gen -> make check -> make lint is the definition of done;
  both gates described, lint not in the pre-commit hook
- AGENT_Context_Project.md: How-to-modify step 7 updated
- MAINTENANCE.md: next-session brief uses make lint; gate commit marked DONE
2026-08-14 15:17:02 -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 886ac2351c fix: communication scrcpy — empty SCRCPY_EXTRA_FLAGS emitted a blank line that became an empty scrcpy arg (Unexpected additional argument) 2026-08-13 18:49:47 +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 8b0ce3ba89 refactor: transparent bootstrap output — name installs, show skips, drop dup apt update 2026-08-13 05:00:33 -04:00
Your Name a3c01a0394 feat: usb-automount feature — udev+systemd auto-mount of USB sticks, flag-gated like autostart
features/usb-automount.sh (installed via ./install.sh --feature, flag
usb-automount) mounts every unmounted removable block device at
/media/<label> — world-writable via -o umask=000 (fallback plain mount),
label-collision bump -2/-3, no-label -> usb-<name>. First root run
self-installs the hotplug udev rule (/etc/udev/rules.d/99-usb-automount.rules,
SYSTEMD_WANTS=usb-automount.service) + udevadm reload/trigger; an existing
rule is never overwritten. systemd/usb-automount.service (Type=oneshot,
WantedBy=multi-user.target) covers boot + hotplug + manual start, gated in
postinstall.sh's systemd loop exactly like autostart. Purpose: a plugged-in
stick is ready for pos system backup's post-verify USB copy without manual
mounting. Docs: SYSTEMD/SCRIPTS/README/AGENT_Context (tree, filetable —
postinstall.sh count corrected 152->163, it was already stale). Verified:
stub suite /tmp/opencode/usb-automount-test 47/47 green; make gen && make check.
2026-08-13 03:40:13 -04: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 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 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 ac44f972dc docs: DEV/AGENTS doc improvements from the SMB session — deps-guard-before-help, test seams + stub-PATH pattern, managed config blocks idiom, completed docs checklist 2026-08-11 16:21:13 -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 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