refactor: ponytail audit
This commit is contained in:
1 parent
de8b59ec16
commit
f080ebe36e
57 files changed
+418
-1989
No files matched your search
+91
-476
@@ -2,499 +2,114 @@
|
|||||||
|
|
||||||
Source: [`../workflow-discovery.md`](../workflow-discovery.md)
|
Source: [`../workflow-discovery.md`](../workflow-discovery.md)
|
||||||
|
|
||||||
Apply the global and repository-local `AGENTS.md` files and the ponytail skill
|
The declarative workflow implementation is complete. This file is the living
|
||||||
at full intensity throughout. Preserve user work, prefer native capabilities,
|
handoff for operational constraints and external gates; implementation history
|
||||||
and add no abstraction without a demonstrated repeated need.
|
is available in Git.
|
||||||
|
|
||||||
## Non-negotiable activation boundary
|
## Activation boundary
|
||||||
|
|
||||||
Only the user may switch or activate configurations. The agent must never run
|
Only the user may switch or activate configurations. Agents must not run
|
||||||
`nixos-rebuild switch`, a Home Manager activation or switch command, or any
|
`nixos-rebuild switch`, Home Manager activation, or an equivalent command that
|
||||||
equivalent operation that changes the active generation. Building and
|
changes the active generation. Evaluation and builds are allowed; after a
|
||||||
evaluating configurations is allowed; after a successful build, give the user
|
successful build, provide the exact activation command and wait for the user.
|
||||||
the exact activation command and wait for confirmation.
|
|
||||||
|
|
||||||
On 2026-09-05 the agent violated this boundary by directly running a built Home
|
This boundary includes changes described as user-level, harmless, temporary, or
|
||||||
Manager activation package. It restarted the Kitty service and closed the
|
necessary for live verification. A direct Home Manager activation previously
|
||||||
user's terminal session. Do not repeat this, including for changes described as
|
restarted Kitty and closed the user's terminal session.
|
||||||
user-level, harmless, temporary, or needed only for live verification.
|
|
||||||
|
|
||||||
## Execution discipline
|
## Execution discipline
|
||||||
|
|
||||||
Advance every safe independent lane before asking the user to act. Batch
|
- Advance all safe independent work before asking the user to act.
|
||||||
declarative changes behind one user-controlled activation and consolidate
|
- Batch declarative changes behind user-controlled activation.
|
||||||
empirical, credential, hardware, and approval gates into one checklist only
|
- Consolidate empirical, credential, hardware, and approval gates only after no
|
||||||
after no autonomous work remains. A single pilot reaching its user gate does
|
autonomous work remains.
|
||||||
not make it the global next step while another pilot can still progress.
|
- Keep repositories and worktrees outside `~/sync`; synchronize authored
|
||||||
|
artifacts instead.
|
||||||
Never place repositories or worktrees under `~/sync`; synchronize authored
|
- Keep GitHub and other repository remotes strictly read-only.
|
||||||
artifacts instead. The folder's sole ignore pattern is the local `.zk` state.
|
|
||||||
|
|
||||||
## Current checkpoint
|
## Current checkpoint
|
||||||
|
|
||||||
- Tranche: autonomous consolidation across repositories, tools, and pilots
|
- State: declarative implementation and autonomous verification complete.
|
||||||
- State: autonomous implementation exhausted; remaining gates are external or
|
- Branch: `chore/workflow-system`.
|
||||||
explicitly deferred
|
- Validation: `nix flake check --no-build --quiet` plus no-link Zenith and Orion
|
||||||
- Branch: `chore/workflow-system`
|
system builds passed on 2026-09-06 after Orion became the sole transcription
|
||||||
- Baseline: `nix flake check --no-build --quiet` and no-link Zenith and Orion
|
owner. The expected dirty-tree and unknown `modules` warnings were emitted.
|
||||||
system builds passed on 2026-09-06 after making Orion the sole transcription
|
- Live state: Walker project and terminal actions, daily notes, stable web apps,
|
||||||
owner; only the expected dirty-tree and unknown `modules` warnings were
|
Evolution D-Bus activation, the Zenith VPN, invocation-scoped GitHub and
|
||||||
emitted. The generated project menu finds 30 live repositories
|
Context7 credentials, Pinta, and Orion transcription passed their completed
|
||||||
without `.archive` or `.worktrees` entries, and the generated daily-note
|
pilots.
|
||||||
configuration passes an isolated same-day idempotence test. The managed Actual
|
|
||||||
and WhatsApp entries are active in the current user session, Evolution's
|
|
||||||
source registry activates over D-Bus, and the VPN reconnects successfully.
|
|
||||||
The user activated the terminal root fix: `xdg-terminal-exec` now selects
|
|
||||||
Kitty correctly and Yazi
|
|
||||||
launches from Walker. After restarting the stale Elephant and Walker
|
|
||||||
processes, repository launch also succeeds and exiting Neovim leaves a shell
|
|
||||||
in the repository. The daily-note launcher and migrated notebook contents
|
|
||||||
also pass their live sanity check. The attempted Elephant menu restart trigger
|
|
||||||
stopped its dependent Walker during activation without bringing Walker back,
|
|
||||||
so it has been removed in favor of applying rare menu changes at login. After
|
|
||||||
activating that removal and relogging, Walker opens normally and repository
|
|
||||||
selection starts Neovim in Oil at the project root. Five fresh local clones
|
|
||||||
pass their flake checks, expose their tracked command catalogs, and remain
|
|
||||||
clean after shell entry. The dashboard contract additionally passes its full
|
|
||||||
check and a bounded two-process development smoke test. The dashboard and
|
|
||||||
traceability PostgreSQL stacks also ran concurrently while both repositories'
|
|
||||||
checks passed; all test processes and containers were then stopped. The
|
|
||||||
retired workstation tools are absent and `rclone` is live. Herdr preserves
|
|
||||||
its pane across detach and reattach. The data-science contract and a real
|
|
||||||
read-only PR review pilot pass locally. The broad GitHub credentials are gone;
|
|
||||||
a mode-0600 fine-grained token now passes repository, issue, pull-request,
|
|
||||||
Actions, and organization Project reads with no stored fallback credential.
|
|
||||||
The user activated its loader and confirmed a new shell can list organization
|
|
||||||
Projects; the skill directory and durable remote boundary are also live. The
|
|
||||||
activated read-only wrapper leaves `GH_TOKEN` out of cached dev shells while
|
|
||||||
`gh` identifies the work account and Git reads a private Cargo dependency;
|
|
||||||
the complete yookr-api contract passes. The replacement Context7 key is
|
|
||||||
mode 0600, the exposed key is revoked, and a live resolve-and-query round trip
|
|
||||||
passes through the activated runtime header helper. Pinta passed its real-edit
|
|
||||||
trial, and Outlook's installed PWA exposed stable app ID
|
|
||||||
`eoficlgicibekocmfdomjbfnjmehnhcd`; after activation, GIMP is absent and the
|
|
||||||
managed Outlook launcher is the live store-backed entry. A stopped
|
|
||||||
10.28-second Fossify M4A
|
|
||||||
transferred intact into `sync/recordings`, establishing its actual format and
|
|
||||||
path. The user selected Fossify's native `recordings/inbox` destination, and
|
|
||||||
the event-driven Orion CPU pipeline passes both an isolated transcription and
|
|
||||||
a live remote run of that recording without exposing its contents. Orion
|
|
||||||
waited for the full settlement interval, archived the byte-identical original,
|
|
||||||
published the expected fallback Markdown, and exited successfully. The user
|
|
||||||
confirmed its bilingual output, and a guarded rerun with the copied pyannote
|
|
||||||
model replaced that fallback with a successfully diarized transcript. A pathological
|
|
||||||
synchronized repository tree was removed from the Pixel. Repositories are now
|
|
||||||
explicitly outside the Syncthing boundary instead of relying on an expanding
|
|
||||||
generated-directory ignore list.
|
|
||||||
- Final audit: the complete branch diff passes `git diff --check`; removed
|
|
||||||
Helix, Foot, Zed, and stable-Nixpkgs owners have no remaining Nix references,
|
|
||||||
and the lockfile cleanup contains no replacement inputs. The current desktop,
|
|
||||||
Walker, Niri, host, and transcription owners were reviewed in full without
|
|
||||||
finding another autonomous correction to make.
|
|
||||||
- Next: continue independent external pilots as their real inputs arrive. No
|
|
||||||
configuration activation is pending.
|
|
||||||
|
|
||||||
## Progress
|
## External or deferred gates
|
||||||
|
|
||||||
| Batch | State | Evidence or blocker |
|
These gates do not block work on each other.
|
||||||
| --- | --- | --- |
|
|
||||||
| Bootstrap and repository ownership | Complete | Repository reconciliation, local plaintext credential cleanup, and Context7 rotation pass |
|
|
||||||
| Declarative workstation foundation | Complete | All-host builds pass with one Nixpkgs pin, `just`, and an explicit Podman Compose provider |
|
|
||||||
| Repository contracts and workbench | Waiting externally | Five clean-checkout contracts, the full yookr-api check, and read-only Kubernetes pass; API user credentials, database, report, and S3 inputs remain externally gated |
|
|
||||||
| Desktop navigation and interaction | Waiting externally | Walker project and terminal actions plus stable Actual, WhatsApp, and Outlook launchers work; the two-output check awaits a docked session |
|
|
||||||
| Agent workflow | Waiting externally | Herdr, read-only PR review, the corrected skill owner, durable remote boundary, invocation-scoped credentials, and organization Projects pass; a real Monday ticket remains external |
|
|
||||||
| Notes | Complete | The daily launcher and migrated notebook pass live checks; the approved rollback copy is recoverable from Trash |
|
|
||||||
| PIM | Deferred | Evolution 3.60.2 with Microsoft 365 support remains available beside Thunderbird; the user deferred account setup and uses Thunderbird plus Outlook meanwhile |
|
|
||||||
| Transcription | Complete | Real Fossify transfer, settlement, bilingual CPU transcription, diarization, fallback, archive, and synchronization pass on Orion; Zenith has no transcription owner |
|
|
||||||
| Conditional retirement and completion | Active | Superseded tools and GIMP are absent and Pinta passed; Bruno, DBeaver, and PIM clients remain behind separate gates |
|
|
||||||
|
|
||||||
## Repository checkpoints
|
- During a docked Zenith session, capture the external display's stable identity
|
||||||
|
and test the two-output `Super+A` exchange. The current recorded session exposed
|
||||||
| Repository | Branch | Commit | Purpose |
|
only `eDP-1`.
|
||||||
| --- | --- | --- | --- |
|
- Resume Evolution only when the user chooses to configure the personal,
|
||||||
| NixOS configuration | `chore/workflow-system` | `41bc61b` | Discovery, paths, Git identity, and Codex defaults |
|
old-personal, university, work, and Radicale accounts. Keep Thunderbird and
|
||||||
| NixOS configuration | `chore/workflow-system` | `69552b7` | Simplify flake inputs and declare workstation lifecycle tools |
|
Outlook until the daily-use gate passes.
|
||||||
| NixOS configuration | `chore/workflow-system` | `0c121a6` | Declare Garden tooling and the local workbench |
|
- On Android, complete the DAVx5/Radicale and Tasks.org pilots, including default
|
||||||
| NixOS configuration | `chore/workflow-system` | `2fb6061` | Package Garden completion declaratively |
|
accounts, recurrence, reminders, and Microsoft To Do within documented limits.
|
||||||
| NixOS configuration | `chore/workflow-system` | `ad01b9b` | Enable NetworkManager's native OpenVPN plugin |
|
- Supply one real Yookr S3 task, a least-privileged remote, and explicit permission
|
||||||
| NixOS configuration | `chore/workflow-system` | `c9ee688` | Advance VPN, desktop, agent, note, and PIM pilots |
|
for any upload. `rclone` is installed; no remote or wrapper is preconfigured.
|
||||||
| NixOS configuration | `chore/workflow-system` | `cfa5d6d` | Correct PWA ownership and Evolution service activation |
|
- Deploy a GET image exposing `/full-api-docs/openapi.json`, then rerun
|
||||||
| NixOS configuration | `chore/workflow-system` | `c2f48df` | Restore terminal-backed Walker actions |
|
`just openapi-refresh test`.
|
||||||
| NixOS configuration | `chore/workflow-system` | `6631889` | Open Walker projects at their repository root |
|
- Provide current API user credentials before the planned login and harmless
|
||||||
| NixOS configuration | `chore/workflow-system` | `ca65328` | Remove the unsafe Elephant restart trigger |
|
administrator read. The recovered legacy service credentials returned 401 and
|
||||||
| NixOS configuration | `chore/workflow-system` | `d085512` | Advance from Walker to the agent pilot |
|
were not repurposed.
|
||||||
| NixOS configuration | `chore/workflow-system` | `ee64a7b` | Retire superseded tools and prepare the S3 pilot |
|
- Add workbench database connections and a Marimo-to-HTML report only when a real
|
||||||
| NixOS configuration | `chore/workflow-system` | `2ef74d4` | Expose the NixOS skill as a supported directory link |
|
cross-system investigation gives them durable value.
|
||||||
| NixOS configuration | `chore/workflow-system` | `1996411` | Load the machine-local read-only GitHub credential |
|
- Keep Bruno, DBeaver, and PIM clients until their separate pilots decide them.
|
||||||
| NixOS configuration | `chore/workflow-system` | `422a1ea` | Scope GitHub and Context7 credentials to their callers |
|
- Wait for a real Monday ticket before adding anything beyond native GitHub,
|
||||||
| NixOS configuration | `chore/workflow-system` | `ec54ddd` | Own Outlook's stable launcher and select Pinta over GIMP |
|
Herdr, Git, and worktree workflows.
|
||||||
| NixOS configuration | `chore/workflow-system` | `656f144` | Prepare event-driven CPU transcription on Orion |
|
|
||||||
| NixOS configuration | `chore/workflow-system` | `01c8855` | Make Orion the sole transcription owner after its live pass |
|
|
||||||
| NixOS configuration | `chore/workflow-system` | `76e9d03` | Declare ADB for the Android sync recovery |
|
|
||||||
| NixOS configuration | `chore/workflow-system` | `fa17d77` | Exclude generated devenv state from Syncthing |
|
|
||||||
| NixOS configuration | `chore/workflow-system` | `b38fb9e` | Keep repository trees outside the Syncthing boundary |
|
|
||||||
| NixOS configuration | `chore/workflow-system` | `5fa85c5` | Complete the bilingual and diarized transcription pilot |
|
|
||||||
| `yookr-dashboard-new` | `feat/gogv2` | `934605d` | Remove obsolete dashboard converter |
|
|
||||||
| `yookr-dashboard-new` | `feat/gogv2` | `8e6e4bc` | Establish its project contract and native lifecycle |
|
|
||||||
| `yookr-dashboard-new` | `feat/gogv2` | `c99f8b6` | Move runtime configuration to its machine-local owner |
|
|
||||||
| `rules-service` | `chore/workflow-contract` | `555d9cd` | Establish the first common repository contract |
|
|
||||||
| `yookr-api` | `chore/workflow-contract` | `a76b2b7` | Establish the HTTP and OpenAPI contract |
|
|
||||||
| `traceability-data-model` | `chore/workflow-contract` | `33cb7ff` | Establish the database and schema contract |
|
|
||||||
| `traceability-data-model` | `chore/workflow-contract` | `774e710` | Remove Mathesar and simplify the local stack to PostgreSQL |
|
|
||||||
| `yookr-data-science` | `chore/workflow-contract` | `fa410e1` | Establish its non-mutating project contract |
|
|
||||||
| `yookr-workbench` | `main` | `badc61c` | Create the workbench and isolate its Garden session |
|
|
||||||
|
|
||||||
## Deferred or externally blocked actions
|
|
||||||
|
|
||||||
None of these block work on independent pilots. Surface the exact applicable
|
|
||||||
step to the user only when it blocks the current task.
|
|
||||||
|
|
||||||
- During a docked Zenith session, tell the agent the external display is
|
|
||||||
attached so its stable identity and the two-output `Super+A` pilot can be
|
|
||||||
completed. The current session exposes only `eDP-1`.
|
|
||||||
- When the user resumes the deferred Evolution pilot, add accounts without removing any
|
|
||||||
existing client or changing authority: personal and old-personal through
|
|
||||||
their existing IMAP/SMTP service, university and work through the
|
|
||||||
`Microsoft 365` account type, and Radicale through native CalDAV, CardDAV,
|
|
||||||
and VTODO. Complete tenant consent/sign-in when prompted, then tell the agent
|
|
||||||
which accounts connected; the full mail/calendar/contact/task gate remains
|
|
||||||
a daily-use pilot rather than a one-time setup claim.
|
|
||||||
- On Android, complete the DAVx5/Radicale and Tasks.org pilots described in the
|
|
||||||
discovery plan, including correct default accounts, recurrence, reminders,
|
|
||||||
and Microsoft To Do within its documented limits.
|
|
||||||
- Supply one real Yookr S3 task plus a least-privileged remote and authorize one
|
|
||||||
bounded upload. `rclone` is prepared, but no remote or wrapper is guessed.
|
|
||||||
- Deploy a GET image that exposes `/full-api-docs/openapi.json`, then rerun
|
|
||||||
`just openapi-refresh test`; the current test deployment returns 404.
|
|
||||||
- Provide current API user credentials for the ignored private HTTP environment,
|
|
||||||
then perform the planned login and harmless administrator read. The recovered
|
|
||||||
legacy service UUID/password returned 401 from production and was not copied
|
|
||||||
into the user-login schema.
|
|
||||||
|
|
||||||
## Deferred Polaris replication
|
## Deferred Polaris replication
|
||||||
|
|
||||||
Do not access or test Polaris during this implementation. Treat a Zenith pass
|
Do not access or test Polaris unless the user resumes this deferred replication.
|
||||||
as representative, but retain these machine-local steps for later execution on
|
Zenith's result remains representative meanwhile.
|
||||||
Polaris:
|
|
||||||
|
|
||||||
1. Activate this NixOS configuration so `networkmanager-openvpn` is installed.
|
1. Activate this NixOS configuration so `networkmanager-openvpn` is installed.
|
||||||
2. Run `chmod 600 ~/sync/yookr-vpn.ovpn`.
|
2. Restrict `~/sync/yookr-vpn.ovpn` to mode 0600.
|
||||||
3. Run `nmcli connection import type openvpn file ~/sync/yookr-vpn.ovpn`.
|
3. Import it with `nmcli connection import type openvpn file ~/sync/yookr-vpn.ovpn`.
|
||||||
4. Rename the imported `yookr-vpn` connection to `Yookr VPN`, disable
|
4. Rename the connection to `Yookr VPN`, disable autoconnect, and add
|
||||||
autoconnect, and add the required legacy cipher:
|
`data-ciphers=AES-256-CBC`.
|
||||||
`nmcli connection modify yookr-vpn connection.id "Yookr VPN" connection.autoconnect no +vpn.data data-ciphers=AES-256-CBC`.
|
|
||||||
5. Connect with `nmcli connection up "Yookr VPN"`.
|
5. Connect with `nmcli connection up "Yookr VPN"`.
|
||||||
6. Create `~/.config/yookr/github-read-only.token` without a trailing newline,
|
6. Create mode-0600 `~/.config/yookr/github-read-only.token` without a trailing
|
||||||
containing the fine-grained `yookrdev` token, and set its mode to 0600. Open
|
newline, then verify a new shell can run
|
||||||
a new Zsh after activation and verify `gh project list --owner yookrdev`.
|
`gh project list --owner yookrdev`.
|
||||||
7. Create `~/.config/context7/api-key` without a trailing newline, containing a
|
7. Create mode-0600 `~/.config/context7/api-key` without a trailing newline,
|
||||||
current Context7 key, and set its mode to 0600. Restart Codex after activation
|
restart Codex after activation, and run one Context7 lookup.
|
||||||
and run one Context7 documentation lookup.
|
|
||||||
|
|
||||||
## Decisions and discoveries
|
## Durable implementation decisions
|
||||||
|
|
||||||
- Use `/home/kiri/work/repos/yookr-dashboard-new` as the reconciliation base;
|
- Active work repositories live under `~/dev/work`, archives under `.archive`,
|
||||||
its `feat/gogv2` head is 17 commits newer than the sync copy and matches its
|
and worktrees under `.worktrees`. Repository trees never enter Syncthing.
|
||||||
remote-tracking branch.
|
- Participating repositories expose non-mutating direnv shells, minimal flake
|
||||||
- The user confirmed the legacy BSON migration is no longer needed and the
|
checks, native commands through `just`, concise `AGENTS.md`, and machine-local
|
||||||
former work copy is authoritative. The sync copy was explicitly deleted;
|
credential inputs.
|
||||||
its removal may propagate through Syncthing.
|
- `yookr-workbench` starts with cross-system work only; isolation and additional
|
||||||
- Active repositories now live under `/home/kiri/dev/work`; inactive material
|
tools wait for observed needs.
|
||||||
is preserved intact under `.archive`, and the registered dashboard sensor
|
- Walker's native Elephant menu scans repository roots and calls one Nix-owned
|
||||||
worktree is under `.worktrees`.
|
`open-project` command. Rare menu changes take effect at login.
|
||||||
- Removed the obsolete dashboard converter app and Python dependency. The
|
- Kitty and Neovim are the sole declared terminal and editor. Retired duplicate
|
||||||
dashboard flake evaluates, while the pre-existing feature work remains
|
applications and global language runtimes stay absent unless a concrete owner
|
||||||
uncommitted and unstaged.
|
appears.
|
||||||
- Pruned the absent `feat/echarts-domain` worktree metadata; its branch and
|
- The fine-grained GitHub token and Context7 key stay in mode-0600 machine-local
|
||||||
commit remain. The registered sensor worktree is valid at its new path.
|
files and are exposed only to their callers. Secrets do not enter Nix or broad
|
||||||
- Shared Codex defaults and MCP endpoints are generated at
|
process environments.
|
||||||
`/etc/codex/config.toml`. Context7's credential is supplied at connection time
|
- `sync/notes` is the single notebook owner. Daily notes, meetings, and raw
|
||||||
by Codex's native HTTP-header helper reading `~/.config/context7/api-key`; no
|
transcripts have separate paths, and agents do not create issues or ingest
|
||||||
secret enters Nix or the process-wide environment. The unused generic
|
transcripts automatically.
|
||||||
`~/.config/mcp/mcp.json` is absent.
|
- Orion is the sole transcription owner. It waits for file settlement, validates
|
||||||
- Removed redundant legacy-path trust entries from the current Codex config;
|
media, archives originals, and publishes an unlabeled transcript when
|
||||||
the existing trusted home scope covers the moved repositories.
|
diarization fails.
|
||||||
- Bruno's transitional OpenAPI reference now follows the archived management
|
- Evolution remains a deferred presentation-layer pilot. Microsoft 365 and
|
||||||
repository until the HTTP pilot retires or retains Bruno.
|
Radicale remain the data authorities; Thunderbird and Outlook remain available.
|
||||||
- Post-move repository IDs, remotes, dirty counts, and the registered sensor
|
- GitHub and every other repository remote stay read-only. Local files, commits,
|
||||||
worktree match the pre-move inventory. The Nix flake still evaluates.
|
fetches, clones, and worktrees remain available.
|
||||||
- No-link system builds for Zenith, Polaris, and Orion pass with the migrated
|
|
||||||
paths and declarative Codex defaults.
|
## Next step
|
||||||
- Removed the unused stable Nixpkgs input and made Noctalia follow the root
|
|
||||||
package-set pin. Added `just` to the workstation tools and selected the
|
Continue an external pilot only when its real input arrives. Otherwise no workflow
|
||||||
store-backed `podman-compose` provider through native `containers.conf`.
|
implementation action remains.
|
||||||
- The resulting flake check and no-link builds for all three hosts pass.
|
|
||||||
- The verified-empty legacy directories `~/work/.data/mongodb`, `~/work/.data`,
|
|
||||||
and `~/work/repos` are removed. The stale `~/.config/codex` tree was moved to
|
|
||||||
desktop Trash after explicit approval; the active `~/.codex` tree is intact.
|
|
||||||
- `Sync/uni/algorithms` remained on the Pixel after its Zenith and Orion copies
|
|
||||||
were deleted. Android Files and MTP crashed, while recursive ADB operations
|
|
||||||
appeared to hang because `.devenv/state/venv` contained at least one thousand
|
|
||||||
generated files and deeply nested package data behind Android's FUSE layer;
|
|
||||||
no malformed top-level entry or filesystem failure was found. With the
|
|
||||||
Syncthing-Fork folder paused and explicit approval, ADB atomically renamed and
|
|
||||||
then permanently deleted only that exact tree. The live and temporary paths
|
|
||||||
are absent. A later Files hang was isolated to the remaining stale `Sync`
|
|
||||||
tree, which included a repository with a very large `node_modules`; that
|
|
||||||
1.7 GiB quarantined tree was permanently removed with explicit approval, and
|
|
||||||
both its visible and hidden paths are absent. The durable rule is that
|
|
||||||
repositories and worktrees never enter `~/sync`; the
|
|
||||||
shared folder therefore keeps only its intentional `**/.zk` ignore.
|
|
||||||
- `rules-service` now has a non-mutating direnv shell, minimal Nix toolchain and
|
|
||||||
formatting check, native Cargo recipes, factual repository instructions,
|
|
||||||
one `.http` request collection, explicit test/live deployment paths, and a
|
|
||||||
corrected test-oriented environment example. The full locked Cargo check
|
|
||||||
passes; Clippy reports 18 pre-existing advisory warnings.
|
|
||||||
- Private Cargo Git dependencies remain at their upstream HTTPS URLs and use
|
|
||||||
Git's existing `gh auth git-credential` integration. They are not vendored or
|
|
||||||
rewritten.
|
|
||||||
- `yookr-api` now owns its reviewed OpenAPI 3.1 contract, local/test/live HTTP
|
|
||||||
metadata, curated login/health/admin-read requests, a non-mutating shell, and
|
|
||||||
one explicit snapshot-and-diff recipe. `oasdiff` 1.31.0 is pinned with source
|
|
||||||
and vendor hashes because Nixpkgs does not provide it.
|
|
||||||
- The API flake evaluation, complete locked Rust test suite, and OpenAPI
|
|
||||||
validation pass. The fine-grained token reads the exact locked
|
|
||||||
`constant-store` commit and two other private Yookr crates through the
|
|
||||||
invocation-scoped `gh` credential helper; no dependency URL changed. The
|
|
||||||
validator retains two pre-existing informational example findings. The test
|
|
||||||
service is reachable, but its currently deployed GET image returns 404 for
|
|
||||||
the full OpenAPI route already present in local source and ingress
|
|
||||||
configuration.
|
|
||||||
- `traceability-data-model` preserves the existing domain/schema redesign while
|
|
||||||
replacing automatic schema recreation with explicit `just reset`. Ordinary
|
|
||||||
`just dev` retains its Compose volumes, and the flake check loads fixtures in
|
|
||||||
text-ID mode plus a fresh schema in UUID-ID mode. Both the built check and the
|
|
||||||
pinned `podman-compose` configuration validation pass.
|
|
||||||
- Mathesar is removed from `traceability-data-model`; the development stack now
|
|
||||||
owns only PostgreSQL plus the explicit schema-reset job. The active named
|
|
||||||
volume and its historical local role are preserved to avoid stranding data;
|
|
||||||
the obsolete `mathesar_django` database and orphaned secrets volume were
|
|
||||||
explicitly approved and deleted. `just reset`, `just dev`, the PostGIS
|
|
||||||
fixture query, Compose validation, and the flake check pass.
|
|
||||||
- `yookr-dashboard-new` now has the same minimal project contract: a
|
|
||||||
non-mutating flake shell, `just dev` over its existing Process Compose graph,
|
|
||||||
`just check`, factual `AGENTS.md` and README guidance, a flake formatter and
|
|
||||||
formatting check, and a complete public environment example. Its full type,
|
|
||||||
lint, and format checks pass; a bounded smoke test reached ready MongoDB and
|
|
||||||
Vite processes and stopped cleanly. The commit contains only contract files;
|
|
||||||
the user's existing dashboard source work remains unstaged and untouched.
|
|
||||||
- The active ignored `rules-service/.env` is moved unchanged to
|
|
||||||
`~/.config/yookr/rules-service.env`; its existing `.envrc` now loads that
|
|
||||||
file successfully. The dashboard environment is likewise moved unchanged to
|
|
||||||
`~/.config/yookr/yookr-dashboard-new.env`, and its `.envrc`, instructions,
|
|
||||||
and README now name that owner. Both files are mode 0600, both shells expose
|
|
||||||
their expected variables without recreating repository `.env` files, and the
|
|
||||||
dashboard commit contains only those three contract files. The unrelated
|
|
||||||
dashboard source work remains unstaged.
|
|
||||||
- The unreferenced `/home/kiri/work/SECRETS` file overlapped an older
|
|
||||||
rules-service environment but contained different credentials, so it was not
|
|
||||||
merged or discarded. It is preserved byte-for-byte as the mode-0600
|
|
||||||
`~/.config/yookr/rules-service-legacy.env`; the original path is absent. Its
|
|
||||||
production Yookr service UUID/password returned 401 from `/serviceLogin`; no
|
|
||||||
token was retained and the credentials were not repurposed as a user login.
|
|
||||||
- Fresh local clones of `rules-service`, `yookr-api`,
|
|
||||||
`traceability-data-model`, `yookr-dashboard-new`, and `yookr-data-science`
|
|
||||||
pass their flake and project checks, expose their tracked `just` catalogs,
|
|
||||||
and remain clean after shell entry. Credential-bearing and externally blocked
|
|
||||||
checks remain separate gates.
|
|
||||||
- `yookr-data-science` now has a non-mutating shell and explicit `just setup`,
|
|
||||||
`check`, `run`, and `fetch-live` boundaries. Locked local checks and the
|
|
||||||
archived notebook use repository-relative paths; live Yookr access remains
|
|
||||||
explicit and was not invoked. Stale path-bound caches were replaced through
|
|
||||||
the explicit setup command, local credentials are mode 0600, and a fresh
|
|
||||||
clone passes the full contract without shell-created files.
|
|
||||||
- Gardenctl 2.14.0 and Gardenlogin 0.10.0 are pinned from their official release
|
|
||||||
assets; the hashes match the existing binaries byte-for-byte. All three host
|
|
||||||
builds pass, the OIDC kubectl plugin is declarative, and Zsh consumes the
|
|
||||||
native `gardenctl rc zsh` output with its completion packaged declaratively.
|
|
||||||
- The local-only `yookr-workbench` has no remote and initially owns only
|
|
||||||
`just k8s test`. Each invocation creates an isolated Garden session, rejects
|
|
||||||
every environment except test, and opens K9s read-only. Its flake check and
|
|
||||||
command catalog pass, and the live rejection path exits before Garden access.
|
|
||||||
- The user activated and rebooted into the Garden tooling, then confirmed that
|
|
||||||
`just k8s test` opens the test shoot in read-only K9s. The initial shell error
|
|
||||||
came from Garden writing completion into an absent Flatpak `$fpath` entry; the
|
|
||||||
initial target warning came from the fresh session inheriting its parent's
|
|
||||||
`KUBECONFIG`. Completion is now store-owned, and the child recipe initializes
|
|
||||||
Garden's session-local `KUBECONFIG` before targeting instead of unsetting it.
|
|
||||||
The former mutable Garden binaries and generic MCP output are already absent,
|
|
||||||
so their stale cleanup gate is closed without further user work.
|
|
||||||
- NetworkManager's native OpenVPN plugin is declared on Zenith and Polaris;
|
|
||||||
no profile is embedded in Nix or imported automatically.
|
|
||||||
- Zenith's initial NetworkManager activation never established a tunnel:
|
|
||||||
OpenVPN 2.6 preserved the profile's legacy `cipher=AES-256-CBC` setting but
|
|
||||||
excluded it from cipher negotiation. Adding `data-ciphers=AES-256-CBC` to
|
|
||||||
the imported connection fixes the negotiation; NetworkManager then installs
|
|
||||||
the pushed tunnel address, default route, private routes, and DNS servers.
|
|
||||||
Company database access, disconnect/reconnect, suspend, and reboot pass on
|
|
||||||
Zenith, so OpenVPN 3 is retired.
|
|
||||||
- For the entire workflow implementation, do not access or test Polaris.
|
|
||||||
Zenith results are accepted for both workstations; preserve exact deferred
|
|
||||||
Polaris replication steps instead.
|
|
||||||
- OpenVPN 3 is removed from the configuration. A full Zenith system build
|
|
||||||
passes, and the first password-authorized switch removed it from the live
|
|
||||||
generation. NetworkManager reconnected the VPN successfully afterward.
|
|
||||||
- Walker's native cached Lua menu scans the four identity roots and refreshes
|
|
||||||
when their top level changes. Its default action pipes the selected path to
|
|
||||||
one Nix-owned `open-project` command. Elephant supplies that path without a
|
|
||||||
terminating newline, so the launcher now accepts a successful partial read
|
|
||||||
instead of exiting under `errexit`. It opens Neovim through the configured
|
|
||||||
`xdg-terminal-exec` owner and leaves an interactive shell after Neovim exits.
|
|
||||||
Elephant reads menu actions only at startup, so rare declarative menu changes
|
|
||||||
take effect at the next login. The generated Walker configuration extends,
|
|
||||||
rather than copies or replaces, the pinned default provider list and prefixes.
|
|
||||||
- The shared terminal-launch failure came from the Kitty package rewrite:
|
|
||||||
unanchored `sed` changed both `Exec=kitty` and `TryExec=kitty` to include
|
|
||||||
`-1`. Arguments are invalid in `TryExec`, causing `xdg-terminal-exec` to
|
|
||||||
reject the configured terminal. The rewrite now changes only `Exec`; live
|
|
||||||
resolver output selects `kitty.desktop` and retains `kitty -1`, and Yazi
|
|
||||||
launches successfully from Walker.
|
|
||||||
- Restarting the pre-change Elephant and Walker processes loaded the corrected
|
|
||||||
project action. The user confirmed that repository launch works and exiting
|
|
||||||
Neovim leaves a usable shell in that repository. Passing the project root to
|
|
||||||
Neovim now opens the configured Oil default directory explorer immediately.
|
|
||||||
- A custom restart trigger for Elephant proved unsafe: Walker requires Elephant,
|
|
||||||
so activation stopped Walker with its backend but restarted only Elephant.
|
|
||||||
The trigger is removed; relogging is the deliberately simple refresh path
|
|
||||||
unless real usage proves that inconvenient. The user activated the removal,
|
|
||||||
relogged, and confirmed both Walker and the project-root Oil action work.
|
|
||||||
- Removed the decided Niri arrow/Page Up/Down/numbered duplicates, direct quit
|
|
||||||
and monitor-power bindings, extra screenshot modes, first/last and centering
|
|
||||||
actions, repeated resize families, and their four shortcut-only scripts. The
|
|
||||||
existing `Super+A` helper remains until a two-output session can validate its
|
|
||||||
bounded name-based replacement.
|
|
||||||
- Home Manager owns the existing Vivaldi launcher filenames for Actual and
|
|
||||||
WhatsApp at the higher-precedence user-data location, so both invoke Vivaldi
|
|
||||||
8.1.4087.70 with the `Default` profile and stable app ID. Direct activation
|
|
||||||
replaced both generated files with managed links and retained the originals
|
|
||||||
as adjacent `.bak` files. The entries use native forced ownership because
|
|
||||||
Vivaldi may regenerate those exact paths. The installed Outlook PWA identified
|
|
||||||
itself as `eoficlgicibekocmfdomjbfnjmehnhcd`; its prepared managed launcher
|
|
||||||
preserves mailto handling and the calendar, compose, and new-event actions.
|
|
||||||
- The first `nixos-maintainer` skill is instruction-only, Nix-owned, and passes
|
|
||||||
the skill-creator validator. It encodes repository-specific ownership,
|
|
||||||
research, formatting, no-switch, and affected-host validation behavior
|
|
||||||
without duplicating generic agent guidance or adding scripts.
|
|
||||||
- Removed Zed, the inactive Helix modules and note integration, Helix's cache
|
|
||||||
settings and complete lock subgraph, and inactive Foot modules. Neovim and
|
|
||||||
Kitty remain the sole declared editor and terminal. A repository-wide search
|
|
||||||
found no configured npm caller, so global Node.js and Bun are also removed;
|
|
||||||
project shells retain language runtimes where needed.
|
|
||||||
- Postman, HTTPie, Posting, and Resterm are removed after their valuable request
|
|
||||||
definitions moved to tracked HTTP owners; Bruno remains through its own
|
|
||||||
pilot. Rainfrog, dblab, Harlequin and its profile, Tabularis, DbGate, pgAdmin,
|
|
||||||
MongoDB Compass, pgModeler, tbls, global `usql`, and global MariaDB are
|
|
||||||
removed; Dadbod and wrapper-local clients remain, while DBeaver stays through
|
|
||||||
its gate. Obsidian, Planify, and Calcure are removed after note and task
|
|
||||||
authority was established. Pinta replaces GIMP; the Evolution-era PIM clients
|
|
||||||
remain independently gated.
|
|
||||||
- `rclone` is installed as the only preparation for the selected S3 pilot. No
|
|
||||||
remote, wrapper, or interactive browser is added before a real task and
|
|
||||||
least-privileged credentials exist.
|
|
||||||
- GitHub remote state is absolutely read-only; local files, commits, fetches,
|
|
||||||
clones, and worktrees remain available. The generated global agent guidance
|
|
||||||
records this boundary. The former broad `jellespr` credential and stale,
|
|
||||||
invalid `kirigar` credential are removed locally. The only working API route
|
|
||||||
is now a fine-grained `github_pat_` token in the mode-0600 machine-local
|
|
||||||
`~/.config/yookr/github-read-only.token`. The Nix-owned `gh` package wrapper
|
|
||||||
reads it only when `GH_TOKEN` is otherwise absent, so `gh` and its Git
|
|
||||||
credential helper work inside Nix dev shells without copying the secret into
|
|
||||||
Nix, exporting it process-wide, or adding per-repository configuration.
|
|
||||||
- The fine-grained token passes identity, repository contents, issues, pull
|
|
||||||
requests, Actions, and organization Projects reads with no stored fallback.
|
|
||||||
The organization exposes 219 open issues, five open pull requests, and 60
|
|
||||||
Projects. Project 52 is a 38-issue high-level overview; Project 8 is an
|
|
||||||
82-item software backlog with the native ticket fields needed for the planned
|
|
||||||
workflow. Its only three items assigned to `jellespr` are Done, while the two
|
|
||||||
open issues assigned across the organization are not present there. Keep the
|
|
||||||
native `gh` and Git workflow and wait for the first real Monday ticket; add no
|
|
||||||
dashboard or wrapper before usage exposes a concrete gap.
|
|
||||||
- The user activated the initial GitHub token loader, whole-directory skill
|
|
||||||
owner, and durable remote boundary. A fresh shell contained the fine-grained
|
|
||||||
`GH_TOKEN`, `nixos-maintainer` resolved to a store-backed directory, the
|
|
||||||
generated global `AGENTS.md` contained the strict remote-state policy, and
|
|
||||||
the user confirmed `gh project list --owner yookrdev` succeeds. A cached
|
|
||||||
nix-direnv shell then proved it strips inherited `GH_TOKEN`; this concrete gap
|
|
||||||
prompted the invocation-scoped wrapper above. After activation, a cached dev
|
|
||||||
shell contains no `GH_TOKEN`, while `gh api user` identifies `jellespr` and
|
|
||||||
Git reads the private `constant-store` remote through the wrapper-backed
|
|
||||||
credential helper.
|
|
||||||
- The former Context7 declaration put a literal key in
|
|
||||||
`env_http_headers`, whose values Codex interprets as environment-variable
|
|
||||||
names; it therefore exposed the secret without supplying the documented
|
|
||||||
authentication. The static key is absent from the current worktree. Official
|
|
||||||
Codex configuration and Context7 documentation instead support the built
|
|
||||||
`http_headers_helper`, which emits the required `Authorization: Bearer` header.
|
|
||||||
The user replaced and revoked the historical key, the machine-local file is
|
|
||||||
mode 0600, and a restarted Codex session successfully resolves Nixpkgs and
|
|
||||||
queries its documentation through Context7.
|
|
||||||
- The PR gate used `prediction-api#125`: native `gh pr view`, `checks`, and
|
|
||||||
`diff` reads work, while an isolated exact-base reconstruction passes patch,
|
|
||||||
whitespace, and Rust formatting checks and leaves no durable checkout. The PR
|
|
||||||
has no CI, review, linked issue, or concurrency/retry regression test for its
|
|
||||||
deadlock change; private dependency and MySQL requirements prevented a safe
|
|
||||||
full test. Native GitHub and Git tooling suffice without another review UI.
|
|
||||||
- Five authorized ephemeral read-only Codex evaluations respected the no-switch
|
|
||||||
boundary and generally selected the right owners, but exposed that the live
|
|
||||||
`nixos-maintainer` file was absent from the model-visible skill catalog. Home
|
|
||||||
Manager now links the whole skill directory, the shape documented as supported
|
|
||||||
by Codex, rather than linking only `SKILL.md`. The flake and generated Home
|
|
||||||
Manager build pass, and an isolated Codex discovery probe returns
|
|
||||||
`DISCOVERED`; the live store-backed directory is now discoverable.
|
|
||||||
- Herdr reports the agent lifecycle correctly and preserves its pane and output
|
|
||||||
across detach and reattach. Its native defaults suffice; no configuration or
|
|
||||||
wrapper was added.
|
|
||||||
- In zsh, never use lowercase `path` as a loop or local variable: it is tied to
|
|
||||||
`PATH`. A diagnostic command temporarily hid normal executables by doing so;
|
|
||||||
the declarative session environment was correct and needed no patch.
|
|
||||||
- Pinta passed the bounded real-edit trial and is selected; GIMP is absent from
|
|
||||||
the active workstation package set.
|
|
||||||
- `sync/notes` is now the sole declarative notebook owner, with `daily`,
|
|
||||||
`meetings`, and `transcripts` directories, a native `zk daily` alias, and a
|
|
||||||
`Super+N` dedicated Kitty/Neovim launcher. The five unique authored work notes
|
|
||||||
were copied byte-for-byte, and both distinct todo lists were merged without
|
|
||||||
dropping an item. Syncthing returned to idle with no needed files, pull
|
|
||||||
errors, or new conflicts. The user confirmed the daily launcher and migrated
|
|
||||||
contents, then explicitly approved moving the intact `sync/work/notes`
|
|
||||||
rollback copy to desktop Trash. The pre-merge todo copies in `/tmp` may now
|
|
||||||
expire normally.
|
|
||||||
- The Fossify pilot produced a 10.28-second, mono 48 kHz AAC/M4A named
|
|
||||||
`20260906_004200.m4a`. Zenith's Syncthing log records its completed transfer at
|
|
||||||
00:44:12, after the recording stopped, and the received file remains stable
|
|
||||||
and media-readable. Fossify will write future recordings directly into
|
|
||||||
`recordings/inbox`; this is a native one-time producer setting, not a manual
|
|
||||||
filing step. Orion now owns the CPU `whisper-cpp` consumer through a systemd
|
|
||||||
path unit. The scanner waits for five minutes of unchanged size, nanosecond
|
|
||||||
mtime, and inode, validates media duration, archives without clobbering, and
|
|
||||||
publishes an unlabeled transcript when diarization is unavailable. A copied
|
|
||||||
sample passed that complete CPU fallback path in an isolated sync tree. The
|
|
||||||
user deployed Orion with
|
|
||||||
`nixos-rebuild switch --target-host orion --flake ~/.config/nixos#orion`,
|
|
||||||
activated Zenith's desktop changes, and stopped Zenith's old timer before the
|
|
||||||
shared-inbox test. Moving only the observed sample into Orion's inbox triggered
|
|
||||||
the path unit; after the full settlement interval, roughly two minutes of CPU
|
|
||||||
inference produced a 563-byte fallback transcript and archived the original
|
|
||||||
at its unchanged 126741-byte size with no failure artifact. The results synced
|
|
||||||
back to Zenith, and both current generations match the simplified
|
|
||||||
configuration: Orion is the sole declarative transcription owner. The user
|
|
||||||
confirmed the sample's bilingual output. Zenith's already accepted 33 MB
|
|
||||||
pyannote model contained no credential files and was copied byte-for-byte to
|
|
||||||
Orion; a guarded isolated rerun then completed diarization and atomically
|
|
||||||
replaced the fallback transcript with the user's approval while preserving
|
|
||||||
the archived audio hash. All five temporary audio/transcript test directories
|
|
||||||
were removed from Zenith and Orion; the canonical synchronized archive and
|
|
||||||
transcript remain.
|
|
||||||
- Evolution 3.60.2 is composed through Nixpkgs with `evolution-ews` 3.60.2,
|
|
||||||
whose pinned source contains the separate native Microsoft 365 mail,
|
|
||||||
calendar, contacts, recurrence, and OAuth backends. Live inspection caught
|
|
||||||
that overriding `evolutionWithPlugins.plugins` replaced its default Evolution
|
|
||||||
package, and that a Home Manager package alone did not register the data
|
|
||||||
server on D-Bus. The pilot now uses NixOS's native `programs.evolution`
|
|
||||||
integration with the EWS plugin beside Thunderbird. The follow-up activation
|
|
||||||
succeeded, its source-registry service activates through D-Bus, no account is
|
|
||||||
preconfigured, and no authority is changed. The user deferred account setup;
|
|
||||||
Thunderbird and the Outlook PWA remain the working clients meanwhile.
|
|
||||||
- Named database connections and a Marimo-to-HTML report remain workbench
|
|
||||||
evaluation evidence, not scaffolding requirements. Add them only for a real
|
|
||||||
cross-system investigation that gives the queries and report durable value.
|
|
||||||
- Run independent pilots in parallel, but gate every retirement separately.
|
|
||||||
+158
-785
@@ -1,818 +1,191 @@
|
|||||||
# Workflow system blueprint
|
# Workflow system blueprint
|
||||||
|
|
||||||
Status: authoritative design; discovery complete, implementation tracked in
|
Status: implemented. Current external gates and operational handoff live in
|
||||||
[`plans/workflow-system.md`](plans/workflow-system.md)
|
[`plans/workflow-system.md`](plans/workflow-system.md).
|
||||||
|
|
||||||
Last revised: 2026-09-05
|
This document is the durable design for the workstation and surrounding Yookr
|
||||||
|
workflow. Implementation history belongs in Git.
|
||||||
This document is the source of truth for streamlining the workstation and the
|
|
||||||
surrounding Yookr workflow. It records the intended system, the changes needed
|
|
||||||
to reach it, the trials that must precede conditional decisions, and work that
|
|
||||||
is deliberately deferred. Historical exploration and rejected alternatives are
|
|
||||||
not retained unless they prevent a likely wrong turn.
|
|
||||||
|
|
||||||
Remaining uncertainty is empirical rather than conceptual. Every unsettled
|
|
||||||
choice below has a bounded pilot, a pass condition, and a fallback; it is not an
|
|
||||||
invitation to resume general tool discovery.
|
|
||||||
|
|
||||||
## Governing intent
|
## Governing intent
|
||||||
|
|
||||||
Build a quiet, keyboard-first control plane over development, investigation,
|
Build a quiet, keyboard-first control plane over development, investigation,
|
||||||
operations, agents, and personal knowledge. The goal is a small coherent set of
|
operations, agents, and personal knowledge. Keep the system small and give each
|
||||||
interfaces, not one application pretending to do every job.
|
intention one canonical owner.
|
||||||
|
|
||||||
The governing rules are:
|
- Standardize vocabulary and entry points without forcing unlike workloads onto
|
||||||
|
one implementation.
|
||||||
- Give each intention one canonical owner. A native CLI may remain as a
|
- Put frequent actions on direct keys and less frequent actions on their owning
|
||||||
troubleshooting substrate without becoming a second documented workflow.
|
discovery surface.
|
||||||
- Standardize vocabulary, entry points, and lifecycle boundaries. Do not force
|
- Keep stable packages, services, integration, and durable preferences in Nix.
|
||||||
unlike workloads onto the same implementation merely for visual uniformity.
|
Keep credentials, sessions, databases, caches, and other mutable state with
|
||||||
- Put frequent actions on direct keys and make less frequent actions
|
their owning application.
|
||||||
discoverable through the surface that owns them.
|
- Prefer native file formats and supported application layers. Add wrappers only
|
||||||
- Keep stable packages, services, integration, and durable preferences under
|
for demonstrated gaps.
|
||||||
Nix. Keep application databases, caches, sessions, trust, credentials, and
|
|
||||||
other mutable state with the application that owns them.
|
|
||||||
- Prefer supported application layers and native file formats. Add adapters or
|
|
||||||
wrappers only for a demonstrated gap.
|
|
||||||
- Repositories own reproducible development context, executable project
|
- Repositories own reproducible development context, executable project
|
||||||
documentation, and artifacts specific to their code or schema. Global state
|
documentation, and code-specific artifacts.
|
||||||
is reserved for genuinely cross-project or personal material.
|
- Select `local`, `test`, or `live` per operation; do not depend on an ambient
|
||||||
- Select an environment per operation. Do not rely on a long-lived ambient
|
|
||||||
production context.
|
production context.
|
||||||
- Keep destructive or production actions more deliberate than navigation and
|
- Make production and destructive actions more deliberate than navigation and
|
||||||
read-only inspection.
|
read-only inspection.
|
||||||
- Promote automation only after the underlying manual workflow has repeated and
|
- Promote automation only after the manual workflow repeats and can be verified.
|
||||||
can be verified. A pilot is not yet a permanent abstraction.
|
|
||||||
- Prefer maintained free and open-source software. A paid tool is acceptable
|
|
||||||
only when it has an unusually strong, non-reproducible advantage.
|
|
||||||
- Optimize conceptual complexity and review burden, not package count or line
|
- Optimize conceptual complexity and review burden, not package count or line
|
||||||
count in isolation.
|
count in isolation.
|
||||||
|
|
||||||
The principal vocabulary is:
|
The main coordinates are scope (`work`, `own`, `ext`, or `forks`), Yookr domain,
|
||||||
|
environment (`local`, `test`, or `live`), and intention (develop, inspect, query,
|
||||||
|
review, operate, or deploy).
|
||||||
|
|
||||||
- scope: `work`, `own`, `ext`, or `forks`;
|
## Ownership model
|
||||||
- Yookr domain: a service/product repository, data science,
|
|
||||||
`traceability-data-model`, or the cross-system `yookr-workbench`;
|
|
||||||
- environment: exactly `local`, `test`, or `live`;
|
|
||||||
- intention: develop, inspect, query, review, operate, or deploy;
|
|
||||||
- status: **selected**, **pilot**, **retire after migration**, or **deferred**.
|
|
||||||
|
|
||||||
These coordinates compose. They are not stages in a mandatory linear process.
|
|
||||||
|
|
||||||
### Explicit exception
|
|
||||||
|
|
||||||
Credentials and `.env` files normally stay outside Git, the Nix store, and
|
|
||||||
broad synchronization. The existing secret-bearing `yookr-vpn.ovpn` is a
|
|
||||||
user-accepted exception: it may remain in Syncthing for use on Zenith and
|
|
||||||
Polaris. Restrict the source file to the user where Syncthing permits, never
|
|
||||||
print or commit its contents, and import it into each machine's root-owned
|
|
||||||
NetworkManager connection store. Do not generalize this exception.
|
|
||||||
|
|
||||||
## Target ownership model
|
|
||||||
|
|
||||||
<!-- markdownlint-disable MD013 -->
|
<!-- markdownlint-disable MD013 -->
|
||||||
|
|
||||||
| Intention | Canonical surface | Owner and status |
|
| Intention | Canonical owner |
|
||||||
| --- | --- | --- |
|
| --- | --- |
|
||||||
| Find applications, projects, or open windows | Walker/Elephant | **Selected**; applications plus an Elephant Lua project menu |
|
| Find applications, projects, or windows | Walker/Elephant and direct Niri bindings |
|
||||||
| Search personal passwords globally | Walker with `rbw` | **Selected** for personal Vaultwarden; company Bitwarden remains in its browser extension |
|
| Search personal passwords | Walker with `rbw`; company Bitwarden stays in its browser extension |
|
||||||
| Navigate tabs, history, bookmarks, and browser commands | Vivaldi Quick Commands (`F2`) | **Selected**; Vivaldi remains the only bookmark authority |
|
| Navigate browser state | Vivaldi Quick Commands |
|
||||||
| Arrange windows and displays | Niri | **Selected**; dynamic workspaces and no application-specific display roles |
|
| Arrange windows and displays | Niri dynamic workspaces |
|
||||||
| Work in a terminal | Kitty | **Selected**; no routine Kitty tiling or second terminal implementation |
|
| Work in a terminal | Kitty |
|
||||||
| Edit related files and views | Neovim | **Selected**; buffers and temporary splits, without automatic session restoration |
|
| Edit related files and views | Neovim |
|
||||||
| Enter a repository environment | `direnv` with `nix-direnv` | **Selected**; tracked `.envrc` and a default flake development shell |
|
| Enter a repository environment | `direnv` with `nix-direnv` |
|
||||||
| Discover non-obvious project actions | `just --list` | **Selected** for participating repositories; recipes delegate to native tools |
|
| Discover project actions | `just --list` |
|
||||||
| Run actively edited first-party code | Native processes, optionally Process Compose | **Selected** for fast reload and debugger access |
|
| Run edited first-party code | Native processes, optionally Process Compose |
|
||||||
| Run a container-only repository stack | Rootless Podman Compose | **Selected**; foreground, explicit, and scoped to the work session |
|
| Run a container-only project stack | Rootless Podman Compose |
|
||||||
| Run a persistent containerized user service | Rootless Podman Quadlet | **Selected**; user systemd owns lifecycle and logs |
|
| Run a persistent containerized user service | Rootless Podman Quadlet |
|
||||||
| Run a durable host service | NixOS module and systemd | **Selected** when a maintained native module fits |
|
| Run a durable host service | NixOS modules and systemd |
|
||||||
| Exercise APIs | Kulala and `xh` | **Selected**; JetBrains-compatible `.http` files are the durable artifact |
|
| Exercise APIs | Kulala and `xh`, with tracked `.http` files |
|
||||||
| Query databases | Dadbod and native driver CLIs | **Selected**; named machine-local connections and repository-owned queries |
|
| Query databases | Dadbod and native driver CLIs |
|
||||||
| Investigate across Yookr services | `yookr-workbench` | **Selected**, initially local to Zenith |
|
| Investigate across Yookr systems | `yookr-workbench` |
|
||||||
| Connect the Yookr VPN | Noctalia Network control center | **Pilot** NetworkManager/OpenVPN migration; OpenVPN 3 remains the fallback until both hosts pass |
|
| Connect the Yookr VPN | NetworkManager/OpenVPN through Noctalia |
|
||||||
| Inspect test Kubernetes | `just k8s test` to Gardenctl and `k9s` | **Selected**; isolated session and unchanged parent shell |
|
| Inspect test Kubernetes | `just k8s test` using Gardenctl and read-only K9s |
|
||||||
| Inspect or operate RabbitMQ | Official management UI | **Selected**; `rabbitmqadmin` is the terminal fallback |
|
| Inspect RabbitMQ | Official management UI; `rabbitmqadmin` for exact terminal operations |
|
||||||
| Browse S3-compatible storage | `rclone` | **Pilot**; explicit read/list/copy commands before interactive mutation surfaces |
|
| Browse S3-compatible storage | Native `rclone` commands |
|
||||||
| Capture and find notes | `zk` through Neovim | **Selected**; one synchronized Markdown notebook and one daily intake path |
|
| Capture and find notes | `zk` through Neovim in one synchronized Markdown notebook |
|
||||||
| Present work/personal PIM on desktop | Evolution | **Pilot**; server authorities do not change during evaluation |
|
| Present work and personal PIM | Evolution pilot beside Thunderbird and Outlook |
|
||||||
| Present personal PIM on Android | DAVx5, aCalendar+, Google Contacts, Tasks.org | **Pilot**; the server authorities remain unchanged |
|
| Present personal PIM on Android | DAVx5, aCalendar+, Google Contacts, and Tasks.org |
|
||||||
| Give agents durable project context | `AGENTS.md` and project commands | **Selected**; concise facts, invariants, architecture pointers, and checks |
|
| Give agents durable project context | `AGENTS.md` and project commands |
|
||||||
| Run top-level interactive agents | Herdr | **Pilot** for persistence, attention state, notifications, and worktrees |
|
| Run top-level agents | Herdr on demand |
|
||||||
| Maintain conversation state and internal subagents | Each native agent, primarily Codex | **Selected**; Herdr does not mirror internal subagents |
|
| Maintain conversation state and subagents | Each native agent, primarily Codex |
|
||||||
| Review local changes | LazyGit in the task checkout | **Selected**; Git remains branch/worktree truth |
|
| Review local changes | LazyGit in the task checkout |
|
||||||
| Review a pull request | `gh` for metadata/diff, then a review worktree when needed | **Pilot**; do not add another review application yet |
|
| Review pull requests | `gh`, then a review worktree when local checks are useful |
|
||||||
|
|
||||||
<!-- markdownlint-enable MD013 -->
|
<!-- markdownlint-enable MD013 -->
|
||||||
|
|
||||||
## Change program
|
## Repository contract
|
||||||
|
|
||||||
The phases below are dependency ordered. Each change appears once; trial details
|
Active work repositories live under `~/dev/work`; inactive repositories live
|
||||||
live in the evaluation section rather than being restated throughout the plan.
|
under `~/dev/work/.archive`, and worktrees under `~/dev/work/.worktrees`.
|
||||||
|
Repositories and worktrees never live under `~/sync`.
|
||||||
### Phase 1: reconcile state and ownership
|
|
||||||
|
Participating repositories use the following small contract:
|
||||||
#### Repositories and paths
|
|
||||||
|
- A tracked `.envrc` enters the default flake development shell without starting
|
||||||
- Before moving any repository, inspect its dirty state, linked worktrees,
|
services, fetching data, or mutating the checkout.
|
||||||
destination collisions, and authored path consumers. Move registered
|
- `flake.nix` owns reproducible dependencies, checks, packages, and formatting.
|
||||||
worktrees with `git worktree move` where possible and run
|
- `just --list` indexes non-obvious tasks and delegates to native commands.
|
||||||
`git worktree repair` after changing a repository root. Do not apply a broad
|
- `AGENTS.md` contains concise project facts, invariants, architecture pointers,
|
||||||
filesystem move to unchecked repositories.
|
and checks without duplicating global guidance.
|
||||||
- Reconcile the divergent dirty copies of `yookr-dashboard-new` under `~/sync`
|
- Service-owned `.http` and schema-owned `.sql` files stay beside their owner;
|
||||||
and `~/work/repos` before moving or deleting either. Establish the
|
generated views, caches, and scratch output do not become durable sources.
|
||||||
authoritative commit and preserve unique tracked, untracked, ignored, local
|
- Secrets enter at runtime from an approved source or a user-only file outside
|
||||||
data, and secret inputs deliberately. A general archive operation must not
|
checkouts, initially `~/.config/yookr/<repository>.env`.
|
||||||
choose between these copies implicitly.
|
- A new worktree behaves like a fresh clone and requires its own explicit
|
||||||
- Consolidate source repositories under the existing XDG projects root:
|
`direnv allow`.
|
||||||
`~/dev/work/<repository>`. Do not keep the accidental `~/work` root, the
|
- Branch-derived ports, databases, and container names are added only after a
|
||||||
intermediate `repos/` directory, or a permanent compatibility symlink.
|
real collision.
|
||||||
- Keep these work repositories active: `aggregation-api`, `prediction-api`,
|
|
||||||
`rules-service`, `yookr-api`, `yookr-dashboard`, `yookr-dashboard-new`,
|
Use Process Compose only when multiple foreground processes benefit from one
|
||||||
`yookr-data-science`, `yookr-management-svelte-redo`, and
|
visible lifecycle. Use Podman Compose for wholly containerized project stacks,
|
||||||
`traceability-data-model` (currently `schemas`). Add `yookr-workbench` when
|
Quadlet for persistent user containers, and NixOS modules for durable host
|
||||||
its pilot begins.
|
services. Do not nest lifecycle tools for another status screen.
|
||||||
- Rename `schemas` to `traceability-data-model` during the move. Update authored
|
|
||||||
path consumers; generated Codex, shell, and Herdr histories may remain
|
`yookr-workbench` owns cross-system API requests, operational queries, the
|
||||||
historical.
|
Garden/Kubernetes entry point, and Marimo investigations. It does not collect
|
||||||
- Move every other repository from the current work inventory intact to
|
service OpenAPI specifications, schema migrations, deployable model code, or
|
||||||
`~/dev/work/.archive`. This includes `yookr-management-new`,
|
copied application state.
|
||||||
`yookr-management-svelte`, `yookr-dashboard-new.old`, `pipelines.old`,
|
|
||||||
`yookr-dashboard-new.zip`, `rules-service-hex`,
|
## Interaction and knowledge boundaries
|
||||||
`yookr-data-science-no-kedro`, and tutorial repositories. Do not infer active
|
|
||||||
status from a product-looking name.
|
- Walker scans the four repository roots, excludes `.archive` and `.worktrees`,
|
||||||
- Archive the small `~/work/rabbitmq` scratch project. Remove the empty legacy
|
and invokes one Nix-owned `open-project` command. The command opens Kitty at
|
||||||
`.data/mongodb` directory only after a final emptiness check; do not move the
|
the repository root, starts Neovim, and leaves a shell after Neovim exits.
|
||||||
global `.data` directory into the source tree.
|
- Vivaldi remains the bookmark and web-app authority. Home Manager owns stable
|
||||||
- Make Git identity rules explicit and non-overlapping: work identity below
|
launchers for Actual, WhatsApp, and Outlook without duplicating browser state.
|
||||||
`~/dev/work`, personal identity below `~/dev/own`, `~/dev/ext`, and
|
- Niri keeps dynamic general-purpose workspaces and a compact navigation and
|
||||||
`~/dev/forks`. Update the old `~/work` conditional include.
|
movement vocabulary. The two-output active-workspace exchange remains a
|
||||||
- Treat work/personal labels as identity and navigation boundaries, not privacy
|
bounded pilot.
|
||||||
boundaries. Non-secret work material may synchronize to the Pixel and Orion;
|
- Codex is primary; Claude Code and Pi are fallbacks. Herdr owns persistence and
|
||||||
source checkouts, credentials, and runtime state do not belong in the broad
|
attention for top-level sessions, while each agent owns its internal state.
|
||||||
`~/sync` tree.
|
- Use one primary writer per checkout. Subagents may perform bounded independent
|
||||||
- Remove stale path-bound Codex trust and obsolete approval entries after the
|
read-heavy work, but overlapping changes are sequenced.
|
||||||
move. Update the transitional Bruno workspace path only if Bruno still needs
|
- Substantial multi-session work may keep one living
|
||||||
it during migration.
|
`docs/plans/<task-slug>.md`; lasting knowledge moves to normal documentation
|
||||||
|
and transient execution history is removed when finished.
|
||||||
#### Nix and mutable application state
|
- `~/sync/notes` is the Markdown/zk authority. Daily intake uses
|
||||||
|
`daily/YYYY-MM-DD.md`; planned meetings and raw transcripts use `meetings/`
|
||||||
- Preserve the existing host/profile/capability structure, typed facts,
|
and `transcripts/` respectively.
|
||||||
flake-parts composition, Home Manager integration, and primary-tool
|
- Microsoft 365 remains authoritative for work/university PIM and Radicale for
|
||||||
indirection. No repository-wide architecture migration is justified.
|
personal CalDAV, VTODO, and CardDAV. Clients present those authorities without
|
||||||
- Keep flakes and `nh os switch` as the normal activation path. Keep Neovim's
|
bridging or copying them.
|
||||||
Lua, wrapper, plugins, language servers, and formatters store-backed; accept
|
- Fossify records on Android and Syncthing delivers completed recordings to
|
||||||
the measured rebuild cost rather than adding an out-of-store fast path.
|
Orion. Orion owns event-driven CPU transcription, diarization fallback,
|
||||||
- Do not prototype Hjem/Rum, replace flakes with `npins`, or add a separate Home
|
archival, and Markdown publication.
|
||||||
Manager activation wrapper. These do not address the accepted ownership
|
|
||||||
model.
|
## Safety boundaries
|
||||||
- Remove the unused `nixpkgs-stable` input and its dead local binding. Let
|
|
||||||
Noctalia follow the root Nixpkgs input if the pinned configuration evaluates
|
GitHub and all other remotes are read-only. Local commits, clones, fetches, and
|
||||||
unchanged; describe this as dependency-graph hygiene, not a latency fix.
|
worktrees are allowed; remote mutation requires a separate change to policy.
|
||||||
- Retire or rewrite the stale root `PLAN.md` after checking whether it contains
|
|
||||||
unfinished Neovim work. It must not continue to claim that Helix is active.
|
Credentials and `.env` files normally stay outside Git, the Nix store, and broad
|
||||||
- Keep Flatpak enabled as an intentionally available installation facility, but
|
synchronization. The accepted `yookr-vpn.ovpn` is a narrow exception for Zenith
|
||||||
add no declarative Flatpak manager, remotes, or applications while it has no
|
and Polaris: keep it user-restricted and import it into NetworkManager without
|
||||||
consumers.
|
printing or committing its contents.
|
||||||
- Continue declaring Noctalia's stable policy through Nix. When behavior differs
|
|
||||||
from the declaration, inspect its writable XDG state as a second supported
|
Only the user activates a NixOS or Home Manager generation. Agents may evaluate
|
||||||
application layer; keep only genuinely local runtime state there rather than
|
and build configurations, then provide an activation command.
|
||||||
adding another synchronization mechanism.
|
|
||||||
|
## Remaining pilots
|
||||||
#### Codex configuration ownership
|
|
||||||
|
- Capture Zenith's external display identity during a docked session and test the
|
||||||
- Rotate the exposed Context7/MCP credential and replace plaintext headers with
|
two-output `Super+A` exchange.
|
||||||
an environment-backed header or supported credential mechanism.
|
- Resume Evolution and Android PIM only when the user chooses to run those daily
|
||||||
- Generate stable Codex defaults at `/etc/codex/config.toml`: MCP endpoints,
|
use pilots.
|
||||||
approval defaults, notifications when Codex owns them, and other durable
|
- Add workbench database connections and a Marimo report only for a real
|
||||||
cross-machine preferences. Official precedence makes this a lower-precedence
|
cross-system investigation.
|
||||||
default layer.
|
- Configure an S3 remote only for a real task with least-privileged credentials
|
||||||
- Leave `~/.codex/config.toml` writable and machine-local for project trust and
|
and explicit upload authorization.
|
||||||
unavoidable local settings. Review non-trust keys occasionally: promote a
|
- Rerun the Yookr OpenAPI refresh after the deployed image exposes
|
||||||
deliberate cross-machine preference to Nix, retain generated/machine state,
|
`/full-api-docs/openapi.json`; run authenticated API checks only with current
|
||||||
and remove accidental overrides. Do not add a drift daemon.
|
user credentials.
|
||||||
- Keep global `AGENTS.md`, intentional rules, and user-authored skills under
|
- Keep Bruno, DBeaver, and existing PIM clients until their independent gates are
|
||||||
Nix/Home Manager. Keep authentication, conversations, databases, caches,
|
resolved.
|
||||||
downloaded plugins/skills, and generated Herdr integrations untracked.
|
|
||||||
- Remove the stale `~/.config/codex` tree; its preservation audit found no unique
|
|
||||||
authored material worth migrating.
|
|
||||||
|
|
||||||
### Phase 2: establish the project contract and Yookr workbench
|
|
||||||
|
|
||||||
#### Common repository contract
|
|
||||||
|
|
||||||
Participating repositories expose the same concepts without copying an empty
|
|
||||||
directory taxonomy:
|
|
||||||
|
|
||||||
- A tracked `.envrc` enters the default flake development shell and selects only
|
|
||||||
non-secret local defaults. Activation must not perform `uv sync`, start
|
|
||||||
services, fetch data, or do other mutating/network work.
|
|
||||||
- `flake.nix` owns reproducible dependencies, packages, checks, and the
|
|
||||||
formatter. A flake app remains only when it is an actual runnable or
|
|
||||||
distributable program.
|
|
||||||
- `just --list` is the documented index of non-obvious human and agent tasks.
|
|
||||||
Recipes delegate to native commands and omit trivial one-off operations; the
|
|
||||||
native CLI remains available for diagnosis without becoming a second catalog.
|
|
||||||
- Install `just` as a workstation bootstrap tool and include it in participating
|
|
||||||
development shells so the repository remains portable.
|
|
||||||
- `AGENTS.md` records architecture pointers, invariants, project commands, and
|
|
||||||
required checks. It stays factual and concise; it does not duplicate generic
|
|
||||||
global behavior.
|
|
||||||
- Service-owned `.http` examples and schema-owned `.sql` files live beside the
|
|
||||||
code or schema they describe. Generated views, caches, and scratch results are
|
|
||||||
not durable sources.
|
|
||||||
- Environment selection is per operation. Kulala selects a buffer environment,
|
|
||||||
Dadbod selects a visibly named connection, and recipes accept an explicit
|
|
||||||
argument such as `just k8s test`.
|
|
||||||
- Secrets enter at runtime from the service's approved source or a user-only
|
|
||||||
machine file outside all checkouts, initially
|
|
||||||
`~/.config/yookr/<repository>.env`. A tracked `.envrc` may load that stable
|
|
||||||
path with `dotenv_if_exists`.
|
|
||||||
- A new worktree behaves like a fresh clone. Recreate dependencies, caches,
|
|
||||||
generated files, and build output; do not copy ignored state from a main
|
|
||||||
checkout. Require an explicit `direnv allow` for each worktree.
|
|
||||||
- Do not pre-allocate branch-derived ports, databases, Compose projects, or
|
|
||||||
container names. Add targeted isolation only after a real task exposes a
|
|
||||||
collision.
|
|
||||||
|
|
||||||
First prove this contract in `rules-service`, paired with the API workflow in
|
|
||||||
`yookr-api` and the database workflow in `traceability-data-model`. Only after
|
|
||||||
two repositories reveal genuinely repeated files should a small native Nix
|
|
||||||
flake-template repository be extracted. Language-native initializers continue
|
|
||||||
to own language source layout.
|
|
||||||
|
|
||||||
Repository-specific corrections are part of the pilots:
|
|
||||||
|
|
||||||
- In `rules-service`, add a README, flake, `.envrc`, `justfile`, and concise
|
|
||||||
`AGENTS.md`; document the local run path; correct the obsolete environment
|
|
||||||
example; use `test`, not `dev`, for the deployed test environment. Do not
|
|
||||||
encode the transitional rollout as a durable `deploy` recipe.
|
|
||||||
- In `traceability-data-model`, rename the repository and make destructive
|
|
||||||
schema recreation an explicitly named reset action rather than the ordinary
|
|
||||||
`dev` path.
|
|
||||||
- In `yookr-data-science`, default ordinary fetching away from live, remove
|
|
||||||
`uv sync` from shell activation, keep the deployable soil-moisture pipeline,
|
|
||||||
and move only generic cross-system exploration to the workbench.
|
|
||||||
- In `yookr-dashboard-new`, preserve the useful visible Process Compose
|
|
||||||
lifecycle. Expose it through `just dev` when the project adopts the common
|
|
||||||
contract instead of maintaining a workflow-only flake app in parallel.
|
|
||||||
|
|
||||||
#### Workload lifecycle
|
|
||||||
|
|
||||||
- Run actively edited first-party code natively.
|
|
||||||
- Use Process Compose only for two or more native or mixed foreground processes
|
|
||||||
that need one visible lifecycle, dependency graph, and log view.
|
|
||||||
- Use rootless Podman Compose for a wholly containerized repository stack. Keep
|
|
||||||
support stacks manual, foreground, and scoped to a work session; preserve
|
|
||||||
named volumes between runs and make running state visible to Podman tools.
|
|
||||||
- Use Quadlet for persistent containerized user services and NixOS modules for
|
|
||||||
durable host services when a good module exists. Do not nest lifecycle tools
|
|
||||||
merely to obtain another status screen.
|
|
||||||
- Configure Podman's external Compose provider deterministically. Do not use
|
|
||||||
Compose dotenv behavior as the secret contract.
|
|
||||||
|
|
||||||
#### `yookr-workbench`
|
|
||||||
|
|
||||||
Create a minimal `yookr-workbench` on Zenith before adding workbench-owned API,
|
|
||||||
database, or Kubernetes commands. Keep it without a remote while proving its
|
|
||||||
contents. It owns only cross-system work:
|
|
||||||
|
|
||||||
- curated cross-service `.http` requests;
|
|
||||||
- operational queries and MongoDB scripts that do not belong to one service;
|
|
||||||
- explicit local/test investigation commands;
|
|
||||||
- the Garden/Kubernetes entry point;
|
|
||||||
- uv-managed Marimo analyses, disposable experiments, and report exports.
|
|
||||||
|
|
||||||
It does not own service OpenAPI specifications, schema migrations, deployable
|
|
||||||
model code, general bookmarks, RabbitMQ URLs, or copied application state.
|
|
||||||
Scratch work is promoted to its nearest durable owner or deleted. Unrelated
|
|
||||||
personal Dadbod scratch stays under XDG data.
|
|
||||||
|
|
||||||
Use Marimo's Python files as the analysis source. Ignore raw/local data and
|
|
||||||
scratch output. Share source notebooks with technical readers, self-contained
|
|
||||||
HTML as the faithful general report, browser-produced PDF when the delivery
|
|
||||||
channel favors it, and individual SVG/PNG files only when a figure is itself the
|
|
||||||
deliverable. Do not add a notebook hub or report server.
|
|
||||||
|
|
||||||
Production data may be used on a developer machine; this streamline adds no
|
|
||||||
separate anonymization or local-retention policy. Raw datasets and
|
|
||||||
secret-bearing output still remain outside Git and broad synchronization.
|
|
||||||
|
|
||||||
#### API and database workflow
|
|
||||||
|
|
||||||
- Make Kulala and `xh` the editor/CLI pair. Keep hand-curated `.http` files as
|
|
||||||
durable examples; use `kulala-fmt` OpenAPI conversion only to seed a migration
|
|
||||||
or produce a disposable view.
|
|
||||||
- Commit non-secret `local`, `test`, and `live` metadata in
|
|
||||||
`http-client.env.json`. Keep credentials in ignored
|
|
||||||
`http-client.private.env.json` or runtime environment variables. Make
|
|
||||||
`local` the default environment; keep test/live selection explicit and
|
|
||||||
visible per buffer. Kubernetes being test-only does not remove explicit live
|
|
||||||
HTTP access.
|
|
||||||
- Use Yookr API as the first proof. Support the sibling service-owned
|
|
||||||
`openapi.yaml` and ignored snapshots fetched from test/live
|
|
||||||
`/full-api-docs/openapi.json`. Authenticate through ordinary login and run a
|
|
||||||
harmless administrator-authorized read.
|
|
||||||
- Compare local and network specifications semantically with `oasdiff`. A
|
|
||||||
network refresh writes and validates an ignored cache; it never overwrites a
|
|
||||||
checked-in contract automatically. Do not add timestamped archives or polling.
|
|
||||||
- Add `just openapi` to a service only when that repository has a reproducible
|
|
||||||
generation command. A service repository remains authoritative for its
|
|
||||||
specification; the workbench does not collect copied specs.
|
|
||||||
- Use Dadbod UI's machine-local named connection store, normally
|
|
||||||
`~/.local/share/db_ui/connections.json`, instead of the current single
|
|
||||||
`DATABASE_URL` assumption. Name entries
|
|
||||||
`<environment>-<service-or-domain>-<engine>`, for example
|
|
||||||
`test-rules-mysql`, `test-prediction-mysql`, and
|
|
||||||
`local-traceability-postgres`.
|
|
||||||
- Support PostgreSQL, MySQL/MariaDB, and MongoDB while the migration requires all
|
|
||||||
three. Keep relational artifacts as `.sql` and MongoDB artifacts in their
|
|
||||||
native JavaScript format. Durable queries belong in repositories; DBUI saved
|
|
||||||
queries are personal scratch.
|
|
||||||
- Prefer read-only credentials for workbench inspection where available.
|
|
||||||
Dadbod is not itself a safety boundary. Intentional schema or data mutations
|
|
||||||
belong in an owning repository or an explicitly reviewed operation.
|
|
||||||
- Populate connection URLs manually. Do not extract Kubernetes Secrets or build
|
|
||||||
a Bitwarden-to-Dadbod translation layer before manual connection management
|
|
||||||
demonstrates a real cost.
|
|
||||||
|
|
||||||
#### Kubernetes, RabbitMQ, S3, and SharePoint
|
|
||||||
|
|
||||||
- Install `networkmanager-openvpn` on Polaris and Zenith, import the accepted
|
|
||||||
VPN profile separately as a root-owned connection with autoconnect disabled,
|
|
||||||
give it the same visible name on both machines, and use Noctalia's built-in
|
|
||||||
Network control center. Retain OpenVPN 3 until the migration gate passes on
|
|
||||||
both hosts.
|
|
||||||
- Package official `gardenctl` and `gardenlogin` releases through Nix, use the
|
|
||||||
nixpkgs OIDC plugin, remove duplicate binaries from `~/.garden` and
|
|
||||||
`~/.local/bin`, and replace handwritten Zsh initialization with
|
|
||||||
`gardenctl rc zsh`. Keep Garden configuration and kubeconfigs mutable and
|
|
||||||
private outside the store.
|
|
||||||
- Implement `just k8s test` in the workbench. It creates a fresh
|
|
||||||
`GCTL_SESSION_ID`, targets Garden `leafcloud-test`, project `ryxtdg8ydl`, shoot
|
|
||||||
`test`, derives `KUBECONFIG`, and opens `k9s` in the foreground. The parent
|
|
||||||
shell remains unchanged. Use explicit `kubectl --namespace` for exceptional
|
|
||||||
terminal work; do not guess a namespace.
|
|
||||||
- Do not expose live Kubernetes or a deploy command. Image construction and GHCR
|
|
||||||
publication remain in GitHub Actions while the team release process is
|
|
||||||
unresolved.
|
|
||||||
- Use the official RabbitMQ management UI for inspection, publishing/getting,
|
|
||||||
and purge. Put `https://test.rabbitmq.yookr.org` and
|
|
||||||
`https://rabbitmq.yookr.org` in a Vivaldi operations bookmark folder with
|
|
||||||
explicit test/live labels rather than duplicating them as workbench recipes or
|
|
||||||
Walker actions. Keep `rabbitmqadmin` for exact terminal operations; purge
|
|
||||||
remains visibly interactive.
|
|
||||||
- Pilot one machine-local `rclone` S3 remote using the least-privileged available
|
|
||||||
credentials. Begin with `lsd`, `lsjson`, `tree`, and explicit read/copy
|
|
||||||
operations. Do not expose `rclone ncdu` initially because its interface also
|
|
||||||
deletes and has no read-only mode.
|
|
||||||
- Reuse `rclone`'s OneDrive backend for a later SharePoint browse/download pilot
|
|
||||||
before considering a second SharePoint tool. Do not introduce continuous sync
|
|
||||||
or a mount until the real access pattern and company consent are known.
|
|
||||||
|
|
||||||
#### Pull-request review
|
|
||||||
|
|
||||||
- Use `gh pr view` for metadata/checks and `gh pr diff` for a quick read-only
|
|
||||||
review.
|
|
||||||
- Create a dedicated review worktree when local navigation, tests, or agent
|
|
||||||
assistance are needed, then use LazyGit in that checkout.
|
|
||||||
- Add no PR dashboard or wrapper until repeated reviews expose a specific gap.
|
|
||||||
|
|
||||||
### Phase 3: simplify global navigation and desktop interaction
|
|
||||||
|
|
||||||
#### Walker and project opening
|
|
||||||
|
|
||||||
- Keep Walker/Elephant as the global discovery surface and Niri direct bindings
|
|
||||||
for the most frequent intentions. Keep `z <project>` as the shell fast path;
|
|
||||||
it is another invocation surface over the filesystem, not another catalog.
|
|
||||||
- Use Elephant's native dynamic Lua menu support as `menus:projects`. Scan Git
|
|
||||||
roots across `~/dev/work`, `~/dev/own`, `~/dev/ext`, and `~/dev/forks`; exclude
|
|
||||||
`.archive` and every worktree root. Show one flat result set with scope labels.
|
|
||||||
- Have each result invoke one Nix-owned `open-project` command. It opens an
|
|
||||||
interactive Kitty shell at the repository root, starts Neovim, and returns to
|
|
||||||
a usable prompt after Neovim exits. It restores no buffers, layouts, or
|
|
||||||
services.
|
|
||||||
- Treat `yookr-workbench` as an ordinary project result. Do not generate a
|
|
||||||
desktop entry per repository or maintain a separate project registry.
|
|
||||||
- Retain Elephant's shipped provider defaults/prefixes instead of copying them
|
|
||||||
into Nix. Keep the current `?` Bitwarden prefix as the local exception.
|
|
||||||
Clipboard and credentials remain prefixed; quiet navigation providers may
|
|
||||||
participate in unprefixed search.
|
|
||||||
- Do not include bookmarks in Walker until a maintained provider can read
|
|
||||||
Vivaldi live. Elephant's one-time CSV import would create a second authority.
|
|
||||||
|
|
||||||
#### Browser ownership
|
|
||||||
|
|
||||||
- Keep one neutral Vivaldi profile. Work/personal cookie and history isolation
|
|
||||||
has no demonstrated value; rename the misleading `Work` profile if visible.
|
|
||||||
- Use Vivaldi Quick Commands for tabs, history, bookmarks, and browser commands.
|
|
||||||
Keep vertical tabs. Do not initially add Vivaldi workspaces, pinned tabs, Web
|
|
||||||
Panels, command chains, or another Chromium browser.
|
|
||||||
- Keep Actual, WhatsApp, and Outlook as web apps. Vivaldi owns installation,
|
|
||||||
identity, authentication, permissions, and sync. After capturing each app ID,
|
|
||||||
Home Manager owns one stable desktop entry invoking current Vivaldi with
|
|
||||||
`--profile-directory=Default --app-id=<id>`; suppress the duplicate
|
|
||||||
Vivaldi-generated launcher. Reuse the known Actual ID
|
|
||||||
`ahoihnifhakgijcmjlhbcgehigihinlo` and WhatsApp ID
|
|
||||||
`hnpfjngllnobngcgfapefoaidbinmjnm`; capture Outlook's ID after installing it.
|
|
||||||
This prevents stale Nix-store paths.
|
|
||||||
- Keep a small Speed Dial beginning with ChatGPT and the Yookr GitHub
|
|
||||||
organization. Google remains the search engine rather than a bookmark.
|
|
||||||
- Sync durable bookmarks/Speed Dials, supported settings, extensions, and web
|
|
||||||
apps between Zenith and Polaris. Keep open tabs and history local. Passwords
|
|
||||||
remain Bitwarden-owned.
|
|
||||||
- Use Bitwarden's multi-account browser extension for personal Vaultwarden and
|
|
||||||
company Bitwarden. Walker's `rbw` provider remains personal-only; do not copy
|
|
||||||
company secrets, create another browser profile, or build a private adapter.
|
|
||||||
|
|
||||||
#### Niri vocabulary
|
|
||||||
|
|
||||||
- Design for two general-purpose displays with dynamic workspaces. Do not pin
|
|
||||||
applications, roles, or content to a monitor. On Zenith, place the external
|
|
||||||
widescreen to the right and focus it initially once its stable identity has
|
|
||||||
been captured during a docked session.
|
|
||||||
- Keep `Super+H/J/K/L` for focus and `Super+Alt+H/J/K/L` for frequent
|
|
||||||
window/column movement. Keep `Super+U/I` for workspace navigation, the
|
|
||||||
corresponding deliberate move/reorder operations, useful mouse-wheel
|
|
||||||
bindings, and touchpad gestures.
|
|
||||||
- Remove arrow-key duplicates, Page Up/Down aliases, numbered-workspace
|
|
||||||
bindings, first/last-column jumps, centering, maximize-to-edges, direct
|
|
||||||
compositor quit, monitor power-off, and the unused hotkey-overlay binding.
|
|
||||||
- Remove the NixOS-config terminal, NixOS-switch, edit-secrets, and color-picker
|
|
||||||
shortcuts and their shortcut-only scripts. Underlying terminal commands stay.
|
|
||||||
- Consolidate screenshots on Niri's interactive `Super+S` UI. Keep
|
|
||||||
`Super+O` overview, `Super+Q` close, and `Super+Ctrl+L` lock.
|
|
||||||
- Keep `Super+R` preset width cycling, one incremental resize family, column
|
|
||||||
maximize, and fullscreen. Retain stacking/consume-expel actions, tabbed
|
|
||||||
columns, toggle floating, and focus switching between floating and tiling as
|
|
||||||
secondary capabilities.
|
|
||||||
- Replace the fragile mutable-index `Super+A` helper only through the bounded
|
|
||||||
pilot below. Niri 26.04 actions accept a workspace index or name, not stable
|
|
||||||
IPC workspace IDs, and have no atomic active-workspace swap.
|
|
||||||
|
|
||||||
### Phase 4: make the agent workflow coherent
|
|
||||||
|
|
||||||
#### Context, skills, and client boundaries
|
|
||||||
|
|
||||||
- Keep Codex primary and Claude Code/Pi as experimental fallbacks without fixed
|
|
||||||
specializations or forced feature parity.
|
|
||||||
- Share repository `AGENTS.md`, concise global guidance, project commands,
|
|
||||||
user-authored skills where natively supported, and verified MCP endpoint
|
|
||||||
facts. Keep client-specific model/UI settings, approvals, authentication,
|
|
||||||
trust, and runtime state native.
|
|
||||||
- Centralize MCP endpoint facts in the Nix AI capability only after Codex and
|
|
||||||
Claude both consume them, then render thin native configurations. Pi has no
|
|
||||||
native MCP owner and should not receive a wrapper for cosmetic parity. Remove
|
|
||||||
generic Home Manager `programs.mcp` output if it remains unused.
|
|
||||||
- Do not create a prompt-template menu or demonstration skills. Promote a
|
|
||||||
procedure only after it has stable inputs, outputs, and verification.
|
|
||||||
- Create the instruction-only `nixos-maintainer` skill as the first demonstrated
|
|
||||||
candidate. It inspects repository instructions and the complete current
|
|
||||||
owner, prefers native options and existing patterns, researches
|
|
||||||
version-sensitive choices, keeps mutable state outside the store, makes
|
|
||||||
focused idiomatic edits, formats them, and performs the smallest meaningful
|
|
||||||
no-switch validation for affected hosts. Switching a generation requires a
|
|
||||||
separate explicit request. Add scripts only after a deterministic repeated
|
|
||||||
operation appears.
|
|
||||||
|
|
||||||
#### Top-level agents and worktrees
|
|
||||||
|
|
||||||
- Pilot Herdr as owner of top-level Codex, Claude, and Pi processes, cross-agent
|
|
||||||
attention state, detach/reattach, desktop notifications, and the normal
|
|
||||||
create/open/list/remove worktree flow.
|
|
||||||
- Start or attach Herdr on demand. Do not add a supervised login service: the
|
|
||||||
client already starts a persistent background session. Stop it deliberately
|
|
||||||
with `herdr server stop`. Keep ordinary terminals, Neovim, dev processes, and
|
|
||||||
LazyGit outside Herdr.
|
|
||||||
- Configure Herdr as the sole notification owner during the pilot. If it fails,
|
|
||||||
use Codex's built-in TUI notifications before an external notify command.
|
|
||||||
- Use one workspace per active checkout or cross-repository investigation and
|
|
||||||
one pane per top-level agent. Internal Codex subagents remain in Codex.
|
|
||||||
- Let Herdr use Git worktrees as its substrate. For the first work-only pilot,
|
|
||||||
place them under `~/dev/work/.worktrees/<repository>/<branch-slug>` and exclude
|
|
||||||
that tree from Walker. Use an explicit path for other identity scopes until a
|
|
||||||
scope-preserving convention is proven.
|
|
||||||
- Do not install Worktrunk initially. Herdr 0.8.2 covers the proposed basic
|
|
||||||
lifecycle and leaves branches intact for human review. Revisit Worktrunk only
|
|
||||||
for demonstrated needs such as richer cross-worktree state, shell switching,
|
|
||||||
CI/PR views, process cleanup, or integration-aware branch removal. Keep native
|
|
||||||
`git worktree list`, `repair`, and `prune` as maintenance escape hatches.
|
|
||||||
- Defer `codex agents`. Codex 0.153.4 exposes it, but local diagnostics show
|
|
||||||
ephemeral app-server mode and daemon bootstrap that assumes a standalone
|
|
||||||
managed install rather than the Nix-store binary. Do not add a second mutable
|
|
||||||
Codex installation or custom daemon workaround.
|
|
||||||
|
|
||||||
#### Task lifecycle
|
|
||||||
|
|
||||||
- Use one primary writer per checkout. It may delegate bounded independent
|
|
||||||
read-heavy work; concurrently running internal subagents do not edit the same
|
|
||||||
checkout. Confirmed read-only investigations may share a checkout and need no
|
|
||||||
branch or worktree. Sequence tasks expected to overlap in files or behavior.
|
|
||||||
- Use `feat/<issue>-<slug>`, `fix/<issue>-<slug>`, or
|
|
||||||
`chore/<issue>-<slug>`, omitting the issue when none exists. Reuse the slug for
|
|
||||||
the checkout, Herdr label, and optional execution plan.
|
|
||||||
- Keep setup explicit: create the worktree, review and authorize `.envrc`, then
|
|
||||||
start the agent there. Do not add hooks, copy ignored files, launch agents from
|
|
||||||
Walker, or hide these state changes in a wrapper.
|
|
||||||
- Use Codex `/plan` when design is uncertain, then one `/goal` containing the
|
|
||||||
outcome, constraints, and verification for substantial execution. A goal is a
|
|
||||||
persistent target, not a milestone hierarchy.
|
|
||||||
- For genuinely substantial multi-session work, keep one living
|
|
||||||
`docs/plans/<task-slug>.md` in the branch and reference it from the goal. Record
|
|
||||||
scope/non-goals, architectural facts, verifiable milestones, progress,
|
|
||||||
discoveries, decisions, evidence, and the exact next step. Link to source
|
|
||||||
instead of copying logs. Move lasting knowledge to normal docs/ADR at the end
|
|
||||||
and delete a transient plan when it has no continuing value.
|
|
||||||
- Let the primary agent make local commits at meaningful verified or resumption
|
|
||||||
boundaries, not mechanically after every milestone. It does not push, merge,
|
|
||||||
open a pull request, or mutate GitHub without an explicit request.
|
|
||||||
- End on a checked, locally committed branch with a handoff covering outcome,
|
|
||||||
verification, limitations, and unresolved decisions. Review with LazyGit in
|
|
||||||
the task worktree. The user chooses publication, integration, revision, or
|
|
||||||
abandonment; remove the checkout only afterward.
|
|
||||||
|
|
||||||
### Phase 5: consolidate notes, PIM, and transcription
|
|
||||||
|
|
||||||
#### Notes and meeting knowledge
|
|
||||||
|
|
||||||
- Consolidate both notebooks into `~/sync/notes` on one fully synchronized node
|
|
||||||
with no concurrent writers. Preserve authored notes/images and merge the two
|
|
||||||
`todo.md` files deliberately. Stop generating `~/sync/work/notes`.
|
|
||||||
- Use `daily/YYYY-MM-DD.md` as the unclassified intake path, with no title prompt
|
|
||||||
or required frontmatter. Use a `zk` group/alias for idempotent daily-note
|
|
||||||
creation. Keep ordinary titled notes at the notebook root until use justifies
|
|
||||||
another collection.
|
|
||||||
- Bind unused `Mod+N` to a small Nix-owned command that opens today's note at the
|
|
||||||
append position in a dedicated Kitty/Neovim window and closes with Neovim.
|
|
||||||
- Store planned meetings as dated files under `meetings/` and raw transcripts
|
|
||||||
separately under `transcripts/`. A person curates decisions/context into the
|
|
||||||
meeting note. During the Monday development meeting, the team cooperatively
|
|
||||||
decides and creates issues, which the meeting note then links. Agents do not
|
|
||||||
create issues or automatically ingest transcripts into daily notes.
|
|
||||||
- Keep Markdown/zk as notes authority. Personal actionable tasks belong in
|
|
||||||
Radicale VTODO, private/email-derived work follow-ups in Microsoft To Do, and
|
|
||||||
shared development work in GitHub issues. Link Markdown context instead of
|
|
||||||
duplicating it into another task database.
|
|
||||||
|
|
||||||
#### PIM authority and presentation
|
|
||||||
|
|
||||||
- The PIM foundation must remain free of charge, with open-source components
|
|
||||||
preferred. Paid services such as Morgen are excluded from this role.
|
|
||||||
- Keep Microsoft 365 authoritative for work/university mail, calendar, people,
|
|
||||||
and Microsoft To Do. Keep Radicale authoritative for personal CalDAV
|
|
||||||
calendars/VTODO and CardDAV contacts. Clients may present both but do not copy
|
|
||||||
data between authorities or create a bidirectional bridge.
|
|
||||||
- Pilot Evolution with all four active mail identities: personal, old personal,
|
|
||||||
university, and work. Use its Microsoft 365 account type for Microsoft
|
|
||||||
identities, not legacy Exchange/EWS. Connect personal accounts and Radicale
|
|
||||||
through native IMAP/SMTP, CalDAV, CardDAV, and VTODO.
|
|
||||||
- Keep Thunderbird and the Outlook Vivaldi app throughout the pilot. Change no
|
|
||||||
authority until consent and daily behavior pass. If Evolution passes its
|
|
||||||
gate, make it the canonical desktop PIM and retire Thunderbird. Keep Outlook
|
|
||||||
as the Microsoft-native fallback, not a second general PIM workflow.
|
|
||||||
- Keep Radicale rather than adding Baikal or Nextcloud. A larger groupware stack
|
|
||||||
does not solve Microsoft federation and no personal web UI is required.
|
|
||||||
- On Android, use DAVx5 as the sole Radicale adapter. aCalendar+ and Google
|
|
||||||
Contacts consume Android providers; Tasks.org consumes DAVx5/OpenTasks and may
|
|
||||||
separately connect to Microsoft To Do. Do not configure Radicale twice.
|
|
||||||
- Use free/F-Droid DAVx5 and Tasks.org builds. Account for Tasks.org's Microsoft
|
|
||||||
To Do limits--partial recurrence, one reminder, no attachments, and no manual
|
|
||||||
ordering--and give each collection one notification owner. Test Outlook's
|
|
||||||
optional calendar/contact export and correct default accounts.
|
|
||||||
- Before removing the last independent PIM copy, test restoration of Radicale
|
|
||||||
collections and authentication data. Keep broader Orion backup redesign out
|
|
||||||
of scope.
|
|
||||||
|
|
||||||
#### Meeting transcription
|
|
||||||
|
|
||||||
- Use Fossify Voice Recorder on the Pixel and Syncthing directly to Orion. Orion
|
|
||||||
becomes the always-on transcription owner; this does not reopen general
|
|
||||||
backup, CI, builder, or agent-offload design.
|
|
||||||
- First observe a real recording transfer. Fossify writes directly to its final
|
|
||||||
filename while recording, so a Syncthing/path event alone does not prove the
|
|
||||||
meeting ended. Prefer an automatic post-record move to a dedicated inbox if
|
|
||||||
available; otherwise require an unchanged size/mtime settlement period plus
|
|
||||||
media readability/duration validation.
|
|
||||||
- Once completion detection is proven, refactor the Zenith/Vulkan module for
|
|
||||||
Orion's CPU `whisper-cpp` runtime and one inbox/processing/archive/failed tree.
|
|
||||||
Use an event-triggered path/service pair to wake an idempotent scanner instead
|
|
||||||
of polling every two minutes.
|
|
||||||
- Keep the multilingual model and automatic language handling. Run diarization
|
|
||||||
by default, but publish an unlabeled transcript when Whisper succeeds and
|
|
||||||
diarization fails; record the partial failure instead of withholding it.
|
|
||||||
- Write transcripts under `~/sync/notes/transcripts` and preserve originals in
|
|
||||||
the recordings archive. The transcript is the quiet success signal;
|
|
||||||
systemd state/logs expose failures. Add no desktop notification.
|
|
||||||
- Validate with a Dutch/English meeting, preferably with code switching, and
|
|
||||||
require completion by the next morning. Consider a GPU worker only if Orion
|
|
||||||
misses that service level. Syncthing replication is not backup.
|
|
||||||
|
|
||||||
### Phase 6: retire duplicate applications and dead configuration
|
|
||||||
|
|
||||||
Perform removals after the corresponding migration or pilot.
|
|
||||||
|
|
||||||
- After valuable definitions are migrated, remove Postman, HTTPie, Posting, and
|
|
||||||
Resterm. Keep Kulala and `xh`; keep Bruno only through the HTTP pilot and
|
|
||||||
remove it if no indispensable capability appears.
|
|
||||||
- Remove Rainfrog, dblab, Harlequin, Tabularis, DbGate, pgAdmin, Beekeeper
|
|
||||||
Studio, MongoDB Compass, pgModeler, and tbls. Remove the Harlequin profile.
|
|
||||||
Keep Dadbod and wrapper-local clients; keep DBeaver only through the database
|
|
||||||
pilot and remove it if no GUI-only need emerges.
|
|
||||||
- Remove global `usql` and MariaDB. Keep PostgreSQL, MariaDB, and `mongosh` only
|
|
||||||
in the Neovim wrapper or repository environments that own them.
|
|
||||||
- Search once for an application/plugin that shells out to npm. If found,
|
|
||||||
declare Node with that owner; otherwise remove global Node.js and Bun and keep
|
|
||||||
language runtimes in repository flakes.
|
|
||||||
- Remove Zed and the inactive Helix module, cache settings, and flake input.
|
|
||||||
Keep Neovim. Retain Jujutsu as a **deferred** experiment with no assigned
|
|
||||||
workflow until a concrete use case exists.
|
|
||||||
- Remove inactive Foot modules and keep Kitty as the only terminal.
|
|
||||||
- Remove Obsidian, Planify, and Calcure after note/PIM ownership is in place;
|
|
||||||
none owns data that needs migration.
|
|
||||||
- If Evolution passes, remove Khal, Todoman, and local `pimsync`. Keep Noctalia
|
|
||||||
as a read-oriented calendar glance surface. Add no terminal PIM client without
|
|
||||||
a demonstrated operation.
|
|
||||||
- Install Pinta beside GIMP for its bounded trial. Remove GIMP only if Pinta
|
|
||||||
covers the workload; otherwise remove Pinta and retain GIMP.
|
|
||||||
- Retain Spotify, OnlyOffice, Nautilus, imv, Sioyek, mpv, qBittorrent, and
|
|
||||||
Discord. Keep Nautilus as graphical file manager/directory default and
|
|
||||||
`xdg-desktop-portal-gnome` with GTK fallback as file chooser. Do not add
|
|
||||||
Thunar, Dolphin, Nemo, or another file manager without a concrete gap.
|
|
||||||
|
|
||||||
## Evaluation gates
|
|
||||||
|
|
||||||
### Project contract and workbench
|
|
||||||
|
|
||||||
Pass when a fresh checkout of each pilot repository can enter its environment,
|
|
||||||
discover relevant commands, run checks, and reach a useful local state using
|
|
||||||
only tracked configuration plus documented machine-local inputs. Confirm no
|
|
||||||
shell activation mutates state and a new worktree reads no ignored files from
|
|
||||||
another checkout. Extract templates only after two pilots share real boilerplate.
|
|
||||||
|
|
||||||
Run two representative development servers and test suites concurrently using
|
|
||||||
their native behavior. Continue deferring branch-derived ports, databases, and
|
|
||||||
container-project names only if endpoints remain discoverable and no actual
|
|
||||||
resource collision appears; otherwise add isolation only for the observed
|
|
||||||
conflict.
|
|
||||||
|
|
||||||
For the workbench, prove one authenticated Yookr API read, one named connection
|
|
||||||
for every needed database engine, isolated `just k8s test`, and one
|
|
||||||
Marimo-to-HTML report. Publish or expand it only after those artifacts confirm
|
|
||||||
the boundary.
|
|
||||||
|
|
||||||
### Herdr and worktrees
|
|
||||||
|
|
||||||
Exercise short and long Codex sessions, an approval-blocked session,
|
|
||||||
detach/reattach, one Claude or Pi fallback, and two independently writing task
|
|
||||||
worktrees. Evaluate runtime/attention, notifications, and worktree handling as
|
|
||||||
separate components, retaining only those that pass. Attention state must be
|
|
||||||
accurate, exactly one notification must be delivered, paths must be predictable,
|
|
||||||
dirty removal must be refused, branches must remain for review, and layout
|
|
||||||
overhead must cost less than the polling/navigation it replaces. If Herdr's
|
|
||||||
runtime or notification role fails, retain native agent sessions and Codex TUI
|
|
||||||
notifications. If its worktree role fails, use native
|
|
||||||
`git worktree add/list/remove`; compare Worktrunk only after that ceremony
|
|
||||||
becomes repeated friction.
|
|
||||||
|
|
||||||
### Agent conventions
|
|
||||||
|
|
||||||
Test the instruction-only `nixos-maintainer` skill with representative prompts
|
|
||||||
that add, change, remove, and diagnose a capability, plus unrelated prompts that
|
|
||||||
must not trigger it. Pass when it follows repository ownership, makes focused
|
|
||||||
edits, performs appropriate no-switch validation, and leaves switching to an
|
|
||||||
explicit request.
|
|
||||||
|
|
||||||
Separately, give a fresh Codex session only the repository, its `AGENTS.md`, and
|
|
||||||
a living execution plan from a substantial paused task. Promote the convention
|
|
||||||
only if it can identify the exact next step and resume correctly without chat
|
|
||||||
history or copied logs.
|
|
||||||
|
|
||||||
### S3 and SharePoint
|
|
||||||
|
|
||||||
On one real Yookr task, configure a machine-local, least-privileged S3 remote and
|
|
||||||
prove target selection, listing, download, and an explicitly authorized upload
|
|
||||||
without accidental mutation. Pass when native `rclone` commands are clear and
|
|
||||||
auditable enough that no interactive browser is needed; otherwise remove the
|
|
||||||
pilot configuration and package. Keep SharePoint deferred until company consent
|
|
||||||
and a real browse/download case exist.
|
|
||||||
|
|
||||||
### Pull-request review gate
|
|
||||||
|
|
||||||
Exercise one `gh pr view`/`gh pr diff` review and one review worktree with local
|
|
||||||
navigation or tests. Pass when metadata, checks, local verification, LazyGit,
|
|
||||||
and optional agent assistance are reachable without another review UI. If it
|
|
||||||
fails, record the exact missing operation before evaluating one maintained
|
|
||||||
alternative.
|
|
||||||
|
|
||||||
### Evolution and Android PIM
|
|
||||||
|
|
||||||
Pass Evolution only after all four accounts prove send/receive, folder behavior,
|
|
||||||
search, offline mail, invitations, recurrence exceptions, contacts/GAL,
|
|
||||||
Microsoft To Do recurrence/reminders, and acceptable daily UX. Confirm tenant
|
|
||||||
consent and one notification owner per collection. If it fails, retain
|
|
||||||
Thunderbird plus Outlook PWA and keep Radicale clients native.
|
|
||||||
|
|
||||||
On Android, prove two-way Radicale calendar/contact/task synchronization,
|
|
||||||
Microsoft To Do within documented limits, clear collection labels, correct
|
|
||||||
default accounts, recurrence, reminders, and Outlook export where permitted.
|
|
||||||
If DAVx5 fails, keep personal Radicale data in the existing desktop/native
|
|
||||||
clients and Outlook as the Microsoft 365 Android client. If only Tasks.org's
|
|
||||||
Microsoft integration fails, keep Tasks.org for personal VTODO through DAVx5
|
|
||||||
and use Outlook for Microsoft tasks. Neither failure changes server authority.
|
|
||||||
|
|
||||||
### NetworkManager VPN
|
|
||||||
|
|
||||||
Install `networkmanager-openvpn`, import the profile separately on Polaris and
|
|
||||||
Zenith with autoconnect disabled, and use Noctalia's existing Network control
|
|
||||||
center as the only desktop toggle. Pass after route, DNS, test-service access,
|
|
||||||
suspend/resume, reconnect, and reboot work on both machines. Remove OpenVPN 3
|
|
||||||
only after both pass.
|
|
||||||
|
|
||||||
### Niri active-workspace exchange
|
|
||||||
|
|
||||||
Pilot a two-output-only helper that assigns collision-free temporary names to
|
|
||||||
both active workspaces, preserves original names, moves each named workspace to
|
|
||||||
the other output, makes both arrivals active, restores names, and returns focus
|
|
||||||
to the original physical output. It remains non-atomic and must restore names
|
|
||||||
on failure where possible. Keep it only if repeated swaps are reliable and the
|
|
||||||
visible transition is acceptable; otherwise retain the current shortcut
|
|
||||||
temporarily and track a native Niri action rather than growing the wrapper.
|
|
||||||
|
|
||||||
Capture Zenith's external display identity before encoding right-hand placement
|
|
||||||
and initial focus.
|
|
||||||
|
|
||||||
### Pinta
|
|
||||||
|
|
||||||
Reproduce recent edits covering clipboard/open, selection, crop/resize/canvas,
|
|
||||||
text/drawing/shapes, layers/transparency, basic adjustments, and PNG/JPEG export.
|
|
||||||
If every required operation works, select Pinta and remove GIMP. Otherwise
|
|
||||||
remove Pinta and keep GIMP; do not retain both indefinitely.
|
|
||||||
|
|
||||||
### Transcription
|
|
||||||
|
|
||||||
Observe whether Syncthing transfers a growing Fossify recording and prove the
|
|
||||||
completion protocol before automation. Then validate one real Dutch/English
|
|
||||||
meeting end to end: recording, completed-file detection, transfer, CPU
|
|
||||||
transcription, diarization fallback, archive, and Markdown by the next morning.
|
|
||||||
Remove Zenith's timer only after Orion passes.
|
|
||||||
|
|
||||||
### Stable web-app launchers
|
|
||||||
|
|
||||||
Capture the Outlook app ID, replace stale generated launchers for Actual and
|
|
||||||
WhatsApp, and verify every Walker result starts current Vivaldi with the intended
|
|
||||||
app/profile after a NixOS upgrade and Vivaldi Sync cycle. Expose one launcher per
|
|
||||||
app.
|
|
||||||
|
|
||||||
## Deferred work
|
## Deferred work
|
||||||
|
|
||||||
- Design the team release process: intentional releases, immutable
|
- Define the team release process and OpenAPI publication policy before encoding
|
||||||
commit-addressed images, explicit revision promotion, rollout verification,
|
deployment automation.
|
||||||
rollback evidence, and Kubernetes-native base/overlay composition before a
|
- Adopt a company-wide infrastructure secret source only after Yookr selects one.
|
||||||
heavier GitOps platform. Do not encode mutable `:latest` rollout as a
|
- Publish `yookr-workbench` only when sharing becomes useful.
|
||||||
canonical workstation action.
|
- Pilot SharePoint browse/download through `rclone` after Microsoft consent.
|
||||||
- Establish service-owned OpenAPI generation, publication, provenance, and
|
- Revisit Worktrunk, `codex agents`, Walker-to-agent launching, formal agent
|
||||||
consumer-refresh policy. Existing local/network drift calls for review, not
|
evaluation, remote builders, CI runners, and agent offload only after a concrete
|
||||||
automatic overwrite.
|
gap appears.
|
||||||
- Adopt a company-wide infrastructure secret source when Yookr chooses one.
|
- Add report servers, notebook hubs, groupware, terminal PIM, meeting summaries,
|
||||||
Until then, keep manually supplied machine-local inputs and do not assume that
|
concurrency isolation, OCR, dictation, clipboard remapping, or additional
|
||||||
Bitwarden Secrets Manager is available merely because Password Manager is.
|
convenience surfaces only after repeated use establishes an owner.
|
||||||
- Publish `yookr-workbench` privately when sharing becomes useful; do not create
|
|
||||||
a temporary synchronization path.
|
|
||||||
- Pilot SharePoint browse/download through `rclone` after Microsoft consent is
|
|
||||||
known. Continuous sync and mounts require a separate demonstrated need.
|
|
||||||
- Revisit Walker bookmark search only with a live Vivaldi reader, and company
|
|
||||||
credential search only with maintained multi-vault support or repeated cost.
|
|
||||||
- Revisit Worktrunk only after a concrete Herdr worktree gap. Revisit
|
|
||||||
`codex agents` after Nix-managed daemon startup works without a second mutable
|
|
||||||
installation.
|
|
||||||
- Build a formal agent evaluation harness only after representative tasks and
|
|
||||||
concrete configurations exist. Compare repeated runs on correctness, human
|
|
||||||
intervention, review burden, conceptual complexity, wall time, and token use;
|
|
||||||
structured agent output is telemetry, not the quality judgment. Controlled
|
|
||||||
Codex evaluations consume `codex exec --json`; they never parse the
|
|
||||||
interactive TUI or mutable internal databases.
|
|
||||||
- Add Walker-to-agent launching only after the explicit Herdr/worktree sequence
|
|
||||||
becomes repetitive enough to define a stable contract.
|
|
||||||
- Keep remote Herdr, builders, CI runners, agent offload, and general Orion
|
|
||||||
backup redesign out of scope until a concrete bottleneck justifies them.
|
|
||||||
- Add a report server, notebook hub, Nextcloud groupware/Notes, terminal PIM
|
|
||||||
client, or meeting-summary skill only after a missing capability is proven.
|
|
||||||
- Add branch-derived ports, databases, container projects, or other concurrency
|
|
||||||
isolation only after an observed resource collision.
|
|
||||||
- Add LocalSend, OCR, dictation, global clipboard remapping, a second hotkey-help
|
|
||||||
surface, or other distribution-inspired conveniences only after repeated use
|
|
||||||
gives them a clear owner.
|
|
||||||
|
|
||||||
## Reference baseline
|
## Reference baseline
|
||||||
|
|
||||||
Implementation must recheck fast-moving interfaces against the pinned version.
|
Recheck fast-moving interfaces against their pinned versions before changing
|
||||||
|
them.
|
||||||
|
|
||||||
<!-- markdownlint-disable MD013 -->
|
<!-- markdownlint-disable MD013 -->
|
||||||
|
|
||||||
- Projects: [Nix flake templates](https://nix.dev/manual/nix/latest/command-ref/new-cli/nix3-flake-init), [nix-direnv](https://github.com/nix-community/nix-direnv), [just manual](https://just.systems/man/en/), [Podman Compose](https://docs.podman.io/en/latest/markdown/podman-compose.1.html), [Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html), [Marimo](https://docs.marimo.io/).
|
- Projects: [Nix flake templates](https://nix.dev/manual/nix/latest/command-ref/new-cli/nix3-flake-init), [nix-direnv](https://github.com/nix-community/nix-direnv), [just manual](https://just.systems/man/en/), [Podman Compose](https://docs.podman.io/en/latest/markdown/podman-compose.1.html), [Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html), [Marimo](https://docs.marimo.io/).
|
||||||
- APIs/data: [Kulala environments](https://kulala.app/usage/environments), [Kulala](https://github.com/mistweaverco/kulala.nvim), [Dadbod](https://github.com/tpope/vim-dadbod), [Dadbod UI](https://github.com/kristijanhusak/vim-dadbod-ui/blob/master/doc/dadbod-ui.txt), [RabbitMQ management](https://www.rabbitmq.com/docs/management), [rclone S3](https://rclone.org/s3/), [rclone OneDrive/SharePoint](https://rclone.org/onedrive/).
|
- APIs/data: [Kulala](https://kulala.app/), [Dadbod](https://github.com/tpope/vim-dadbod), [RabbitMQ management](https://www.rabbitmq.com/docs/management), [rclone S3](https://rclone.org/s3/), [rclone OneDrive/SharePoint](https://rclone.org/onedrive/).
|
||||||
- Desktop: [Walker providers](https://walkerlauncher.com/docs/providers), [Elephant menus](https://github.com/abenz1267/elephant/tree/master/internal/providers/menus), [Vivaldi web apps](https://help.vivaldi.com/desktop/miscellaneous/progressive-web-apps/), [Vivaldi Sync](https://help.vivaldi.com/desktop/tools/sync/), [Niri IPC](https://niri-wm.github.io/niri/IPC.html), [Niri actions](https://niri-wm.github.io/niri/niri_ipc/enum.Action.html), [Pinta guide](https://www.pinta-project.com/user-guide/).
|
- Desktop: [Walker](https://walkerlauncher.com/docs/providers), [Elephant menus](https://github.com/abenz1267/elephant/tree/master/internal/providers/menus), [Vivaldi web apps](https://help.vivaldi.com/desktop/miscellaneous/progressive-web-apps/), [Niri IPC](https://niri-wm.github.io/niri/IPC.html).
|
||||||
- Agents: [Codex configuration precedence](https://learn.chatgpt.com/docs/config-file/config-basic#configuration-precedence), [Codex long-running work](https://learn.chatgpt.com/docs/long-running-work), [Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents), [Codex notifications](https://learn.chatgpt.com/docs/config-file/config-advanced#notifications), [Herdr configuration](https://herdr.dev/docs/configuration/), [Herdr CLI](https://herdr.dev/docs/cli-reference/), [Git worktrees](https://git-scm.com/docs/git-worktree), [Worktrunk](https://worktrunk.dev/).
|
- Agents: [Codex configuration](https://learn.chatgpt.com/docs/config-file/config-basic), [Codex long-running work](https://learn.chatgpt.com/docs/long-running-work), [Herdr](https://herdr.dev/docs/configuration/), [Git worktrees](https://git-scm.com/docs/git-worktree).
|
||||||
- PIM/knowledge: [Evolution account types](https://help.gnome.org/evolution/intro-account-types.html), [Evolution Microsoft 365 implementation](https://gitlab.gnome.org/GNOME/evolution-ews/-/tree/master/src/Microsoft365), [Radicale](https://radicale.org/v3.html), [DAVx5](https://manual.davx5.com/introduction.html), [Tasks.org with DAVx5](https://tasks.org/docs/sync_davx5/), [Tasks.org Microsoft To Do](https://tasks.org/docs/sync_microsoft/), [`zk` daily journal](https://github.com/zk-org/zk/blob/main/docs/tips/daily-journal.md).
|
- PIM/knowledge: [Evolution account types](https://help.gnome.org/evolution/intro-account-types.html), [Radicale](https://radicale.org/v3.html), [DAVx5](https://manual.davx5.com/introduction.html), [Tasks.org](https://tasks.org/docs/), [`zk` daily journal](https://github.com/zk-org/zk/blob/main/docs/tips/daily-journal.md).
|
||||||
- Infrastructure: [Gardenctl v2](https://gardener.cloud/docs/gardenctl-v2/), [NetworkManager `nmcli`](https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/nmcli.html), [NetworkManager keyfiles](https://networkmanager.dev/docs/api/latest/nm-settings-keyfile.html), [Syncthing synchronization](https://docs.syncthing.net/users/syncing), [Fossify recorder implementation](https://github.com/FossifyOrg/Voice-Recorder/blob/main/app/src/main/kotlin/org/fossify/voicerecorder/services/RecorderService.kt).
|
- Infrastructure: [Gardenctl](https://gardener.cloud/docs/gardenctl-v2/), [NetworkManager](https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/nmcli.html), [Syncthing](https://docs.syncthing.net/users/syncing).
|
||||||
|
|
||||||
<!-- markdownlint-enable MD013 -->
|
<!-- markdownlint-enable MD013 -->
|
||||||
Generated
+18
-43
@@ -57,9 +57,13 @@
|
|||||||
"elephant": {
|
"elephant": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
"walker",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": "systems"
|
"systems": [
|
||||||
|
"walker",
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784365424,
|
"lastModified": 1784365424,
|
||||||
@@ -156,7 +160,7 @@
|
|||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": "systems_2",
|
"systems": "systems",
|
||||||
"treefmt-nix": "treefmt-nix"
|
"treefmt-nix": "treefmt-nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -215,7 +219,9 @@
|
|||||||
},
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1788335262,
|
"lastModified": 1788335262,
|
||||||
@@ -234,15 +240,15 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767892417,
|
"lastModified": 1788400875,
|
||||||
"narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=",
|
"narHash": "sha256-v4ZEET1Ah1K9+wMaIwPH/JTQK3MwW/gZC/SyjnlBX74=",
|
||||||
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
|
"rev": "5545adfad2e98de106a5544ca7067e03010410bd",
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz"
|
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1066699.5545adfad2e9/nixexprs.tar.xz"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
|
"url": "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
@@ -260,19 +266,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1788400875,
|
|
||||||
"narHash": "sha256-v4ZEET1Ah1K9+wMaIwPH/JTQK3MwW/gZC/SyjnlBX74=",
|
|
||||||
"rev": "5545adfad2e98de106a5544ca7067e03010410bd",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1066699.5545adfad2e9/nixexprs.tar.xz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"noctalia": {
|
"noctalia": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@@ -296,7 +289,6 @@
|
|||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"disko": "disko",
|
"disko": "disko",
|
||||||
"elephant": "elephant",
|
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"import-tree": "import-tree",
|
"import-tree": "import-tree",
|
||||||
@@ -304,7 +296,7 @@
|
|||||||
"nix-index-database": "nix-index-database",
|
"nix-index-database": "nix-index-database",
|
||||||
"nix-wrapper-modules": "nix-wrapper-modules",
|
"nix-wrapper-modules": "nix-wrapper-modules",
|
||||||
"nixos-hardware": "nixos-hardware",
|
"nixos-hardware": "nixos-hardware",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs",
|
||||||
"noctalia": "noctalia",
|
"noctalia": "noctalia",
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
"walker": "walker"
|
"walker": "walker"
|
||||||
@@ -331,21 +323,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689347949,
|
|
||||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
@@ -360,7 +337,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems_3": {
|
"systems_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689347949,
|
"lastModified": 1689347949,
|
||||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||||
@@ -398,13 +375,11 @@
|
|||||||
},
|
},
|
||||||
"walker": {
|
"walker": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"elephant": [
|
"elephant": "elephant",
|
||||||
"elephant"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": "systems_3"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1784217994,
|
"lastModified": 1784217994,
|
||||||
|
|||||||
@@ -20,7 +20,10 @@
|
|||||||
url = "github:BirdeeHub/nix-wrapper-modules";
|
url = "github:BirdeeHub/nix-wrapper-modules";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
nixos-hardware = {
|
||||||
|
url = "github:NixOS/nixos-hardware/master";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
|
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
|
||||||
noctalia = {
|
noctalia = {
|
||||||
url = "github:noctalia-dev/noctalia";
|
url = "github:noctalia-dev/noctalia";
|
||||||
@@ -35,13 +38,8 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
elephant = {
|
|
||||||
url = "github:abenz1267/elephant";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
walker = {
|
walker = {
|
||||||
url = "github:abenz1267/walker";
|
url = "github:abenz1267/walker";
|
||||||
inputs.elephant.follows = "elephant";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -232,9 +232,7 @@ process_scope() {
|
|||||||
local source processing_target recording_status signature index scope_status=0
|
local source processing_target recording_status signature index scope_status=0
|
||||||
local -a sources signatures
|
local -a sources signatures
|
||||||
|
|
||||||
if ! mkdir -p "$inbox_dir" "$processing_dir" "$archive_dir" "$failed_dir" "$transcript_dir"; then
|
mkdir -p "$inbox_dir" "$processing_dir" "$archive_dir" "$failed_dir" "$transcript_dir" || return 1
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
while IFS= read -r -d '' source; do
|
while IFS= read -r -d '' source; do
|
||||||
if is_recording "$source"; then
|
if is_recording "$source"; then
|
||||||
@@ -291,4 +289,3 @@ mkdir -p "$runtime_dir"
|
|||||||
|
|
||||||
set +o errexit
|
set +o errexit
|
||||||
process_scope "$TRANSCRIBE_SYNC_ROOT/recordings" "$TRANSCRIBE_SYNC_ROOT/notes/transcripts"
|
process_scope "$TRANSCRIBE_SYNC_ROOT/recordings" "$TRANSCRIBE_SYNC_ROOT/notes/transcripts"
|
||||||
exit $?
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
alsa.enable = true;
|
alsa.enable = true;
|
||||||
pulse.enable = true;
|
pulse.enable = true;
|
||||||
jack.enable = true;
|
jack.enable = true;
|
||||||
wireplumber.enable = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.desktop-commands =
|
flake.modules.homeManager.desktop-commands =
|
||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
@@ -35,12 +34,20 @@
|
|||||||
actualId = "ahoihnifhakgijcmjlhbcgehigihinlo";
|
actualId = "ahoihnifhakgijcmjlhbcgehigihinlo";
|
||||||
outlookId = "eoficlgicibekocmfdomjbfnjmehnhcd";
|
outlookId = "eoficlgicibekocmfdomjbfnjmehnhcd";
|
||||||
whatsappId = "hnpfjngllnobngcgfapefoaidbinmjnm";
|
whatsappId = "hnpfjngllnobngcgfapefoaidbinmjnm";
|
||||||
actualDesktop = pkgs.makeDesktopItem {
|
in
|
||||||
name = "vivaldi-${actualId}-Default";
|
{
|
||||||
desktopName = "Actual";
|
desktop.commands.browser = [ command ];
|
||||||
|
home = {
|
||||||
|
packages = [ pkgs.vivaldi ];
|
||||||
|
sessionVariables.BROWSER = command;
|
||||||
|
};
|
||||||
|
xdg = {
|
||||||
|
desktopEntries = {
|
||||||
|
"vivaldi-${actualId}-Default" = {
|
||||||
|
name = "Actual";
|
||||||
exec = appCommand actualId;
|
exec = appCommand actualId;
|
||||||
icon = "vivaldi-${actualId}-Default";
|
icon = "vivaldi-${actualId}-Default";
|
||||||
extraConfig.StartupWMClass = "crx_${actualId}";
|
settings.StartupWMClass = "crx_${actualId}";
|
||||||
actions = {
|
actions = {
|
||||||
Accounts = {
|
Accounts = {
|
||||||
name = "Accounts";
|
name = "Accounts";
|
||||||
@@ -56,20 +63,18 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
whatsappDesktop = pkgs.makeDesktopItem {
|
"vivaldi-${whatsappId}-Default" = {
|
||||||
name = "vivaldi-${whatsappId}-Default";
|
name = "WhatsApp Web";
|
||||||
desktopName = "WhatsApp Web";
|
|
||||||
exec = appCommand whatsappId;
|
exec = appCommand whatsappId;
|
||||||
icon = "vivaldi-${whatsappId}-Default";
|
icon = "vivaldi-${whatsappId}-Default";
|
||||||
extraConfig.StartupWMClass = "crx_${whatsappId}";
|
settings.StartupWMClass = "crx_${whatsappId}";
|
||||||
};
|
};
|
||||||
outlookDesktop = pkgs.makeDesktopItem {
|
"vivaldi-${outlookId}-Default" = {
|
||||||
name = "vivaldi-${outlookId}-Default";
|
name = "Outlook";
|
||||||
desktopName = "Outlook";
|
|
||||||
exec = "${appCommand outlookId} %U";
|
exec = "${appCommand outlookId} %U";
|
||||||
icon = "vivaldi-${outlookId}-Default";
|
icon = "vivaldi-${outlookId}-Default";
|
||||||
mimeTypes = [ "x-scheme-handler/mailto" ];
|
mimeType = [ "x-scheme-handler/mailto" ];
|
||||||
extraConfig.StartupWMClass = "crx_${outlookId}";
|
settings.StartupWMClass = "crx_${outlookId}";
|
||||||
actions = {
|
actions = {
|
||||||
Calendar = {
|
Calendar = {
|
||||||
name = "Open calendar";
|
name = "Open calendar";
|
||||||
@@ -85,27 +90,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
|
||||||
{
|
|
||||||
desktop.commands.browser = [ command ];
|
|
||||||
home = {
|
|
||||||
packages = [ pkgs.vivaldi ];
|
|
||||||
sessionVariables.BROWSER = command;
|
|
||||||
};
|
|
||||||
xdg = {
|
|
||||||
dataFile = {
|
|
||||||
"applications/vivaldi-${actualId}-Default.desktop" = {
|
|
||||||
force = true;
|
|
||||||
source = "${actualDesktop}/share/applications/vivaldi-${actualId}-Default.desktop";
|
|
||||||
};
|
|
||||||
"applications/vivaldi-${whatsappId}-Default.desktop" = {
|
|
||||||
force = true;
|
|
||||||
source = "${whatsappDesktop}/share/applications/vivaldi-${whatsappId}-Default.desktop";
|
|
||||||
};
|
|
||||||
"applications/vivaldi-${outlookId}-Default.desktop" = {
|
|
||||||
force = true;
|
|
||||||
source = "${outlookDesktop}/share/applications/vivaldi-${outlookId}-Default.desktop";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
mimeApps.defaultApplicationPackages = [ pkgs.vivaldi ];
|
mimeApps.defaultApplicationPackages = [ pkgs.vivaldi ];
|
||||||
};
|
};
|
||||||
@@ -168,9 +152,6 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
cacheHome = "${localDir}/cache";
|
cacheHome = "${localDir}/cache";
|
||||||
configHome = "${homeDir}/.config";
|
|
||||||
dataHome = "${localDir}/share";
|
|
||||||
stateHome = "${localDir}/state";
|
|
||||||
|
|
||||||
userDirs = {
|
userDirs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.dev-tools =
|
flake.modules.homeManager.dev-tools =
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
@@ -44,10 +43,7 @@
|
|||||||
gardenlogin
|
gardenlogin
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.lazygit = {
|
programs.lazygit.enable = true;
|
||||||
enable = true;
|
|
||||||
enableZshIntegration = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.jujutsu.enable = true;
|
programs.jujutsu.enable = true;
|
||||||
programs.jq.enable = true;
|
programs.jq.enable = true;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
{
|
{
|
||||||
flake.modules.nixos.flatpak = {
|
flake.modules.nixos.flatpak.services.flatpak.enable = true;
|
||||||
services.flatpak.enable = true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -28,21 +28,9 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
fontconfig = {
|
fontconfig = {
|
||||||
enable = true;
|
|
||||||
antialias = true;
|
|
||||||
allowBitmaps = false;
|
allowBitmaps = false;
|
||||||
useEmbeddedBitmaps = false;
|
useEmbeddedBitmaps = false;
|
||||||
|
subpixel.lcdfilter = "none";
|
||||||
hinting = {
|
|
||||||
enable = true;
|
|
||||||
autohint = false;
|
|
||||||
style = "slight";
|
|
||||||
};
|
|
||||||
|
|
||||||
subpixel = {
|
|
||||||
rgba = "none";
|
|
||||||
lcdfilter = "none";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
{
|
{
|
||||||
flake.modules.homeManager.keyring = {
|
flake.modules.homeManager.keyring.services.gnome-keyring.enable = true;
|
||||||
services.gnome-keyring.enable = true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{ config, lib, ... }:
|
{ lib, ... }:
|
||||||
let
|
let
|
||||||
palette = (import ./_kanagawa.nix).palette;
|
palette = (import ./_kanagawa.nix).palette;
|
||||||
hex = lib.removePrefix "#";
|
hex = lib.removePrefix "#";
|
||||||
@@ -9,9 +9,9 @@ in
|
|||||||
flake.modules.nixos.limine =
|
flake.modules.nixos.limine =
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
displayValues = builtins.attrValues config.facts.machine.displays;
|
primaryDisplay = lib.findFirst (display: display.primary) null (
|
||||||
primaryDisplays = lib.filter (display: display.primary) displayValues;
|
builtins.attrValues config.facts.machine.displays
|
||||||
primaryDisplay = if primaryDisplays == [ ] then null else builtins.head primaryDisplays;
|
);
|
||||||
interfaceResolution =
|
interfaceResolution =
|
||||||
if primaryDisplay != null && primaryDisplay.width != null then
|
if primaryDisplay != null && primaryDisplay.width != null then
|
||||||
"${toString primaryDisplay.width}x${toString primaryDisplay.height}"
|
"${toString primaryDisplay.width}x${toString primaryDisplay.height}"
|
||||||
@@ -24,6 +24,7 @@ in
|
|||||||
limine = {
|
limine = {
|
||||||
enable = true;
|
enable = true;
|
||||||
maxGenerations = 10;
|
maxGenerations = 10;
|
||||||
|
resolution = interfaceResolution;
|
||||||
|
|
||||||
style = {
|
style = {
|
||||||
backdrop = hex palette.secondaryBackground;
|
backdrop = hex palette.secondaryBackground;
|
||||||
@@ -64,14 +65,10 @@ in
|
|||||||
interface = {
|
interface = {
|
||||||
branding = config.networking.hostName;
|
branding = config.networking.hostName;
|
||||||
brandingColor = hex palette.accents.blue;
|
brandingColor = hex palette.accents.blue;
|
||||||
helpHidden = false;
|
|
||||||
resolution = interfaceResolution;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (interfaceResolution != null) {
|
|
||||||
resolution = interfaceResolution;
|
resolution = interfaceResolution;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,7 @@
|
|||||||
{
|
{
|
||||||
programs.mpv = {
|
programs.mpv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
bindings = {
|
bindings.D = "cycle deband";
|
||||||
D = "cycle deband";
|
|
||||||
};
|
|
||||||
config = {
|
config = {
|
||||||
profile = "high-quality";
|
profile = "high-quality";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
account = config.facts.account;
|
account = config.facts.account;
|
||||||
homeModules = config.flake.modules.homeManager;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.neovim =
|
flake.modules.homeManager.neovim =
|
||||||
@@ -214,15 +213,13 @@ in
|
|||||||
|
|
||||||
kulalaCorePath = "${pkgs.kulala-core}/bin/kulala-core";
|
kulalaCorePath = "${pkgs.kulala-core}/bin/kulala-core";
|
||||||
};
|
};
|
||||||
|
|
||||||
binName = "nvim";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.homeManager.primary-editor-neovim =
|
flake.modules.homeManager.primary-editor-neovim =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [ homeModules.neovim ];
|
imports = [ config.flake.modules.homeManager.neovim ];
|
||||||
|
|
||||||
home.sessionVariables = {
|
home.sessionVariables = {
|
||||||
EDITOR = "nvim";
|
EDITOR = "nvim";
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ for _, lhs in ipairs({ "grn", "gra", "grx", "grr", "gri", "grt", "gO" }) do
|
|||||||
vim.keymap.del("n", lhs)
|
vim.keymap.del("n", lhs)
|
||||||
end
|
end
|
||||||
vim.keymap.del("x", "gra")
|
vim.keymap.del("x", "gra")
|
||||||
vim.keymap.del("i", "<C-S>")
|
vim.keymap.del({ "i", "s" }, "<C-S>")
|
||||||
vim.keymap.del("s", "<C-S>")
|
|
||||||
|
|
||||||
vim.keymap.set("n", "<C-h>", "<C-w><C-h>", { desc = "Focus left window" })
|
vim.keymap.set("n", "<C-h>", "<C-w><C-h>", { desc = "Focus left window" })
|
||||||
vim.keymap.set("n", "<C-j>", "<C-w><C-j>", { desc = "Focus lower window" })
|
vim.keymap.set("n", "<C-j>", "<C-w><C-j>", { desc = "Focus lower window" })
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ require("lz.n").load({
|
|||||||
after = function()
|
after = function()
|
||||||
require("blink.cmp").setup({
|
require("blink.cmp").setup({
|
||||||
keymap = {
|
keymap = {
|
||||||
preset = "default",
|
|
||||||
["<C-j>"] = { "select_next", "fallback" },
|
["<C-j>"] = { "select_next", "fallback" },
|
||||||
["<C-k>"] = { "select_prev", "fallback" },
|
["<C-k>"] = { "select_prev", "fallback" },
|
||||||
["<Tab>"] = { "select_and_accept", "fallback" },
|
["<Tab>"] = { "select_and_accept", "fallback" },
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ require("lz.n").load({
|
|||||||
after = function()
|
after = function()
|
||||||
require("nvim-treesitter-textobjects").setup({
|
require("nvim-treesitter-textobjects").setup({
|
||||||
select = { lookahead = true },
|
select = { lookahead = true },
|
||||||
move = { set_jumps = true },
|
|
||||||
})
|
})
|
||||||
|
|
||||||
local select = require("nvim-treesitter-textobjects.select")
|
local select = require("nvim-treesitter-textobjects.select")
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ require("lz.n").load({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
after = function()
|
after = function()
|
||||||
local conform = require("conform")
|
require("conform").setup({
|
||||||
conform.setup({
|
|
||||||
formatters_by_ft = formatters_by_ft,
|
formatters_by_ft = formatters_by_ft,
|
||||||
format_on_save = function(bufnr)
|
format_on_save = function(bufnr)
|
||||||
if formatters_by_ft[vim.bo[bufnr].filetype] then
|
if formatters_by_ft[vim.bo[bufnr].filetype] then
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ require("lz.n").load({
|
|||||||
"nvim-lspconfig",
|
"nvim-lspconfig",
|
||||||
event = { "BufReadPre", "BufNewFile" },
|
event = { "BufReadPre", "BufNewFile" },
|
||||||
after = function()
|
after = function()
|
||||||
local attach_group = vim.api.nvim_create_augroup("lux-lsp-attach", { clear = true })
|
|
||||||
local detach_group = vim.api.nvim_create_augroup("lux-lsp-detach", { clear = true })
|
|
||||||
local highlight_group = vim.api.nvim_create_augroup("lux-lsp-highlight", { clear = true })
|
local highlight_group = vim.api.nvim_create_augroup("lux-lsp-highlight", { clear = true })
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd("LspAttach", {
|
vim.api.nvim_create_autocmd("LspAttach", {
|
||||||
group = attach_group,
|
group = vim.api.nvim_create_augroup("lux-lsp-attach", { clear = true }),
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
local client = assert(vim.lsp.get_client_by_id(args.data.client_id))
|
local client = assert(vim.lsp.get_client_by_id(args.data.client_id))
|
||||||
local bufnr = args.buf
|
local bufnr = args.buf
|
||||||
@@ -85,7 +83,7 @@ require("lz.n").load({
|
|||||||
})
|
})
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd("LspDetach", {
|
vim.api.nvim_create_autocmd("LspDetach", {
|
||||||
group = detach_group,
|
group = vim.api.nvim_create_augroup("lux-lsp-detach", { clear = true }),
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
local supports_highlights = vim
|
local supports_highlights = vim
|
||||||
.iter(vim.lsp.get_clients({
|
.iter(vim.lsp.get_clients({
|
||||||
|
|||||||
@@ -103,21 +103,15 @@ require("lz.n").load({
|
|||||||
actions.smart_send_to_qflist(prompt_bufnr)
|
actions.smart_send_to_qflist(prompt_bufnr)
|
||||||
vim.cmd("Trouble qflist open")
|
vim.cmd("Trouble qflist open")
|
||||||
end
|
end
|
||||||
|
local picker_mappings = {
|
||||||
|
["<C-j>"] = actions.move_selection_next,
|
||||||
|
["<C-k>"] = actions.move_selection_previous,
|
||||||
|
["<C-q>"] = promote,
|
||||||
|
}
|
||||||
|
|
||||||
require("telescope").setup({
|
require("telescope").setup({
|
||||||
defaults = {
|
defaults = {
|
||||||
mappings = {
|
mappings = { i = picker_mappings, n = picker_mappings },
|
||||||
i = {
|
|
||||||
["<C-j>"] = actions.move_selection_next,
|
|
||||||
["<C-k>"] = actions.move_selection_previous,
|
|
||||||
["<C-q>"] = promote,
|
|
||||||
},
|
|
||||||
n = {
|
|
||||||
["<C-j>"] = actions.move_selection_next,
|
|
||||||
["<C-k>"] = actions.move_selection_previous,
|
|
||||||
["<C-q>"] = promote,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
extensions = {
|
extensions = {
|
||||||
["ui-select"] = require("telescope.themes").get_dropdown(),
|
["ui-select"] = require("telescope.themes").get_dropdown(),
|
||||||
|
|||||||
@@ -60,29 +60,22 @@ require("lz.n").load({
|
|||||||
change = { text = "│" },
|
change = { text = "│" },
|
||||||
delete = { text = "_" },
|
delete = { text = "_" },
|
||||||
topdelete = { text = "‾" },
|
topdelete = { text = "‾" },
|
||||||
changedelete = { text = "~" },
|
|
||||||
untracked = { text = "┆" },
|
|
||||||
},
|
},
|
||||||
on_attach = function(bufnr)
|
on_attach = function(bufnr)
|
||||||
local gs = require("gitsigns")
|
local gs = require("gitsigns")
|
||||||
vim.keymap.set("n", "]h", function()
|
local map_hunk = function(lhs, direction, desc)
|
||||||
|
vim.keymap.set("n", lhs, function()
|
||||||
if vim.wo.diff then
|
if vim.wo.diff then
|
||||||
return "]h"
|
return lhs
|
||||||
end
|
end
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
gs.nav_hunk("next")
|
gs.nav_hunk(direction)
|
||||||
end)
|
end)
|
||||||
return "<Ignore>"
|
return "<Ignore>"
|
||||||
end, { buffer = bufnr, desc = "Next git hunk", expr = true })
|
end, { buffer = bufnr, desc = desc, expr = true })
|
||||||
vim.keymap.set("n", "[h", function()
|
|
||||||
if vim.wo.diff then
|
|
||||||
return "[h"
|
|
||||||
end
|
end
|
||||||
vim.schedule(function()
|
map_hunk("]h", "next", "Next git hunk")
|
||||||
gs.nav_hunk("prev")
|
map_hunk("[h", "prev", "Previous git hunk")
|
||||||
end)
|
|
||||||
return "<Ignore>"
|
|
||||||
end, { buffer = bufnr, desc = "Previous git hunk", expr = true })
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
{
|
{
|
||||||
browser,
|
browser,
|
||||||
launcher,
|
launcher,
|
||||||
shortcutCommands,
|
swapMonitorWorkspaces,
|
||||||
terminal,
|
terminal,
|
||||||
}:
|
}:
|
||||||
|
let
|
||||||
|
spawnLocked = command: {
|
||||||
|
spawn-sh = command;
|
||||||
|
_props.allow-when-locked = true;
|
||||||
|
};
|
||||||
|
withCooldown = action: {
|
||||||
|
${action} = { };
|
||||||
|
_props.cooldown-ms = 150;
|
||||||
|
};
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# Application and utility launchers
|
# Application and utility launchers
|
||||||
"Mod+Return" = {
|
"Mod+Return" = {
|
||||||
@@ -25,46 +35,16 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Hardware media, volume, and brightness keys
|
# Hardware media, volume, and brightness keys
|
||||||
"XF86AudioPlay" = {
|
"XF86AudioPlay" = spawnLocked "playerctl play-pause";
|
||||||
spawn-sh = "playerctl play-pause";
|
"XF86AudioStop" = spawnLocked "playerctl stop";
|
||||||
_props.allow-when-locked = true;
|
"XF86AudioPrev" = spawnLocked "playerctl previous";
|
||||||
};
|
"XF86AudioNext" = spawnLocked "playerctl next";
|
||||||
"XF86AudioStop" = {
|
"XF86AudioRaiseVolume" = spawnLocked "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+";
|
||||||
spawn-sh = "playerctl stop";
|
"XF86AudioLowerVolume" = spawnLocked "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-";
|
||||||
_props.allow-when-locked = true;
|
"XF86AudioMute" = spawnLocked "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
|
||||||
};
|
"XF86AudioMicMute" = spawnLocked "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle";
|
||||||
"XF86AudioPrev" = {
|
"XF86MonBrightnessUp" = spawnLocked "brightnessctl s 5%+";
|
||||||
spawn-sh = "playerctl previous";
|
"XF86MonBrightnessDown" = spawnLocked "brightnessctl s 5%-";
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86AudioNext" = {
|
|
||||||
spawn-sh = "playerctl next";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86AudioRaiseVolume" = {
|
|
||||||
spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86AudioLowerVolume" = {
|
|
||||||
spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86AudioMute" = {
|
|
||||||
spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86AudioMicMute" = {
|
|
||||||
spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86MonBrightnessUp" = {
|
|
||||||
spawn-sh = "brightnessctl s 5%+";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
"XF86MonBrightnessDown" = {
|
|
||||||
spawn-sh = "brightnessctl s 5%-";
|
|
||||||
_props.allow-when-locked = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
"Mod+S".screenshot = { };
|
"Mod+S".screenshot = { };
|
||||||
@@ -105,7 +85,7 @@
|
|||||||
"Mod+Tab".focus-monitor-next = { };
|
"Mod+Tab".focus-monitor-next = { };
|
||||||
"Mod+A" = {
|
"Mod+A" = {
|
||||||
_props.repeat = false;
|
_props.repeat = false;
|
||||||
spawn = shortcutCommands.swapMonitorWorkspaces;
|
spawn = swapMonitorWorkspaces;
|
||||||
_props.hotkey-overlay-title = "Swap Monitor Workspaces";
|
_props.hotkey-overlay-title = "Swap Monitor Workspaces";
|
||||||
};
|
};
|
||||||
"Mod+Alt+Tab".move-column-to-monitor-next = { };
|
"Mod+Alt+Tab".move-column-to-monitor-next = { };
|
||||||
@@ -124,22 +104,10 @@
|
|||||||
"Mod+Shift+I".move-workspace-up = { };
|
"Mod+Shift+I".move-workspace-up = { };
|
||||||
|
|
||||||
# Mouse workspace navigation
|
# Mouse workspace navigation
|
||||||
"Mod+WheelScrollDown" = {
|
"Mod+WheelScrollDown" = withCooldown "focus-workspace-down";
|
||||||
focus-workspace-down = { };
|
"Mod+WheelScrollUp" = withCooldown "focus-workspace-up";
|
||||||
_props.cooldown-ms = 150;
|
"Mod+Alt+WheelScrollDown" = withCooldown "move-column-to-workspace-down";
|
||||||
};
|
"Mod+Alt+WheelScrollUp" = withCooldown "move-column-to-workspace-up";
|
||||||
"Mod+WheelScrollUp" = {
|
|
||||||
focus-workspace-up = { };
|
|
||||||
_props.cooldown-ms = 150;
|
|
||||||
};
|
|
||||||
"Mod+Alt+WheelScrollDown" = {
|
|
||||||
move-column-to-workspace-down = { };
|
|
||||||
_props.cooldown-ms = 150;
|
|
||||||
};
|
|
||||||
"Mod+Alt+WheelScrollUp" = {
|
|
||||||
move-column-to-workspace-up = { };
|
|
||||||
_props.cooldown-ms = 150;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Mouse column navigation and movement
|
# Mouse column navigation and movement
|
||||||
"Mod+WheelScrollRight".focus-column-or-monitor-right = { };
|
"Mod+WheelScrollRight".focus-column-or-monitor-right = { };
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
{
|
{ pkgs }:
|
||||||
lib,
|
pkgs.writeShellApplication {
|
||||||
pkgs,
|
|
||||||
}:
|
|
||||||
rec {
|
|
||||||
scripts = {
|
|
||||||
swapMonitorWorkspaces = pkgs.writeShellApplication {
|
|
||||||
name = "niri-shortcut-swap-monitor-workspaces";
|
name = "niri-shortcut-swap-monitor-workspaces";
|
||||||
runtimeInputs = [
|
runtimeInputs = [
|
||||||
pkgs.jq
|
pkgs.jq
|
||||||
@@ -39,8 +34,4 @@ rec {
|
|||||||
niri msg action focus-workspace "$target_workspace_idx"
|
niri msg action focus-workspace "$target_workspace_idx"
|
||||||
niri msg action move-workspace-to-monitor "$focused_output"
|
niri msg action move-workspace-to-monitor "$focused_output"
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
commands = lib.mapAttrs (_: lib.getExe) scripts;
|
|
||||||
}
|
}
|
||||||
@@ -29,12 +29,7 @@ in
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
palette = kanagawa.palette;
|
palette = kanagawa.palette;
|
||||||
shortcuts = import ./_shortcuts.nix {
|
swapMonitorWorkspaces = import ./_shortcuts.nix { inherit pkgs; };
|
||||||
inherit
|
|
||||||
lib
|
|
||||||
pkgs
|
|
||||||
;
|
|
||||||
};
|
|
||||||
machine = config.facts.machine;
|
machine = config.facts.machine;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -47,7 +42,7 @@ in
|
|||||||
brightnessctl
|
brightnessctl
|
||||||
wireplumber
|
wireplumber
|
||||||
]
|
]
|
||||||
++ lib.attrValues shortcuts.scripts;
|
++ [ swapMonitorWorkspaces ];
|
||||||
};
|
};
|
||||||
|
|
||||||
dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark";
|
dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark";
|
||||||
@@ -140,7 +135,7 @@ in
|
|||||||
launcher
|
launcher
|
||||||
terminal
|
terminal
|
||||||
;
|
;
|
||||||
shortcutCommands = shortcuts.commands;
|
swapMonitorWorkspaces = lib.getExe swapMonitorWorkspaces;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,15 +3,12 @@ let
|
|||||||
account = config.facts.account;
|
account = config.facts.account;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.nix =
|
flake.modules.nixos.nix = {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
nix = {
|
nix = {
|
||||||
gc.automatic = true;
|
gc.automatic = true;
|
||||||
optimise.automatic = true;
|
optimise.automatic = true;
|
||||||
registry.nixpkgs.flake = inputs.nixpkgs;
|
|
||||||
channel.enable = false;
|
channel.enable = false;
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
|
|||||||
@@ -61,17 +61,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
desktop_widgets = {
|
desktop_widgets.enabled = false;
|
||||||
enabled = false;
|
|
||||||
schema_version = 2;
|
|
||||||
widget_order = [ ];
|
|
||||||
grid = {
|
|
||||||
cell_size = 16;
|
|
||||||
major_interval = 4;
|
|
||||||
visible = true;
|
|
||||||
};
|
|
||||||
widget = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
location.address = "Meterik, The Netherlands";
|
location.address = "Meterik, The Netherlands";
|
||||||
|
|
||||||
@@ -98,7 +88,6 @@
|
|||||||
font_family = "Lexend";
|
font_family = "Lexend";
|
||||||
polkit_agent = true;
|
polkit_agent = true;
|
||||||
screen_time_enabled = true;
|
screen_time_enabled = true;
|
||||||
settings_show_advanced = true;
|
|
||||||
animation.speed = 1.5;
|
animation.speed = 1.5;
|
||||||
screen_corners = {
|
screen_corners = {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
@@ -127,7 +116,6 @@
|
|||||||
|
|
||||||
widget = {
|
widget = {
|
||||||
bluetooth.hide_when_no_connected_device = true;
|
bluetooth.hide_when_no_connected_device = true;
|
||||||
clock.format = "{:%H:%M}";
|
|
||||||
media = {
|
media = {
|
||||||
art_size = 90.0;
|
art_size = 90.0;
|
||||||
max_length = 800;
|
max_length = 800;
|
||||||
|
|||||||
@@ -12,16 +12,13 @@ in
|
|||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
pinentryPackage = pkgs.pinentry-gnome3;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
programs.rbw = {
|
programs.rbw = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
base_url = facts.services.vaultwarden.origin;
|
base_url = facts.services.vaultwarden.origin;
|
||||||
email = account.emails.${account.primaryEmail}.address;
|
email = account.emails.${account.primaryEmail}.address;
|
||||||
pinentry = pinentryPackage;
|
pinentry = pkgs.pinentry-gnome3;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ in
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
@@ -31,7 +30,6 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
enable = true;
|
|
||||||
inherit address;
|
inherit address;
|
||||||
realName = account.realName;
|
realName = account.realName;
|
||||||
userName = address;
|
userName = address;
|
||||||
@@ -50,7 +48,6 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
enable = true;
|
|
||||||
inherit address;
|
inherit address;
|
||||||
realName = account.realName;
|
realName = account.realName;
|
||||||
userName = address;
|
userName = address;
|
||||||
@@ -59,13 +56,11 @@ in
|
|||||||
authentication = "plain";
|
authentication = "plain";
|
||||||
host = "taylor.mxrouting.net";
|
host = "taylor.mxrouting.net";
|
||||||
port = 993;
|
port = 993;
|
||||||
tls.enable = true;
|
|
||||||
};
|
};
|
||||||
smtp = {
|
smtp = {
|
||||||
authentication = "plain";
|
authentication = "plain";
|
||||||
host = "taylor.mxrouting.net";
|
host = "taylor.mxrouting.net";
|
||||||
port = 465;
|
port = 465;
|
||||||
tls.enable = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
mkEmailAccount =
|
mkEmailAccount =
|
||||||
@@ -103,9 +98,6 @@ in
|
|||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
calendarsPath = "${config.xdg.dataHome}/calendars";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [ homeModules.sops ];
|
imports = [ homeModules.sops ];
|
||||||
|
|
||||||
@@ -136,16 +128,11 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
accounts.calendar = {
|
accounts.calendar = {
|
||||||
basePath = calendarsPath;
|
basePath = "${config.xdg.dataHome}/calendars";
|
||||||
accounts.radicale = {
|
accounts.radicale = {
|
||||||
primary = true;
|
primary = true;
|
||||||
primaryCollection = "personal";
|
primaryCollection = "personal";
|
||||||
|
|
||||||
local = {
|
|
||||||
type = "filesystem";
|
|
||||||
fileExt = ".ics";
|
|
||||||
};
|
|
||||||
|
|
||||||
remote = {
|
remote = {
|
||||||
url = "${facts.services.radicale.origin}/";
|
url = "${facts.services.radicale.origin}/";
|
||||||
type = "caldav";
|
type = "caldav";
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
|
||||||
homeModules = config.flake.modules.homeManager;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.nixos.podman =
|
flake.modules.nixos.podman =
|
||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
home-manager.sharedModules = [ homeModules.podman ];
|
home-manager.sharedModules = [ config.flake.modules.homeManager.podman ];
|
||||||
|
|
||||||
virtualisation.podman.enable = true;
|
virtualisation.podman.enable = true;
|
||||||
virtualisation.containers.containersConf.settings.engine.compose_providers = [
|
virtualisation.containers.containersConf.settings.engine.compose_providers = [
|
||||||
|
|||||||
@@ -7,9 +7,7 @@
|
|||||||
printing = {
|
printing = {
|
||||||
enable = true;
|
enable = true;
|
||||||
browsed.enable = true;
|
browsed.enable = true;
|
||||||
drivers = with pkgs; [
|
drivers = [ pkgs.cnijfilter2 ];
|
||||||
cnijfilter2
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
avahi = {
|
avahi = {
|
||||||
|
|||||||
@@ -13,9 +13,7 @@
|
|||||||
theme = "${
|
theme = "${
|
||||||
pkgs.sddm-astronaut.override { embeddedTheme = "purple_leaves"; }
|
pkgs.sddm-astronaut.override { embeddedTheme = "purple_leaves"; }
|
||||||
}/share/sddm/themes/sddm-astronaut-theme";
|
}/share/sddm/themes/sddm-astronaut-theme";
|
||||||
extraPackages = with pkgs; [
|
extraPackages = [ pkgs.kdePackages.qtmultimedia ];
|
||||||
kdePackages.qtmultimedia
|
|
||||||
];
|
|
||||||
settings.Theme = {
|
settings.Theme = {
|
||||||
CursorTheme = "phinger-cursors-light";
|
CursorTheme = "phinger-cursors-light";
|
||||||
CursorSize = 24;
|
CursorSize = 24;
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
|
||||||
service = config.facts.services.actual;
|
|
||||||
nixosModules = config.flake.modules.nixos;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.nixos.actual = {
|
flake.modules.nixos.actual = {
|
||||||
imports = [ nixosModules.caddy ];
|
imports = [ config.flake.modules.nixos.caddy ];
|
||||||
|
|
||||||
services.actual = {
|
services.actual = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = false;
|
|
||||||
settings = {
|
settings = {
|
||||||
hostname = "127.0.0.1";
|
hostname = "127.0.0.1";
|
||||||
port = 3000;
|
port = 3000;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.caddy.virtualHosts.${service.domain}.extraConfig = "reverse_proxy 127.0.0.1:3000";
|
services.caddy.virtualHosts.${config.facts.services.actual.domain}.extraConfig =
|
||||||
|
"reverse_proxy 127.0.0.1:3000";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -19,9 +19,6 @@ in
|
|||||||
ROOT_URL = "${service.origin}/";
|
ROOT_URL = "${service.origin}/";
|
||||||
HTTP_PORT = 3001;
|
HTTP_PORT = 3001;
|
||||||
HTTP_ADDR = "127.0.0.1";
|
HTTP_ADDR = "127.0.0.1";
|
||||||
|
|
||||||
START_SSH_SERVER = false;
|
|
||||||
SSH_PORT = 22;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
service.DISABLE_REGISTRATION = true;
|
service.DISABLE_REGISTRATION = true;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
account = config.facts.account;
|
account = config.facts.account;
|
||||||
personalPublicKeys =
|
personalPublicKeys = map (machine: machine.sshKeys.personal.publicKey) (
|
||||||
machines:
|
lib.filter (machine: machine.sshKeys ? personal) (builtins.attrValues config.facts.machines)
|
||||||
map (machine: machine.sshKeys.personal.publicKey) (
|
|
||||||
lib.filter (machine: machine.sshKeys ? personal) (builtins.attrValues machines)
|
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -15,9 +13,7 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.openssh =
|
flake.modules.nixos.openssh = {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
@@ -27,6 +23,6 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.${account.name}.openssh.authorizedKeys.keys = personalPublicKeys config.facts.machines;
|
users.users.${account.name}.openssh.authorizedKeys.keys = personalPublicKeys;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
|
||||||
service = config.facts.services.radicale;
|
|
||||||
nixosModules = config.flake.modules.nixos;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.nixos.radicale = {
|
flake.modules.nixos.radicale = {
|
||||||
imports = [ nixosModules.caddy ];
|
imports = [ config.flake.modules.nixos.caddy ];
|
||||||
|
|
||||||
services.radicale = {
|
services.radicale = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -17,15 +13,12 @@ in
|
|||||||
htpasswd_filename = "/var/lib/radicale/users";
|
htpasswd_filename = "/var/lib/radicale/users";
|
||||||
htpasswd_encryption = "bcrypt";
|
htpasswd_encryption = "bcrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
storage.filesystem_folder = "/var/lib/radicale/collections";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.caddy.virtualHosts.${service.domain}.extraConfig = ''
|
services.caddy.virtualHosts.${config.facts.services.radicale.domain}.extraConfig = ''
|
||||||
reverse_proxy 127.0.0.1:5232 {
|
reverse_proxy 127.0.0.1:5232 {
|
||||||
header_up X-Script-Name /
|
header_up X-Script-Name /
|
||||||
header_up X-Forwarded-For {remote}
|
|
||||||
header_up X-Remote-User {http.auth.user.id}
|
header_up X-Remote-User {http.auth.user.id}
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
service = config.facts.services.vaultwarden;
|
service = config.facts.services.vaultwarden;
|
||||||
nixosModules = config.flake.modules.nixos;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.vaultwarden = {
|
flake.modules.nixos.vaultwarden = {
|
||||||
imports = [ nixosModules.caddy ];
|
imports = [ config.flake.modules.nixos.caddy ];
|
||||||
|
|
||||||
services.vaultwarden = {
|
services.vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
flake.modules.nixos.vps-insights =
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
localAddress = "127.0.0.1";
|
|
||||||
grafanaDataDir = config.services.grafana.dataDir;
|
|
||||||
lokiDataDir = config.services.loki.dataDir;
|
|
||||||
lokiUrl = "http://${localAddress}:3100";
|
|
||||||
prometheusUrl = "http://${localAddress}:9090";
|
|
||||||
hasCaddy = config.services.caddy.enable;
|
|
||||||
hasOpenSSH = config.services.openssh.enable;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
environment = {
|
|
||||||
etc."alloy/config.alloy".text = ''
|
|
||||||
loki.relabel "journal" {
|
|
||||||
forward_to = []
|
|
||||||
|
|
||||||
rule {
|
|
||||||
source_labels = ["__journal__systemd_unit"]
|
|
||||||
target_label = "unit"
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
source_labels = ["__journal_syslog_identifier"]
|
|
||||||
target_label = "syslog_identifier"
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
source_labels = ["__journal_priority_keyword"]
|
|
||||||
target_label = "level"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.source.journal "system" {
|
|
||||||
forward_to = [loki.write.local.receiver]
|
|
||||||
relabel_rules = loki.relabel.journal.rules
|
|
||||||
max_age = "24h"
|
|
||||||
labels = {
|
|
||||||
host = "${config.networking.hostName}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.write "local" {
|
|
||||||
endpoint {
|
|
||||||
url = "${lokiUrl}/loki/api/v1/push"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
systemPackages = with pkgs; [
|
|
||||||
goaccess
|
|
||||||
lynis
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
# Keep local system logs available for Loki and manual inspection.
|
|
||||||
journald.extraConfig = ''
|
|
||||||
Storage=persistent
|
|
||||||
SystemMaxUse=1G
|
|
||||||
MaxRetentionSec=30day
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Detect and block common attacks against SSH and Caddy.
|
|
||||||
crowdsec = {
|
|
||||||
enable = true;
|
|
||||||
hub.collections = [ "crowdsecurity/linux" ] ++ lib.optional hasCaddy "crowdsecurity/caddy";
|
|
||||||
localConfig.acquisitions =
|
|
||||||
lib.optional hasOpenSSH {
|
|
||||||
source = "journalctl";
|
|
||||||
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
|
|
||||||
labels.type = "syslog";
|
|
||||||
}
|
|
||||||
++ lib.optional hasCaddy {
|
|
||||||
filenames = [ "/var/log/caddy/*.log" ];
|
|
||||||
labels.type = "caddy";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
crowdsec-firewall-bouncer = {
|
|
||||||
enable = true;
|
|
||||||
registerBouncer.bouncerName = "${config.networking.hostName}-firewall-bouncer";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Keep Grafana local and separate from Actual's port.
|
|
||||||
grafana = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
analytics.reporting_enabled = false;
|
|
||||||
server = {
|
|
||||||
http_addr = localAddress;
|
|
||||||
http_port = 3002;
|
|
||||||
};
|
|
||||||
security = {
|
|
||||||
admin_password = "$__file{${grafanaDataDir}/admin-password}";
|
|
||||||
secret_key = "$__file{${grafanaDataDir}/secret-key}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
provision.datasources.settings = {
|
|
||||||
prune = true;
|
|
||||||
datasources = [
|
|
||||||
{
|
|
||||||
name = "Prometheus";
|
|
||||||
type = "prometheus";
|
|
||||||
uid = "prometheus";
|
|
||||||
url = prometheusUrl;
|
|
||||||
isDefault = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "Loki";
|
|
||||||
type = "loki";
|
|
||||||
uid = "loki";
|
|
||||||
url = lokiUrl;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Store local logs in Loki and feed them from journald through Alloy.
|
|
||||||
loki = {
|
|
||||||
enable = true;
|
|
||||||
configuration = {
|
|
||||||
analytics.reporting_enabled = false;
|
|
||||||
auth_enabled = false;
|
|
||||||
|
|
||||||
server = {
|
|
||||||
http_listen_address = localAddress;
|
|
||||||
http_listen_port = 3100;
|
|
||||||
grpc_listen_address = localAddress;
|
|
||||||
grpc_listen_port = 9096;
|
|
||||||
};
|
|
||||||
|
|
||||||
common = {
|
|
||||||
path_prefix = lokiDataDir;
|
|
||||||
replication_factor = 1;
|
|
||||||
instance_interface_names = [ "lo" ];
|
|
||||||
ring = {
|
|
||||||
instance_addr = localAddress;
|
|
||||||
kvstore.store = "inmemory";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
schema_config.configs = [
|
|
||||||
{
|
|
||||||
from = "2025-01-01";
|
|
||||||
store = "tsdb";
|
|
||||||
object_store = "filesystem";
|
|
||||||
schema = "v13";
|
|
||||||
index = {
|
|
||||||
prefix = "index_";
|
|
||||||
period = "24h";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
storage_config.filesystem.directory = "${lokiDataDir}/chunks";
|
|
||||||
|
|
||||||
compactor = {
|
|
||||||
working_directory = "${lokiDataDir}/compactor";
|
|
||||||
retention_enabled = true;
|
|
||||||
delete_request_store = "filesystem";
|
|
||||||
};
|
|
||||||
|
|
||||||
limits_config.retention_period = "720h";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
alloy = {
|
|
||||||
enable = true;
|
|
||||||
extraFlags = [ "--server.http.listen-addr=${localAddress}:12345" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Collect basic VPS health metrics for Grafana.
|
|
||||||
prometheus = {
|
|
||||||
enable = true;
|
|
||||||
listenAddress = localAddress;
|
|
||||||
retentionTime = "30d";
|
|
||||||
scrapeConfigs = [
|
|
||||||
{
|
|
||||||
job_name = "prometheus";
|
|
||||||
static_configs = [
|
|
||||||
{
|
|
||||||
targets = [ "${localAddress}:9090" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
job_name = "node";
|
|
||||||
static_configs = [
|
|
||||||
{
|
|
||||||
targets = [ "${localAddress}:9100" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
exporters.node = {
|
|
||||||
enable = true;
|
|
||||||
listenAddress = localAddress;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.grafana.preStart = ''
|
|
||||||
umask 077
|
|
||||||
|
|
||||||
if [ ! -s ${grafanaDataDir}/admin-password ]; then
|
|
||||||
${pkgs.openssl}/bin/openssl rand -base64 32 > ${grafanaDataDir}/admin-password
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -s ${grafanaDataDir}/secret-key ]; then
|
|
||||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${grafanaDataDir}/secret-key
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
dotDir = "${config.xdg.configHome}/zsh";
|
dotDir = "${config.xdg.configHome}/zsh";
|
||||||
|
|
||||||
enableCompletion = true;
|
|
||||||
completionInit = ''
|
completionInit = ''
|
||||||
autoload -U compinit
|
autoload -U compinit
|
||||||
compinit -C
|
compinit -C
|
||||||
@@ -50,16 +49,7 @@
|
|||||||
|
|
||||||
historySubstringSearch.enable = true;
|
historySubstringSearch.enable = true;
|
||||||
|
|
||||||
history = {
|
history.path = "${config.xdg.dataHome}/zsh_history";
|
||||||
ignoreDups = true;
|
|
||||||
save = 10000;
|
|
||||||
size = 10000;
|
|
||||||
path = "${config.xdg.dataHome}/zsh_history";
|
|
||||||
};
|
|
||||||
|
|
||||||
profileExtra = lib.optionalString (config.home.sessionPath != [ ]) ''
|
|
||||||
export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}"
|
|
||||||
'';
|
|
||||||
|
|
||||||
initContent = ''
|
initContent = ''
|
||||||
source <(gardenctl rc zsh --no-completion)
|
source <(gardenctl rc zsh --no-completion)
|
||||||
@@ -118,19 +108,8 @@
|
|||||||
|
|
||||||
programs.starship = {
|
programs.starship = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableZshIntegration = true;
|
|
||||||
settings = {
|
settings = {
|
||||||
add_newline = true;
|
format = "$nix_shell$hostname$directory$git_branch$git_state$line_break$character";
|
||||||
|
|
||||||
format = lib.concatStrings [
|
|
||||||
"$nix_shell"
|
|
||||||
"$hostname"
|
|
||||||
"$directory"
|
|
||||||
"$git_branch"
|
|
||||||
"$git_state"
|
|
||||||
"$line_break"
|
|
||||||
"$character"
|
|
||||||
];
|
|
||||||
|
|
||||||
directory = {
|
directory = {
|
||||||
truncation_length = 99;
|
truncation_length = 99;
|
||||||
@@ -147,8 +126,6 @@
|
|||||||
format = "([$state( $progress_current/$progress_total)]($style)) ";
|
format = "([$state( $progress_current/$progress_total)]($style)) ";
|
||||||
style = "bright-black";
|
style = "bright-black";
|
||||||
};
|
};
|
||||||
|
|
||||||
line_break.disabled = false;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,15 +134,9 @@
|
|||||||
extraOptions = [ "--group-directories-first" ];
|
extraOptions = [ "--group-directories-first" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.zoxide = {
|
programs.zoxide.enable = true;
|
||||||
enable = true;
|
|
||||||
enableZshIntegration = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.fzf = {
|
programs.fzf.enable = true;
|
||||||
enable = true;
|
|
||||||
enableZshIntegration = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.bottom.enable = true;
|
programs.bottom.enable = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
{ lib, config, ... }:
|
{ lib, config, ... }:
|
||||||
let
|
let
|
||||||
kanagawa = import ./_kanagawa.nix;
|
|
||||||
homeModules = config.flake.modules.homeManager;
|
homeModules = config.flake.modules.homeManager;
|
||||||
|
in
|
||||||
kittySingleInstance =
|
{
|
||||||
pkgs:
|
flake.modules.homeManager.terminal-kitty =
|
||||||
pkgs.symlinkJoin {
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
theme = import ./_kanagawa.nix;
|
||||||
|
palette = theme.palette;
|
||||||
|
kitty = pkgs.symlinkJoin {
|
||||||
name = "kitty-single";
|
name = "kitty-single";
|
||||||
paths = [ pkgs.kitty ];
|
paths = [ pkgs.kitty ];
|
||||||
meta = pkgs.kitty.meta;
|
meta = pkgs.kitty.meta;
|
||||||
@@ -16,15 +19,6 @@ let
|
|||||||
sed 's/^Exec=kitty/Exec=kitty -1/' ${pkgs.kitty}/share/applications/kitty.desktop > $out/share/applications/kitty.desktop
|
sed 's/^Exec=kitty/Exec=kitty -1/' ${pkgs.kitty}/share/applications/kitty.desktop > $out/share/applications/kitty.desktop
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
flake.modules.homeManager.terminal-kitty =
|
|
||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
theme = kanagawa;
|
|
||||||
palette = theme.palette;
|
|
||||||
kitty = kittySingleInstance pkgs;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.kitty = {
|
programs.kitty = {
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
hmModules = config.flake.modules.homeManager;
|
|
||||||
cursor = {
|
cursor = {
|
||||||
name = "phinger-cursors-light";
|
name = "phinger-cursors-light";
|
||||||
packageName = "phinger-cursors";
|
|
||||||
size = 24;
|
size = 24;
|
||||||
};
|
};
|
||||||
mkCursor = pkgs: cursor // { package = pkgs.${cursor.packageName}; };
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.theme =
|
flake.modules.nixos.theme =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
|
||||||
cursorTheme = mkCursor pkgs;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
home-manager.sharedModules = [ hmModules.theme ];
|
home-manager.sharedModules = [ config.flake.modules.homeManager.theme ];
|
||||||
environment.systemPackages = [ cursorTheme.package ];
|
environment.systemPackages = [ pkgs.phinger-cursors ];
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.homeManager.theme =
|
flake.modules.homeManager.theme =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
let
|
||||||
cursorTheme = mkCursor pkgs;
|
|
||||||
version = "unstable-2025-10-23";
|
version = "unstable-2025-10-23";
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "Fausto-Korpsvart";
|
owner = "Fausto-Korpsvart";
|
||||||
@@ -52,13 +45,9 @@ in
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
home.pointerCursor = {
|
home.pointerCursor = cursor // {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (cursorTheme)
|
package = pkgs.phinger-cursors;
|
||||||
name
|
|
||||||
package
|
|
||||||
size
|
|
||||||
;
|
|
||||||
dotIcons.enable = false;
|
dotIcons.enable = false;
|
||||||
gtk.enable = true;
|
gtk.enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
|
||||||
homeModules = config.flake.modules.homeManager;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.transcription =
|
flake.modules.homeManager.transcription =
|
||||||
{
|
{
|
||||||
@@ -111,7 +108,6 @@ in
|
|||||||
"TRANSCRIBE_DIARIZATION_MODEL=${diarizationModel}"
|
"TRANSCRIBE_DIARIZATION_MODEL=${diarizationModel}"
|
||||||
"TRANSCRIBE_DIARIZATION_MODEL_NAME=${diarizationModelName}"
|
"TRANSCRIBE_DIARIZATION_MODEL_NAME=${diarizationModelName}"
|
||||||
"TRANSCRIBE_DIARIZATION_MODEL_REVISION=${diarizationModelRevision}"
|
"TRANSCRIBE_DIARIZATION_MODEL_REVISION=${diarizationModelRevision}"
|
||||||
"TRANSCRIBE_SETTLE_SECONDS=300"
|
|
||||||
"TRANSCRIBE_SYNC_ROOT=${home}/sync"
|
"TRANSCRIBE_SYNC_ROOT=${home}/sync"
|
||||||
];
|
];
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
@@ -124,18 +120,13 @@ in
|
|||||||
systemd.user.paths.transcribe-recordings = {
|
systemd.user.paths.transcribe-recordings = {
|
||||||
Unit.Description = "Watch for synchronized recordings";
|
Unit.Description = "Watch for synchronized recordings";
|
||||||
|
|
||||||
Path = {
|
Path.PathChanged = "${home}/sync/recordings/inbox";
|
||||||
PathChanged = "${home}/sync/recordings/inbox";
|
|
||||||
Unit = "transcribe-recordings.service";
|
|
||||||
};
|
|
||||||
|
|
||||||
Install.WantedBy = [ "paths.target" ];
|
Install.WantedBy = [ "paths.target" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.transcription =
|
flake.modules.nixos.transcription = {
|
||||||
{ ... }:
|
home-manager.sharedModules = [ config.flake.modules.homeManager.transcription ];
|
||||||
{
|
|
||||||
home-manager.sharedModules = [ homeModules.transcription ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
{ config, inputs, ... }:
|
{ config, inputs, ... }:
|
||||||
let
|
|
||||||
homeModules = config.flake.modules.homeManager;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.nixos.walker = {
|
flake.modules.nixos.walker = {
|
||||||
home-manager.sharedModules = [ homeModules.walker ];
|
home-manager.sharedModules = [ config.flake.modules.homeManager.walker ];
|
||||||
|
|
||||||
nix.settings = {
|
nix.settings = {
|
||||||
extra-substituters = [
|
extra-substituters = [
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
{
|
{
|
||||||
flake.modules.nixos.yookr-dev =
|
flake.modules.nixos.yookr-dev = {
|
||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
security.pki.certificateFiles = [
|
security.pki.certificateFiles = [
|
||||||
./yookr-dev/zenith-rootCA.pem
|
./yookr-dev/zenith-rootCA.pem
|
||||||
./yookr-dev/polaris-rootCA.pem
|
./yookr-dev/polaris-rootCA.pem
|
||||||
|
|||||||
+1
-3
@@ -266,9 +266,7 @@ in
|
|||||||
machines
|
machines
|
||||||
topology
|
topology
|
||||||
;
|
;
|
||||||
services = lib.mapAttrs (_: service: {
|
services = lib.mapAttrs (_: service: removeAttrs service [ "origin" ]) osConfig.facts.services;
|
||||||
inherit (service) scheme domain;
|
|
||||||
}) osConfig.facts.services;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,15 +7,10 @@
|
|||||||
let
|
let
|
||||||
mkHost =
|
mkHost =
|
||||||
name: machine:
|
name: machine:
|
||||||
{ pkgs, ... }:
|
hostArgs@{ pkgs, ... }:
|
||||||
let
|
let
|
||||||
account = config.facts.account;
|
account = config.facts.account;
|
||||||
machineFacts = machine // {
|
services = lib.mapAttrs (_: service: removeAttrs service [ "origin" ]) config.facts.services;
|
||||||
inherit name;
|
|
||||||
};
|
|
||||||
services = lib.mapAttrs (_: service: {
|
|
||||||
inherit (service) scheme domain;
|
|
||||||
}) config.facts.services;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -30,7 +25,9 @@ let
|
|||||||
topology
|
topology
|
||||||
;
|
;
|
||||||
inherit services;
|
inherit services;
|
||||||
machine = machineFacts;
|
machine = machine // {
|
||||||
|
inherit name;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.hostName = name;
|
networking.hostName = name;
|
||||||
@@ -38,9 +35,12 @@ let
|
|||||||
|
|
||||||
programs.zsh.enable = true;
|
programs.zsh.enable = true;
|
||||||
|
|
||||||
|
sops.secrets.hashed-password.neededForUsers = true;
|
||||||
|
|
||||||
users.users.${account.name} = {
|
users.users.${account.name} = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
home = account.homeDirectory;
|
home = account.homeDirectory;
|
||||||
|
hashedPasswordFile = hostArgs.config.sops.secrets.hashed-password.path;
|
||||||
extraGroups = [
|
extraGroups = [
|
||||||
"wheel"
|
"wheel"
|
||||||
"networkmanager"
|
"networkmanager"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
boot = {
|
boot = {
|
||||||
name = "boot";
|
|
||||||
size = "1M";
|
size = "1M";
|
||||||
type = "EF02";
|
type = "EF02";
|
||||||
};
|
};
|
||||||
@@ -25,7 +24,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
root = {
|
root = {
|
||||||
name = "root";
|
|
||||||
size = "100%";
|
size = "100%";
|
||||||
content = {
|
content = {
|
||||||
type = "lvm_pv";
|
type = "lvm_pv";
|
||||||
@@ -43,7 +41,6 @@
|
|||||||
type = "filesystem";
|
type = "filesystem";
|
||||||
format = "ext4";
|
format = "ext4";
|
||||||
mountpoint = "/";
|
mountpoint = "/";
|
||||||
mountOptions = [ "defaults" ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,16 +7,9 @@
|
|||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"ata_piix"
|
"ata_piix"
|
||||||
"uhci_hcd"
|
"uhci_hcd"
|
||||||
"virtio_pci"
|
|
||||||
"virtio_scsi"
|
|
||||||
"sd_mod"
|
"sd_mod"
|
||||||
"sr_mod"
|
"sr_mod"
|
||||||
];
|
];
|
||||||
boot.initrd.kernelModules = [ ];
|
|
||||||
boot.kernelModules = [ ];
|
|
||||||
boot.extraModulePackages = [ ];
|
|
||||||
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
nixosModules = config.flake.modules.nixos;
|
nixosModules = config.flake.modules.nixos;
|
||||||
account = config.facts.account;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
facts.machines.orion = {
|
facts.machines.orion = {
|
||||||
@@ -11,9 +10,7 @@ in
|
|||||||
stateVersion = "24.05";
|
stateVersion = "24.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.orion =
|
flake.modules.nixos.orion = {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
nixosModules.host-base
|
nixosModules.host-base
|
||||||
|
|
||||||
@@ -22,7 +19,6 @@ in
|
|||||||
nixosModules.caddy
|
nixosModules.caddy
|
||||||
nixosModules.server-firewall
|
nixosModules.server-firewall
|
||||||
nixosModules.sudo-ssh-agent-auth
|
nixosModules.sudo-ssh-agent-auth
|
||||||
# nixosModules.vps-insights
|
|
||||||
nixosModules.vaultwarden
|
nixosModules.vaultwarden
|
||||||
nixosModules.radicale
|
nixosModules.radicale
|
||||||
nixosModules.actual
|
nixosModules.actual
|
||||||
@@ -34,6 +30,6 @@ in
|
|||||||
|
|
||||||
environment.enableAllTerminfo = true;
|
environment.enableAllTerminfo = true;
|
||||||
|
|
||||||
users.users.${account.name}.linger = true;
|
users.users.${config.facts.account.name}.linger = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
{
|
{ lib, modulesPath, ... }:
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
@@ -17,9 +12,7 @@
|
|||||||
"usb_storage"
|
"usb_storage"
|
||||||
"sd_mod"
|
"sd_mod"
|
||||||
];
|
];
|
||||||
boot.initrd.kernelModules = [ ];
|
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
boot.extraModulePackages = [ ];
|
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" = {
|
||||||
device = "/dev/disk/by-uuid/bda7f8b9-2b3d-4190-8518-baa50490227e";
|
device = "/dev/disk/by-uuid/bda7f8b9-2b3d-4190-8518-baa50490227e";
|
||||||
@@ -35,10 +28,5 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
|
||||||
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
|
||||||
}
|
}
|
||||||
@@ -9,32 +9,24 @@ in
|
|||||||
{
|
{
|
||||||
facts.machines.polaris = {
|
facts.machines.polaris = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
sshKeys = {
|
sshKeys.personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVORk45HKkX7gaGGp90KsVyUy6t+fKhbWN/grjkf3cQ kiri@polaris";
|
||||||
personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVORk45HKkX7gaGGp90KsVyUy6t+fKhbWN/grjkf3cQ kiri@polaris";
|
sshKeys.work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5DMV6EQzsscgEOE0912mNglUHTEl+LPnaWYjj0y57B kiri@polaris#work";
|
||||||
work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5DMV6EQzsscgEOE0912mNglUHTEl+LPnaWYjj0y57B kiri@polaris#work";
|
|
||||||
};
|
|
||||||
|
|
||||||
syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
|
syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
|
||||||
|
|
||||||
stateVersion = "24.05";
|
stateVersion = "24.05";
|
||||||
|
|
||||||
displays = {
|
displays = {
|
||||||
"LG Electronics LG ULTRAGEAR 103NTYT8R290" = {
|
"LG Electronics LG ULTRAGEAR 103NTYT8R290" = { };
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
"LG Electronics LG ULTRAGEAR 103NTJJ8R332" = {
|
"LG Electronics LG ULTRAGEAR 103NTJJ8R332" = {
|
||||||
primary = true;
|
primary = true;
|
||||||
x = 2560;
|
x = 2560;
|
||||||
y = 0;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.polaris =
|
flake.modules.nixos.polaris = {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
nixosModules.workstation-base
|
nixosModules.workstation-base
|
||||||
nixosModules.openssh
|
nixosModules.openssh
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
"usb_storage"
|
"usb_storage"
|
||||||
"sd_mod"
|
"sd_mod"
|
||||||
];
|
];
|
||||||
boot.initrd.kernelModules = [ ];
|
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
|
||||||
boot.extraModulePackages = [ ];
|
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" = {
|
||||||
device = "/dev/disk/by-uuid/6d8f6f33-c9d9-4e90-b496-d5b3ef5e9aeb";
|
device = "/dev/disk/by-uuid/6d8f6f33-c9d9-4e90-b496-d5b3ef5e9aeb";
|
||||||
@@ -28,9 +25,5 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
|
||||||
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
}
|
}
|
||||||
@@ -10,10 +10,8 @@ in
|
|||||||
facts.machines.zenith = {
|
facts.machines.zenith = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
|
|
||||||
sshKeys = {
|
sshKeys.personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIQy4k04gU7UpjBgyUQ57kUwxOdt79LvMCiCekXZeZhd kiri@zenith";
|
||||||
personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIQy4k04gU7UpjBgyUQ57kUwxOdt79LvMCiCekXZeZhd kiri@zenith";
|
sshKeys.work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk kiri@zenith#work";
|
||||||
work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk kiri@zenith#work";
|
|
||||||
};
|
|
||||||
|
|
||||||
syncthingId = "5VMGBZJ-NNAVCLY-YWHCJLM-EJ3SCFC-EOGCECD-DGXC7EL-J5NXAAG-4JDEMQG";
|
syncthingId = "5VMGBZJ-NNAVCLY-YWHCJLM-EJ3SCFC-EOGCECD-DGXC7EL-J5NXAAG-4JDEMQG";
|
||||||
|
|
||||||
@@ -30,18 +28,14 @@ in
|
|||||||
stateVersion = "24.05";
|
stateVersion = "24.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.zenith =
|
flake.modules.nixos.zenith = {
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
nixosModules.workstation-base
|
nixosModules.workstation-base
|
||||||
nixosModules.laptop-power
|
nixosModules.laptop-power
|
||||||
{
|
|
||||||
hardware.enableRedistributableFirmware = true;
|
|
||||||
services.fwupd.enable = true;
|
|
||||||
}
|
|
||||||
./_hardware.nix
|
./_hardware.nix
|
||||||
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu
|
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.fwupd.enable = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ in
|
|||||||
inputs.home-manager.nixosModules.home-manager
|
inputs.home-manager.nixosModules.home-manager
|
||||||
nixosModules.nix
|
nixosModules.nix
|
||||||
nixosModules.locale
|
nixosModules.locale
|
||||||
nixosModules.sops-password
|
nixosModules.sops
|
||||||
];
|
];
|
||||||
|
|
||||||
home-manager = {
|
home-manager = {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
let
|
let
|
||||||
nixosModules = config.flake.modules.nixos;
|
nixosModules = config.flake.modules.nixos;
|
||||||
homeModules = config.flake.modules.homeManager;
|
homeModules = config.flake.modules.homeManager;
|
||||||
account = config.facts.account;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.workstation-base = {
|
flake.modules.nixos.workstation-base = {
|
||||||
@@ -32,12 +31,10 @@ in
|
|||||||
nixosModules.yookr-dev
|
nixosModules.yookr-dev
|
||||||
];
|
];
|
||||||
|
|
||||||
services.dbus.implementation = "broker";
|
|
||||||
|
|
||||||
programs.nix-ld.enable = true;
|
programs.nix-ld.enable = true;
|
||||||
environment.localBinInPath = true;
|
environment.localBinInPath = true;
|
||||||
|
|
||||||
home-manager.users.${account.name}.imports = [
|
home-manager.users.${config.facts.account.name}.imports = [
|
||||||
homeModules.workstation-base
|
homeModules.workstation-base
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
keys:
|
|
||||||
- &admin age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl
|
|
||||||
- &orion age1upsxyevxdv3xax8jhnffclryuve70k63cjrca69ffds4h2m3nvuql59ufw
|
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: secrets.yaml$
|
- path_regex: secrets.yaml$
|
||||||
key_groups:
|
age: >-
|
||||||
- age:
|
age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl,
|
||||||
- *admin
|
age1upsxyevxdv3xax8jhnffclryuve70k63cjrca69ffds4h2m3nvuql59ufw
|
||||||
- *orion
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{ config, ... }:
|
|
||||||
let
|
|
||||||
account = config.facts.account;
|
|
||||||
nixosModules = config.flake.modules.nixos;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
flake.modules.nixos.sops-password =
|
|
||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
imports = [ nixosModules.sops ];
|
|
||||||
|
|
||||||
sops.secrets.hashed-password.neededForUsers = true;
|
|
||||||
|
|
||||||
users.users.${account.name}.hashedPasswordFile = config.sops.secrets.hashed-password.path;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -15,12 +15,7 @@ in
|
|||||||
sops.defaultSopsFile = ./secrets.yaml;
|
sops.defaultSopsFile = ./secrets.yaml;
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.nixos.sops-admin-key-file =
|
flake.modules.nixos.sops-admin-key-file = {
|
||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
adminKeyDir = builtins.dirOf sopsAdminKeyPath;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ nixosModules.sops ];
|
imports = [ nixosModules.sops ];
|
||||||
|
|
||||||
home-manager.sharedModules = [ hmModules.sops ];
|
home-manager.sharedModules = [ hmModules.sops ];
|
||||||
@@ -28,7 +23,7 @@ in
|
|||||||
sops.age.keyFile = sopsAdminKeyPath;
|
sops.age.keyFile = sopsAdminKeyPath;
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d ${adminKeyDir} 0750 root wheel -"
|
"d ${builtins.dirOf sopsAdminKeyPath} 0750 root wheel -"
|
||||||
"z ${sopsAdminKeyPath} 0640 root wheel -"
|
"z ${sopsAdminKeyPath} 0640 root wheel -"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user