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
|
# NixOS configuration
|
||||||
|
|
||||||
Host identity and topology live in `modules/hosts/<host>/default.nix`; shared account,
|
One shared daily environment on Polaris and Zenith, with shared services on Orion.
|
||||||
service, external-device, and server-topology facts live in `modules/facts.nix`.
|
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,
|
## Start here
|
||||||
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`.
|
|
||||||
|
|
||||||
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
|
```console
|
||||||
nix fmt
|
nix develop --quiet ~/.config/nixos#workbench --command bash --norc
|
||||||
nix flake check --no-build
|
|
||||||
nh os switch
|
|
||||||
sops edit modules/secrets/secrets.yaml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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 =
|
flake.modules.homeManager.dev-tools =
|
||||||
{ config, pkgs, ... }:
|
{ 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.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo";
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
@@ -40,8 +11,6 @@
|
|||||||
scc
|
scc
|
||||||
visidata
|
visidata
|
||||||
just
|
just
|
||||||
gardenctl
|
|
||||||
gardenlogin
|
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.lazygit.enable = true;
|
programs.lazygit.enable = true;
|
||||||
|
|||||||
@@ -1,35 +1,11 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
account = config.facts.account;
|
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 =
|
mkScope =
|
||||||
scope:
|
config: scope:
|
||||||
let
|
let
|
||||||
email = account.emails.${scope}.address;
|
email = account.emails.${scope}.address;
|
||||||
key = machine.sshKeys.${scope} or null;
|
key = config.facts.machine.sshKeys.${scope} or null;
|
||||||
hasSigningKey = key != null;
|
hasSigningKey = key != null;
|
||||||
privateKeyPath =
|
privateKeyPath =
|
||||||
if hasSigningKey && key.privateKeyPath != null then key.privateKeyPath else "~/.ssh/id_${scope}";
|
if hasSigningKey && key.privateKeyPath != null then key.privateKeyPath else "~/.ssh/id_${scope}";
|
||||||
@@ -47,17 +23,18 @@ in
|
|||||||
}
|
}
|
||||||
// lib.optionalAttrs hasSigningKey {
|
// lib.optionalAttrs hasSigningKey {
|
||||||
core.sshCommand = "ssh -i ${privateKeyPath} -o IdentitiesOnly=yes";
|
core.sshCommand = "ssh -i ${privateKeyPath} -o IdentitiesOnly=yes";
|
||||||
gpg.ssh.allowedSignersFile = allowedSignersFile;
|
gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
in
|
||||||
personal = mkScope "personal";
|
{
|
||||||
work = mkScope "work";
|
flake.modules.homeManager.git =
|
||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
personal = mkScope config "personal";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" (
|
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" personal.allowedSigners;
|
||||||
personal.allowedSigners ++ work.allowedSigners ++ [ "" ]
|
|
||||||
);
|
|
||||||
|
|
||||||
programs.git = {
|
programs.git = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -73,34 +50,52 @@ in
|
|||||||
email = account.emails.personal.address;
|
email = account.emails.personal.address;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
includes = [
|
includes =
|
||||||
{
|
map
|
||||||
condition = "gitdir:${account.nixosConfigurationPath}/";
|
(path: {
|
||||||
|
condition = "gitdir:${path}/";
|
||||||
contents = personal.git;
|
contents = personal.git;
|
||||||
}
|
})
|
||||||
{
|
[
|
||||||
condition = "gitdir:${config.home.homeDirectory}/yookr/";
|
account.nixosConfigurationPath
|
||||||
contents = work.git;
|
"${config.xdg.userDirs.projects}/own"
|
||||||
}
|
"${config.xdg.userDirs.projects}/ext"
|
||||||
{
|
"${config.xdg.userDirs.projects}/forks"
|
||||||
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;
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.gh = {
|
programs.gh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = gh;
|
|
||||||
settings.git_protocol = "ssh";
|
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 = {
|
flake.modules.nixos.yookr-dev = {
|
||||||
security.pki.certificateFiles = [
|
security.pki.certificateFiles = [
|
||||||
./yookr-dev/zenith-rootCA.pem
|
./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.theme
|
||||||
nixosModules.ai
|
nixosModules.ai
|
||||||
nixosModules.yunzi-b75-pro
|
nixosModules.yunzi-b75-pro
|
||||||
nixosModules.openvpn
|
|
||||||
nixosModules.walker
|
nixosModules.walker
|
||||||
nixosModules.yookr-dev
|
nixosModules.work
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.nix-ld.enable = true;
|
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