Commit Graph
283 Commits
Author SHA1 Message Date
lyrathorpe 39b2b1d24b Merge pull request 'fix(tmux): stop clip.exe mangling non-ASCII in the WSL clipboard' (#103) from fix/tmux-clipboard-utf8 into main
CI / flake (push) Successful in 5m47s
Reviewed-on: #103
2026-08-24 13:36:15 +01:00
lyrathorpe 0022a152e3 Merge pull request 'fix(edaas): restore passwordless wheel under sudo-rs' (#102) from fix/edaas-passwordless-sudo-rs into main
CI / flake (push) Successful in 7m44s
Reviewed-on: #102
2026-08-24 13:29:39 +01:00
Emma Thorpe d9db12c4a5 fix(tmux): stop clip.exe mangling non-ASCII in the WSL clipboard
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 7m8s
tmux-yank autodetects WSL and pipes the selection to clip.exe, which
decodes its stdin as the console OEM codepage rather than UTF-8. Copying
an em dash out of a pane put "ΓÇö" on the Windows clipboard; the same
applies to every non-ASCII character.

Override the copy command to route through tmux's own buffer. With
set-clipboard on, that emits OSC 52 and the terminal receives UTF-8
directly, with no Windows-side helper in the path. Windows Terminal
honours OSC 52; verified against the running client.

Guarded on /proc/version so only WSL is affected. iTerm2 does not accept
OSC 52 by default, so the Darwin hosts keep pbcopy.

Set in the plugin's extraConfig rather than the shared block because
yank.tmux bakes the copy command into its key bindings at load time, and
home-manager emits plugin extraConfig before the run-shell.
2026-08-24 13:26:21 +01:00
Emma Thorpe 4ac9d1108b docs(shell): record the EDaaS passwordless-wheel exception
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m10s
The sudo-rs section claimed the whole fleet runs the stock "wheel, with a
password" policy, which is no longer true for the WSL host. Explain why the
NixOS-WSL default does not survive the sudo-rs swap, and mark the difference in
the per-host table.
2026-08-24 11:16:15 +01:00
Emma Thorpe 0c151943de fix(edaas): restore passwordless wheel under sudo-rs
NixOS-WSL sets `security.sudo.wheelNeedsPassword = false`, but that option
belongs to the `security.sudo` module and does not carry over to the sudo-rs
swap in modules/common-nixos.nix, whose equivalent option defaults to true.
Since that swap landed, sudo on this host prompts for the account password --
which WSL set during install and nobody knows -- so escalation only worked
through `wsl -u root`.

Set `security.sudo-rs.wheelNeedsPassword = false` on the host to match the
NixOS-WSL default. Other NixOS hosts are unaffected and keep the prompt.
2026-08-24 11:16:12 +01:00
renovate-bot dcb8a5e66a Merge pull request 'chore(deps): lock file maintenance flake inputs' (#101) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 6m6s
2026-08-24 03:10:24 +01:00
Renovate Bot bdb21a6d50 chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 7m14s
2026-08-24 02:02:49 +00:00
renovate-bot 1da34d6232 Merge pull request 'chore(deps): lock file maintenance flake inputs' (#100) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 4m53s
2026-08-24 00:07:42 +01:00
Renovate Bot 19e0b7f13f chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 4m53s
2026-08-23 23:02:35 +00:00
lyrathorpe 1ff333a896 Merge pull request 'fix(docs): pin the site section title so it renders as nixfiles' (#97) from fix/docs-section-title into main
CI / flake (push) Successful in 6m33s
Reviewed-on: #97
2026-08-19 18:24:40 +01:00
Emma Thorpe 9d199bc087 fix(docs): pin the site section title so it renders as nixfiles
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 1m10s
With no entry in the docs-site nav (removed there so awesome-pages can
discover the synced trees), MkDocs derives the section name from the directory
and title-cases it, rendering "Nixfiles". The previous hardcoded nav spelled it
lowercase. Setting title in docs/.pages restores that without reintroducing a
nav entry.

Verified by rebuilding the aggregated site locally with both source trees
synced as the workflow does.
2026-08-19 18:15:48 +01:00
lyrathorpe c7adcccbb3 Merge pull request 'docs: publish the prose documentation to docs.lyrapup.pet' (#96) from docs/publish-to-docs-site into main
CI / flake (push) Successful in 4m9s
Reviewed-on: #96
2026-08-19 17:51:40 +01:00
Emma Thorpe dcc13f94e0 docs: move prose documentation into docs/ so the docs site publishes it
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m21s
The docs-site build syncs this repo's README.md and docs/ into the site
tree; nothing else is copied. All prose apart from the README therefore lived
outside the sync and never appeared on https://docs.lyrapup.pet/nixfiles/, and
the one page that did publish carried 18 link targets that resolved to nothing.

Moves:

  home/README.md           -> docs/shell.md
  home/KEYBINDINGS.md      -> docs/keybindings.md
  hosts/<Name>/README.md   -> docs/hosts/<name>.md

docs/.pages and docs/hosts/.pages give the awesome-pages plugin an explicit
order; new pages are picked up by the trailing '...' without an edit.

Links are rewritten so a single URL is correct in both Gitea and the published
site: absolute Gitea source URLs for .nix files and directories, relative links
between pages under docs/, and absolute docs.lyrapup.pet URLs from the root
README, which the build republishes at a different depth from the rest of the
tree. In-code comments that pointed at a moved README are updated to the new
path.

The README gains a Documentation section covering the sync contract and the
linking rules, and CLAUDE.md carries the short version so future edits do not
reintroduce unsynced pages or dead links.

Verified by reproducing the docs-site assembly locally against its pinned
toolchain (mkdocs 1.6.1, mkdocs-material 9.7.7, awesome-pages 2.10.1): pages
render at the URLs used above and in the declared order.
2026-08-19 17:38:50 +01:00
lyrathorpe d30d8f9892 Merge pull request 'feat(cli): modern replacements for the classic coreutils tools, and sudo-rs' (#95) from feat/modern-cli-replacements into main
CI / flake (push) Successful in 4m4s
Reviewed-on: #95
2026-08-19 17:21:40 +01:00
Emma Thorpe dfafac8de9 feat(security): swap sudo for the memory-safe sudo-rs
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m6s
security.sudo-rs.enable sets security.sudo.enable = false via mkDefault, so
this is a straight swap; the two modules assert against being on together.

The fleet only uses the stock policy -- wheel may run anything, with a password
-- which sudo-rs implements fully. It does not cover host aliases, LDAP/SSSD
sudoers, sudoreplay or most Defaults settings; needing any of those means
reverting to security.sudo. The macOS host is unaffected and keeps Apple's sudo
with Touch ID.

Recovery from a host that will not escalate is documented in the module and in
home/README.md: get a root shell that does not go through sudo, then roll back
the generation.
2026-08-19 17:03:15 +01:00
Emma Thorpe d9464009f0 feat(cli): replace the classic coreutils tools with modern equivalents
Adds Rust/Go replacements for the day-to-day utilities and shadows four of
them with aliases. Only read-only commands are shadowed (cat, du, df, ps), so a
wrong flag costs a retype rather than data; rm, grep, find and sed keep their
originals and the replacements are reached by their own names.

The aliases land in .zshrc, so they apply to interactive zsh only -- scripts,
`sudo <cmd>` and anything exec'd by another program still get the real binary.

New on every host: dust, dysk, procs, trash-cli, doggo, xh, ouch, jnv, hexyl,
fq and tealdeer. dysk is used rather than duf, which is unmaintained upstream.

git gains difftastic behind a `git dft` alias. diff.external is deliberately
left unset so delta remains the renderer for git diff/show and for anything
parsing them.

The work box gains kubecolor, aliased over kubectl; it wraps the real kubectl
and drops colour when stdout is not a terminal, so pipes are unchanged.

home/README.md documents the alias map, the flag incompatibilities (including
the two that fail silently: dust -s is --apparent-size, and procs reads a bare
`aux` as a search keyword) and the rationale for what was left alone.
2026-08-19 17:03:07 +01:00
lyrathorpe d654eac1e2 Merge pull request 'feat(macpro31): NVIDIA P400 with CUDA Docker, and a fleet-wide CPU capability gate' (#94) from feat/macpro31-nvidia-cuda into main
CI / flake (push) Successful in 4m44s
Reviewed-on: #94
2026-08-17 20:59:21 +01:00
Emma Thorpe d4e7475db9 fix(macpro31): load the NVIDIA modules and guard the CDI generator
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m12s
The CDI generator aborted with "failed to initialize NVML: Driver Not
Loaded", taking docker.service with it (requiredBy) and failing the
switch.

Two causes. The nixpkgs NVIDIA module only adds nvidia/nvidia_modeset/
nvidia_drm to boot.kernelModules when services.xserver.enable is set,
which is false on this Wayland-only host, so load them explicitly.
nvidia_uvm stays out: the module's modprobe softdep loads it once the GPU
device exists.

The generator also runs during activation, when a module rebuilt against a
new kernel cannot be loaded until reboot -- a guaranteed failure after
every kernel bump. Guard it with ConditionPathExists on
/proc/driver/nvidia/version so it skips rather than fails; the toolkit's
udev rule restarts it when the device appears, so the specs are generated
on the next boot.
2026-08-17 20:47:33 +01:00
Emma Thorpe 0f7fb7f78a feat(macpro31): NVIDIA Quadro P400 driver and CUDA-enabled Docker
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m11s
The stock GPU has been replaced with a Quadro P400 (Pascal, GP108). Add
hosts/MacPro31/nvidia.nix:

- Driver branch 580 (nvidiaPackages.legacy_580), not the nixpkgs default
  production branch (595.x). 580 is the last branch supporting
  Maxwell/Pascal/Volta and is an LTS branch until Aug 2028; a newer one
  does not drive this card.
- modesetting.enable for Wayland (nvidia-drm.modeset=1), open = false
  (the open kernel modules need Turing or later), and sway
  --unsupported-gpu, which wlroots requires with the proprietary driver.
- Docker with GPU access via CDI (hardware.nvidia-container-toolkit),
  rather than the deprecated virtualisation.docker.enableNvidia runtime
  wrapper. Containers run with --device=nvidia.com/gpu=all and must ship
  a CUDA 12.x or older runtime: CUDA 13 dropped sm_61.

The driver packages are unfree, so allowlist them in unfreePackages; they
are not cached and the kernel module builds on the host.

Also declare features.cpu.microarchLevel = 1 for this machine: the
Harpertown Xeons have SSE4.1 but no SSE4.2/POPCNT, which switches off
Claude Code through the fleet-wide gate.
2026-08-17 20:35:39 +01:00
Emma Thorpe 0d13581896 feat(features): gate Claude Code on the host CPU microarchitecture level
Claude Code runs on Node, whose V8 build requires SSE4.2 and POPCNT
(x86-64-v2). On an older x86_64 CPU it does not run, so it must not be
installed there in the first place.

Nix cannot detect the CPU (pure evaluation, hosts often built elsewhere),
so add features.cpu.microarchLevel: the psABI level a host declares about
itself, defaulting to 2. features.claudeCode.enable derives from it, and
home/claude.nix reads that through home-manager's osConfig and installs
nothing -- CLI, CLAUDE.md, output style or memory symlink -- when it is
off. Hosts without the option (Darwin, the standalone homeConfigurations)
keep the tool enabled.

An assertion fails evaluation if a host force-enables the flag below the
required level, so the mistake surfaces in nix flake check rather than as
an illegal-instruction crash on the machine.
2026-08-17 20:35:29 +01:00
renovate-bot 526e6a08e2 Merge pull request 'chore(deps): lock file maintenance flake inputs' (#93) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 3m58s
2026-08-17 01:07:10 +01:00
Renovate Bot 9e749cce2b chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 4m28s
2026-08-17 00:02:26 +00:00
renovate-bot 1766fb7b3f Merge pull request 'chore(deps): lock file maintenance flake inputs' (#92) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 7m14s
2026-08-17 00:14:19 +01:00
Renovate Bot dba73e1199 chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 9m17s
2026-08-16 23:04:32 +00:00
renovate-bot e9835372cd Merge pull request 'chore(deps): update gitea actions to 13d8dd5' (#91) from renovate/gitea-actions into main
CI / flake (push) Successful in 3m58s
2026-08-13 16:05:40 +01:00
Renovate Bot bd613ef07f chore(deps): update gitea actions to 13d8dd5
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 4m13s
2026-08-13 15:01:13 +00:00
lyrathorpe c5b41ba6fd Merge pull request 'feat(claude): WSP local build memory, and structural terseness rules for the Soviet Engineer style' (#90) from feat/claude-wsp-build-memory-and-terseness into main
CI / flake (push) Successful in 4m23s
Reviewed-on: #90
2026-08-13 13:59:37 +01:00
Emma Thorpe 7041dfebfa fix(claude): make the Soviet Engineer style enforce terseness structurally
CI / flake (pull_request) Successful in 1m16s
CI / flake (push) Skipped
The style asked for terseness in tonal terms only, so a dry register wrapped in
headers, tables and a full status recap each turn passed its self-check while
being exactly the verbose output the style exists to prevent.

Add explicit limits: a default length ceiling, headers only for four or more
items, report the delta rather than the accumulated state, and state a caveat
once. Replace the self-check with one that tests length and form rather than
tone.
2026-08-13 13:23:58 +01:00
Emma Thorpe 4d6ad47837 docs(claude): record how to build and test core-services-cloud locally
The repo documents its own build and test commands, but assumes Windows and
PowerShell. This captures only the deltas that make them run on this machine:
dotnet from nixpkgs, artifactory credentials sourced per command because shell
state does not persist between tool calls, and a curl check that distinguishes
an auth failure from a code failure, since a rejected token surfaces as a
NuGet error that reads like a network fault.

Also records the two Docker Desktop leftovers that break the component test
environment, and the unleash registration a component test canary needs.
2026-08-13 13:23:58 +01:00
lyrathorpe f471d226e0 Merge pull request 'feat(work): headless Secret Service for gcx keychain tokens' (#89) from feat/gcx-secret-service into main
CI / flake (push) Successful in 3m58s
Reviewed-on: #89
2026-08-11 15:09:26 +01:00
Emma ThorpeandClaude Opus 5 10f713103c feat(work): headless Secret Service for gcx keychain tokens
CI / flake (pull_request) Successful in 3m57s
CI / flake (push) Skipped
gcx stores its OAuth access and refresh tokens in the system keychain
unconditionally -- its config file keeps only opaque `keychain:gcx:v2:...`
handles -- and exposes no plaintext fallback. With nothing owning
org.freedesktop.secrets on this headless WSL box, `gcx login` authenticates
against Grafana and then dies writing its config: "The name is not activatable".

Add services.headlessSecretService: gnome-keyring as a systemd --user service,
unlocking the login keyring at start. home-manager's own services.gnome-keyring
does not fit here on two counts -- it is WantedBy graphical-session-pre.target,
which never activates without a desktop session, and it passes no --unlock, so
writes would block on a GUI prompter that does not exist.

Only the secrets component is started. The ssh component is deliberately off: it
would claim SSH_AUTH_SOCK and displace services.ssh-agent, breaking SSH auth and
signed commits.

The unlock password defaults to a random one generated on first activation under
$XDG_DATA_HOME. The passwordFile option is the seam for supplying it from an
agenix secret instead, once that lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 15:03:18 +01:00
lyrathorpe cc6cb24c78 Merge pull request 'feat(work): install gcx on the work profile' (#88) from feat/gcx-work-profile into main
CI / flake (push) Successful in 3m58s
Reviewed-on: #88
2026-08-11 14:30:25 +01:00
Emma Thorpe 240facdbbb feat(work): install gcx on the work profile
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 3m57s
gcx is the Grafana Cloud CLI (dashboards, datasources, SLOs, synthetic
monitoring, alerts), used against the Citrix Grafana stack.

Pull it from nixpkgs-unstable via the existing overlay rather than the pinned
channel: 26.05 ships 0.2.14, which predates the stacks/contexts configuration
model and the agento11y commands, so the current tooling and docs do not apply
to it.
2026-08-11 14:24:52 +01:00
renovate-bot c1456decaf Merge pull request 'chore(deps): lock file maintenance flake inputs' (#87) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 4m22s
2026-08-10 00:07:11 +01:00
Renovate Bot e06495ae69 chore(deps): lock file maintenance flake inputs
CI / flake (pull_request) Successful in 5m7s
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
2026-08-09 23:01:49 +00:00
lyrathorpe 6868182ef5 Merge pull request 'feat(darwin): install mole' (#86) from feat/mole-macos into main
CI / flake (push) Successful in 4m19s
Reviewed-on: #86
2026-08-07 11:40:58 +01:00
lyrathorpe 90a57ab73b feat(darwin): install mole
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m24s
useful to clean up caches
2026-08-07 11:35:06 +01:00
lyrathorpe 75f4e22624 Merge pull request 'feat: add darktable to all systems' (#85) from feat/darktable-install into main
CI / flake (push) Successful in 4m8s
Reviewed-on: #85
2026-08-07 11:16:17 +01:00
lyrathorpe cf96fec63e feat: add darktable to all systems
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 3m54s
so i can edit photos wherever i have a gui
2026-08-07 11:11:55 +01:00
lyrathorpe 3cdf4d4e54 Merge pull request 'chore(claude): require ticket-scoped conventional commits on every commit' (#84) from chore/claude-memory-commit-conventions into main
CI / flake (push) Successful in 4m35s
Reviewed-on: #84
2026-08-06 16:57:27 +01:00
Emma Thorpe f61a206977 style(claude): apply prettier formatting to the git conventions memory
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 1m6s
treefmt runs prettier over markdown in this repository and the CI
formatting check failed on the two preceding commits. Prettier prefers
underscores for emphasis and requires blank lines around fenced code
blocks.

No wording changes.
2026-08-06 16:54:16 +01:00
Emma Thorpe 1d5a5adbcc chore(claude): exempt repos without an issue tracker from the ticket scope
CI / flake (push) Skipped
CI / flake (pull_request) Failing after 1m8s
The previous commit required a ticket scope on every commit in every
repository. This repository has no Jira project, so the rule as written
would either block a commit or invite a fabricated WSP number.

Record the exception: in personal repositories the scope is the area of
the change (claude, deps, hosts) and conventional form still applies.
The ticket requirement is scoped to the Jira-backed work repositories
that enforce it in CI.
2026-08-06 15:20:53 +01:00
Emma Thorpe 4029866ed4 chore(claude): require ticket-scoped conventional commits on every commit
The git conventions memory said to match the repository's existing log
style. Several repositories (multicluster, core-services-cloud) have
histories dominated by bare "WSP-1234: summary" subjects, so matching
them produced commits that were not in conventional form. A related
failure was scope decay within a session: the first commit was correct
and later ones degraded to bare "test:" or "refactor:" subjects. Both
required commit history to be rebased by hand.

- Make "<type>(<TICKET-ID>): <summary>" mandatory on every commit and
  explicitly override repository log style. Style matching now applies
  to branch names only.
- Describe how to establish the real ticket ID (named in the request,
  extracted from the branch, or taken from existing commits on the
  branch) and require asking rather than guessing when none is
  available. Replace the literal WSP-1234 examples with <TICKET-ID> so
  the placeholder cannot be committed verbatim.
- Record scope decay across a session as a named failure mode.
- Cover merge commits, preferring rebase and requiring an explicit
  message when a merge commit is unavoidable.
- Add a pre-push verification grep that must return no output.
- Note that a clean git log does not prove a subject was correct when
  written, because rebasing replaces it; compare author and committer
  dates instead.

Update the MEMORY.md index entry to match.
2026-08-06 15:20:16 +01:00
renovate-bot 66b27517ba Merge pull request 'chore(deps): lock file maintenance flake inputs' (#83) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 5m13s
2026-08-03 00:08:39 +01:00
Renovate Bot 6b43e76457 chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 5m50s
2026-08-02 23:02:21 +00:00
renovate-bot cbf2fdac42 Merge pull request 'chore(deps): lock file maintenance flake inputs' (#82) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 4m2s
2026-07-27 05:05:54 +01:00
Renovate Bot 1fdd048eed chore(deps): lock file maintenance flake inputs
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m8s
2026-07-27 04:01:34 +00:00
renovate-bot 9b72a81d43 Merge pull request 'chore(deps): lock file maintenance flake inputs' (#81) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 5m1s
2026-07-27 04:06:30 +01:00
Renovate Bot 2f0302d66e chore(deps): lock file maintenance flake inputs
CI / flake (push) Skipped
renovate/stability-days Updates have not met minimum release age requirement
CI / flake (pull_request) Successful in 4m36s
2026-07-27 03:01:35 +00:00
renovate-bot 256a9a9745 Merge pull request 'chore(deps): lock file maintenance flake inputs' (#80) from renovate/lock-file-maintenance-flake-inputs into main
CI / flake (push) Successful in 6m50s
2026-07-27 01:10:14 +01:00