The DPMS wake failure is the monitor no-signal auto power-off (HPD cycling during idle), not the refresh rate: the 120 Hz pin did not fix it. Disabled in the OSD and recorded as WA-041; pin 144.000 explicitly so niri stops silently falling back.
Assisted-by: DeepSeek Harness (deepseek-flash)
The 4090 reports the panel 120 Hz mode as 119.880, not 120, so niri fell back to 144 Hz; that DSC link stays dark after a DPMS wake.
Assisted-by: DeepSeek Harness (deepseek-flash)
EasyEffects 8 keeps its KConfig settings database plus user presets, autoload
profiles and imported models under $HOME, which the tmpfs root drops on
reboot; bind-mount both directories from /persistent.
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
Aquamarine builds for ai and shoukei across the three platforms, with both
daemons logging in as root. They authenticate with their passphrase-free SSH
host keys, and ssh_known_hosts now carries each builder's address.
Assisted-by: DeepSeek Harness 0.2.0-rc.2 (deepseek-flash)
disko creates the swapfile only when it formats the pool, so the live 96G files
keep their size until they are recreated with btrfs filesystem mkswapfile; that
frees 64G per host.
Assisted-by: DeepSeek Harness 0.2.0-rc.2 (deepseek-flash)
* fix(ssh): retry and multiplex LAN connections
* fix(ai): shrink the neighbour-probe fallback to ~1s
Assisted-by: DeepSeek Harness 0.2.0-rc.2 (deepseek-flash)
Enabling the module runs `openrgb --server` at boot and installs its udev rules,
so the GUI and the CLI reach the MSI controller without root.
Assisted-by: DeepSeek Harness (deepseek-flash)
The module loads i2c-dev and grants /dev/i2c-* to the i2c group and locally
logged-in users, so ddcutil no longer needs root.
Assisted-by: DeepSeek Harness (deepseek-flash)
The second NVMe and its LUKS volume leave with the Z890 board, so the data-disk disko module is deleted; `ai` must activate this change before the disk is pulled, or its initrd blocks on the missing volume.
Assisted-by: DeepSeek Harness (deepseek-flash)
* feat(mihomo): keep ranges that can never be proxied out of TUN
The list lives in policy.yaml as tun_exclude_address; sources.yaml may override
it. 198.18.0.0/15 stays in TUN: that is the fake-ip range itself.
* feat(mihomo): match Valve's content servers by ASN
The 20 hand-copied prefixes had drifted from what AS32590 announces. The rule
type needs GeoLite2-ASN.mmdb, so geox-url.asn points at the same mirror.
* feat(mihomo): render the gateway config from the same sources
The hand-kept copy had drifted: a manual sync carried the desktop's secret onto
the gateway and dropped external-ui-url. --redact yields a shareable template.
* fix(mihomo): open the link DNS takeover only once the core serves it
The core opens :1053 after parsing rules, and rule parsing is where missing
geodata gets fetched. Flipping at fork time made that fetch SERVFAIL, the config
fatal, and the unit unstartable.
* fix(justfile): keep local endpoints out of the agent proxy
With only HTTP_PROXY set, a request to this host's own llama-swap endpoint went
to mihomo. Node matches exact hosts only, so the literals carry it; the CIDRs
serve curl and Go.
* feat(justfile): seed mihomo geodata into the service state dir
So a cold start never needs the download that the DNS takeover made unstartable.
The bring-up runs at the default 1.25 V; afterwards Gear mode is set to
Gear2 and VDD/VDDQ are raised to 1.28 V, changing nothing else. 1.29 V and
up do not train. Also record that the 1.25 V config passed stressapptest
but still hard-froze under a real llama.cpp load, so a passing test is not
proof of stability.
- replace the btop screenshot with the 2026-10-06 annotated capture
(btop + fastfetch + the strata/llama.cpp serving logs); the old
2026-10-01 file is gone, so the README link moves to the new name
- drop the Helix/AI-agents screenshot and its README reference
- fix stale hardware descriptions: the hosts/README.md inventory row and
the idols-ai header comment still said i5-13600KF, and the zswap pool
comment sized its percentages against the old 96G of RAM (now 128G)
- record the hardware history: the platform was rebuilt on 2026-04-27
(PR #257/#258) onto the Colorful CVN Z890 ARK FROZEN + Core Ultra 7
270K Plus, replacing the MSI board and i5-13600KF the host was added
with in 2023-05; the 2x48G kit predates that rebuild, the 2x16G kit
was added 2026-10-06
- make the DIMM bring-up order mandatory and record its failure mode:
with the 48G pair in first, or all four DIMMs from the start, the
board does not POST
- gloss the Chinese BIOS labels in English, marked as translations of
the labels rather than the firmware's own English wording
Left alone on purpose: the 96G swapfile in hosts/idols-ai/disko-fs.nix.
It was grown from 20G to 1x-RAM on 2026-10-02 (a26ab3be), when the host
still had 96G; resizing it again means re-running disko on the machine,
so that stays a separate decision.
Document the 4-DIMM kit mix (2×48G JUHOR + 2×16G GLOWY) on the Colorful
CVN Z890 ARK FROZEN V20:
- hardware (CPU, board, and both kits)
- the install order that trains (16G pair first)
- the only stable settings (XMP off, DDR5-4800 @ 1.25 V)
- the stress-test recipe and results
- the XMP @ 5600 failure and how to recover a board that will not POST
- re-enrolling the LUKS TPM unlock after a BIOS change
dsh keeps its session transcripts, workspace storages, and profiles in
DSH_HOME=~/.dsh, which was outside the backup allowlist. Exclude its
.credentials.yaml like the module's other credential paths.
Vinput's streaming Zipformer models have unbounded dynamic shapes, so
OpenVINO cannot compile them for the GPU or the NPU; the `openvino`
provider and ai's Intel NPU enablement could never run on the NPU (noted
as unverified in WORKAROUNDS WA-017). Remove the backend option, the
daemon's OpenVINO library path, and the intel-npu module enable, and
update the eval test, README and WORKAROUNDS (drop WA-016 and WA-017).
Keep Vinput's stock package and its bundled sherpa-onnx (1.13.4): the
fork-based and nixpkgs-master sherpa overrides existed only to provide the
`openvino` provider, so drop package.nix with them.
Assisted-by: opencode (DeepSeek V4.1 Flash)
Vinput stores its core config in ~/.config/vinput/config.json and its
downloaded sherpa-onnx models in ~/.local/share/vinput/models/. Neither
was bind-mounted from /persistent on the tmpfs-root hosts, so a reboot
wiped both and vinput-daemon started with "Local ASR provider model is
not configured". Persist both directories and document the one-shot CLI
model setup in the vinput README.
* fix(desktop): tie ai's link DNS takeover to mihomo's lifecycle
sing-tun normally points systemd-resolved at the TUN DNS by running
resolvectl (dns/domain/default-route). Under nixpkgs' hardened
DynamicUser mihomo unit that hand-off fails silently: the unit's
RestrictAddressFamilies blocks resolvectl's D-Bus socket and resolve1
requires privileged authorization, so resolved keeps querying the
physical-link DNS, fake-ip is bypassed, and domain rules degrade to
MATCH.
Do the hand-off as '+' ExecStartPost/ExecStopPost hooks instead: '+'
commands run outside the sandbox (systemd.exec: address-family
restrictions do not apply to them) and ExecStopPost reverts even on
crashes, so a dead mihomo leaves DNS usable.
Signed-off-by: Ryan Yin <xiaoyin_c@qq.com>
* docs(mihomo): record sing-tun's resolvectl hand-off as the leak cause
Signed-off-by: Ryan Yin <xiaoyin_c@qq.com>
* refactor(desktop): keep mihomo only on ai and shoukei
ruby/kana never ran the core (service inactive live), and their
resolved + TUN combo would reintroduce the resolver leak once enabled.
Drop the enable and the explicit module import from computer-use; the
eval test now pins mihomo=false for both guests.
---------
Signed-off-by: Ryan Yin <xiaoyin_c@qq.com>
Kimi Code moved its desktop client into an internal repository in July 2026 (MoonshotAI/kimi-code#1849), so the polished surface is no longer open source; the CLI that stays behind overlaps opencode2 and pi. Removing it drops one more redundant harness.
oh-my-pi is a feature-complete superset of pi, so its role is already covered: opencode2 for a batteries-included harness, pi for the minimal/local-model one. Keeping it meant maintaining two nearly identical harnesses.
* chore(workarounds): re-evaluate stale hardware/kernel fixes
Prune workarounds whose root cause is gone, fix one vendor typo, and
document the ones we keep:
- drop `transparent_hugepage=madvise` on shoryu/shushou/youko: it was tied to
the old fixed 1G hugetlb pool, and the VMs now use ordinary memory
- shoryu: `hardware.cpu.intel.updateMicrocode` -> `amd` (it is an AMD APU)
- ai: drop `i915.enable_guc=3` (GuC/HuC submission is the default on modern
i915/Xe)
- kernel-hardening: name the Dirty Frag CVEs (CVE-2026-43284 / CVE-2026-43500)
and the re-evaluation condition
- document re-eval conditions for the Insta360 resume fix, the darwin
auto-optimise-store workaround, and the youko USB-SATA bridge mitigations
* chore(workarounds): keep the Dirty Frag module blacklist as defence in depth
* chore(ai): correct the i915.enable_guc rationale (verified against the kernel)
* chore(darwin): drop the auto-optimise-store workaround (nix#7273 fixed)
* fix(ai): relax NVMe power-management workarounds and enable smartd
Logs show no NVMe errors, so allow APST again (capped at 100 ms), restore
the default io_timeout, and drop pcie_aspm=off. Add smartd for drive
health visibility.
* feat(storage): add drive/SSD SMART monitoring on physical hosts
node_exporter's nvme collector only exposes node_nvme_info and namespace
capacity, not SMART health, so SSD wear/lifespan and drive temperature were
not observable anywhere.
- enable services.prometheus.exporters.smartctl on physical hosts, gated on
modules.hardwareTools (off on QEMU/MicroVM guests), bound to the host's LAN
address on port 9633
- firewall: drop 9633 from anything but the monitoring host
- youko: scrape smartctl-<host> for the physical hosts
- alert rules (storage.yml): SMART health, NVMe wear, available spare, media
errors, critical warning, and drive temperature (warn 70 / crit 80 C)
- Grafana dashboard "Drive SMART (smartctl)"
* feat(idols-ai): persist /var/tmp and small state dirs, wipe /var/tmp at boot
Move the strata model staging area (~3G) off the root tmpfs onto the
persistent btrfs volume to free RAM, preserve btrbk/cups/logrotate
state, and wipe /var/tmp at boot so it only accumulates between
reboots.
* chore(idols-ai): add nosuid,nodev to root tmpfs and tmp btrfs mounts
Hardens /, /tmp and /snapshots; safe because /dev, /run, /nix and
/run/setuid-programs are separate mounts, so nothing there needs suid
bits or device nodes.
* chore(idols-ai): add noatime to the @tmp btrfs mount
Temp files do not need access times; matches the @nix subvolume style
and saves btrfs metadata writes.
* chore(idols-ai): harden the /var/tmp bind mount with nosuid,nodev
World-writable staging data should not honor suid bits or device
nodes, same as /tmp and /snapshots.
* fix(idols-ai): preserve logrotate state as a file, fix persisted dir ownership
- /var/lib/logrotate.status is a regular file, not a directory: move it from
preservation directories to files. A missing state entry makes logrotate
treat every log as freshly rotated, so it must survive reboots.
- keep /var/lib/btrbk owned by btrbk:btrbk 0750 so preservation does not
override the btrbk module's rule with root:root.
- set /var/tmp mode 1777 explicitly instead of relying on systemd's tmp.conf
ordering.
- rewrite comments to describe the paths generically.
* chore(idols-ai): cap journal, wipe coredumps at boot, persist upower/noctalia
- services.journald.settings.Journal: SystemMaxUse=10G, RuntimeMaxUse=256M,
matching the cap already set on idols-kana/idols-ruby.
- wipe /var/lib/systemd/coredump at boot: it lives in the persisted
/var/lib/systemd and crash dumps can contain secrets copied from memory.
- persist /var/lib/upower (device battery history) and
~/.local/state/noctalia (shell settings, notification/clipboard history).