Commit Graph

121 Commits

Author SHA1 Message Date
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
ci-ok/010e0679355a1a684fa78620874d879430b72b37
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
ci-fail/a0152fa87c6057ede968184536b674148138eb97
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.
ci-ok/a09f9cfafa529b21a4250c18b6eadd3699311da4
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).
ci-ok/23d69b795e5e70eceb8d2c786a4f9ba99e42e7b9
2026-08-15 04:01:54 -04:00
Your Name 9ca78ee080 Merge branch 'main' of https://gitea.skink-platy.ts.net/admin/Linux_post_install
.
2026-08-15 03:53:31 -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
ci-ok/16bda822ff83821bd8d532637359076ca4b8aea2
2026-08-14 18:02:03 -04:00
he 8026300005 chore(ci): report gate result as ci-ok/ci-fail tags + scripts/ci-status.sh
gates / consistency-and-conventions (push) Successful in 45s
ci-ok/80263000051c57d1e2875bab9e4f771c24854880
2026-08-14 17:19:28 -04:00
he 03dd92370c feat: pos system backup -- optional --no-encrypt (BACKUP_ENCRYPT=0) 2026-08-14 17:19:17 -04:00
he 44c08ef4a4 docs: DEV.md — stub-harness gotchas from pos system backup USB suite
gates / consistency-and-conventions (push) Successful in 45s
2026-08-14 17:05:52 -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 16c7cc32ae docs: consolidate AGENT_TODO into single Now/Next/Later/Done layout
gates / consistency-and-conventions (push) Successful in 44s
2026-08-14 16:20:03 -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 b507d17e3d docs: record verified CI verdicts in AGENT_TODO
gates / consistency-and-conventions (push) Successful in 43s
2026-08-14 15:59:21 -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 e0b5b11bf9 ci: add Gitea Actions gate (make gen/check/lint on push/PR)
gates / consistency-and-conventions (push) Failing after 44s
- .gitea/workflows/lint.yml: on push + pull_request runs make gen, then
  git diff --exit-code (gen-drift check), then make check, then make lint
- requires a registered act_runner (ubuntu-latest label) to execute
- docs: AGENTS.md Quick facts 'no CI' -> CI bullet (runner required, gates
  still run locally); DEV.md stub-harness note clarifies CI is static-gates
  only; AGENT_TODO Done entry + Next item for runner registration
- verified locally: gen idempotent (0 gen-managed files changed), check OK,
  lint 0 FAIL / 0 WARN
2026-08-14 15:25:39 -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 ad70819379 Merge branch 'main' of https://gitea.skink-platy.ts.net/admin/Linux_post_install
.
2026-08-13 10:33:43 -04: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 4484104150 Merge branch 'main' of https://gitea.skink-platy.ts.net/admin/Linux_post_install
.
2026-08-13 10:29:32 -04: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 57972ebb3b Merge branch 'main' of https://gitea.skink-platy.ts.net/admin/Linux_post_install
.
2026-08-13 10:14:34 -04: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 72cf73b227 Merge branch 'main' of https://gitea.skink-platy.ts.net/admin/Linux_post_install
session travel problem
2026-08-13 09:37:40 -04: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 e9c3cb8a40 session 2026-08-13 09:02:57 -04: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 6504c69154 docs: DEV.md env-seam registry + stub-harness guidance; scheduler migrate semantics
Session-learned hardening (sole-developer project — terse, actionable):
- §7 env-override precedent list gains USER_SYSTEMD_DIR (network-download,
  communication listeners, scheduler-lib) + the scheduler's SCHEDULE_* seams,
  plus the missing-:-guard gotcha that silently writes to the real $HOME
  under stub runs.
- New-tool test checklist gains an env-seam review step (grep for unguarded
  config writes, prove with VAR=/tmp/x).
- §7 notes stub harnesses are throwaway by design: build in
  /tmp/opencode/<tool>-test/, leave there, keep only the pattern.
- howto/schedule.md: migrate copies the rule LHS verbatim as COMMAND — the
  old tool never had disk root/loadavg shorthands; rewrite those jobs.
2026-08-13 02:14:51 -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 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 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 c0693b0093 feat: postinstall asks to install event-rules.template
If event.env exists with no rules yet, prompt whether to copy
config/event-rules.template (starter CPU/memory/disk/NVMe/network/
process rules). Never overwrites existing rules; honors DRY_RUN.
2026-08-09 18:24:47 +00:00