Establish repository foundation and shared work environment
This commit is contained in:
1 parent
3c022ad2f9
commit
f164d8b76e
15 files changed
+551
-503
No files matched your search
@@ -0,0 +1,34 @@
|
||||
# Working in this repository
|
||||
|
||||
Read [the design](docs/design.md) and [current work](docs/current-work.md) before
|
||||
continuing the foundation pass. [README.md](README.md) maps configuration owners
|
||||
and maintenance entry points. Global instructions remain applicable.
|
||||
|
||||
- Keep design discussion and shared decisions in the main conversation. Discuss
|
||||
two to four related choices with evidence, a recommendation, and alternatives.
|
||||
Ask before changes to architecture, terminology, ownership, dependencies,
|
||||
persistent data, user-visible behavior, or durable workflows. Implement routine
|
||||
consequences of an accepted batch without repeated confirmation.
|
||||
- Use subagents only for bounded, independent work when coverage or context benefits
|
||||
justify it. No fixed team or delegation pattern is required.
|
||||
- The pass covers existing or clearly intended capabilities. Consult relevant parts
|
||||
of `~/sync/notes/setup-todo.md` as evidence, not authorization or a backlog.
|
||||
Do not edit that note without an explicit request.
|
||||
- Preserve unrelated changes. Coherent local commits are allowed for agreed batches.
|
||||
Do not push or make other remote changes without explicit approval. System
|
||||
activation remains user-owned.
|
||||
- Do not read secret values for discovery, source the workbench credential-loading
|
||||
environment, or access live company systems with write authority. Test writes need
|
||||
task-specific authority. Moving credentials or synchronizing company content
|
||||
requires agreement; ordinary repository work does not authorize either.
|
||||
- Follow the user's testing policy: automated tests only when explicitly requested
|
||||
or covered by an established repository policy. A test file alone does not establish
|
||||
a general policy. Use the smallest relevant review, build, or manual check.
|
||||
- Use `just validate` for a completed configuration batch, or name affected hosts
|
||||
for iteration. Read the short result first; inspect saved logs only for failures
|
||||
or a concrete unresolved concern. Documentation-only edits need no system build.
|
||||
- Replace superseded state in `docs/current-work.md`; keep durable rationale in
|
||||
`docs/design.md` and operational detail beside its owner. Use Git for chronology.
|
||||
Remove temporary state when it no longer serves a purpose.
|
||||
- Do not declare the pass complete unilaterally. Present the resulting model,
|
||||
changes, evidence, and deferrals, and ask whether another area needs attention.
|
||||
@@ -1,24 +1,90 @@
|
||||
# NixOS configuration
|
||||
|
||||
Host identity and topology live in `modules/hosts/<host>/default.nix`; shared account,
|
||||
service, external-device, and server-topology facts live in `modules/facts.nix`.
|
||||
One shared daily environment on Polaris and Zenith, with shared services on Orion.
|
||||
NixOS and Home Manager are composed through flake-parts and import-tree.
|
||||
|
||||
- Add a package used by both workstations to the relevant Home Manager capability,
|
||||
or to `workstation-apps` in `modules/capabilities/desktop-defaults.nix` when it needs
|
||||
no configuration.
|
||||
- Add a host-specific capability to that host's import list in
|
||||
`modules/hosts/<host>/default.nix`.
|
||||
- Change the selected terminal or editor by replacing the corresponding
|
||||
`primary-terminal-*` import in `modules/profiles/workstation-base.nix` or
|
||||
`primary-editor-*` import in `modules/profiles/host-base.nix`.
|
||||
- Keep native theme settings with the application. Explicit Kanagawa color mappings
|
||||
may import `modules/capabilities/_kanagawa.nix`.
|
||||
## Start here
|
||||
|
||||
Common commands:
|
||||
- [Design](docs/design.md): vocabulary, ownership, and rationale.
|
||||
- [Agent instructions](AGENTS.md): repository collaboration boundaries.
|
||||
- [Current work](docs/current-work.md): accepted scope, open decisions, and next step.
|
||||
|
||||
## Configuration map
|
||||
|
||||
| Owner | Location | Responsibility |
|
||||
| --- | --- | --- |
|
||||
| Hosts | `modules/hosts/<host>/` | Identity, hardware, machine-specific selection |
|
||||
| Profiles | `modules/profiles/` | Combinations of capabilities |
|
||||
| Capabilities | `modules/capabilities/` | Behavior and integration across NixOS and Home Manager |
|
||||
| Facts | `modules/facts.nix` | Shared identity and topology; host facts are declared with hosts |
|
||||
| Composition | `flake.nix`, `modules/flake-parts.nix` | Inputs, discovery, host construction |
|
||||
| Secrets | `modules/secrets/` | Existing SOPS declarations and encrypted data |
|
||||
|
||||
Discovery makes named modules available; imports select them. Underscore-prefixed
|
||||
helpers and directories are excluded from automatic discovery and imported explicitly.
|
||||
Add shared behavior to its capability and select it through the relevant profile.
|
||||
Keep machine differences in hosts. A capability can own system and user modules.
|
||||
|
||||
The primary editor is selected in `host-base.nix`, the primary terminal in
|
||||
`workstation-base.nix`. `modules/capabilities/theme.nix` selects the complete theme;
|
||||
Kanagawa lives in `modules/capabilities/_themes/kanagawa.nix`. Appearance belongs
|
||||
there; interaction and layout belong with the capability.
|
||||
|
||||
## Work environment (provisional)
|
||||
|
||||
Both workstations import `modules/profiles/work.nix`: company network/development
|
||||
integration, Garden tools, and work Git settings. This is a trial boundary, not
|
||||
an independent workstation variant. SharePoint remains Zenith-only for now.
|
||||
|
||||
The tools-only environment is owned by
|
||||
`modules/capabilities/yookr-dev/environment.nix`. It shares Garden definitions in
|
||||
`_packages.nix` with installed tools and uses the system's nixpkgs pin:
|
||||
|
||||
```console
|
||||
nix fmt
|
||||
nix flake check --no-build
|
||||
nh os switch
|
||||
sops edit modules/secrets/secrets.yaml
|
||||
nix develop --quiet ~/.config/nixos#workbench --command bash --norc
|
||||
```
|
||||
|
||||
This does not clear inherited credentials; start from a clean environment for
|
||||
agent work. It does not load secrets, mount storage, or install Python dependencies.
|
||||
Workspace `.envrc` files select it; the workbench's human credential and mount
|
||||
steps remain workspace-owned. Requests, queries, analysis, and `uv.lock` stay there.
|
||||
After loader changes, the user must review and re-allow the changed `.envrc` files
|
||||
with direnv. No loader is sourced as part of validation.
|
||||
|
||||
## Maintenance
|
||||
|
||||
Run from this repository:
|
||||
|
||||
```console
|
||||
just validate # format, evaluate, build every host and the workbench
|
||||
just validate polaris # same workflow, build only the named host(s)
|
||||
```
|
||||
|
||||
The command includes current tracked files and non-ignored new files, respects
|
||||
working-tree deletions, and never changes the Git index. It resolves the pinned
|
||||
formatter from a temporary source snapshot, formats included Nix files in the
|
||||
working tree, then refreshes the snapshot for evaluation and builds. Ignored
|
||||
untracked files and `.git` are excluded. Avoid concurrent edits during validation:
|
||||
results describe the snapshot, not subsequent changes.
|
||||
|
||||
Output is limited to stage results and a short excerpt on failure. Full logs remain
|
||||
in the printed `/tmp/nixos-validate-*` directory; source snapshots are removed on
|
||||
exit. Failed stages stop the command. Inputs are not updated, no result links are
|
||||
created, and nothing is activated. Host names are discovered from the flake.
|
||||
|
||||
`just` and Python are already declared for both workstations. The implementation
|
||||
is `scripts/validate.py`; the justfile is only its entry point. The formatter output
|
||||
currently targets this repository's sole system, `x86_64-linux`.
|
||||
|
||||
Use full validation after a configuration batch and targeted hosts during iteration.
|
||||
Documentation-only edits need review, local link checks, and `git diff --check`,
|
||||
not system builds. Evaluation, build, activation, and confirmed behavior are
|
||||
separate evidence. Outside this wrapper, ordinary Git-backed flake commands still
|
||||
require intended new files to be added to Git.
|
||||
|
||||
The user activates with `nh os switch`. Edit encrypted data with
|
||||
`sops edit modules/secrets/secrets.yaml`; keep plaintext out of Nix expressions
|
||||
and the store. No new credential-delivery design is selected yet.
|
||||
|
||||
Historical material under `docs/.archive/` is evidence, not current instructions
|
||||
or a backlog. Consult it only for relevant unresolved questions.
|
||||
@@ -1,301 +0,0 @@
|
||||
# Constellation: working state
|
||||
|
||||
Read [the design](constellation.md) and this file to resume. Keep this file short:
|
||||
replace superseded state rather than appending a chronological log.
|
||||
|
||||
## Working agreement
|
||||
|
||||
- Explore the philosophy through concrete use, discuss meaningful choices, then
|
||||
implement a small coherent change. Curiosity and alternative designs are welcome;
|
||||
an idea need not prove a defect before we explore it.
|
||||
- Write succinctly without losing important details. Distinguish accepted choices,
|
||||
proposals and observations. Ask when intent would change the design; resolve
|
||||
routine implementation details autonomously. Infer opportunities from the user's
|
||||
philosophy and actual use; contribute design ideas beyond literal backlog items.
|
||||
Continue to the next natural step when the user could only usefully say "continue";
|
||||
pause for material choices or missing authority, not routine progress.
|
||||
- Minimize input stops: plan a coherent batch of autonomous work and gather the
|
||||
material inputs needed for the next batch together. Avoid serial question/action
|
||||
loops. When pausing, state exactly what input is needed and what it will decide;
|
||||
otherwise continue with the next logical step rather than ending with an offer.
|
||||
- The main agent owns alignment, design and integration and may do small work.
|
||||
Use subagents for bounded independent investigations or implementation with clear
|
||||
ownership. Begin with at most two workers; avoid overlapping writes, duplicate
|
||||
investigations and mandatory delegation of trivial tasks.
|
||||
- Give workers the question, relevant paths, constraints and expected result.
|
||||
Prefer a compact brief and fresh context when sufficient; retain relevant prior
|
||||
context for follow-ups. Return conclusions, uncertainty and evidence pointers,
|
||||
not raw logs. Astra/Sol orchestration is a candidate to learn from, not a fixed rule.
|
||||
- Read only what can affect the current decision. Use quiet commands and bounded
|
||||
output; keep large logs in `/tmp` and inspect relevant failures. Do not repeatedly
|
||||
check settled facts. Consult current documentation for consequential or unfamiliar
|
||||
interfaces when needed for the task.
|
||||
- No tests unless explicitly requested. Keep other verification proportional;
|
||||
report only what was actually checked. Avoid turning small changes into campaigns.
|
||||
- Keep durable decisions in the design and current questions/next steps here.
|
||||
Add an area-specific document only when an active topic outgrows this arrangement.
|
||||
No separate backlog, scratchpad, audit ledger or agent-role files for now.
|
||||
|
||||
## Boundaries
|
||||
|
||||
Repository remotes are read-only. Only the user activates system generations.
|
||||
Agents must not have write access to live company systems; test writes require
|
||||
task-specific authority and care. Do not read secret values for layout discovery.
|
||||
Current exploration does not authorize relocating credentials, synchronizing
|
||||
company content or deleting existing material. Existing local changes are preserved.
|
||||
|
||||
## Git baseline — 2026-09-09
|
||||
|
||||
The accumulated NixOS changes are recorded in focused local commits on
|
||||
`chore/workflow-system`: AI tooling/inputs, editor ergonomics, query persistence
|
||||
and target context, workspace navigation, Notes, SharePoint, Zellij and TeamViewer.
|
||||
The original long handoff and archived plans are preserved in commit `4e3a3ac`;
|
||||
use Git history for chronology. `nvim.log` is retained locally and ignored.
|
||||
Workbench changes are committed on its local `main`: `eb8da6a` organizes HTTP/SQL
|
||||
material and `063157c` archives helpers and documents native tools. The ordinary
|
||||
company-root files are outside either repository and remain user-owned.
|
||||
This cleanup preserves implementation behavior; a commit does not establish runtime
|
||||
acceptance. Keep subsequent implementation and its documentation in the same
|
||||
coherent commit before starting unrelated work.
|
||||
|
||||
## Implemented state
|
||||
|
||||
- **Places:** `~/yookr` has ordinary `.envrc` and `AGENTS.md` files; its environment
|
||||
loads workbench tools only. Workbench is at `~/yookr/workbench`, company projects
|
||||
at `~/yookr/projects`, and personal groups at `~/projects/{own,ext,forks}`.
|
||||
Direct moves retained archives/worktrees; all three linked dashboard worktrees
|
||||
were repaired. Nix owns tools/integration, not these workspace files.
|
||||
- **Navigation:** Walker enters Yookr or a repository; Git identity follows the
|
||||
company root; XDG projects points to `~/projects`. Notes has a desktop entry
|
||||
opening `~/sync/notes` without creating a daily note. Existing note commands,
|
||||
project search and Niri daily-note behavior remain.
|
||||
- **Synchronization:** Bruno collections were previously moved to Trash on Zenith
|
||||
and their shared Syncthing entry removed. Other devices' files were untouched.
|
||||
Syncthing was subsequently observed running. Notes and credentials remain in place.
|
||||
- **API/database work:** workbench `http/` groups requests by service with shared
|
||||
authentication; `databases/` groups reusable queries by database. Private HTTP
|
||||
environment files are ignored at any depth. Dadbod working queries persist under
|
||||
`stdpath('data')/db_ui/working`; write them there without promoting them into Git.
|
||||
Saved-query storage also contains connection state and must stay outside Git.
|
||||
Lualine uses native Kulala environment and Dadbod connection/timing components.
|
||||
These indicators are not access controls.
|
||||
- **Editor ergonomics:** word-boundary wrapping, count-aware displayed-line `j/k`
|
||||
in ordinary normal/visual buffers, and default Escape behavior to leave insert
|
||||
mode. The Neovim smoke tests were removed; earlier smoke-check evidence is in
|
||||
the archived plan.
|
||||
- **Agents:** Herdr is selected; agent-deck and tmux remain installed alongside it.
|
||||
Codex has agent-deck notifications and hooks enabled. Shared Context7/NixOS skills
|
||||
live under `.agents/skills`.
|
||||
Zellij is also declared on workstations. Further project workflow work is deferred.
|
||||
- **SharePoint:** Zenith declares an hourly service syncing `company-sharepoint:`
|
||||
into `~/.local/share/yookr-reference/sharepoint/Algemeen` and
|
||||
`company-sharepoint-projecten:` into `Projecten`. Each invocation has
|
||||
`--max-delete 100`; new files use `UMask=0077`. The latest implementation only
|
||||
checks for `rclone.conf`; the old environment-file gate is gone. Archived setup
|
||||
instructions describe an earlier version. Consent, remote configuration and
|
||||
synchronization state were not inspected during this cleanup.
|
||||
- **Remote support:** Zenith enables TeamViewer. Temporary Xorg/Xfce settings are
|
||||
comments only. The purpose beyond remote support and runtime acceptance were
|
||||
not recorded; preserve the change without calling it a settled design.
|
||||
- **Inputs:** accumulated lock updates are retained, including an older Elephant
|
||||
revision (`376ee71c` replacing `23f37238`). No rollback rationale was recorded.
|
||||
|
||||
## Activation and verification
|
||||
|
||||
Earlier handoffs report user activation of the relocated XDG/Git/Walker paths and
|
||||
Dadbod working-query persistence. Notes and the newer target statusline were last
|
||||
recorded as pending activation. Only Zenith's filesystem was relocated; other hosts
|
||||
need their own migration before adopting the shared paths. Reopen shells or
|
||||
recreate path-dependent development environments as needed; no compatibility links
|
||||
or cache rewrites were introduced.
|
||||
|
||||
For this cleanup, `nix flake check --no-build --quiet` and diff whitespace checking
|
||||
passed in both NixOS and workbench. NixOS emitted the expected dirty-tree and unknown
|
||||
`modules` warnings; workbench emitted only the dirty-tree warning.
|
||||
No builds, tests, activation, credential reads or company-service calls were
|
||||
performed. Active-generation differences were not checked; earlier activation
|
||||
reports are not a fresh comparison with this baseline.
|
||||
|
||||
## Open choices and next discussion
|
||||
|
||||
Current focus: look and feel/theming, informed by `~/sync/notes/setup-todo.md`.
|
||||
The user accepted complete Nix theme modules with arbitrary plugin/configuration
|
||||
behavior, rather than Stylix or a palette-only abstraction. The single import in
|
||||
`modules/capabilities/theme.nix` selects `./_themes/kanagawa.nix`. `_themes` is
|
||||
excluded from automatic module discovery, so unselected themes are not loaded.
|
||||
Kanagawa owns GTK/icons/cursor, Qt integration, Kitty, Niri colors, Noctalia
|
||||
palette/font/wallpaper, Herdr colors, the native Neovim plugin and its setup, and
|
||||
Limine, Noctalia Greeter and Plymouth appearance. Only Kanagawa is implemented
|
||||
so far; switching means selecting another module and rebuilding, not a live
|
||||
theme picker.
|
||||
Walker shares a compact layout with theme-provided colors: reduced padding,
|
||||
24px icons, clearer secondary text, and a smaller minimum window height.
|
||||
Limine's terminal background is fully transparent with no edge gradient so it
|
||||
does not obscure the wallpaper. Runtime appearance needs user verification.
|
||||
Noctalia Greeter uses the same tracked green-leaves wallpaper, Lexend font,
|
||||
Phinger cursor and dark Kanagawa palette as the desktop. Its logo and scheme
|
||||
selector are hidden while power controls remain available. The pinned greeter
|
||||
does not expose Niri's pointer acceleration or touchpad settings, so those retain
|
||||
the greeter compositor defaults. Plymouth's spinner is retained; redesigning its
|
||||
low-frame-rate animation remains open. Runtime appearance needs user verification.
|
||||
Verification: flake evaluation and both workstation builds passed. A headless
|
||||
check of the built Neovim confirmed Kanagawa Wave, inactive-window dimming and
|
||||
the custom gutter setting. Rendered Herdr TOML, Walker XML and Limine settings
|
||||
also passed targeted checks. Targeted evaluation confirmed identical greeter
|
||||
settings for both workstations, and `nix flake check --no-build --quiet` passed
|
||||
for the greeter change. No system activation or live desktop changes performed.
|
||||
|
||||
Dictation: plain local transcription is selected; rambling cleanup is deferred.
|
||||
Handy preferences are application-owned again: the Nix settings generator and
|
||||
startup reset are removed. The existing settings file is left untouched.
|
||||
Nix installs Handy/wtype and runs Handy as a graphical-session user service.
|
||||
Super+D launches a short-lived Python/evdev listener: hold to record, release D
|
||||
or Super to finish. Both keys must be on the same keyboard. Niri owns the shortcut
|
||||
and disables repeat; no persistent keyboard logger or exclusive input grab runs.
|
||||
A udev uaccess rule grants the active local user access to keyboard event devices.
|
||||
Super+Shift+D toggles; Super+Ctrl+D cancels. Both stop any active hold listener
|
||||
before issuing their Handy command, preventing a later release from restarting
|
||||
recording. Begin push-to-talk from idle: Handy exposes toggles, not idempotent
|
||||
start/stop commands. Niri 26.04 itself has no key-release bindings.
|
||||
Noctalia suppresses microphone activity popups/indicators; camera and screen-sharing
|
||||
indications remain. Automatic paste and live capture need interactive checks.
|
||||
|
||||
Hang investigation, parked at the user's request: a debugger capture confirmed
|
||||
Handy's recorder waits for another audio chunk before processing its stop command.
|
||||
When capture stalls, stopping can therefore hang indefinitely; the transcription
|
||||
worker was idle. Bluetooth transport failures accompanied the hangs, and the user
|
||||
reported dictation working after disconnecting the Sony WH-1000XM6. The user wants
|
||||
its microphone when connected. Keeping the headset in a microphone-enabled HFP
|
||||
profile was proposed to avoid repeated profile transitions, but was not applied
|
||||
or verified; the reconnect attempt timed out. No source or Bluetooth configuration
|
||||
was changed. CPU and Vulkan batch inference both worked; changing inference backend
|
||||
is not an established fix. Resume this investigation only if requested.
|
||||
Synthetic listener checks cover release during startup, repeat, modifier-first
|
||||
release, device disconnect and cancellation, without live input/audio access.
|
||||
System activation and an interactive hold/release trial remain user-owned.
|
||||
Formatting, flake evaluation, both workstation builds, synthetic listener checks
|
||||
and whitespace checking passed. No live input listener or microphone was started.
|
||||
|
||||
The focus is the broader environment, not further API/database polish. Candidate
|
||||
areas remain places/ownership, navigation/interaction, human/agent collaboration,
|
||||
and system operation/maintenance; these are discussion areas, not a work queue.
|
||||
|
||||
Herdr's configured keys are accepted: the user reports liking them in practice.
|
||||
Niri workspace grouping stays informal while the user discovers what fits; Herdr
|
||||
provides enough structure for now. No workspace rules or fixed layout are needed.
|
||||
The user reopened Herdr configuration on 2026-09-10 for direct shortcuts and less
|
||||
interaction friction, using supported configuration only. Layout presets and
|
||||
launchers are explicitly unwanted; arrange panes manually. Agent evaluation is
|
||||
explicitly deferred. Do not resume replacement-tool comparisons or ask for an
|
||||
evaluation task/budget as a prerequisite for this work.
|
||||
|
||||
Read-only inspection found existing Niri overview, workspace movement and tabbed
|
||||
columns; Kitty has no declared project/session organization. Installed versions:
|
||||
Kitty 0.48.2, Niri 26.04, tmux 3.7c, Zellij 0.45.1 and Herdr 0.9.0.
|
||||
Herdr's installed default config confirms remappable navigation and agent jumps.
|
||||
Current [Herdr keyboard docs](https://herdr.dev/docs/keyboard/) describe direct
|
||||
chords; [Kitty sessions](https://sw.kovidgoyal.net/kitty/sessions/) supply native
|
||||
session creation/switching. Session layouts and window overviews do not themselves
|
||||
provide authoritative agent attention states. tmux detach keeps processes alive;
|
||||
Zellij resurrection recreates layouts/commands, not process memory. None of these
|
||||
capabilities was exercised interactively; no sessions were inspected or changed.
|
||||
|
||||
Deferred agent workflow proposal (not accepted or a Niri workspace requirement):
|
||||
one lead conversation owns each coherent change. Use bounded subagents when work
|
||||
is independent, with explicit ownership and evidence returned to the lead. Separate
|
||||
worktrees for independent writing efforts, one integration owner. Keep enduring
|
||||
repository rules in AGENTS.md, current goals/acceptance in task prompts, and durable
|
||||
decisions/current state in existing project docs. No fixed agent team is selected.
|
||||
|
||||
Herdr configuration is now declared in `modules/capabilities/ai.nix`, including
|
||||
the existing Kanagawa theme, workspace-sorted agent panel and disabled toasts.
|
||||
Home Manager owns `~/.config/herdr/config.toml` after activation; maintain these
|
||||
preferences in Nix. Its configured `.bak` mechanism preserves the previous regular
|
||||
file. Direct Ctrl+Alt bindings supplement the existing Ctrl+B prefix shortcuts:
|
||||
|
||||
| Ctrl+Alt + | Action |
|
||||
| --- | --- |
|
||||
| H / J / K / L | Focus pane left / down / up / right |
|
||||
| U / I | Next / previous workspace |
|
||||
| O / G | Workspace picker / goto picker |
|
||||
| P / N | Previous / next agent |
|
||||
| [ / ] | Previous / next tab |
|
||||
| Enter | New tab |
|
||||
| V / Minus | Split right / down |
|
||||
| F | Zoom pane |
|
||||
| Q | Detach, leaving the session running |
|
||||
| Shift+H / J / K / L | Swap panes left / down / up / right (Shift on each) |
|
||||
| Shift+arrows | Resize pane directly |
|
||||
| R | Resize mode |
|
||||
| Tab / Shift+Tab | Next / previous pane |
|
||||
| Backspace | Return to last pane, including across tabs/spaces |
|
||||
| X / Shift+X | Close pane / tab |
|
||||
| Shift+P / Shift+A | Rename pane / tab |
|
||||
| Shift+[ / Shift+] | Move tab earlier / later |
|
||||
| Shift+Enter | New space |
|
||||
| Shift+W / Shift+D | Rename / close space |
|
||||
| W / Shift+B | Open / create worktree |
|
||||
| Y / E | Copy mode / open scrollback in Neovim |
|
||||
| Shift+G | Lazygit popup |
|
||||
| B | Toggle sidebar |
|
||||
| / | Keybinding help |
|
||||
| S / Shift+R | Settings / reload configuration |
|
||||
|
||||
Inside workspace navigation, U/I moves down/up and H/J/K/L retains pane navigation.
|
||||
Niri and Kitty bindings are unchanged. Direct number bindings are removed because
|
||||
the user finds them unergonomic; built-in prefix shortcuts remain available.
|
||||
|
||||
Use one space per project or worktree, tabs for different activities, and panes
|
||||
for tools needed together. Start Neovim in a shell, split right with Ctrl+Alt+V
|
||||
for an agent shell, and optionally split that pane down with Ctrl+Alt+Minus for
|
||||
tests or a server. Choose and launch the agent manually. No preset is installed.
|
||||
Ctrl+Alt+Shift+G opens lazygit at 90% width/height in the focused pane's working
|
||||
directory. Quit lazygit to return; the popup owns input until its command exits.
|
||||
|
||||
Tabs now open immediately with generated names; rename them only when useful.
|
||||
New spaces already skip naming, and new panes inherit the current directory by
|
||||
default. Workspace-close confirmation remains enabled to protect running work.
|
||||
Direct resizing, previous/next agent navigation, last-pane switching, copy mode,
|
||||
and Neovim scrollback access avoid extra navigation or mode-entry steps.
|
||||
No documented native setting or CLI action opens Goto directly in search mode;
|
||||
that limitation remains under the configuration-only constraint. No input macros,
|
||||
plugins, or package patches are added.
|
||||
|
||||
After activating Nix, reload Herdr with Ctrl+B then Shift+R; subsequent reloads
|
||||
can use Ctrl+Alt+Shift+R. The expanded shortcuts require interactive verification
|
||||
through Kitty, including popup working directory, pane swapping/resizing, and
|
||||
scrollback opening. The earlier bindings were reported working by the user.
|
||||
Verification (2026-09-10): formatting, flake evaluation, Polaris and Zenith no-link
|
||||
system builds, and whitespace checks passed. Both hosts generate identical Herdr
|
||||
TOML, accepted by installed Herdr 0.9.0's `config check`. No activation or live
|
||||
Herdr session changes were performed.
|
||||
The earlier activation installed the Herdr config and preserved `config.toml.bak`,
|
||||
but Home Manager later timed out (below).
|
||||
|
||||
Activation fix (2026-09-09): Home Manager's service switch stopped and restarted
|
||||
the running SharePoint oneshot, then waited until Home Manager's five-minute start
|
||||
timeout. Service-state inspection identified SharePoint as the sole pending user
|
||||
job; its oneshot start timeout is unlimited. This was not a Herdr file collision.
|
||||
Set `Unit.X-SwitchMethod = "keep-old"` in `sharepoint-reference.nix` so activation
|
||||
leaves an in-flight sync running; subsequent timer runs use the updated unit.
|
||||
Verified against pinned Home Manager/sd-switch source. Formatting, flake evaluation,
|
||||
Zenith build and whitespace checks passed; the focused sd-switch dry run reported
|
||||
`Keep active sharepoint-reference-sync.service`, with no restart planned. No live
|
||||
units were changed and no company content or credentials were read. The user must
|
||||
retry activation to verify the full switch; sync health/content completeness were
|
||||
not investigated.
|
||||
|
||||
Mail search remains unresolved. The workbench's custom mail reader, inventory
|
||||
pilot, justfile and old README are archived; native Garden/kubectl/K9s now own the
|
||||
documented operations. No replacement mail helper or semantic index is selected;
|
||||
raw mailbox grep is not assumed sufficient. No new ingestion is authorized.
|
||||
|
||||
Human credential delivery remains both test/live via environment variables with
|
||||
ordinary editor startup. Workbench `.envrc` supplies aggregate credentials; agents
|
||||
must not source it. Separate read-only agent credentials and access isolation are
|
||||
explicitly deferred, not prerequisites for unrelated work. Do not resume the
|
||||
rejected per-connection launchers or per-selection decryption proposal.
|
||||
|
||||
Notes placement and further company material organization remain open. Work is
|
||||
mostly project-based and notes mostly meetings; do not impose investigation
|
||||
folders, outer project containers or company-wide editor search without a need.
|
||||
@@ -1,98 +0,0 @@
|
||||
# Constellation
|
||||
|
||||
An evolving personal computing environment. This is the current design, starting
|
||||
fresh with iteration two; decisions can change through discussion and use.
|
||||
See [working state](constellation-work.md) for how we collaborate and where to resume.
|
||||
|
||||
## Philosophy
|
||||
|
||||
Build a quiet, keyboard-driven, text-oriented environment from understandable
|
||||
tools that compose naturally. Keep information accessible through standard formats
|
||||
and interfaces, so humans and agents can work with the same underlying resources.
|
||||
Organize files and workflows consistently, making it intuitive where to look,
|
||||
where things belong and how to proceed. Let structure guide everyday work while
|
||||
leaving room for exploration and exceptions. Use graphical applications where
|
||||
they serve the task well.
|
||||
|
||||
Make the usual path obvious and exceptions understandable. Consistency should
|
||||
reduce remembering and decision-making without requiring identical bindings or
|
||||
fixed procedures everywhere. A terminal interface alone does not establish fit.
|
||||
|
||||
Nix configures installed tools and system integration. Working directories,
|
||||
checkouts, workspace `.envrc` files and context documents are ordinary user-owned
|
||||
files, maintained directly rather than generated by Home Manager. A workbench may
|
||||
use a flake to declare its tools without Nix owning the surrounding workspace.
|
||||
|
||||
## What that means so far
|
||||
|
||||
- Themes are complete Nix modules, not just palettes. Select one through
|
||||
`modules/capabilities/theme.nix`; it may install native theme plugins, configure
|
||||
their behavior and choose assets for each application. Kanagawa is the first
|
||||
implementation. Shared interaction/layout choices stay in capability modules.
|
||||
Stylix is not selected: preserving theme-specific behavior matters more than
|
||||
forcing applications through one generated color scheme.
|
||||
- Neovim, Niri, Walker and the terminal feel right: direct, keyboard-driven
|
||||
interaction with useful connections to the rest of the environment.
|
||||
- Use Handy for local plain dictation, mainly English with occasional Dutch.
|
||||
Use native Wayland automatic paste and optional live text with a streaming model.
|
||||
Handy owns its preferences, models and recordings. Nix installs and starts it
|
||||
and supplies desktop shortcuts, including a short-lived push-to-talk listener. Cleanup
|
||||
through Codex, a cloud API or a local language model is deferred.
|
||||
- Outlook is acceptable as an application, but its interaction and integration
|
||||
do not fit as naturally. Accessible mail for tools and agents matters separately
|
||||
from choosing a mail reader. Preserve meaning and source context, not just text.
|
||||
- Herdr is the chosen agent workspace manager: its spaces, running-agent overview
|
||||
and attention states fit. Its configured keybindings are accepted in daily use.
|
||||
Use Ctrl+Alt for direct Herdr actions alongside Super for Niri and Ctrl navigation
|
||||
in Neovim; retain Herdr's prefix bindings. Agent-deck's startup issues and other
|
||||
session-manager alternatives are not the current focus.
|
||||
- Keep Niri workspaces flexible. Herdr supplies enough structure that no strict
|
||||
desktop grouping, fixed workspace names or project-to-workspace mapping is
|
||||
needed now. Let actual use inform any later organization.
|
||||
- Further Herdr configuration, agent workflows and project management are deferred
|
||||
until the user chooses to revisit them. Existing configuration remains in use.
|
||||
Alignment, maintainability and human attention matter
|
||||
alongside speed/cost. Agent-workflow evaluation is deferred; no fixed delegation
|
||||
pattern has been selected.
|
||||
- Repositories should contain code and documentation needed by that code, not
|
||||
become containers for general notes and company material destined for Git remotes.
|
||||
- Company work includes repositories, reference material, notes, credentials and
|
||||
investigation tools. Its organization must accommodate those different roles.
|
||||
- Actual work is mostly project-based; notes are primarily meeting notes so far.
|
||||
Do not impose a topic/investigation workflow or a fixed future note taxonomy.
|
||||
- Yookr workbench is an investigation environment, not a product repository.
|
||||
Its placement and versioning can be considered separately.
|
||||
- Accepted direction: workbench supplies the environment at the company-workspace
|
||||
root. Its reusable requests live in `workbench/http/` and queries in
|
||||
`workbench/databases/`, grouped by service/database;
|
||||
the company root need not itself be a Git repository.
|
||||
- Expose native capabilities and useful context rather than a menu of predetermined
|
||||
investigations. The custom inventory and mail helpers are archived; native
|
||||
Garden/kubectl/K9s own the documented Kubernetes workflow. Mail retrieval and
|
||||
broader system access remain exploratory.
|
||||
- Accepted interaction direction: find HTTP requests by service; start database
|
||||
exploration from a named connection. Keep targets visible and use the existing
|
||||
execution vocabulary. Working queries should survive restart without automatically
|
||||
becoming reusable tracked material. Company-wide Neovim search is deferred: no
|
||||
concrete use case currently justifies adding it.
|
||||
- Human credential delivery uses environment variables with both test and live
|
||||
credentials available. Keep ordinary editor startup; no per-connection launcher
|
||||
or on-demand decryption workflow. Agent authority is a separate concern.
|
||||
- Separate read-only company credentials for agents are the eventual direction.
|
||||
Access isolation is explicitly deferred: new credentials cannot be made now.
|
||||
Existing agent access boundaries remain in force; this does not block unrelated
|
||||
design and organization work.
|
||||
|
||||
The company root is `~/yookr`, with repositories in `~/yookr/projects` and the
|
||||
cross-project workbench in `~/yookr/workbench`. Personal/non-company repositories
|
||||
live under `~/projects/{own,ext,forks}`. Projects currently mostly live in their
|
||||
repositories; no extra project containers are needed. Meeting notes remain in
|
||||
`~/sync/notes`. Remaining layout and credential locations are still being explored.
|
||||
|
||||
## Sources
|
||||
|
||||
`~/sync/notes/setup-todo.md` is the idea inbox, not a committed backlog.
|
||||
Existing implementation is the starting system, not a fixed future architecture.
|
||||
Documents under [.archive/](.archive/) are historical evidence; consult only the
|
||||
relevant parts when needed. Their plans, priorities and old approvals do not define
|
||||
this iteration. Preserve existing work while reconsidering its design.
|
||||
@@ -0,0 +1,78 @@
|
||||
# Current work
|
||||
|
||||
## Scope and accepted decisions
|
||||
|
||||
Foundation pass started 2026-09-19. Improve existing capabilities through discussion
|
||||
and coherent implementation batches; completion requires the user's agreement.
|
||||
|
||||
Accepted: retain host/profile/capability/facts composition and explicit ownership;
|
||||
Polaris and Zenith have identical intended use; use the four-file harness. Validation
|
||||
uses a Git-ignore-aware snapshot without index changes, prioritizing low token cost.
|
||||
The work profile is explicitly provisional. Consolidate the workbench environment
|
||||
only, using the shared NixOS nixpkgs pin; authored material and the Python lock stay
|
||||
in the writable workbench. See [design](design.md) for durable boundaries.
|
||||
|
||||
## Completed and evidence
|
||||
|
||||
- Replaced Constellation with the four-file harness after preserving useful knowledge;
|
||||
older archives remain historical sources. Survey began from clean `3c022ad` on Polaris.
|
||||
- Implemented `just validate` with optional host arguments. Full runs format, evaluate,
|
||||
build all hosts, and now build the workbench shell. Logs are brief; details remain
|
||||
in `/tmp`. The index is untouched by validation. Both prerequisites were already
|
||||
declared on workstations.
|
||||
- Added provisional `modules/profiles/work.nix`, imported by both workstations.
|
||||
It selects existing VPN/development integration, Garden tools, and work Git settings.
|
||||
Generic development/editor tools remain shared; SharePoint remains Zenith-only.
|
||||
- Garden definitions now have one owner in `yookr-dev/_packages.nix`, used by both
|
||||
installed tools and `devShells.x86_64-linux.workbench`. Preserved the workbench's
|
||||
tools and Python variables; its nixpkgs pin now follows the system as agreed.
|
||||
- Updated `~/yookr/.envrc` and `~/yookr/workbench/.envrc` to select the shared
|
||||
environment; updated workbench README/instructions and removed its redundant
|
||||
flake/lock. Its credential/mount body is unchanged. Requests, queries, analysis,
|
||||
Python lock, existing changes, and generated data remain in place. Pre-change
|
||||
migration files: `/tmp/workbench-environment-before-6k4dwzuo`.
|
||||
- Full validation passed formatting, evaluation, Orion/Polaris/Zenith builds, and
|
||||
workbench shell build on 2026-09-19. Logs: `/tmp/nixos-validate-4ojjb2q7`.
|
||||
The existing unknown `modules` output warning remains. Whitespace review passed
|
||||
in both repositories; loader changes were compared against pre-change copies.
|
||||
No tests, activation, credential loading, mounts, or remote changes.
|
||||
|
||||
## Next step and user-owned actions
|
||||
|
||||
User reviews and re-allows the two changed `.envrc` files with direnv, and activates
|
||||
NixOS when ready. Do not run those loaders as an agent. The workbench retains
|
||||
unrelated uncommitted analysis, documentation, and mount-helper work; do not commit
|
||||
that work as part of this pass. Replicate the two loader changes and removal of the
|
||||
old environment definition on Zenith; only Polaris's workspace was changed here.
|
||||
|
||||
Evaluate the provisional work boundary in practice, then discuss secret delivery.
|
||||
Current constraints: human workbench entry exposes both test/live credentials and
|
||||
starts read-only object-storage mounts; the tools-only environment does neither
|
||||
but does not erase inherited credentials. SOPS is already used, with different
|
||||
key locations for system and company material. No credential values were read.
|
||||
Clarify encrypted-file/key distribution across machines before proposing changes.
|
||||
Devenv and secretspec remain candidates, not dependencies. No new live authority
|
||||
or per-connection launchers are authorized.
|
||||
|
||||
## Questions to carry into relevant areas
|
||||
|
||||
- Desktop integration: terminal/launcher interfaces have inconsistent consumers;
|
||||
Mailspring coexists with Thunderbird account declarations; Herdr coexists with
|
||||
agent-deck notifications and multiple session tools. Determine purpose before
|
||||
removing anything. The disabled nixos-maintainer skill's source remains.
|
||||
- Cross-host behavior: earlier workspace migration was reported only on Zenith.
|
||||
Verify Polaris paths before assuming equivalent filesystem state. TeamViewer and
|
||||
SharePoint currently exist only on Zenith despite identical intended use.
|
||||
- Runtime evidence: earlier theme/greeter, expanded Herdr shortcuts, Handy
|
||||
hold/release/paste, and SharePoint activation checks were incomplete. Old build
|
||||
results do not establish current behavior. Ask in the relevant area.
|
||||
- Handy hang investigation remains parked unless requested: a prior debugger
|
||||
capture found the recorder waiting for an audio chunk before handling stop;
|
||||
Bluetooth failures coincided, and disconnecting Sony WH-1000XM6 helped. The user
|
||||
wants that microphone. Persistent HFP was proposed but never applied or verified;
|
||||
inference-backend changes were not an established fix.
|
||||
- Agent evaluation, new mail ingestion, and company credential isolation were
|
||||
deferred. Secret-management discussion reopens design, not live access.
|
||||
|
||||
The inbox is not a backlog. Detailed old handoffs remain in Git before this batch;
|
||||
consult them only when their evidence affects a current choice.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# Repository design
|
||||
|
||||
These are working decisions, subject to evidence from implementation and use.
|
||||
|
||||
## Purpose and vocabulary
|
||||
|
||||
Build a quiet, keyboard-driven, text-oriented environment from understandable tools
|
||||
and standard interfaces. Humans and agents should use the same underlying resources.
|
||||
Use graphical applications where they fit. Consistency should reduce remembering,
|
||||
without forcing identical bindings or procedures everywhere.
|
||||
|
||||
- **Host:** machine identity, hardware, and differences in selection.
|
||||
- **Profile:** a deliberate combination of capabilities.
|
||||
- **Capability:** behavior and necessary integration, potentially spanning NixOS
|
||||
and Home Manager, multiple applications, or several files.
|
||||
- **Facts:** genuinely shared identity and topology, not a bucket for all settings.
|
||||
- **Theme:** application-specific appearance, including native plugins and assets.
|
||||
Interaction and layout remain with capabilities. Kanagawa is selected; themes
|
||||
need not fit a palette-only abstraction.
|
||||
|
||||
Retain the composition model. Introduce shared interfaces only for actual consumers.
|
||||
Capability boundaries matter more than one-module-per-file uniformity.
|
||||
|
||||
Polaris and Zenith have identical intended use and should offer the same daily
|
||||
experience. Hardware remains host-specific. The workstation
|
||||
profile now imports a provisional `work` profile selecting company network/development
|
||||
integration, Garden tools, and work Git identity/token integration. Try this boundary
|
||||
in practice before treating it as settled. Generic editor and development tools
|
||||
remain shared. Existing host-only services do not
|
||||
automatically establish a desired difference between machines.
|
||||
|
||||
## Ownership
|
||||
|
||||
Nix owns reproducible installation, integration, and deliberately selected settings.
|
||||
Applications own credentials, sessions, content, and preferences intentionally left
|
||||
interactive. Record feature-specific exceptions where they are implemented.
|
||||
|
||||
Current layout: company root `~/yookr`, projects in `~/yookr/projects`, workbench in
|
||||
`~/yookr/workbench`; personal projects in `~/projects/{own,ext,forks}`; meeting notes
|
||||
in `~/sync/notes`. Workspace files remain user-owned. This repository owns the tools-only
|
||||
`devShells.x86_64-linux.workbench` environment and shares Garden package definitions
|
||||
with the workstation installation. It follows the same nixpkgs pin as the system.
|
||||
Requests, queries, analysis, findings, private context, runtime data, and the Python
|
||||
project lock remain in the writable workbench. The ordinary workspace `.envrc` files
|
||||
select this environment; credential loading and mounts remain unchanged pending
|
||||
a separate design decision.
|
||||
|
||||
Repositories should hold their code and necessary documentation, not absorb general
|
||||
company material. Work is mostly project-based and notes mostly meetings; no new
|
||||
note taxonomy, outer project containers, or company-wide editor search is assumed.
|
||||
|
||||
## Existing experience and constraints
|
||||
|
||||
These useful decisions and operational cautions are carried forward from earlier
|
||||
work. They are starting evidence, not fresh runtime verification.
|
||||
|
||||
- Niri workspaces remain flexible. Herdr supplies agent workspace organization;
|
||||
choose agents and arrange panes manually. Preset layouts and launchers were
|
||||
unwanted. Super belongs to Niri, Ctrl+Alt to direct Herdr actions, and Ctrl
|
||||
navigation to Neovim; native prefix bindings remain available. Earlier Herdr
|
||||
bindings were accepted in use; later additions lack a fresh acceptance report.
|
||||
Configuration and help own the binding reference, rather than a duplicate table.
|
||||
- Herdr configuration is Home Manager-owned in `modules/capabilities/ai.nix`.
|
||||
After activation reload with Ctrl+Alt+Shift+R (or Ctrl+B then Shift+R). The existing
|
||||
Home Manager `.bak` mechanism can preserve previous regular files. No fixed agent
|
||||
team or agent-workflow evaluation program is selected.
|
||||
- Handy provides local plain dictation, mainly English with occasional Dutch.
|
||||
Preferences, models, and recordings remain application-owned. Start push-to-talk
|
||||
from idle; D and Super must be on the same keyboard. A short-lived listener handles
|
||||
releases around Handy's toggle commands. Nix grants active-user keyboard event
|
||||
access for this integration. Cloud/LLM cleanup is deferred.
|
||||
- Native Garden/kubectl/K9s replaced custom workbench inventory helpers. Reusable
|
||||
HTTP material is grouped by service and SQL by database. Named targets and editor
|
||||
indicators help orientation but are not access controls. Mail retrieval remains
|
||||
unresolved; no new ingestion or semantic index was selected.
|
||||
- Dadbod working queries persist under `stdpath('data')/db_ui/working`; saving there
|
||||
does not promote work to reusable repository material. Saved-query storage also
|
||||
contains connection state and must stay out of Git. See
|
||||
`modules/capabilities/neovim/lua-config/lua/plugins/database.lua`.
|
||||
- Prior human credential delivery exposes both test/live environments with normal
|
||||
editor startup. Per-connection launchers and per-selection decryption were
|
||||
rejected. Separate read-only agent credentials were desired but unavailable;
|
||||
isolation was deferred. Credential delivery is reopened for discussion, while
|
||||
existing access boundaries remain in force.
|
||||
- SharePoint sync is currently Zenith-only. Its hourly unit uses two configured
|
||||
rclone company remotes, private file permissions, and a deletion limit per
|
||||
invocation. `X-SwitchMethod = "keep-old"` prevents activation restarting and waiting
|
||||
for an in-flight sync; later timer runs use the updated unit. See
|
||||
`modules/capabilities/sharepoint-reference.nix`. Remote setup, sync completeness,
|
||||
and the full activation fix need confirmation when this area is reviewed.
|
||||
|
||||
## Knowledge and maintenance
|
||||
|
||||
README owns navigation and commands; AGENTS owns repository collaboration rules;
|
||||
this document owns durable reasoning; current-work owns resumable state. Keep
|
||||
implementation details near code and use Git instead of chronological handoffs.
|
||||
Archived plans are historical sources, not authority.
|
||||
|
||||
A unified validation command is wanted to prevent repeated agent improvisation.
|
||||
It must include new and modified working-tree files without changing the Git index,
|
||||
format, evaluate, and build every host for a full configuration batch. Targeted
|
||||
iteration and lightweight documentation checks are accepted. The priority is low
|
||||
agent token cost, not minimum elapsed time: one invocation, concise results, and
|
||||
saved failure logs. Use `just validate` backed by one repository script. Validate a temporary snapshot
|
||||
of tracked and non-ignored new files using working-tree contents; leave the index
|
||||
untouched. Git ignores remain the file-inclusion boundary. Build
|
||||
success does not establish activation or interactive acceptance.
|
||||
@@ -0,0 +1,7 @@
|
||||
# List repository maintenance commands.
|
||||
default:
|
||||
@just --list
|
||||
|
||||
# Format, evaluate, and build all hosts and the workbench; optionally name hosts for iteration.
|
||||
validate *hosts:
|
||||
@python3 scripts/validate.py {{hosts}}
|
||||
@@ -1,35 +1,6 @@
|
||||
{
|
||||
flake.modules.homeManager.dev-tools =
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
gardenctl = pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "gardenctl";
|
||||
version = "2.14.0";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/gardener/gardenctl-v2/releases/download/v2.14.0/gardenctl_v2_linux_amd64";
|
||||
hash = "sha256-JCZ0eJLgYbd2ZMCCWFlhX4vOhHKZL40oR2a3EZ3i4Q8=";
|
||||
};
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
install -Dm755 "$src" "$out/bin/gardenctl"
|
||||
install -d "$out/share/zsh/site-functions"
|
||||
"$out/bin/gardenctl" completion zsh > "$out/share/zsh/site-functions/_gardenctl"
|
||||
'';
|
||||
};
|
||||
gardenlogin = pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "gardenlogin";
|
||||
version = "0.10.0";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/gardener/gardenlogin/releases/download/v0.10.0/gardenlogin_linux_amd64";
|
||||
hash = "sha256-X4nHiZ29Mbnhxv/wlyD6PxX1KxzaX2R27N7Muu/gnH8=";
|
||||
};
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
install -Dm755 "$src" "$out/bin/gardenlogin"
|
||||
ln -s gardenlogin "$out/bin/kubectl-gardenlogin"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo";
|
||||
home.packages = with pkgs; [
|
||||
@@ -40,8 +11,6 @@
|
||||
scc
|
||||
visidata
|
||||
just
|
||||
gardenctl
|
||||
gardenlogin
|
||||
];
|
||||
|
||||
programs.lazygit.enable = true;
|
||||
|
||||
@@ -1,35 +1,11 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
account = config.facts.account;
|
||||
in
|
||||
{
|
||||
flake.modules.homeManager.git =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
machine = config.facts.machine;
|
||||
allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
|
||||
githubTokenFile = "${config.xdg.configHome}/yookr/github-read-only.token";
|
||||
|
||||
gh = pkgs.symlinkJoin {
|
||||
name = "gh-with-read-only-token-${pkgs.gh.version}";
|
||||
paths = [ pkgs.gh ];
|
||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||
meta.mainProgram = "gh";
|
||||
postBuild = ''
|
||||
wrapProgram "$out/bin/gh" \
|
||||
--run 'if [[ -z "''${GH_TOKEN:-}" && -r "${githubTokenFile}" ]]; then export GH_TOKEN="$(< "${githubTokenFile}")"; fi'
|
||||
'';
|
||||
};
|
||||
|
||||
mkScope =
|
||||
scope:
|
||||
config: scope:
|
||||
let
|
||||
email = account.emails.${scope}.address;
|
||||
key = machine.sshKeys.${scope} or null;
|
||||
key = config.facts.machine.sshKeys.${scope} or null;
|
||||
hasSigningKey = key != null;
|
||||
privateKeyPath =
|
||||
if hasSigningKey && key.privateKeyPath != null then key.privateKeyPath else "~/.ssh/id_${scope}";
|
||||
@@ -47,17 +23,18 @@ in
|
||||
}
|
||||
// lib.optionalAttrs hasSigningKey {
|
||||
core.sshCommand = "ssh -i ${privateKeyPath} -o IdentitiesOnly=yes";
|
||||
gpg.ssh.allowedSignersFile = allowedSignersFile;
|
||||
gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
|
||||
};
|
||||
};
|
||||
|
||||
personal = mkScope "personal";
|
||||
work = mkScope "work";
|
||||
in
|
||||
{
|
||||
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" (
|
||||
personal.allowedSigners ++ work.allowedSigners ++ [ "" ]
|
||||
);
|
||||
flake.modules.homeManager.git =
|
||||
{ config, ... }:
|
||||
let
|
||||
personal = mkScope config "personal";
|
||||
in
|
||||
{
|
||||
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" personal.allowedSigners;
|
||||
|
||||
programs.git = {
|
||||
enable = true;
|
||||
@@ -73,34 +50,52 @@ in
|
||||
email = account.emails.personal.address;
|
||||
};
|
||||
};
|
||||
includes = [
|
||||
{
|
||||
condition = "gitdir:${account.nixosConfigurationPath}/";
|
||||
includes =
|
||||
map
|
||||
(path: {
|
||||
condition = "gitdir:${path}/";
|
||||
contents = personal.git;
|
||||
}
|
||||
{
|
||||
condition = "gitdir:${config.home.homeDirectory}/yookr/";
|
||||
contents = work.git;
|
||||
}
|
||||
{
|
||||
condition = "gitdir:${config.xdg.userDirs.projects}/own/";
|
||||
contents = personal.git;
|
||||
}
|
||||
{
|
||||
condition = "gitdir:${config.xdg.userDirs.projects}/ext/";
|
||||
contents = personal.git;
|
||||
}
|
||||
{
|
||||
condition = "gitdir:${config.xdg.userDirs.projects}/forks/";
|
||||
contents = personal.git;
|
||||
}
|
||||
})
|
||||
[
|
||||
account.nixosConfigurationPath
|
||||
"${config.xdg.userDirs.projects}/own"
|
||||
"${config.xdg.userDirs.projects}/ext"
|
||||
"${config.xdg.userDirs.projects}/forks"
|
||||
];
|
||||
};
|
||||
|
||||
programs.gh = {
|
||||
enable = true;
|
||||
package = gh;
|
||||
settings.git_protocol = "ssh";
|
||||
};
|
||||
};
|
||||
|
||||
flake.modules.homeManager.work-git =
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
work = mkScope config "work";
|
||||
githubTokenFile = "${config.xdg.configHome}/yookr/github-read-only.token";
|
||||
gh = pkgs.symlinkJoin {
|
||||
name = "gh-with-read-only-token-${pkgs.gh.version}";
|
||||
paths = [ pkgs.gh ];
|
||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||
meta.mainProgram = "gh";
|
||||
postBuild = ''
|
||||
wrapProgram "$out/bin/gh" \
|
||||
--run 'if [[ -z "''${GH_TOKEN:-}" && -r "${githubTokenFile}" ]]; then export GH_TOKEN="$(< "${githubTokenFile}")"; fi'
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
xdg.configFile."git/allowed_signers".text = lib.mkAfter (
|
||||
lib.concatStringsSep "\n" work.allowedSigners
|
||||
);
|
||||
programs.git.includes = [
|
||||
{
|
||||
condition = "gitdir:${config.home.homeDirectory}/yookr/";
|
||||
contents = work.git;
|
||||
}
|
||||
];
|
||||
programs.gh.package = gh;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,16 @@
|
||||
{
|
||||
flake.modules.homeManager.yookr-tools =
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
tools = import ./yookr-dev/_packages.nix { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
home.packages = [
|
||||
tools.gardenctl
|
||||
tools.gardenlogin
|
||||
];
|
||||
};
|
||||
|
||||
flake.modules.nixos.yookr-dev = {
|
||||
security.pki.certificateFiles = [
|
||||
./yookr-dev/zenith-rootCA.pem
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
{ pkgs }:
|
||||
{
|
||||
gardenctl = pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "gardenctl";
|
||||
version = "2.14.0";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/gardener/gardenctl-v2/releases/download/v2.14.0/gardenctl_v2_linux_amd64";
|
||||
hash = "sha256-JCZ0eJLgYbd2ZMCCWFlhX4vOhHKZL40oR2a3EZ3i4Q8=";
|
||||
};
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
install -Dm755 "$src" "$out/bin/gardenctl"
|
||||
install -d "$out/share/zsh/site-functions"
|
||||
"$out/bin/gardenctl" completion zsh > "$out/share/zsh/site-functions/_gardenctl"
|
||||
'';
|
||||
};
|
||||
gardenlogin = pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "gardenlogin";
|
||||
version = "0.10.0";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/gardener/gardenlogin/releases/download/v0.10.0/gardenlogin_linux_amd64";
|
||||
hash = "sha256-X4nHiZ29Mbnhxv/wlyD6PxX1KxzaX2R27N7Muu/gnH8=";
|
||||
};
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
install -Dm755 "$src" "$out/bin/gardenlogin"
|
||||
ln -s gardenlogin "$out/bin/kubectl-gardenlogin"
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
perSystem =
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
tools = import ./_packages.nix { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
# Tooling only: no credential loading, mounts, or Python dependency installs.
|
||||
devShells.workbench = pkgs.mkShell {
|
||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
|
||||
pkgs.stdenv.cc.cc.lib
|
||||
pkgs.zlib
|
||||
];
|
||||
UV_PYTHON = "${pkgs.python314}/bin/python";
|
||||
UV_PYTHON_DOWNLOADS = "never";
|
||||
packages = [
|
||||
tools.gardenctl
|
||||
tools.gardenlogin
|
||||
]
|
||||
++ (with pkgs; [
|
||||
k9s
|
||||
kubectl
|
||||
kubelogin-oidc
|
||||
jq
|
||||
just
|
||||
python314
|
||||
rclone
|
||||
sops
|
||||
util-linux
|
||||
uv
|
||||
]);
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
nixosModules = config.flake.modules.nixos;
|
||||
homeModules = config.flake.modules.homeManager;
|
||||
in
|
||||
{
|
||||
# Provisional boundary: both workstations select the same company integration.
|
||||
flake.modules.nixos.work = {
|
||||
imports = [
|
||||
nixosModules.openvpn
|
||||
nixosModules.yookr-dev
|
||||
];
|
||||
home-manager.sharedModules = [ homeModules.work ];
|
||||
};
|
||||
|
||||
flake.modules.homeManager.work = {
|
||||
imports = [
|
||||
homeModules.yookr-tools
|
||||
homeModules.work-git
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -27,9 +27,8 @@ in
|
||||
nixosModules.theme
|
||||
nixosModules.ai
|
||||
nixosModules.yunzi-b75-pro
|
||||
nixosModules.openvpn
|
||||
nixosModules.walker
|
||||
nixosModules.yookr-dev
|
||||
nixosModules.work
|
||||
];
|
||||
|
||||
programs.nix-ld.enable = true;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate current repository files without changing the Git index."""
|
||||
|
||||
from collections import deque
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(ROOT)
|
||||
run_dir = Path(tempfile.mkdtemp(prefix="nixos-validate-", dir="/tmp"))
|
||||
print(f"Logs: {run_dir}", flush=True)
|
||||
|
||||
def run(label, command):
|
||||
log = run_dir / f"{label}.log"
|
||||
print(f"{label} ...", flush=True)
|
||||
with log.open("wb") as output:
|
||||
result = subprocess.run(command, stdout=output, stderr=subprocess.STDOUT)
|
||||
if result.returncode:
|
||||
print(f"{label}: FAILED ({result.returncode}); {log}", flush=True)
|
||||
with log.open(errors="replace") as output:
|
||||
excerpt = "".join(deque(output, maxlen=40))
|
||||
print(excerpt[-12000:])
|
||||
raise SystemExit(result.returncode)
|
||||
print(f"{label}: OK", flush=True)
|
||||
|
||||
# Git supplies selection only: contents always come from the working tree.
|
||||
paths = subprocess.check_output(
|
||||
["git", "ls-files", "--cached", "--others", "--exclude-standard", "-z"]
|
||||
).split(b"\0")
|
||||
files = sorted({os.fsdecode(path) for path in paths if path})
|
||||
files = [name for name in files if os.path.lexists(ROOT / name)]
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="nixos-source-", dir="/tmp") as temp:
|
||||
source = Path(temp) / "source"
|
||||
|
||||
def snapshot():
|
||||
if source.exists():
|
||||
shutil.rmtree(source)
|
||||
source.mkdir()
|
||||
for name in files:
|
||||
original = ROOT / name
|
||||
destination = source / name
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if original.is_symlink():
|
||||
destination.symlink_to(os.readlink(original))
|
||||
elif original.is_file():
|
||||
shutil.copy2(original, destination)
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported source entry: {name}")
|
||||
|
||||
snapshot()
|
||||
flake = f"path:{source}"
|
||||
nix = ["nix", "--quiet"]
|
||||
locked = ["--no-update-lock-file"]
|
||||
# The repository currently exposes only x86_64-linux outputs.
|
||||
nix_files = [str(ROOT / name) for name in files if name.endswith(".nix")]
|
||||
run("format", nix + ["run", *locked, f"{flake}#formatter.x86_64-linux", "--", *nix_files])
|
||||
snapshot()
|
||||
run("check", nix + ["flake", "check", "--no-build", *locked, flake])
|
||||
hosts_file = run_dir / "hosts.json"
|
||||
# Keep machine-readable output separate from Nix diagnostics.
|
||||
with hosts_file.open("wb") as output, (run_dir / "hosts.log").open("wb") as errors:
|
||||
result = subprocess.run(
|
||||
nix + ["eval", *locked, "--json", f"{flake}#nixosConfigurations", "--apply", "builtins.attrNames"],
|
||||
stdout=output, stderr=errors,
|
||||
)
|
||||
if result.returncode:
|
||||
print(f"Host discovery failed; see {run_dir / 'hosts.log'}")
|
||||
raise SystemExit(result.returncode)
|
||||
available = json.loads(hosts_file.read_text())
|
||||
hosts = list(dict.fromkeys(sys.argv[1:])) or available
|
||||
unknown = set(hosts) - set(available)
|
||||
if unknown:
|
||||
raise RuntimeError(f"Unknown hosts: {', '.join(sorted(unknown))}")
|
||||
for host in hosts:
|
||||
run(f"build-{host}", nix + ["build", *locked, "--no-link", f"{flake}#nixosConfigurations.{host}.config.system.build.toplevel"])
|
||||
if not sys.argv[1:]:
|
||||
run("build-workbench", nix + ["build", *locked, "--no-link", f"{flake}#devShells.x86_64-linux.workbench"])
|
||||
print(f"Validation passed: {', '.join(hosts)}. Logs: {run_dir}", flush=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except (OSError, ValueError, RuntimeError, subprocess.CalledProcessError) as error:
|
||||
sys.exit(str(error))
|
||||
Reference in new issue
Block a user