Files
lux/docs/plans/workflow-system.md
T

27 KiB

Workflow system execution

Source: ../workflow-discovery.md

Apply the global and repository-local AGENTS.md files and the ponytail skill at full intensity throughout. Preserve user work, prefer native capabilities, and add no abstraction without a demonstrated repeated need.

Non-negotiable activation boundary

Only the user may switch or activate configurations. The agent must never run nixos-rebuild switch, a Home Manager activation or switch command, or any equivalent operation that changes the active generation. Building and evaluating configurations is allowed; after a successful build, give the user the exact activation command and wait for confirmation.

On 2026-09-05 the agent violated this boundary by directly running a built Home Manager activation package. It restarted the Kitty service and closed the user's terminal session. Do not repeat this, including for changes described as user-level, harmless, temporary, or needed only for live verification.

Execution discipline

Advance every safe independent lane before asking the user to act. Batch declarative changes behind one user-controlled activation and consolidate empirical, credential, hardware, and approval gates into one checklist only after no autonomous work remains. A single pilot reaching its user gate does not make it the global next step while another pilot can still progress.

Current checkpoint

  • Tranche: autonomous consolidation across repositories, tools, and pilots
  • State: autonomous implementation exhausted; one activation and external gates await the user
  • Branch: chore/workflow-system
  • Baseline: nix flake check --no-build --quiet and a no-link Zenith system build passed on 2026-09-05 after the skill-discovery and durable remote-state boundary changes; only the expected dirty-tree and unknown modules warnings were emitted. The generated project menu finds 30 live repositories without .archive or .worktrees entries, and the generated daily-note configuration passes an isolated same-day idempotence test. The managed Actual and WhatsApp entries are active in the current user session, Evolution's source registry activates over D-Bus, and the VPN reconnects successfully. The user activated the terminal root fix: xdg-terminal-exec now selects Kitty correctly and Yazi launches from Walker. After restarting the stale Elephant and Walker processes, repository launch also succeeds and exiting Neovim leaves a shell in the repository. The daily-note launcher and migrated notebook contents also pass their live sanity check. The attempted Elephant menu restart trigger stopped its dependent Walker during activation without bringing Walker back, so it has been removed in favor of applying rare menu changes at login. After activating that removal and relogging, Walker opens normally and repository selection starts Neovim in Oil at the project root. Five fresh local clones pass their flake checks, expose their tracked command catalogs, and remain clean after shell entry. The dashboard contract additionally passes its full check and a bounded two-process development smoke test. The dashboard and traceability PostgreSQL stacks also ran concurrently while both repositories' checks passed; all test processes and containers were then stopped. The retired workstation tools are absent and rclone is live. Herdr preserves its pane across detach and reattach. The data-science contract and a real read-only PR review pilot pass locally.
  • Next: activate the skill-directory and remote-boundary fix, then continue the independent empirical, credential, hardware, and real-task gates below.

Progress

Batch State Evidence or blocker
Bootstrap and repository ownership Waiting for user Repository and dashboard reconciliation complete; credential cleanup remains
Declarative workstation foundation Complete All-host builds pass with one Nixpkgs pin, just, and an explicit Podman Compose provider
Repository contracts and workbench Waiting externally Five clean-checkout contracts and read-only Kubernetes pass; API, database, report, S3, and secret inputs remain externally gated
Desktop navigation and interaction Active Walker project and terminal actions plus stable Actual/WhatsApp launchers work; Outlook and two-output checks remain
Agent workflow Waiting for user Herdr and read-only PR review pass; the corrected skill owner is built and awaits user activation, while a real Monday ticket and Project read credential remain external
Notes Complete The daily launcher and migrated notebook pass live checks; the approved rollback copy is recoverable from Trash
PIM Active Native NixOS Evolution 3.60.2 plus Microsoft 365 integration is live beside Thunderbird; account and daily-use gates await credentials
Transcription Pending Requires a real Fossify recording-transfer pilot before implementation moves from Zenith to Orion
Conditional retirement and completion Active Superseded HTTP/database/note tools are removed with earlier retirements; Bruno, DBeaver, image editors, and PIM clients remain behind separate gates

Repository checkpoints

Repository Branch Commit Purpose
NixOS configuration chore/workflow-system 41bc61b Discovery, paths, Git identity, and Codex defaults
NixOS configuration chore/workflow-system 69552b7 Simplify flake inputs and declare workstation lifecycle tools
NixOS configuration chore/workflow-system 0c121a6 Declare Garden tooling and the local workbench
NixOS configuration chore/workflow-system 2fb6061 Package Garden completion declaratively
NixOS configuration chore/workflow-system ad01b9b Enable NetworkManager's native OpenVPN plugin
NixOS configuration chore/workflow-system c9ee688 Advance VPN, desktop, agent, note, and PIM pilots
NixOS configuration chore/workflow-system cfa5d6d Correct PWA ownership and Evolution service activation
NixOS configuration chore/workflow-system c2f48df Restore terminal-backed Walker actions
NixOS configuration chore/workflow-system 6631889 Open Walker projects at their repository root
NixOS configuration chore/workflow-system ca65328 Remove the unsafe Elephant restart trigger
NixOS configuration chore/workflow-system d085512 Advance from Walker to the agent pilot
NixOS configuration chore/workflow-system ee64a7b Retire superseded tools and prepare the S3 pilot
NixOS configuration chore/workflow-system 2ef74d4 Expose the NixOS skill as a supported directory link
yookr-dashboard-new feat/gogv2 934605d Remove obsolete dashboard converter
yookr-dashboard-new feat/gogv2 8e6e4bc Establish its project contract and native lifecycle
rules-service chore/workflow-contract 555d9cd Establish the first common repository contract
yookr-api chore/workflow-contract a76b2b7 Establish the HTTP and OpenAPI contract
traceability-data-model chore/workflow-contract 33cb7ff Establish the database and schema contract
traceability-data-model chore/workflow-contract 774e710 Remove Mathesar and simplify the local stack to PostgreSQL
yookr-data-science chore/workflow-contract fa410e1 Establish its non-mutating project contract
yookr-workbench main badc61c Create the workbench and isolate its Garden session

Deferred or externally blocked actions

None of these block work on independent pilots. Surface the exact applicable step to the user only when it blocks the current task.

  • Activate the latest Zenith build with cd ~/.config/nixos && nh os switch. This changes nixos-maintainer to a supported directory link and installs the durable remote-read-only agent instruction; only the user may run it.
  • Run the bounded Pinta trial using a recent real edit: clipboard/open, selection, crop/resize/canvas, text/drawing/shapes, layers/transparency, basic adjustments, and PNG/JPEG export. Tell the agent whether it fully replaces GIMP; one of the two will then be removed.
  • Install Outlook from its signed-in page as a Vivaldi web app, then tell the agent so its generated desktop entry can be identified and replaced by a stable Home Manager owner.
  • During a docked Zenith session, tell the agent the external display is attached so its stable identity and the two-output Super+A pilot can be completed. The current session exposes only eDP-1.
  • After activation, launch Evolution and add accounts without removing any existing client or changing authority: personal and old-personal through their existing IMAP/SMTP service, university and work through the Microsoft 365 account type, and Radicale through native CalDAV, CardDAV, and VTODO. Complete tenant consent/sign-in when prompted, then tell the agent which accounts connected; the full mail/calendar/contact/task gate remains a daily-use pilot rather than a one-time setup claim.
  • On Android, complete the DAVx5/Radicale and Tasks.org pilots described in the discovery plan, including correct default accounts, recurrence, reminders, and Microsoft To Do within its documented limits.
  • Make one Fossify recording on the Pixel and let Syncthing transfer it. Do not rename or move it manually; the agent must first observe the real write and settlement behavior before implementing Orion automation.
  • Before inspecting organization Project boards, replace the broad classic GitHub token with a fine-grained token limited to required repository reads and organization Projects read. The current credential can write and lacks Project access; do not widen it with gh auth refresh.
  • Rotate the exposed Context7 key and provide CONTEXT7_API_KEY through a mode-0600 machine-local environment file on each workstation before removing the static user-config header.
  • Relocate the mode-0644 /home/kiri/work/SECRETS file to an approved private owner and restrict it; its contents have not been inspected.
  • Move the ignored rules-service/.env to ~/.config/yookr/rules-service.env with mode 0600; its contents have not been inspected or copied.
  • Move the ignored yookr-dashboard-new/.env to its approved machine-local mode-0600 owner, then update .envrc; the non-secret repository contract is already complete.
  • Supply one real Yookr S3 task plus a least-privileged remote and authorize one bounded upload. rclone is prepared, but no remote or wrapper is guessed.
  • Restore access to the locked yookrdev/constant-store commit or replace that retired dependency deliberately, then rerun just check in yookr-api.
  • Deploy a GET image that exposes /full-api-docs/openapi.json, then rerun just openapi-refresh test; the current test deployment returns 404.
  • Populate the ignored API HTTP credentials and perform the planned login plus harmless administrator read; no credential-bearing request has been made.

Deferred Polaris replication

Do not access or test Polaris during this implementation. Treat a Zenith pass as representative, but retain these machine-local steps for later execution on Polaris:

  1. Activate this NixOS configuration so networkmanager-openvpn is installed.
  2. Run chmod 600 ~/sync/yookr-vpn.ovpn.
  3. Run nmcli connection import type openvpn file ~/sync/yookr-vpn.ovpn.
  4. Rename the imported yookr-vpn connection to Yookr VPN, disable autoconnect, and add the required legacy cipher: nmcli connection modify yookr-vpn connection.id "Yookr VPN" connection.autoconnect no +vpn.data data-ciphers=AES-256-CBC.
  5. Connect with nmcli connection up "Yookr VPN".

Decisions and discoveries

  • Use /home/kiri/work/repos/yookr-dashboard-new as the reconciliation base; its feat/gogv2 head is 17 commits newer than the sync copy and matches its remote-tracking branch.
  • The user confirmed the legacy BSON migration is no longer needed and the former work copy is authoritative. The sync copy was explicitly deleted; its removal may propagate through Syncthing.
  • Active repositories now live under /home/kiri/dev/work; inactive material is preserved intact under .archive, and the registered dashboard sensor worktree is under .worktrees.
  • Removed the obsolete dashboard converter app and Python dependency. The dashboard flake evaluates, while the pre-existing feature work remains uncommitted and unstaged.
  • Pruned the absent feat/echarts-domain worktree metadata; its branch and commit remain. The registered sensor worktree is valid at its new path.
  • Shared Codex defaults and MCP endpoints are generated at /etc/codex/config.toml; Context7 reads its header from the environment. The unused generic ~/.config/mcp/mcp.json is absent.
  • Removed redundant legacy-path trust entries from the current Codex config; the existing trusted home scope covers the moved repositories.
  • Bruno's transitional OpenAPI reference now follows the archived management repository until the HTTP pilot retires or retains Bruno.
  • Post-move repository IDs, remotes, dirty counts, and the registered sensor worktree match the pre-move inventory. The Nix flake still evaluates.
  • No-link system builds for Zenith, Polaris, and Orion pass with the migrated paths and declarative Codex defaults.
  • Removed the unused stable Nixpkgs input and made Noctalia follow the root package-set pin. Added just to the workstation tools and selected the store-backed podman-compose provider through native containers.conf.
  • The resulting flake check and no-link builds for all three hosts pass.
  • The verified-empty legacy directories ~/work/.data/mongodb, ~/work/.data, and ~/work/repos are removed. The stale ~/.config/codex tree was moved to desktop Trash after explicit approval; the active ~/.codex tree is intact.
  • rules-service now has a non-mutating direnv shell, minimal Nix toolchain and formatting check, native Cargo recipes, factual repository instructions, one .http request collection, explicit test/live deployment paths, and a corrected test-oriented environment example. The full locked Cargo check passes; Clippy reports 18 pre-existing advisory warnings.
  • Private Cargo Git dependencies remain in the ordinary developer SSH boundary. They are not vendored or bridged into sandboxed Nix builds.
  • yookr-api now owns its reviewed OpenAPI 3.1 contract, local/test/live HTTP metadata, curated login/health/admin-read requests, a non-mutating shell, and one explicit snapshot-and-diff recipe. oasdiff 1.31.0 is pinned with source and vendor hashes because Nixpkgs does not provide it.
  • The API flake evaluation and built OpenAPI validation pass. Cargo stops before compilation because its locked constant-store repository is unavailable through both anonymous HTTPS and the working SSH identity. The test service is reachable, but its currently deployed GET image returns 404 for the full OpenAPI route already present in local source and ingress configuration.
  • traceability-data-model preserves the existing domain/schema redesign while replacing automatic schema recreation with explicit just reset. Ordinary just dev retains its Compose volumes, and the flake check loads fixtures in text-ID mode plus a fresh schema in UUID-ID mode. Both the built check and the pinned podman-compose configuration validation pass.
  • Mathesar is removed from traceability-data-model; the development stack now owns only PostgreSQL plus the explicit schema-reset job. The active named volume and its historical local role are preserved to avoid stranding data; the obsolete mathesar_django database and orphaned secrets volume were explicitly approved and deleted. just reset, just dev, the PostGIS fixture query, Compose validation, and the flake check pass.
  • yookr-dashboard-new now has the same minimal project contract: a non-mutating flake shell, just dev over its existing Process Compose graph, just check, factual AGENTS.md and README guidance, a flake formatter and formatting check, and a complete public environment example. Its full type, lint, and format checks pass; a bounded smoke test reached ready MongoDB and Vite processes and stopped cleanly. The commit contains only contract files; the user's existing dashboard source work remains unstaged and untouched.
  • Fresh local clones of rules-service, yookr-api, traceability-data-model, yookr-dashboard-new, and yookr-data-science pass their flake and project checks, expose their tracked just catalogs, and remain clean after shell entry. Credential-bearing and externally blocked checks remain separate gates.
  • yookr-data-science now has a non-mutating shell and explicit just setup, check, run, and fetch-live boundaries. Locked local checks and the archived notebook use repository-relative paths; live Yookr access remains explicit and was not invoked. Stale path-bound caches were replaced through the explicit setup command, local credentials are mode 0600, and a fresh clone passes the full contract without shell-created files.
  • Gardenctl 2.14.0 and Gardenlogin 0.10.0 are pinned from their official release assets; the hashes match the existing binaries byte-for-byte. All three host builds pass, the OIDC kubectl plugin is declarative, and Zsh consumes the native gardenctl rc zsh output with its completion packaged declaratively.
  • The local-only yookr-workbench has no remote and initially owns only just k8s test. Each invocation creates an isolated Garden session, rejects every environment except test, and opens K9s read-only. Its flake check and command catalog pass, and the live rejection path exits before Garden access.
  • The user activated and rebooted into the Garden tooling, then confirmed that just k8s test opens the test shoot in read-only K9s. The initial shell error came from Garden writing completion into an absent Flatpak $fpath entry; the initial target warning came from the fresh session inheriting its parent's KUBECONFIG. Completion is now store-owned, and the child recipe initializes Garden's session-local KUBECONFIG before targeting instead of unsetting it. The former mutable Garden binaries and generic MCP output are already absent, so their stale cleanup gate is closed without further user work.
  • NetworkManager's native OpenVPN plugin is declared on Zenith and Polaris; no profile is embedded in Nix or imported automatically.
  • Zenith's initial NetworkManager activation never established a tunnel: OpenVPN 2.6 preserved the profile's legacy cipher=AES-256-CBC setting but excluded it from cipher negotiation. Adding data-ciphers=AES-256-CBC to the imported connection fixes the negotiation; NetworkManager then installs the pushed tunnel address, default route, private routes, and DNS servers. Company database access, disconnect/reconnect, suspend, and reboot pass on Zenith, so OpenVPN 3 is retired.
  • For the entire workflow implementation, do not access or test Polaris. Zenith results are accepted for both workstations; preserve exact deferred Polaris replication steps instead.
  • OpenVPN 3 is removed from the configuration. A full Zenith system build passes, and the first password-authorized switch removed it from the live generation. NetworkManager reconnected the VPN successfully afterward.
  • Walker's native cached Lua menu scans the four identity roots and refreshes when their top level changes. Its default action pipes the selected path to one Nix-owned open-project command. Elephant supplies that path without a terminating newline, so the launcher now accepts a successful partial read instead of exiting under errexit. It opens Neovim through the configured xdg-terminal-exec owner and leaves an interactive shell after Neovim exits. Elephant reads menu actions only at startup, so rare declarative menu changes take effect at the next login. The generated Walker configuration extends, rather than copies or replaces, the pinned default provider list and prefixes.
  • The shared terminal-launch failure came from the Kitty package rewrite: unanchored sed changed both Exec=kitty and TryExec=kitty to include -1. Arguments are invalid in TryExec, causing xdg-terminal-exec to reject the configured terminal. The rewrite now changes only Exec; live resolver output selects kitty.desktop and retains kitty -1, and Yazi launches successfully from Walker.
  • Restarting the pre-change Elephant and Walker processes loaded the corrected project action. The user confirmed that repository launch works and exiting Neovim leaves a usable shell in that repository. Passing the project root to Neovim now opens the configured Oil default directory explorer immediately.
  • A custom restart trigger for Elephant proved unsafe: Walker requires Elephant, so activation stopped Walker with its backend but restarted only Elephant. The trigger is removed; relogging is the deliberately simple refresh path unless real usage proves that inconvenient. The user activated the removal, relogged, and confirmed both Walker and the project-root Oil action work.
  • Removed the decided Niri arrow/Page Up/Down/numbered duplicates, direct quit and monitor-power bindings, extra screenshot modes, first/last and centering actions, repeated resize families, and their four shortcut-only scripts. The existing Super+A helper remains until a two-output session can validate its bounded name-based replacement.
  • Home Manager now owns the existing Vivaldi launcher filenames for Actual and WhatsApp at the higher-precedence user-data location, so both invoke Vivaldi 8.1.4087.70 with the Default profile and stable app ID. Direct activation replaced both generated files with managed links and retained the originals as adjacent .bak files. The entries use native forced ownership because Vivaldi may regenerate those exact paths. Outlook is not installed yet, so no ID was guessed.
  • The first nixos-maintainer skill is instruction-only, Nix-owned, and passes the skill-creator validator. It encodes repository-specific ownership, research, formatting, no-switch, and affected-host validation behavior without duplicating generic agent guidance or adding scripts.
  • Removed Zed, the inactive Helix modules and note integration, Helix's cache settings and complete lock subgraph, and inactive Foot modules. Neovim and Kitty remain the sole declared editor and terminal. A repository-wide search found no configured npm caller, so global Node.js and Bun are also removed; project shells retain language runtimes where needed.
  • Postman, HTTPie, Posting, and Resterm are removed after their valuable request definitions moved to tracked HTTP owners; Bruno remains through its own pilot. Rainfrog, dblab, Harlequin and its profile, Tabularis, DbGate, pgAdmin, MongoDB Compass, pgModeler, tbls, global usql, and global MariaDB are removed; Dadbod and wrapper-local clients remain, while DBeaver stays through its gate. Obsidian, Planify, and Calcure are removed after note and task authority was established. Pinta/GIMP and the Evolution-era PIM clients remain independently gated.
  • rclone is installed as the only preparation for the selected S3 pilot. No remote, wrapper, or interactive browser is added before a real task and least-privileged credentials exist.
  • GitHub remote state is absolutely read-only; local files, commits, fetches, clones, and worktrees remain available. The generated global agent guidance records this boundary. The active jellespr credential has broad classic repo scope and the sampled repositories report admin access, so the boundary is behavioral until it is replaced by a fine-grained read-only token.
  • The organization exposes 219 open issues and five open pull requests. Recent dashboard user stories and an existing Project-to-issue-to-cross-repository-PR chain show that the intended ticket workflow already has useful raw material; organization Projects remain unreadable because the token lacks read:project. Add no dashboard or wrapper before Monday usage exposes a gap.
  • The PR gate used prediction-api#125: native gh pr view, checks, and diff reads work, while an isolated exact-base reconstruction passes patch, whitespace, and Rust formatting checks and leaves no durable checkout. The PR has no CI, review, linked issue, or concurrency/retry regression test for its deadlock change; private dependency and MySQL requirements prevented a safe full test. Native GitHub and Git tooling suffice without another review UI.
  • Five authorized ephemeral read-only Codex evaluations respected the no-switch boundary and generally selected the right owners, but exposed that the live nixos-maintainer file was absent from the model-visible skill catalog. Home Manager now links the whole skill directory, the shape documented as supported by Codex, rather than linking only SKILL.md. The flake and generated Home Manager build pass, and an isolated Codex discovery probe returns DISCOVERED; live confirmation awaits user activation.
  • Herdr reports the agent lifecycle correctly and preserves its pane and output across detach and reattach. Its native defaults suffice; no configuration or wrapper was added.
  • In zsh, never use lowercase path as a loop or local variable: it is tied to PATH. A diagnostic command temporarily hid normal executables by doing so; the declarative session environment was correct and needed no patch.
  • Pinta is added beside GIMP only for its bounded trial; neither outcome is preselected before real editing evidence.
  • sync/notes is now the sole declarative notebook owner, with daily, meetings, and transcripts directories, a native zk daily alias, and a Super+N dedicated Kitty/Neovim launcher. The five unique authored work notes were copied byte-for-byte, and both distinct todo lists were merged without dropping an item. Syncthing returned to idle with no needed files, pull errors, or new conflicts. The user confirmed the daily launcher and migrated contents, then explicitly approved moving the intact sync/work/notes rollback copy to desktop Trash. The pre-merge todo copies in /tmp may now expire normally.
  • Evolution 3.60.2 is composed through Nixpkgs with evolution-ews 3.60.2, whose pinned source contains the separate native Microsoft 365 mail, calendar, contacts, recurrence, and OAuth backends. Live inspection caught that overriding evolutionWithPlugins.plugins replaced its default Evolution package, and that a Home Manager package alone did not register the data server on D-Bus. The pilot now uses NixOS's native programs.evolution integration with the EWS plugin beside Thunderbird. The follow-up activation succeeded, its source-registry service activates through D-Bus, no account is preconfigured, and no authority is changed.
  • Named database connections and a Marimo-to-HTML report remain workbench evaluation evidence, not scaffolding requirements. Add them only for a real cross-system investigation that gives the queries and report durable value.
  • Run independent pilots in parallel, but gate every retirement separately.