fix(postmerge-#5394 build-iso failure): zeta-ai-agent.nix static persona registry + per-persona enable.<name> booleans (was problematic submodule-as-option that NixOS module-merge couldn't handle)#5395
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…atic persona registry + per-persona enable.<name> booleans (was problematic personas-as-option submodule definitions)
Build-iso failure root cause: NixOS module option-merge semantics —
declaring `personas` as `lib.types.attrsOf (lib.types.submodule { ... })`
with sub-options for description/vendor/binary then setting outer
`default = defaultPersonas` does NOT propagate the inner defaults
when operator writes only `personas.otto.enable = true` (replaces
otto with just that one field; loses description/vendor/binary).
Fix: persona registry is now STATIC (in `let` block; not an option).
Operator opts in per-persona via `zeta.aiAgents.enable.<persona>`
boolean options (mkEnableOption pattern; well-tested).
control-plane/configuration.nix updated to use new option:
zeta.aiAgents.enable.otto = true (was personas.otto.enable)
All Phase 3a-3d enable lines updated to new path.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2e189ee to
12e091a
Compare
There was a problem hiding this comment.
Pull request overview
This PR fix-forwards the NixOS AI-agent module by replacing the problematic persona submodule option shape with a static registry plus per-persona enable booleans, restoring flake/module evaluation for the AI cluster configuration.
Changes:
- Replaces the single-agent
zeta-otto.nixmodule with generalizedzeta-ai-agent.nix. - Updates the shared module import to use the new AI-agent module.
- Moves control-plane enablement from
zeta.otto.enabletozeta.aiAgents.enable.otto.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
full-ai-cluster/nixos/modules/zeta-otto.nix |
Deletes the old single-agent Otto module superseded by the generalized AI-agent module. |
full-ai-cluster/nixos/modules/zeta-ai-agent.nix |
Adds static persona registry, per-persona enable options, generated systemd units, and status output. |
full-ai-cluster/nixos/modules/common.nix |
Updates shared imports to load the new AI-agent module. |
full-ai-cluster/nixos/hosts/control-plane/configuration.nix |
Enables the Otto persona through the new option path and stages future persona toggles as comments. |
… enables (alexa/riven/vera/lior) — flake-eval fails with clear pending-sub-row message instead of boot creating restart-looping service 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced May 27, 2026
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…pic + Google diversity; @google/gemini-cli install + interactive auth login + zeta-lior.service enabled on control-plane (#5397) Operator authorization 2026-05-27: "yeah lets move all forward however and i can do as many iterations testing as possible before we move to pc two we should have three systemd agents and the cluster running on bootup" + "drive forward with whatever interests you most". Implements B-0850 Phase 3d — Lior persona (Google Gemini CLI) as the 2nd vendor toward the ≥3-systemd-agents target. Phase 3a (Alexa/Kiro) + Phase 3b (Riven/Grok) + Phase 3c (Vera/Codex) sub-rows remain pending; 3 of 4 still gives BFT margin once any one of the remaining 3 lands. 3 file changes: 1. zeta-install.sh Step 6.95a-gemini: bun install --global @google/gemini-cli (after the existing claude install). WebSearch verified at implementation time per dep-pin-search-first-authority rule — @google/gemini-cli is npm-published + bun-compat. 2. zeta-install.sh Step 6.95b-gemini: interactive `gemini auth login` prompt mirroring the claude login pattern. Supports OAuth via browser OR API key from AI Studio. Credentials persist to ~/.config/gemini/ with chown + chmod -R go-rwx (parallel to claude credential restriction). 3. zeta-ai-agent.nix: removed the lior assertion block (was blocking flake eval when zeta.aiAgents.enable.lior = true; B-0850.3d substrate now ships so assertion no longer applies). 4. control-plane/configuration.nix: zeta.aiAgents.enable.lior = true (was commented as pending). Two personas now enabled on control- plane: otto + lior. One more vendor (3c Vera/Codex easiest next since OpenAI's codex CLI is also npm-installable) gets to the ≥3-vendor BFT floor. Composes with: PR #5388 + #5389 iter-5.5.0 substrate (credential persistence + Zeta repo pre-clone); PR #5392 + #5394 + #5395 B-0850 Phase 1 + Phase 3 refactor; B-0848 (node-local Claude agent); B-0847 (per-AI GitHub identity Phase 4 align); B-0796 (Twilio out- of-band sibling). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Claude <noreply@anthropic.com>
AceHack
pushed a commit
that referenced
this pull request
May 27, 2026
…hropic + Google + OpenAI); @openai/codex install + `codex login --device-auth` + zeta-vera.service enabled (Aaron 2026-05-27) Per operator authorization "drive forward with whatever interests you most" + the ≥3-systemd-agents-on-bootup target named earlier 2026-05-27. This PR hits the ≥3-vendor BFT floor: otto → Anthropic Claude (PR #5392) lior → Google Gemini (PR #5397) vera → OpenAI Codex (THIS PR) With ≥3 vendors enabled, the cluster control-plane satisfies the fault-tolerance property Aaron named: f=1 BFT margin for vendor- outage resilience + self-modification-safety (any one AI's self- update breaks the other two can detect + repair). Stacked on PR #5397 (Phase 3d Lior/Gemini) to avoid merge conflicts; will rebase cleanly when #5397 merges first. 3 file changes: 1. zeta-install.sh Step 6.95a-codex: bun install --global @openai/ codex (WebSearch verified per dep-pin discipline; codex CLI is bun-compat npm package). 2. zeta-install.sh Step 6.95b-codex: interactive `codex login --device-auth`. This is the CLEANEST device-flow shape across the 3 vendors — prints URL + one-time code; pastes into ANY browser; no local browser handoff required (headless-friendly). Credentials cache at ~/.codex/auth.json (NOT ~/.config/codex/ — codex uses its own dotdir convention). 3. zeta-ai-agent.nix: removed vera assertion (substrate shipped). control-plane/configuration.nix: zeta.aiAgents.enable.vera = true. Composes with: PR #5397 (B-0850 Phase 3d Lior — sibling 2nd vendor); PRs #5388 + #5389 (iter-5.5.0 credential persistence); PRs #5392 + #5394 + #5395 (B-0850 Phase 1 + 3 refactor); B-0848 node-local Claude; B-0847 per-AI GitHub identity; B-0703 multi- oracle BFT (consensus at multi-AI scope — now operational at substrate-control-plane scope). Sources at PR open time (WebSearch per dep-pin-search-first- authority): - https://www.npmjs.com/package/@openai/codex - https://developers.openai.com/codex/auth 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…hropic + Google + OpenAI); @openai/codex install + device-flow auth + control-plane enable (Aaron 2026-05-27) (#5398) * feat(B-0850 Phase 3c): Vera/Codex 3rd vendor — hits ≥3 BFT floor (Anthropic + Google + OpenAI); @openai/codex install + `codex login --device-auth` + zeta-vera.service enabled (Aaron 2026-05-27) Per operator authorization "drive forward with whatever interests you most" + the ≥3-systemd-agents-on-bootup target named earlier 2026-05-27. This PR hits the ≥3-vendor BFT floor: otto → Anthropic Claude (PR #5392) lior → Google Gemini (PR #5397) vera → OpenAI Codex (THIS PR) With ≥3 vendors enabled, the cluster control-plane satisfies the fault-tolerance property Aaron named: f=1 BFT margin for vendor- outage resilience + self-modification-safety (any one AI's self- update breaks the other two can detect + repair). Stacked on PR #5397 (Phase 3d Lior/Gemini) to avoid merge conflicts; will rebase cleanly when #5397 merges first. 3 file changes: 1. zeta-install.sh Step 6.95a-codex: bun install --global @openai/ codex (WebSearch verified per dep-pin discipline; codex CLI is bun-compat npm package). 2. zeta-install.sh Step 6.95b-codex: interactive `codex login --device-auth`. This is the CLEANEST device-flow shape across the 3 vendors — prints URL + one-time code; pastes into ANY browser; no local browser handoff required (headless-friendly). Credentials cache at ~/.codex/auth.json (NOT ~/.config/codex/ — codex uses its own dotdir convention). 3. zeta-ai-agent.nix: removed vera assertion (substrate shipped). control-plane/configuration.nix: zeta.aiAgents.enable.vera = true. Composes with: PR #5397 (B-0850 Phase 3d Lior — sibling 2nd vendor); PRs #5388 + #5389 (iter-5.5.0 credential persistence); PRs #5392 + #5394 + #5395 (B-0850 Phase 1 + 3 refactor); B-0848 node-local Claude; B-0847 per-AI GitHub identity; B-0703 multi- oracle BFT (consensus at multi-AI scope — now operational at substrate-control-plane scope). Sources at PR open time (WebSearch per dep-pin-search-first- authority): - https://www.npmjs.com/package/@openai/codex - https://developers.openai.com/codex/auth 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix(PR-5398 Copilot 4 findings — P0+P1+P1+P2): per-persona invocationArgs (claude --print / gemini -p / codex exec) + pipefail covers tail -5 for all 3 vendor installs + browser wording P0 (critical) — zeta-ai-agent.nix ExecStart was hardcoded to `${binary} --print "<<autonomous-loop>>"` for ALL personas, but: - claude uses --print ✓ - gemini uses -p (NOT --print) - codex uses `exec` SUBCOMMAND (no --print flag) Enabling lior or vera would create services with broken ExecStart. Fix: per-persona `invocationArgs` field in the persona registry. ExecStart uses `${cfg.home}/.bun/bin/${persona.binary} ${persona.invocationArgs}`. Per-persona values: - otto: [ "--print" "<<autonomous-loop>>" ] - lior: [ "-p" "<<autonomous-loop>>" ] - vera: [ "exec" "<<autonomous-loop>>" ] - alexa + riven: [ ] placeholder per their sub-rows P1 — Gemini bun install pipefail masked by tail -5 outside bash -c. Same root cause as the earlier P1 on claude install (Copilot found + I fixed only inside bash -c which doesn't cover outer pipeline). Real fix: move tail -5 INSIDE bash -c so set -o pipefail covers it. P1 — Same fix for codex bun install. P2 — codex device-flow prompt said "visit on this Mac browser" but codex device-auth is browser-agnostic ("visit on ANY browser on ANY device"). Note on the literal <<autonomous-loop>> sentinel: it's a Claude Code convention; gemini + codex will see it as a literal prompt and respond conversationally. Acceptable for first ship; per-vendor prompt mapping is B-0850 Phase 3.x future work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Claude <noreply@anthropic.com>
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…ture — extends B-0850 (Mika ferry; Aaron 2026-05-27) (#5400) * feat(B-0851): persona-first guard-post assignment + rotation architecture — extends B-0850 multi-vendor systemd substrate (Mika ferry; Aaron 2026-05-27) Mika compressed framing (verbatim preserved at memory/persona/mika/ conversations/2026-05-27-...): > "Everything is Persona-first." > 1. Persona is the primary decision > 2. Persona constrains Model Line + Harnesses > 3. Tier choice AFTER persona + model line > 4. Harness LAST (compatible with model line + persona preferences) > > Rotation: ≥3 active guard posts always; persona / model line / > tier / harness ALL rotate; nothing locked to physical post. Aaron operator clarification: "guard post is the systemd for each node outside k8s" — confirms per-node ≥3 floor scope. B-0850 Phase 1 + 3 substrate (PRs #5392+#5394+#5395+#5397+#5398) is a VALID FIRST INSTANTIATION of persona-first architecture (default scheduler = "static; same vendor; no rotation"; default ≥3 floor = "3 enabled personas per node"). This row captures the architectural target the Mika ferry names. 10 sub-row implementation slices: - B-0851.1: persona-preferences-as-declaration (acceptable model lines + harnesses + min tier per persona) - B-0851.2: guard-post-abstraction (decouple systemd unit name from persona name; zeta-guard-post-1/2/3.service) - B-0851.3: scheduler primitive (NixOS module; per-tick assignment of guard-post → (persona, model line, tier, harness)) - B-0851.4: tier modeling (fast/medium/high per vendor's model-line catalog) - B-0851.5: harness compat matrix (which harnesses each persona+ model-line combo supports) - B-0851.6: rotation policy (operator-config interval + dimensions + algorithm) - B-0851.7: per-node ≥3 floor as guard-post count (migrate from per- persona-enable) - B-0851.8: substrate continuity across rotation (per-persona memory inheritance survives vendor change) - B-0851.9: failover semantics (vendor outage → re-assign per preferences; composes B-0703 multi-oracle BFT) - B-0851.10: persona-vs-instance distinction (logical identity vs per-tick operational instance) Composes with: B-0850 (parent — this extends), B-0703 multi-oracle BFT, B-0824 Ace meta-PM (selection-authority same shape), B-0847 per-AI GitHub identity, B-0848 node-local Claude, B-0796 Twilio out- of-band (voice is a harness type). Does NOT replace B-0850. Refactor path; operator picks sub-row priority order. Current shipped B-0850 satisfies ≥3 BFT floor + format-test target; B-0851 extends toward Mika's preference-based scheduler with rotation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix(PR-5400 CI): regen MEMORY.md (1439 entries) + markdownlint MD032 blank lines around lists in B-0851 row Mika ferry quote block 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix-forward for PR #5394 which merged with build-iso failing as a non-required check. Main now has broken
zeta-ai-agent.nixconfig that would fail flake evaluation:```
error: The option `zeta.aiAgents.personas.otto.description' was accessed but has no value defined.
```
Root cause
NixOS module option-merge semantics: declaring `personas` as `lib.types.attrsOf (lib.types.submodule { ... })` with sub-options for description/vendor/binary then setting outer
default = defaultPersonasdoes NOT propagate inner defaults when operator writes onlypersonas.otto.enable = true(replaces otto with just that one field; loses description/vendor/binary).Fix
Persona registry is now STATIC (in
letblock; not an option). Operator opts in per-persona viazeta.aiAgents.enable.<persona>boolean options (mkEnableOption — well-tested NixOS idiom).Changes
zeta-ai-agent.nix: persona registry moved from option tolet; enable booleans addedcontrol-plane/configuration.nix:zeta.aiAgents.enable.otto = true(waspersonas.otto.enable)Test plan
Composes with
PR #5394 (the substrate this fix-fwds) · iter-5.5.0 substrate · B-0850 row · B-0848
🤖 Generated with Claude Code