diff --git a/README.org b/README.org index d1a419ff..45212850 100644 --- a/README.org +++ b/README.org @@ -148,8 +148,7 @@ The currently important pieces are: under [[file:dotfiles/config/][dotfiles/config/]]. The intended tiling-WM behavior is documented in -[[file:docs/tiling-wm-experience.md][docs/tiling-wm-experience.md]], and the River/XMonad exploration is documented in -[[file:docs/riverwm-evaluation.md][docs/riverwm-evaluation.md]]. +[[file:docs/tiling-wm-experience.md][docs/tiling-wm-experience.md]]. * Emacs And Org @@ -211,7 +210,7 @@ active development. Those are machine-local working state and are ignored. * CI And Caches [[file:.github/workflows/cachix.yml][.github/workflows/cachix.yml]] can build the =strixi-minaj= NixOS closure and -push paths to Cachix. [[file:docs/cachix.md][docs/cachix.md]] documents the cache setup. +push paths to Cachix. The top-level [[file:justfile][justfile]] contains helper commands for populating the =colonelpanic8-dotfiles= Cachix cache from a local machine. diff --git a/docs/cachix.md b/docs/cachix.md deleted file mode 100644 index 756bd7dc..00000000 --- a/docs/cachix.md +++ /dev/null @@ -1,37 +0,0 @@ -# Cachix for this repo - -This repo's NixOS flake lives under `nixos/`. - -The workflow in `.github/workflows/cachix.yml` can build the `strixi-minaj` -system closure on GitHub Actions and push the results to a Cachix cache. - -## One-time setup - -1. Create a Cachix cache (on cachix.org). -2. Create a Cachix auth token with write access to that cache. -3. In the GitHub repo settings: - - Add a repo variable `CACHIX_CACHE_NAME` (the cache name). - - Add a repo secret `CACHIX_AUTH_TOKEN` (the write token). - -After that, pushes to `master` will populate the cache. - -## Using the cache locally - -Option A: ad-hoc (non-declarative) - -```sh -cachix use -``` - -Option B: declarative via flake `nixConfig` (recommended for NixOS) - -1. Get the cache public key from the Cachix UI: - -- Open `https://app.cachix.org/cache/#pull` -- Copy the `Public Key` value shown there. - -2. Add it to `nixos/flake.nix` under `nixConfig.extra-substituters` and - `nixConfig.extra-trusted-public-keys`. - -Note: `nixos/nix.nix` sets `nix.settings.accept-flake-config = true`, so the -flake `nixConfig` is honored during rebuilds. diff --git a/docs/plans/2026-01-28-org-agenda-api-consolidation-design.md b/docs/plans/2026-01-28-org-agenda-api-consolidation-design.md deleted file mode 100644 index 3b7cd022..00000000 --- a/docs/plans/2026-01-28-org-agenda-api-consolidation-design.md +++ /dev/null @@ -1,152 +0,0 @@ -# Org-Agenda-API Consolidation Design - -## Overview - -Consolidate org-agenda-api container builds and fly.io deployment into the dotfiles repository. This eliminates the separate `colonelpanic-org-agenda-api` repo and provides: - -- Container outputs available to NixOS machines directly -- Fly.io deployment from the same repo -- Fewer repos to maintain -- Cachix integration for faster builds - -## Directory Structure - -``` -/home/imalison/dotfiles/ -├── nixos/ -│ ├── flake.nix # Main flake, adds container output -│ ├── org-agenda-api.nix # Existing tangling module (stays here) -│ └── ... -├── org-agenda-api/ -│ ├── container.nix # Container build logic (mkContainer, etc.) -│ ├── configs/ -│ │ ├── colonelpanic/ -│ │ │ ├── custom-config.el -│ │ │ └── overrides.el (optional) -│ │ └── kat/ -│ │ └── custom-config.el -│ ├── fly/ -│ │ ├── fly.toml -│ │ ├── deploy.sh -│ │ └── config-{instance}.env -│ └── secrets/ -│ ├── secrets.nix # agenix declarations -│ └── *.age # encrypted secrets -└── dotfiles/emacs.d/ - └── org-config.org # Source of truth for org config -``` - -## Flake Integration - -The main dotfiles flake at `/home/imalison/dotfiles/nixos/flake.nix` exposes container outputs: - -```nix -outputs = inputs @ { self, nixpkgs, flake-utils, ... }: - { - nixosConfigurations = { ... }; # existing - } // flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { inherit system; }; - containerLib = import ../org-agenda-api/container.nix { - inherit pkgs system; - tangledConfig = (import ./org-agenda-api.nix { - inherit pkgs system; - inputs = inputs; - }).org-agenda-custom-config; - }; - in { - packages = { - container-colonelpanic = containerLib.mkInstanceContainer "colonelpanic"; - container-kat = containerLib.mkInstanceContainer "kat"; - }; - } - ); -``` - -Build with: `nix build .#container-colonelpanic` - -## Custom Elisp & Tangling - -Single source of truth: `org-config.org` tangles to elisp files loaded by containers. - -**What stays in custom-config.el (container-specific glue):** -- Path overrides (`/data/org` instead of `~/org`) -- Stubs for unavailable packages (`org-bullets-mode` no-op) -- Customize-to-setq format conversion -- Template conversion for org-agenda-api format -- Instance-specific settings - -**Audit:** During implementation, verify no actual org logic is duplicated in custom-config.el. - -## Cachix Integration - -### Phase 1: Use upstream cache as substituter - -Add to dotfiles flake's `nixConfig`: - -```nix -nixConfig = { - extra-substituters = [ - "https://org-agenda-api.cachix.org" - ]; - extra-trusted-public-keys = [ - "org-agenda-api.cachix.org-1:PUBLIC_KEY_HERE" - ]; -}; -``` - -Benefits: -- `container-base` (~500MB+ dependencies) fetched from cache -- Rebuilds only process the small custom config layer - -### Phase 2 (future): Push custom builds - -Set up GitHub Action or local push for colonelpanic-specific container builds. - -## Fly.io Deployment - -**What moves:** -- `fly.toml` → `dotfiles/org-agenda-api/fly/fly.toml` -- `deploy.sh` → `dotfiles/org-agenda-api/fly/deploy.sh` -- `configs/*/config.env` → `dotfiles/org-agenda-api/fly/config-{instance}.env` -- Agenix secrets → `dotfiles/org-agenda-api/secrets/` - -**Deploy script changes:** -- Build path: `nix build "../nixos#container-${INSTANCE}"` -- Secrets path adjusts to new location -- Otherwise same logic - -## Implementation Phases - -### Phase 1: Pull latest & verify current state -- Pull latest changes in org-agenda-api and colonelpanic-org-agenda-api -- Build container, verify it works -- Fix any issues before restructuring - -### Phase 2: Create dotfiles structure -- Create `/home/imalison/dotfiles/org-agenda-api/` directory -- Move container.nix logic (adapted from current colonelpanic-org-agenda-api flake) -- Move instance configs (colonelpanic/, kat/) -- Move fly.io deployment files -- Move agenix secrets - -### Phase 3: Integrate with dotfiles flake -- Update `/home/imalison/dotfiles/nixos/flake.nix` to expose container outputs -- Add cachix substituter configuration -- Test build from dotfiles: `nix build .#container-colonelpanic` - -### Phase 4: Verify deployment -- Test deploy.sh from new location -- Verify fly.io deployment works -- Run the container locally on a NixOS machine - -### Phase 5: Audit & cleanup -- Review custom-config.el for any duplicated org logic -- Archive colonelpanic-org-agenda-api repo -- Update any references/documentation - -## Repos Affected - -- **dotfiles** - Receives container build + fly.io deployment -- **colonelpanic-org-agenda-api** - Becomes obsolete after migration -- **org-agenda-api** (upstream) - No changes, used as flake input diff --git a/docs/riverwm-evaluation.md b/docs/riverwm-evaluation.md deleted file mode 100644 index 9399259a..00000000 --- a/docs/riverwm-evaluation.md +++ /dev/null @@ -1,472 +0,0 @@ -# River Window Manager Evaluation - -This evaluates window managers for the current River split-compositor model, -where River delegates policy to a client implementing -`river-window-management-v1`. - -It is intentionally separate from `docs/tiling-wm-experience.md`: that document -describes the target experience, while this document evaluates current River -implementation options against it. - -## Short Recommendation - -The best current candidates are: - -1. `kwm` if the goal is the most usable latest-protocol experiment quickly. -2. `orilla` if the goal is the closest long-term match to an XMonad-like, - code-driven, extensible environment. -3. `rhine` if Hyprland-like IPC and directional commands are more important - than layout maturity. - -No current candidate appears to satisfy the full target experience out of the -box. The largest gaps are equal-width vertical columns, XMonad-like directional -window control, scratchpad/minimize semantics, and taffybar-compatible state. - -## Current River Model - -River is now a non-monolithic Wayland compositor. It does not combine the -compositor and window manager into one process; a separate window manager -implements `river-window-management-v1`. - -Older River layout generators, such as `rivertile`, `river-filtile`, and -`wideriver`, are useful historical context but are not the primary path if the -goal is to use the latest River architecture. - -## Candidate Ranking - -### 1. kwm - -Repository: - -Fit: best practical starting point. - -Reasons to consider it: - -- Zig. -- Most popular candidate found. -- Very active as of late April 2026. -- Implements `river-window-management-v1`. -- Dynamic tiling with `tile`, `grid`, `monocle`, `deck`, `scroller`, and - floating layouts. -- Has tags, shift-tags, regex window rules, modes, runtime configuration reload, - and several window states. -- Uses a runtime `config.zon` file with partial overrides and live reload; it is - DWM-like, but ordinary configuration is not patch-based. - -Risks: - -- It is DWM-like, not XMonad-like. -- Default bindings are mostly next/previous rather than geometric WASD - directional focus and movement. -- The closest built-in layout to equal columns is probably `grid`, but this - needs empirical testing. -- It has its own status bar model; taffybar integration is not solved. - -Use this first if the goal is to get a working River session and discover -practical gaps quickly. - -### 2. orilla - -Repository: - -Fit: best philosophical match. - -Reasons to consider it: - -- Rust. -- Explicitly inspired by XMonad. -- Code-first configuration model. -- Dynamic tiling with composable layouts. -- Has tag actions for switching, shifting, previous tag, next/previous tag, - next empty tag, and shift-to-empty tag. -- Has a fullscreen/monocle-like layout. - -Risks: - -- Early project. -- Low adoption compared with `kwm`. -- Built-in layouts do not appear to include the exact equal-width vertical - columns layout. -- Current exposed actions are ordered focus/swap actions, not geometric - directional navigation. -- The implementation stores window rectangles, so directional navigation looks - patchable, but it is not available today. -- Current layout application appears early in its multi-output support; layout - calculation uses the first output rather than a mature per-output model. -- Output movement, scratchpads, minimization, and taffybar state would likely - require extension work. - -Use this first if the goal is to build toward the exact target experience rather -than maximize out-of-the-box coverage. - -### 3. rhine - -Repository: - -Fit: interesting integration candidate. - -Reasons to consider it: - -- Zig. -- Active as of late April 2026. -- Modular design. -- Has directional commands such as `moveFocus ` and `moveWindow `. -- Has workspace commands including send-to-workspace and move-to-workspace. -- Provides partial Hyprland IPC compatibility, which may be useful for tooling - and taffybar experiments. - -Risks: - -- Only a BSP-style layout appears to be implemented currently. -- Special workspaces and some monitor/workspace behavior are still TODO-level. -- Less popular than `kwm`. -- Equal vertical columns and tabbed/monocle behavior are not obvious fits. - -Use this for a small spike if the Hyprland IPC bridge looks like the shortest -path to taffybar state. - -### 4. beansprout - -Repository: - -Fit: viable but less aligned. - -Reasons to consider it: - -- Zig. -- Active as of late April 2026. -- DWM-style dynamic tiling. -- KDL configuration. - -Risks: - -- Primary/stack model conflicts with equal-width columns. -- Per-output tags conflict with the target shared global workspace model. -- Less popular than `kwm`. - -### 5. rill - -Repository: - -Fit: low. - -Reasons to consider it: - -- Zig. -- Active. -- More popular than several smaller candidates. - -Risks: - -- It is a scrolling window manager, which does not match the target layout - model. - -### 6. notion-river - -Repository: - -Fit: low despite good tab support. - -Reasons to consider it: - -- Rust. -- Has persistent frames and tabbed windows. -- Has IPC and cross-monitor focus/move behavior. - -Risks: - -- It is explicitly static tiling, not dynamic tiling. -- Persistent frames conflict with the target equal dynamic columns behavior. -- Workspaces are assigned per output. - -### 7. rivulet - -Repository: - -Fit: watchlist only. - -Reasons to consider it: - -- Haskell. -- Configured in a Haskell DSL. -- Conceptually closest to the desire for an XMonad-like programmable WM. - -Risks: - -- The README currently says not to use it and that it is not usable as a window - manager yet. -- Many core behaviors are still unfinished. - -### Historical Option: wideriver - -Repository: - -Fit: not a latest-protocol candidate. - -Reasons it is still worth knowing about: - -- Inspired by DWM and XMonad. -- Has layouts closer to classic dynamic tiling expectations. -- More established than several current-protocol candidates. - -Reason not to choose it now: - -- It belongs to the older layout-generator model, not the latest River - `river-window-management-v1` window-manager model. - -## Requirement Fit - -### Dynamic Tiling - -Best candidates: `kwm`, `orilla`, `beansprout`. - -`kwm` has the broadest ready-made layout set. `orilla` is the better extension -target if writing a custom layout is acceptable. - -### Equal Vertical Columns - -No candidate clearly satisfies this out of the box. - -Likely approaches: - -- Test `kwm` grid layout first. -- Implement an `EqualColumns` layout in `orilla`. -- Avoid primary/stack defaults unless they can be configured into equal columns. - -### Monocle or Fullscreen-Like Layout - -Best candidates: `kwm`, `orilla`, `notion-river`. - -`kwm` has monocle. `orilla` has a fullscreen/monocle-like layout. `notion-river` -has strong tabbed behavior but fails the dynamic-layout requirement. - -### Directional Navigation and Window Movement - -Best candidate: `rhine`. - -`rhine` exposes directional focus and movement commands. `kwm` and `orilla` -appear to need either custom action work or careful testing to determine whether -geometric WASD behavior can be made exact. - -### Workspace Movement - -Best candidates: `orilla`, `kwm`, `rhine`. - -`orilla` has explicit tag actions for last tag, next/previous tag, next empty -tag, and shift-to-empty. `kwm` has tags and shift-tags. `rhine` has explicit -send-to-workspace and move-to-workspace commands. - -### Scratchpads and Minimization - -No candidate clearly solves this in the target form. - -Likely implementation requires reserved hidden/special state in the window -manager, not just shell scripts. River's protocol has hide/show primitives, so a -native WM implementation has enough substrate, but each candidate needs review or -extension. - -### Overview and Discovery - -No candidate clearly provides a Hyprexpo-like overview. - -Practical first implementation is probably a rofi/launcher workflow built from -window state. `lswt` may be useful as a compositor-neutral Wayland toplevel -source, but accurate workspace positioning is likely WM-specific. - -### Taffybar State - -Best candidate to investigate: `rhine`. - -The partial Hyprland IPC compatibility is the only candidate feature that looks -directly relevant to existing Hyprland-oriented tooling. Otherwise, taffybar -will need a River/current-WM backend or a normalization daemon. - -Required state includes: - -- workspaces/tags -- focused output -- active workspace per output -- workspace history per output -- windows per workspace -- app-id/class, title, active state, urgency if available -- minimized and scratchpad filtering -- approximate window position - -## Proposed Prototype Plan - -1. Package or run `kwm` and `orilla` locally without making either a default - login session. -2. Start with `kwm` to measure out-of-the-box usability: tags, previous tag, - grid, monocle, send-to-tag, shift-to-empty, and output movement. -3. In parallel or immediately after, sketch an `orilla` configuration with an - `EqualColumns` layout and the workspace actions needed by the spec. -4. Do a small `rhine` spike only for Hyprland IPC and taffybar feasibility. -5. Choose between `kwm` and `orilla` after testing layout fidelity and state - export. - -Expected decision: - -- Choose `kwm` if it gets close enough with configuration and light scripting. -- Choose `orilla` if exact XMonad-like behavior matters enough to write Rust. -- Do not choose `rivulet` until it becomes usable. -- Do not choose `notion-river` unless the dynamic-layout requirement changes. - -## Orilla Deep Dive - -Commit checked: `bd77afb`, "adds support for finding next empty tag". - -### What Orilla Already Has - -- Rust code-first configuration. -- A small action model for keybindings. -- Dynamic layout abstraction through the `Layout` trait. -- Built-in `Tall` and `Full` layouts. -- Per-tag layout selection hooks. -- Tags with switch, toggle, shift, last, next, previous, next empty, and - shift-to-empty actions. -- Window tracking for internal IDs, app-id, title, geometry, focus, tags, - hidden state, and closed state. -- River hide/show calls for non-visible windows. -- A simple JSON IPC stream over a Unix socket containing tags, focused tag, - windows, app-id/title, focused window state, and current layout. -- Passing test suite at the checked commit. - -### Directional Navigation - -Orilla does not currently provide geometric directional navigation. - -Existing window actions are: - -- close focused window -- focus primary -- focus next -- focus previous -- promote focused window -- swap next -- swap previous - -This means `Super+WASD` cannot be mapped directly to "focus the closest window -in that direction" today. - -The good news is that Orilla stores enough geometry to implement it. Each window -has `x`, `y`, `width`, and `height`, and layout application updates those fields. -A plausible patch would add: - -- `Direction::{Up, Down, Left, Right}` -- `WindowAction::FocusDirection(Direction)` -- `WindowAction::SwapDirection(Direction)` -- geometry helpers on `WindowState` -- keybinding constructors such as `action::focus_direction(Direction::Left)` - -The selection heuristic should match XMonad-style behavior: compare candidate -window rectangles against the focused window rectangle, filter to the requested -direction, prefer overlapping windows on the perpendicular axis, then minimize -distance. - -### Equal Columns Layout - -Orilla does not currently include the desired equal-width vertical columns -layout. - -This is straightforward to implement as a new `Layout`: divide the output width -by the number of visible windows, give each visible window full output height, -and distribute remainder pixels across the first columns. - -This is likely easier in Orilla than in most alternatives because layouts are -plain Rust implementations of a small trait. - -### Fullscreen and Monocle - -Orilla has a `Full` layout. It places every visible window at the full output -rectangle and sorts the focused window last so it renders on top. - -This covers monocle-style behavior, but it is not tabbed. Tab UI would need a -separate layer-shell surface, IPC consumer, or native extension. - -Directional focus could still work in `Full` if implemented against window order -as a fallback when all rectangles overlap. - -### Workspaces and Tags - -Orilla's tag model is useful for the target workspace behavior: - -- switch to specific tag -- move focused window to specific tag -- toggle visible tag -- last tagset -- next/previous tag -- next empty tag -- move focused window to next empty tag - -Gaps: - -- "move window to workspace and follow" is not a first-class action, but can be - added by combining shift and switch semantics. -- Last workspace is global to the tag manager, not per monitor. -- There is no monitor-specific workspace history yet. - -### Monitors and Outputs - -This is the largest architectural gap after directional navigation. - -Orilla tracks River outputs, but windows do not currently carry an output -assignment. Layout application uses the first output from the output map and -lays out the global visible window set there. That is enough for early/single -monitor use, but not enough for the target multi-monitor experience. - -To meet the spec, Orilla likely needs: - -- active output tracking -- window-to-output assignment -- per-output visible tag/history model, or a shared tag model with explicit - output occupancy -- layout calculation per output -- focus-output and send-window-to-output actions -- useful focus behavior after moving a window between outputs - -### Scratchpads and Minimization - -Orilla has the basic substrate but not the feature. - -The substrate: - -- windows have tags -- windows have hidden state -- the WM can call River hide/show -- app-id/title are tracked - -Missing: - -- named scratchpad rules -- delayed title/app-id matching policy -- restore behavior -- minimized-window list/order -- keybinding actions for hide/restore -- IPC fields distinguishing normal, scratchpad, and minimized windows - -### Taffybar State - -Orilla's existing IPC is promising but too small. - -Current IPC exports tags, focused tag, current layout, and each tag's windows -with app-id/title/focused. It does not yet export output identity, active output, -window geometry, hidden/minimized/scratchpad classification, urgency, or -per-monitor history. - -This is still a better starting point than having no state export, because it is -already JSON over a Unix socket and sits inside the WM where the necessary state -should live. - -### Bottom Line - -Orilla has the right shape if we are willing to write WM code. It does not have -the exact daily-driver behavior today. - -The likely minimum patch set before serious use is: - -1. Equal-columns layout. -2. Geometric directional focus and swap. -3. Move-focused-window-to-tag-and-follow. -4. Multi-output model. -5. IPC expansion for taffybar and window menus. -6. Scratchpad/minimize state.