Commit Graph

103 Commits

Author SHA1 Message Date
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 59935dc5ef fix: alias create fails with empty-name collision due to dynamic scoping bug
gates / consistency-and-conventions (push) Failing after 9s
_alias_load() used 'name' as its while-read loop variable, which — via
bash dynamic scoping — clobbered the caller's local 'name'. When _alias_create
passed 'searcher', _alias_load overwrote it to '' (last env-file line's name),
making _wrapper_path produce '~/.local/bin/' (the directory itself). Since
directories always exist, [ -e ] triggered a spurious 'already exists' error.

Fix: rename _alias_load loop vars to _ln/_lp/_ls/_lp2/_lr (local), breaking
the dynamic-scope collision. Reproduced and verified with a test harness.

Gates: make gen && make check && make lint = 0 FAIL, 0 WARN
2026-08-27 02:41:57 -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 9f289ba31b feat: pos ai alias — manage AI agent aliases
gates / consistency-and-conventions (push) Failing after 22s
- Create/edit/remove named aliases (provider + session + system prompt)
- Aliases stored in ai-aliases.env, generated ai-aliases.sh sourced by bashrc
- Interactive menu using lib/menu-lib.sh primitives
- Provider auto-discovered from lib/ai-providers/

Fix: _alias_find() return 1 crashed under set -e; changed to return 0
since -1 sentinel is the not-found signal, not the exit code.
2026-08-26 06:00:01 -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 d84a35efce fix: read -e -i stores into variable directly, not stdout
gates / consistency-and-conventions (push) Successful in 2m34s
edited="\$(read ...)" was always empty because read writes to a variable
name, not stdout. Changed to: read -e -p "Command: " -i "\$flat" edited
which stores directly into \$edited.
2026-08-26 04:42:18 -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 7ae2e77a44 fix: ai — per-provider API keys (remove shared AI_API_KEY)
gates / consistency-and-conventions (push) Failing after 11s
Each provider now has its own key: AI_GEMINI_API_KEY and OPENROUTER_API_KEY.
No more shared AI_API_KEY that caused cross-provider key leakage (gemini
getting openrouter key → 400 error). resolve_key() sets AI_API_KEY internally
from the active provider's key for adapter use. Config UI shows both keys.
2026-08-26 02:36:48 -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 1fbdf7ef2d fix: ai — config UI pipe-in-description bug + render tty detection with shell hook
gates / consistency-and-conventions (push) Failing after 11s
- POS_CONFIG header: replace | with 'or' in AI_PROVIDER description
  (bare | was parsed as field separator, splitting one entry into two)
- render_markdown: check /dev/tty as fallback when shell hook redirects
  stdout through tee (breaks [ -t 1 ] but /dev/tty stays writable)
2026-08-25 10:04:10 -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 f0ef13827b fix: ai --last — prefer newer source (auto-capture beats stale pos logs)
gates / consistency-and-conventions (push) Failing after 14s
--last now compares mtime of pos dispatcher logs vs captured output
(last_cmd_output) and uses whichever is newer, instead of always
preferring pos logs even when they are hours old.
2026-08-25 08:49:36 -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 476173ba83 feat: ai — gemini terse+render+last+session+machine, openrouter new tool, capture any command
gemini enhancements:
- built-in terse system prompt with troubleshooting clause + machine context
- markdown→terminal rendering (glow opportunistic + zero-dep awk fallback)
- --last: pos logs + captured output fallback, staleness warning, stderr annotations
- session default always on; --session override; answer separation on tty
- --full flag, --system wholesale override

openrouter (new tool):
- cloned from gemini, adapted for OpenAI-compatible REST API
- Bearer auth, messages array, choices[0].message.content parsing
- config: pos config ai-openrouter → OPENROUTER_API_KEY/MODEL
- default model: openrouter/auto (auto-picks best model)
- all features: ask, chat, sessions, --last, capture

capture subcommand (both tools):
- runs any command, tees output to last_cmd_output for --last
- --last fallback: pos logs (priority) → last_cmd_output (secondary)

shell hook (optional):
- lib/pos-ai-hook.sh: sourceable .bashrc snippet for auto-capture
- exec > >(tee ...) with 1 MB truncation
2026-08-25 08:39:55 -04:00
Your Name 0aaa25150c feat: vbox — categorized create UI with GPU/device/mount/port presets
- category hub with basket counts, review screen, single confirm
- GPU: nvidia-smi → /proc/driver/nvidia → vendor scan detection
- host devices: lsusb/tty/video/snd/lsblk + manual input, dedupe
- dir mounts with (system disk — careful) labels
- SHOULD tier: image/ports/cpus/mem, flag contract --gpu/--device/--dir/--port/--cpus/--memory/--network
- zero-flag run byte-identical to pre-edit
- cmd_unpersist not-found exit 0 → return 0 in both clients
- DOC/howto/docker.md: vbox categorized create section
2026-08-25 08:39:42 -04:00
Your Name 4173fc61e3 feat: share clients — picker enhancements, unmount fixes, confirm default-y convention
- mountpoint picker: synthetic (as on server) candidate + n=new mkdir flow
- unmount-by-pick via findmnt enumeration with confirm
- cmd_unmount idle-persisted branch exit 0 → return 0 + actionable guidance
- all menu handlers normalized … || true
- confirm() rewrite: default-y on Enter, EOF fail-closed, case-insensitive
- latent compose "Y" bug fixed
- DEV.md convention doc for confirm semantics
2026-08-25 08:39:29 -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 5b2a0304e1 feat: share suite — interactive menus for usb/nfs/smb server+client on share-lib domain layer 2026-08-24 14:44:18 -04:00
Your Name b144fe8853 fix: ytsync — multibyte cut delimiter broke last-run rendering; printf dash format rejected 2026-08-24 14:43:57 -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 a0152fa87c .
gates / consistency-and-conventions (push) Failing after 9s
2026-08-21 09:53:10 -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
Your Name 23d69b795e fix: pos media sync finds nothing when the source dir is a symlink
gates / consistency-and-conventions (push) Successful in 54s
GNU find (default -P) does not descend a command-line symlink to a
directory, so `find $HOME/Music ...` returned zero files and the tool
reported '0 added, 0 updated, 0 unchanged' without creating the target.
Switch to `find -H` (follows only command-line symlinks; inner-symlink
semantics unchanged).
2026-08-15 04:01:54 -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 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 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 5da148ac4e fix: share smb-server share warns on Samba-passdb gaps + blocked parent traversal
share now checks both common NT_STATUS_ACCESS_DENIED causes before writing the
config (warnings only — the share is still applied):
- --users entries missing from the Samba passdb (pdbedit -L) get a warning
  pointing at 'pos share smb-server adduser <user>' — valid users = <u> with
  no Samba password previously failed for clients with no clue why.
- every ancestor of the share path is checked for other:+x traversal (sticky
  dirs like /tmp count as traversable); a 700 home dir under the share path
  now warns with 'chmod o+x <dir>'.
Docs: howto/share.md SMB section + NT_STATUS_ACCESS_DENIED troubleshooting.
Verified with a stub-PATH suite (pdbedit/systemctl/smbcontrol/testparm stubs,
SMB_CONF seam): 16/16 green.
2026-08-13 02:14:36 -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 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