Commit Graph
100 Commits
Author SHA1 Message Date
ryan4yin | 二花 4e78fd964a fix(outputs): keep microvm-guest-parity from forcing guest config (#484)
Reading the host's install script evaluated each guest, which pulls the private secrets input, so
CI could not evaluate the suite at all.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-21 21:49:07 +08:00
ryan4yin | 二花 de6a66ccd4 fix(microvm): run k3s guests from their nixosConfigurations entry (#483)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 21:32:56 +08:00
ryan4yin | 二花 41f6db32ed docs(workarounds): record the Colmena version override (#482)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 21:13:52 +08:00
ryan4yin | 二花 9a3cf189cd fix(hypridle): keep displays awake during gamepad use (#480)
Assisted-by: DeepSeek Harness (gpt-6-astra)
2026-10-21 16:17:59 +08:00
ryan4yin | 二花 0dcf547d1f fix(pki): distrust roots with compromised eMudhra intermediates (#479)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (gpt-6.1-sol)
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-20 23:49:52 +08:00
ryan4yin | 二花 274590df63 feat(aquamarine): track linuxPackages_latest (#478)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-20 23:12:37 +08:00
ryan4yin | 二花 d5fac4bcce fix(ai): bound niri's NVIDIA free-buffer pool (#477)
* fix(ai): bound niri's NVIDIA free-buffer pool

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)

* docs(ai): trim the niri VRAM workaround comment

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-flash)
2026-10-19 01:15:54 +08:00
ryan4yin | 二花 b2673908df chore(agents): build dsh-nu from its own flake (#476)
* chore(agents): build dsh-nu from its own flake

NUR now keeps only dsh, so a plugin release needs `nix flake update dsh-nu` instead of a NUR package update.
2026-10-19 01:15:28 +08:00
ryan4yin | 二花 475fcc55f3 chore(agents): use dsh-nu from NUR (#475) 2026-10-18 21:41:14 +08:00
ryan4yin | 二花 373b233f32 feat(agents): steerable turns, PTC, and a Nushell-only dsh (#473)
* feat(agents): use the shell's own dialect; allow 5 s retry backoff

Assisted-by: DeepSeek Harness (deepseek-flash)

* feat(dsh): make Nushell the only shell

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): wait for CI in the background

Pushes to a PR often start multi-minute CI runs, and an agent that holds
the turn open on a foreground watch reports nothing until it ends. Require
the pushed head and running checks to be reported first, the watch to run
in the background, and the result to be collected after independent work
or after ending the turn.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): keep the shell-handoff rule platform-neutral

The global rules carry no Windows assumptions: drop the cmd, pwsh, and
wsl handoff examples and keep the POSIX forms plus the dsh refusal.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(dsh): keep the shell-swap docs POSIX-only

This repository manages Linux and Darwin hosts, not Windows: drop the
Windows handoff examples and terminal-backend wording from dsh.md. The home
patch also disabled pwsh-sandbox redundantly because dsh-base already
disables that row on POSIX; keep only the active bash-sandbox disable and
verify the composed rows with --dump-config.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): keep the global rules runtime-neutral

Global rules are loaded by every agent CLI, so they must not describe one
runtime's behavior. Drop the dsh-specific sentence and wording while keeping
the expectation to prefer Nushell structured pipelines and Python. Runtime
behavior stays documented in home/base/tui/agents/dsh.md.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): default shell work to Nushell

Keep the Nushell preference explicit in the runtime-neutral global rules, and
keep runtime behavior in runtime docs. Bash stays a narrow fallback for tasks
Nushell cannot do.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): tighten global-rule scope and CI guidance

Keep global rules runtime- and project-neutral, and state that boundary in the
file. Remove the duplicated CI turn-steering text in favour of the Communication
rule, resolve the watch run before watching instead of relying on
gh pr checks --watch alone, name the working-directory parameter generically,
and distinguish a bounded retry backoff from a fixed completion wait.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): never estimate a CI run's duration

A CI run has no predictable length, so do not turn "it looks short" into a
reason to wait. The rule is unconditional: report the head and started checks,
start a background watch, and end the turn; collect the result on completion.
The eval scenario now uses an unknown duration.

Assisted-by: DeepSeek Harness (deepseek-flash)

* docs(agents): move maintenance guidance to the README

The runtime/project boundary is guidance for editing the rules, not a rule
agents need loaded every session. The README's Maintaining global rules
section already owns that audience; the loaded rules keep only behavior.

Assisted-by: DeepSeek Harness (deepseek-flash)

* refactor(dsh): render the home patch from a YAML template

Move the home-layer cordis patch into dsh-cordis.patch.yml, substitute the
bundle and Nushell store paths with replaceVars, and link the rendered file
through home.file.source. This module is the only writer of
~/.dsh/cordis.patch.yml, the current host has no such file, and the profile
patch is a separate layer.

Assisted-by: DeepSeek Harness (deepseek-flash)

* refactor(dsh): install the shell plugin through NUR withPlugins

Replace the local runCommand bundle, peer symlink, and home-layer YAML file
with the plugin package and dsh.withPlugins from ryan4yin/nur-packages#43. The
package wrapper adds a generated --patch overlay after the profile layer, so
dsh no longer writes or manages ~/.dsh/cordis.patch.yml. The NUR input is
temporarily pinned to the PR branch and its commit; point it back at main once
the NUR PR merges.

Assisted-by: DeepSeek Harness (deepseek-flash)

* refactor(nix): expose the NUR package set as nurPkgs

Pass one per-system NUR package set through specialArgs instead of repeating
nur-ryan4yin.packages.${pkgs.stdenv.hostPlatform.system} at each call site.
The agents, rime, and idols-ruby modules now use the short binding.

Assisted-by: DeepSeek Harness (deepseek-flash)

* refactor(nix): use nurPkgs in package overlays

The overlays receive specialArgs too, so they can use the per-system NUR
package set instead of rebuilding the long input path from prev. This leaves
only the definition in outputs/default.nix.

Assisted-by: DeepSeek Harness (deepseek-flash)

* refactor(nix): name the per-system NUR set myNurPkgs

Leave room for consuming another NUR repository later, and match the existing
mylib/myvars naming.

Assisted-by: DeepSeek Harness (deepseek-flash)

* chore(dsh): consume the merged NUR package set

nur-ryan4yin now points at main after ryan4yin/nur-packages#43 was squash
merged; the lock records the merge commit. No branch ref remains.

Assisted-by: DeepSeek Harness (deepseek-flash)

* fix(dsh): pass the web profile explicitly

The withPlugins launcher prepends --patch, which historically prevented dsh
from auto-expanding "dsh web" into "--profile web". Pass the profile
explicitly in the Just recipe and the verification commands so they work with
both plain dsh and the wrapper.

Assisted-by: DeepSeek Harness (deepseek-flash)

* chore(dsh): pick up the wrapped-profile fix

Update nur-ryan4yin to the squash merge that keeps an implicit profile name
first, so "dsh web" and "just dsh-web" work through the wrapper again.

Assisted-by: DeepSeek Harness (deepseek-flash)

* chore(dsh): pick up the plugin peer-link fix

Update nur-ryan4yin to the squash merge that links the dsh peer tree at
node_modules/@deepseek-ai instead of nesting it one level deeper. This is the
import failure that stopped nushell-executor from activating after deploy.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-18 12:28:18 +08:00
ryan4yin | 二花 4258538588 feat(aquamarine): make the iGPU usable for media and OpenVINO (#474)
* feat(aquamarine): make the iGPU usable for media and OpenVINO

The R9700s stay reserved for inference: VA-API/QSV transcoding moves to the iGPU media
engine, and `openvino-gpu` works around ROCm's OpenCL loader shadowing the plugin's
`ocl-icd` (WA-038).

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-v4.1-flash)

* docs(aquamarine): document OpenVINO on the iGPU

How to run models on the iGPU: the `openvino-gpu` wrapper, the encoder staticization Whisper needs
on `GPU`, compile/steady timings and memory, and the language and cache caveats.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-v4.1-flash)
2026-10-18 11:15:56 +08:00
ryan4yin | 二花 9f092808fd feat(aquamarine): serve Whisper transcription from the NPU (#472)
The goal is speech recognition on the NPU for vinput, and sherpa-onnx cannot
deliver it: every model it loads keeps a dynamic time axis, which the NPU
compiler rejects outright. Qwen3-ASR and SenseVoice both core-dumped in
vpux-compiler ("Got non broadcastable dimensions pair"), and reshaping the ONNX
inputs does not help because the dynamic dimensions sit inside the graph
(WA-037). Whisper is the only family OpenVINO publishes fully static IRs for,
and its fixed 30 s window is exactly what the compiler accepts.

The host now runs an OpenAI-compatible /v1/audio/transcriptions service backed
by whisper-large-v3-turbo int8 on the NPU: 1.5 s for 11 s of audio against
2.1 s on CPU, with the compiled graph cached in /var/cache so only a cold cache
pays the ~60 s NPU compile. vinput on the desktop sends raw PCM to it through a
small provider script.

Only the NPU driver and compiler still come from the unmerged branch in the
`nixpkgs-npu` input (NixOS/nixpkgs#570230), whose nixpkgs also happens to be
the one where openvino-genai 2026.4.0.0 builds at all.

Assisted-by: DeepSeek Harness 0.2.1-rc.2 (deepseek-v4.1-flash)
2026-10-18 08:34:50 +08:00
ryan4yin | 二花 6c083dbf27 feat(yazi): enlarge image previews and add four plugins (#469)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-17 12:05:30 +08:00
ryan4yin | 二花 d6450d48a2 feat(remote-builders): build ai and shoukei on aquamarine (#467)
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)
2026-10-17 00:49:22 +08:00
ryan4yin | 二花 c82cf72862 fix(theme): keep the catppuccin starship port build across gc (#468)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-17 00:31:47 +08:00
ryan4yin | 二花 3d38ff7433 fix(aquamarine): persist the user's cache directory (#466)
On a tmpfs root the flake/fetch cache is empty at every boot, so
`nix run <flake-ref>` re-downloads its input and fails until DNS is up: a reboot
test showed llama-swap's first start failing on that. Other caches write into
RAM meanwhile.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 21:36:00 +08:00
ryan4yin | 二花 afa7a4c72e fix(aquamarine): persist the user's unit directories (#464)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 21:08:41 +08:00
ryan4yin | 二花 a0ff9f7fd7 fix(ssh,ai): keep connections to idle LAN peers fast (#463)
* 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)
2026-10-16 20:07:19 +08:00
ryan4yin | 二花 3266aad4a2 fix(power): drop TuneD for native CPU scaling (#461) 2026-10-16 16:45:08 +08:00
ryan4yin | 二花 643984e1ab fix(power): mask the package's tuned-ppd unit when ppdSupport is off (#460)
The tuned package ships tuned-ppd.service with WantedBy=graphical.target, so
activation starts it without /etc/tuned/ppd.conf and switch-to-configuration exits 4.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 00:50:41 +08:00
ryan4yin | 二花 b4b293ebfa fix(power): pin the tuned profile per host, cap the VM hosts (#458)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 00:42:48 +08:00
ryan4yin | 二花 65f1c8e306 fix(aquamarine): load the power-cap unit's PATH at the service level (#459)
systemd ignores `path` inside [Service], so the unit ran with the default PATH
instead of the coreutils one it asks for.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 00:41:59 +08:00
ryan4yin | 二花 e6deb4b564 feat(shoukei): cap battery charging at 90% (#457)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-16 00:37:06 +08:00
ryan4yin | 二花 bebe5bcf42 feat(ai,aquamarine): expose board fans and temperatures via SuperIO (#456)
* feat(ai): load nct6683 for the board's NCT6687D SuperIO
* feat(aquamarine): load nct6775 for the board's NCT6798D SuperIO

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-15 23:58:23 +08:00
ryan4yin | 二花 32b4605ab6 feat(aquamarine): cap each R9700 power limit at 250 W #453 2026-10-15 23:27:08 +08:00
ryan4yin | 二花 75a88226c9 refactor(ssh): drop the pinned keys from the LAN block (#446)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-15 15:34:48 +08:00
ryan4yin | 二花 e8819de40c feat(vinput): own the config here and read keys from the environment (#445)
* feat(vinput): read provider keys from an EnvironmentFile
* feat(vinput): manage the config from this repository
2026-10-15 13:54:20 +08:00
ryan4yin | 二花 0034b5f131 feat(aquamarine): enable user lingering (#444)
Assisted-by: DeepSeek Harness (gpt-6-sol)
2026-10-15 13:14:17 +08:00
ryan4yin | 二花 ef953d9521 fix(mihomo): disable gateway IPv6 DNS answers (#443)
The gateway LAN IPv6 transparent path stalls on TCP flows while IPv4 forwarding remains healthy. Withholding AAAA answers keeps LAN clients on the working fake-IPv4 TProxy path until the IPv6 path is fixed

Assisted-by: DeepSeek Harness (gpt-6.1-sol)
2026-10-15 00:58:43 +08:00
ryan4yin | 二花 bb89987640 fix(mihomo): use fake-IP for gateway IPv6 (#442) 2026-10-14 23:50:40 +08:00
ryan4yin | 二花 bac43e0e9f refactor(mihomo): drop the redacted gateway template (#438)
--redact produced a "shareable" template but replaced only the secret and the proxy-subscription urls: rule-provider tokens, private domains, the LAN controller address and the routing rules all stayed. Nothing in the repo consumed it.

Assisted-by: DeepSeek Harness (Qwen3.8-Flash-Next-IQ3_S-ista-text)
2026-10-12 12:59:37 +08:00
ryan4yin | 二花 9c38819517 docs: review and correct comments and documentation (#436) 2026-10-12 10:02:38 +08:00
ryan4yin | 二花 f32d67a5cc feat(agents): add review-comments-and-docs and two evaluation suites (#434)
Adds the review-comments-and-docs skill (1282-word body) and two evaluation suites: a 21-case
measured suite for the skill, and a harness that runs the two concurrency scenarios previously left
unrun in agents/evals/global-rules.md.
2026-10-12 00:35:06 +08:00
ryan4yin | 二花 6a19f6b249 fix(desktop): keep named podman images when pruning (#435)
Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-12 00:29:12 +08:00
ryan4yin | 二花 5c5c11d646 docs(idols-ai): record the mixed-memory freeze and current state (#433)
Assisted-by: DeepSeek Harness (gpt-6.1-sol, deepseek-flash)
2026-10-11 20:13:06 +08:00
ryan4yin | 二花 c347bfe6a9 fix(k3s): drop Home Manager from the test workers (#432)
The worker MicroVMs ran `home-manager-ryan.service`, which failed on two of them
(`/nix/var/nix/temproots` permission denied, and no `/home/ryan`), so
`HostSystemdServiceCrashed` fired for days. Mirror the masters and extend their
regression test to all six nodes.

Assisted-by: DeepSeek Harness 0.2.0-rc.2 (deepseek-flash)
2026-10-11 19:48:14 +08:00
ryan4yin | 二花 2f6f2b6926 fix(monitoring): restore youko metrics, alerts and VM-host deploys (#431)
* flake.lock: Update

nixpkgs only. The new revision builds VictoriaMetrics with cgo
(CGO_ENABLED=1); its pure-Go zstd decoder rejected a stored values block, so
every small-part merge panicked on youko.

* fix(colmena): address the VM hosts by name, not by their IP

`~/.ssh/config` pins the passphrase-protected builder key with IdentitiesOnly
for 192.168.*, so IP-addressed ssh cannot authenticate without a terminal. The
name resolves through the aliases in /etc/ssh/ssh_config.

* fix(monitoring): repair two alert rules VictoriaMetrics rejects

`on(uid)` matches on a label kube-state-metrics no longer emits, and
`!= ON(__name__, instance)` treats every pg_settings series as a duplicate.
They now join on (namespace, pod) and compare with `changes(...[5m])`.

* fix(monitoring): keep disk latency alerts off mechanical disks

Both rules averaged per-op latency with no device or sample guard, so the 4 TB
USB HDD volumes paged constantly (>100 ms/write in 26% of the last 30 days).
They now require a non-rotational physical device and >=5 ops/s.

Assisted-by: DeepSeek Harness 0.2.0-rc.2 (deepseek-flash)
2026-10-11 18:16:04 +08:00
ryan4yin | 二花 497fabbf92 test(agents): tighten language rule eval (#430)
Assisted-by: DeepSeek Harness (gpt-6-luna)
2026-10-11 08:32:50 +08:00
ryan4yin | 二花 3e66bbf24f feat(hosts): add WiVRn CLI streaming for Quest 3 #392 2026-10-10 22:49:48 +08:00
ryan4yin | 二花 d5fac81fdc Merge pull request #429 from ryan4yin/agents/delivery-text-caps
feat(agents): rework agent rules, find-docs, and delivery text
2026-10-10 19:52:29 +08:00
ryan4yin | 二花 e2548cd2aa docs(agents): close rule gaps found by evals and record the method (#428)
* docs(agents): state the boundaries the rules only implied
* docs(agents): grow the scenario tables and record the method
* docs(agents): record the evaluation rounds and their size cost
* docs(agents): require disclosure of AI-assisted contributions
* docs(agents): correct safety boundaries and eval records

Assisted-by: DeepSeek Harness (qwen3.8-flash-next iq3, gpt-6-luna & gpt-6.1-sol)
2026-10-10 15:59:57 +08:00
ryan4yin | 二花 9d69832ff7 refactor(agents): pin global skills and trim always-loaded context (#427)
* feat(agents): pin global skills as flake inputs
* refactor(agents): trim always-loaded agent context
2026-10-10 12:16:56 +08:00
ryan4yin | 二花 0d7c4d7cc1 feat(agents): extract global Git delivery skill #426 2026-10-10 11:18:39 +08:00
ryan4yin | 二花 b52e242bb1 Merge pull request #425 from ryan4yin/docs/agents-rule-gaps
fix: close rule gaps behind repeated corrections and sync stale docs and recipes
2026-10-10 08:50:13 +08:00
ryan4yin | 二花 e11375fbb8 feat(mihomo): sync the policy to Clash Verge on macOS (#424) 2026-10-09 23:27:59 +08:00
ryan4yin | 二花 0e12440148 refactor(secrets): move nushell-secrets.nu out of agenix (#423) 2026-10-09 22:40:50 +08:00
ryan4yin | 二花 92740ec968 fix(mihomo): answer AAAA on a public fake-ip pool, pin guests to a cluster ULA (#420)
* fix(microvm): pin guest IPv6 identity to a cluster ULA

The ISP retires delegated prefixes, so a guest that registers its WAN prefix
loses it and Cilium never refreshes the node address. Derive the identity from
the IPv4 octets inside fd05:5::/64 and trust that ULA in the guest firewall.

* feat(mihomo): answer AAAA and keep the tailnet off the TUN

fake-ip needs one pool per family, and the family a client picks does not pick the
egress family. Exclude the cluster ULA and the Tailscale ranges from the TUN; the ssh
pin and the WA-028 record cover the fake-AAAA stall.

* feat(mihomo): generate the config from the repo, not a copy in the live dir

`just mihomo-gen` runs generate.nu from the module and validates with the core
the service runs. ~/.config/mihomo keeps only sources.yaml and config.yaml.

* fix(mihomo): keep the fake IPv6 pool out of fc00::/7

The v6 fake pool is a lookup key, not the egress path, so it can be a public range: the
shipped ULA default reads as "local" to browsers and prompts for local-network access on
every site. The gvisor stack override goes with it -- mips is upstream's default, and
nftables rules out the kernel stack here.

* feat(mihomo): sniff on the gateway, not on the desktop

LAN clients using DoH dial the IPs they resolved, and a node may not reach an IP a
foreign resolver handed out. The gateway recovers the name from the handshake; on the
desktop the fake-ip table already names every flow. Its binary is a static release
build, not a package: update it by hand and validate the live config with the new core.

* fix(mihomo): name the Singapore nodes instead of matching 新

The single-char keyword also matched 新西兰, so the Singapore group held a New
Zealand node and url-test flipped the exit country mid-session.
2026-10-09 18:38:20 +08:00
ryan4yin | 二花 63b7183381 feat(mihomo): keep unproxiable ranges out of TUN, fix the startup DNS race (#419)
* 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.
2026-10-09 12:31:59 +08:00
ryan4yin | 二花 4a27852fd1 fix(tuios): create sessions with cwd before attaching (#418) 2026-10-08 20:50:28 +08:00
ryan4yin | 二花 48ac4f76bf fix(tuios): keep sessions across reboots and split them by purpose (#416) 2026-10-08 20:29:52 +08:00
ryan4yin | 二花 60bd70bd0c refactor(agents): configure dsh from its profile patch (#415) 2026-10-08 15:29:31 +08:00
ryan4yin | 二花 9e2633f496 feat(gaming): generic umu game installer, skill, and desktop entries (#411) 2026-10-08 14:59:11 +08:00
ryan4yin | 二花 efd279c7d1 fix(noctalia): avoid mihomo network speed double count (#414) 2026-10-08 13:31:57 +08:00
ryan4yin | 二花 dc211bbca3 fix(mihomo): restore the Steam community and store PROXY rules (#412)
The comment trim dropped them. Without a domain rule above the Valve IP ranges,
steamcommunity.com and steampowered.com match those ranges and go DIRECT.
2026-10-08 09:50:41 +08:00
ryan4yin | 二花 257e9b13d2 docs: add the NixOS modernization options and decision record (#409) 2026-10-08 09:49:29 +08:00
ryan4yin | 二花 ded8d91507 feat(mihomo): keep Steam downloads off the proxy so Steam keeps a CN CDN (#408)
Steam picks download caches from the IP it sees on the CM login. Pin the CM hosts
and content CDN DIRECT, keep the community and store proxied, and add Valve's
AS32590 ranges because Steam dials cached CM IPs without a lookup. Sources in
README.md.
2026-10-08 09:41:51 +08:00
ryan4yin | 二花 c89c5e9698 fix(mihomo): say what a dropped catch-all actually costs (#410) 2026-10-08 09:40:17 +08:00
ryan4yin | 二花 835b7f6df1 feat(shoukei): pin home Wi-Fi to a static IPv4 & adjust networking.nix (#407) 2026-10-07 21:27:34 +08:00
ryan4yin | 二花 6f136b50e4 fix(shoukei): mitigate brcmfmac wifi auth failures, document duplicate-profile bug (#406)
BCM4378/brcmfmac intermittently fails Wi-Fi association (ASSOC-REJECT /
authentication timeout) on this laptop. NetworkManager misreads the failure
as a bad key and re-prompts; whichever client reconnects (Noctalia, nmtui,
nmcli) then saves the answer as a duplicate "<SSID> 1" profile. The problem
predates the Noctalia v5 shell and is driven by the driver, not the shell.

- disable Wi-Fi powersave on shoukei, a common source of brcmfmac auth timeouts
- WORKAROUNDS.md WA-024: the powersave mitigation and its removal condition
- WORKAROUNDS.md WA-025: the pending upstream brcmfmac port_authorized fix
- document how to recover a wedged supplicant without rebooting, and that
  deleting an active NM profile is what turned a reconnect into a dead link

Refs: https://patchew.org/linux/20260915-brcmfmac-4way-handshake-offload-authenticated-event-v2-1-fbb9cc7ac177@jannau.net/
2026-10-07 19:52:57 +08:00
ryan4yin | 二花 8f065f24bc feat(nix): use Nix 2.35 via nixVersions.latest (#405)
Nix 2.35 brings lazy flake source copying, mimalloc (5-12% faster
evaluation), lower nix-daemon memory use, HTTP/3 support, and jittered
transfer retries with Retry-After.
2026-10-07 18:32:09 +08:00
ryan4yin | 二花 b64adc4c20 docs(security): correct the M3 pod-to-node control #403 2026-10-07 17:58:54 +08:00
ryan4yin | 二花 df6f9b8d6d feat(k3s): disable kube-proxy for Cilium eBPF replacement (#404) 2026-10-07 17:58:33 +08:00
ryan4yin | 二花 2af97e37b9 feat(shoukei): x86 emulation via muvm+FEX, drop pkgs-x64 (#394)
* feat(shoukei): run x86/x86_64 apps and games via muvm+FEX

Apple Silicon's 16K pages mean FEX cannot run natively and qemu-user cannot
run complex x86_64 binaries. Wire the maintained rowanG077/nix-x86-on-aarch64
runtime (FEX inside a 4K muvm microVM) into shoukei so games, Steam, Wine and
other x86/x86_64 programs work, and let the module own the x86 ELF handlers
instead of qemu-user.

The input is pinned to our fork (ryan4yin/nix-x86-on-aarch64) at the reviewed
commit. Dropping boot.binfmt.emulatedSystems also removes x86_64 from
nix.settings.extra-platforms, so the qemu-user/uncached-x86-build gap is
recorded as WA-022.

- flake.nix: add nix-x86-on-aarch64 input (WA-021)
- hosts/12kingdoms-shoukei/game/: programs.x86-on-arm + steam/wine, 6 GiB VM
- hardware-configuration.nix: drop emulatedSystems/preferStaticEmulators
- apple-silicon.nix: drop the now-redundant box64
- docs: WA-012 resolved; WA-021 and WA-022 added; host README updated

* refactor(nixpkgs): drop the repo-wide pkgs-x64 package set

Every remaining pkgs-x64 consumer runs only on x86_64-linux hosts, where the
native pkgs already carries the same allowUnfree config
(modules/nixos/base/nix.nix) and overlays (modules/base/overlays.nix), so
replace the references with pkgs and drop the extra nixpkgs instantiation
(which also removes an eval on aarch64-darwin).

media.nix keeps the native Zoom app on x86_64 hosts only, since zoom-us has
no aarch64 Linux build.
2026-10-07 16:03:59 +08:00
ryan4yin | 二花 f5a111c638 feat(backup): hourly read-only snapshots and per-backup integrity checks (#402)
* feat(restic): verify the repository after each backup

* feat(youko): snapshot the restic store hourly

* docs(backup): document the snapshot and check layers
2026-10-07 15:26:57 +08:00
ryan4yin | 二花 3694961e74 fix(postgres,darwin): close the loopback superuser path and scope agenix ownership (#401)
* fix(postgres): require a password for superuser over TCP

* test: assert the postgres loopback auth rules

* fix(darwin): keep root-only agenix secrets root-only

* docs(security): record the local auth boundaries and retire WA-015
2026-10-07 15:22:03 +08:00
ryan4yin | 二花 3acb5d4ee5 fix(nfs,libvirt): restrict the golden export and bind VNC to loopback (#400)
* fix(nfs): restrict the golden export to its real clients

* fix(libvirt): bind VNC consoles to loopback

* fix(firewall): drop VNC ports on every host

* docs(security): record the NFS and VNC boundaries
2026-10-07 15:10:52 +08:00
ryan4yin | 二花 43f39e8e9f fix(k3s): deny credential-bearing host ports to pod sources (#399)
* fix(k3s): deny credential-bearing host ports to pod sources

* test: assert the k3s pod firewall drops sensitive ports

* docs(security): record the pod firewall boundary
2026-10-07 15:03:56 +08:00
ryan4yin | 二花 b79c5807ae ci: harden workflows and run the runtime firewall VM test (#398)
* ci: pin actions, scope tokens, run the runtime security VM test

* test: add a just recipe for the runtime firewall VM test
2026-10-07 14:57:34 +08:00
ryan4yin | 二花 5f6a1dadf4 docs: fix stale claims and AI-flavored prose (#397) 2026-10-07 14:48:36 +08:00
ryan4yin | 二花 76c4566e9b fix(k8s): pass inputs to the MicroVM guests (#396)
Host builds have been broken since #375 - function called without argument inputs
2026-10-07 13:20:08 +08:00
ryan4yin | 二花 95b849420e feat(gaming): declarative Proton and dGPU game rendering (#393) 2026-10-07 13:14:42 +08:00
ryan4yin | 二花 90bbe8bc4f fix(monitoring): stop recurring false alerts (#395)
The Telegram channel was dominated by alerts that can never be actionable:

- DriveTemperatureHigh/Critical did not filter temperature_type, so
  max(smartctl_device_temperature) picked the drive's rated
  op_limit_max/critical_limit_max instead of the actual reading. ai reported
  95 C and youko 130 C while the drives actually ran at 40-48 C.
- HostPhysicalComponentTooHot excluded label!="tctl", but the AMD k10temp
  hwmon sensor labels itself Tctl, so the CPU control temperature (up to
  ~100 C under load) tripped the alert on every AMD host.
- MicroVM guests share the host's read-only /nix/store, so their
  nix-gc.service always failed and tripped HostSystemdServiceCrashed on all
  six k3s guests. Disable automatic GC in the guest; the host's nix.gc
  reclaims the shared store.

The remaining k3s alert noise comes from workloads running on the masters
that belong on the workers; that is fixed in k8s-gitops, not by resizing
the control-plane VMs.
2026-10-07 12:51:30 +08:00
ryan4yin | 二花 e653ec3306 docs(hosts): add mixed-memory notes for idols-ai (#391)
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
2026-10-06 21:39:23 +08:00
ryan4yin | 二花 dc65254511 fix(ssh): make sandboxed ssh work on Linux (#390) 2026-10-06 15:20:53 +08:00
ryan4yin | 二花 187577b2da docs(agents): fix the dsh private model route recipe (#389)
`dsh-llm-pi-ai` registers its built-in providers once, so a second instance
in the profile patch fails on mount with `provider "..." is already declared`.
Extend the base `llm-pi-ai` row instead.
2026-10-06 14:10:54 +08:00
ryan4yin | 二花 28e0b156ce refactor(agents): link dsh shared policy as a home-layer patch (#388)
dsh rewrites a profile's cordis.patch.yml at runtime, so linking the web
profile put GUI state in the checkout and let runtime writes clobber manual
edits. Link the stable policy as the $DSH_HOME home layer instead: dsh applies
it after every profile and only reads it.

The host-plane compaction-basic row is disabled on the web surface and each
agent preset owns its own copy, so the top-level override was inert. Drop it;
the model contextWindow/maxTokens are the effective knobs.

- add home/base/tui/agents/dsh/cordis.patch.yml, linked from default.nix
- drop the ~/.dsh/profiles/web link and the tracked web/ profile
- keep runtime state and private/local model routes in the profile patch
- update the eval test and README
2026-10-06 14:04:55 +08:00
ryan4yin | 二花 205f7c622b feat(agents): version the dsh web profile and add a proxied launcher #387 2026-10-06 00:54:30 +08:00
ryan4yin | 二花 85c51f5769 feat(rime): share the Rime config and user dictionary across Linux and macOS (#385)
* feat(rime): share the Rime config and user dictionary across Linux and macOS

Move the Rime data, preferences, and user dictionary into home/base/gui/rime so fcitx5-rime and Squirrel read the same files.

* feat(vinput): open the command palette with right Ctrl

Pin keyd's right-hand modifiers (rightcontrol/rightshift/rightmeta) to their own keycodes; keyd otherwise folds them into the left keys. Set Vinput's MenuKey to right Ctrl and clear CommandKeys, which would shadow it.

* feat(fcitx5): switch CN/EN with Ctrl+Space and right Shift

Clear AltTriggerKeys, whose Shift_L default toggled on left Shift. Left Shift is now a plain modifier and right Shift switches through the shared Rime config.
2026-10-05 22:43:20 +08:00
ryan4yin | 二花 0ec5b8032c fix(desktop): align Qt app fonts with GTK (#386)
* fix(desktop): align Qt app fonts with GTK

Qt apps kept their built-in default font ("Sans Serif" 9) while GTK apps use
`gtk-font-name` (Noto Sans 11), so Telegram and other Qt apps rendered
noticeably smaller than GTK apps like Firefox. Set
QT_QPA_PLATFORMTHEME=gtk3; the plugin ships with qtbase, so it needs no
extra package and also gives Qt apps GTK file dialogs.

* chore(desktop): drop unused Xft.dpi from the Wayland GTK profile

Xft.dpi/ *.dpi are X11 X-resource settings. This file is only imported by
the niri (Wayland) hosts, where xwayland-satellite sets its own Xft.dpi
(96 x output scale, currently 144), and the i3 hosts are headless 1080p
computer-use sessions that do not import it. So the setting had no effect
anywhere; remove it instead of keeping a misleading knob.
2026-10-05 20:01:51 +08:00
ryan4yin | 二花 6b8c5bfae4 feat(vinput): drop NPU/OpenVINO support (#384)
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)
2026-10-05 15:42:48 +08:00
ryan4yin | 二花 50a4182898 feat(mihomo): show hostname in metacubexd page title (#383)
metacubexd hardcodes its tab title in the SPA, so dashboards on
different hosts are indistinguishable. Patch the static <title> and
re-apply the hostname from config.js, since Nuxt's useHead resets
document.title on every route change.
2026-10-05 10:05:12 +08:00
ryan4yin | 二花 b8348bf276 fix(mihomo): order the service after its config mount (#382)
The config deliberately stays out of the store, under the home directory, which is a persistent bind mount on tmpfs-root hosts. When the service and the mount are introduced in the same activation, mihomo can start before the mount is up and fail with "Failed to set up credentials: No such file or directory", making the switch report status 4. Add RequiresMountsFor so the mount is brought up and ordered before the service.
2026-10-05 01:08:08 +08:00
ryan4yin | 二花 502d0c85c7 fix(preservation): keep vinput config and models across reboots (#381)
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.
2026-10-05 00:18:01 +08:00
ryan4yin | 二花 8f0961d9c2 fix(desktop): tie ai's link DNS takeover to mihomo's lifecycle (#380)
* 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>
2026-10-05 00:07:32 +08:00
ryan4yin | 二花 bbfe1fa53b feat(desktop): replace Clash Verge with native mihomo on all NixOS hosts (#379) 2026-10-04 21:04:41 +08:00
ryan4yin | 二花 0a672060a4 feat(voice): add NPU voice input on ai (#377)
* feat(vinput): add NPU speech input on ai

* docs(agents): scope nixpkgs review guidance
2026-10-04 19:52:44 +08:00
ryan4yin | 二花 fdafca930b feat(agents): add dsh from nur-packages (#378) 2026-10-04 17:00:17 +08:00
ryan4yin | 二花 44454022a7 Merge pull request #376 from ryan4yin/refactor/rime-data-flypy-to-nur
refactor(fcitx5): ship flypy rime data from NUR
2026-10-04 13:38:40 +08:00
ryan4yin | 二花 cf6c657e4a refactor: consume computer-use packages from NUR (#375)
* refactor: consume computer-use packages from NUR

* fix: expose flake inputs to package overlays

Package overlays are imported from two places with different argument
shapes: outputs/default.nix passes a set containing `inputs`, while
modules/base/overlays.nix passes the NixOS module args, where genSpecialArgs
spreads each flake input as a top-level argument. The new NUR-backed
overlays read `inputs.nur-ryan4yin`, so evaluation failed on the module
path. Also expose the whole flake input set as `inputs` in genSpecialArgs.

* chore: bump nur-ryan4yin input

Update the locked nur-packages revision to the current main (nixpkgs
26.05, unused packages removed).
2026-10-04 13:11:34 +08:00
ryan4yin | 二花 2ee0b9c7eb chore(tui): remove standalone herdr, superseded by tuios (#374) 2026-10-04 11:23:16 +08:00
ryan4yin | 二花 6259359945 security(monitoring): bind exporters to static LAN addresses (#373)
node_exporter listened on 0.0.0.0, so access control rested entirely on
the nftables allowlist. Bind node/smartctl exporters to the host static
LAN IPv4 (the same address VictoriaMetrics scrapes), keeping the socket
off tailscale/bridge interfaces even if the firewall regresses.

Hosts without a static LAN address (shoukei, akane) now run no exporters
at all instead of loopback-bound ones nobody scrapes; akane, a UTM VM,
previously ran a loopback smartctl exporter with no physical disks.

LAN-bound exporters also get the boot-race treatment from #372
(network-online ordering plus patient restart); loopback-bound hosts
must not pull in network-online because NM wait-online would stall
their offline boots.
2026-10-03 19:07:21 +08:00
ryan4yin | 二花 1b31730db4 fix(monitoring): order smartctl exporter after network-online.target (#372)
The exporter binds to the host LAN address, which systemd-networkd
assigns during boot. Without ordering, the service starts before the
address exists, `bind: cannot assign requested address` trips the
start limit, and the unit stays failed until restarted manually.

Order the unit after network-online.target, and since wait-online is
best-effort (120s timeout), also retry patiently so the unit self-heals
when the link comes up late.
2026-10-03 18:54:08 +08:00
ryan4yin | 二花 3a5b9ec4c6 docs: README audit fixes and de-duplication (#371) 2026-10-03 18:28:58 +08:00
ryan4yin | 二花 6a1b4c699a chore(docs): prune stale TODOs (#370) 2026-10-03 17:50:28 +08:00
ryan4yin | 二花 37d79fbb08 chore(hardening): consolidate system hardening and fix stale docs (#368) 2026-10-03 17:11:51 +08:00
ryan4yin | 二花 afdaa3b869 refactor(agents): manage agent config in a home-manager module (#367) 2026-10-03 16:57:38 +08:00
ryan4yin | 二花 f03907c6a4 feat(security): add balanced kernel and exporter baseline (#365) 2026-10-03 16:33:50 +08:00
ryan4yin | 二花 3fdeedaa78 docs(security): document homelab architecture and agent-first audits
Add SECURITY.md covering the threat model, trust boundaries,
proportionate kernel/process hardening, the update/reboot routine and
remaining prioritized work. Record the dated read-only audit findings
(listeners, privileged workloads, effective RBAC, secret metadata and
sandbox/SSH boundaries) separately from planned controls and runtime
verification.

Define agent-first diagnosis: scoped root read-only access on homelab
hosts, and normal-user diagnostics on core desktops with no new sudo
grants. Add canonical domain-based k3s API endpoint regression tests,
record the unverified Darwin secret-ownership concern as WA-015, and
correct comments claiming mode 0000 blocks privileged root.
2026-10-03 16:26:32 +08:00
ryan4yin | 二花 d5fa86dbc7 fix(qemu-guest): let the NixOS test framework override serial-getty@ttyS0 (#362)
test-instrumentation.nix sets serial-getty@ttyS0.enable = false at normal priority to keep ttyS0 free for the test backdoor console, while qemu-guest.nix set it to true at normal priority. Two conflicting normal-priority definitions made `nix flake check` fail while evaluating packages.x86_64-linux.ruby-nixos-tests.

Use lib.mkDefault so the test framework wins in tests while ordinary QEMU guests still enable the serial getty.
2026-10-03 12:18:46 +08:00
ryan4yin | 二花 18925eac8b fix(colmena): expose colmenaHive for the nix-community evaluator (#361)
* fix(colmena): expose colmenaHive for the new evaluator

nixpkgs now ships the nix-community Colmena rewrite, whose default
evaluator reads an evaluated colmenaHive flake output instead of the raw
colmena hive. Without it every colmena apply recipe failed with
"does not provide attribute colmenaHive".

Add a colmena input pinned to the same v0.5.0 as nixpkgs and expose
colmenaHive = colmena.lib.makeHive <raw hive>, with the raw hive kept as
an internal binding rather than a flake output of its own.

* chore: clean up stale colmena and aquamarine references

- point the Colmena links at nix-community/colmena after the move
- rename the security-aquamarine-metrics test to youko-metrics (it
  already tested youko) and update the outputs README
- drop the commented aquamarine remote-builder example
2026-10-03 12:14:13 +08:00