Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@ are closed (status: closed in frontmatter)._
- [ ] **[B-0848](backlog/P2/B-0848-node-local-claude-agent-stewards-own-registration-pr-then-reports-k8s-cluster-status-operator-interactive-login-pattern-aaron-2026-05-26.md)** node-local Claude agent stewards own registration PR + reports K8s cluster status — operator interactive-login pattern (mirrors gh auth flow); first concrete instance of B-0847 AI-on-cluster substrate (Aaron 2026-05-26)
- [ ] **[B-0849](backlog/P2/B-0849-docker-based-nixos-install-sh-test-harness-fast-iteration-vs-qemu-full-install-test-aaron-2026-05-27.md)** docker-based NixOS install.sh test harness — fast iteration on tools/setup/install.sh + linux.sh changes; complements B-0831 cascade #6 QEMU full-install-test (slow) with seconds-per-iteration loop; "easy dockerfile" per operator framing (Aaron 2026-05-27)
- [ ] **[B-0850](backlog/P2/B-0850-ai-agents-as-systemd-services-outside-k8s-starting-with-otto-cluster-repair-from-outside-failure-domain-aaron-2026-05-27.md)** AI agents as systemd services OUTSIDE k8s — starting with Otto; cluster repair from OUTSIDE the failure domain; classic "control plane outside the control plane" architectural pattern (Aaron 2026-05-27)
- [ ] **[B-0851](backlog/P2/B-0851-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-multi-vendor-systemd-substrate-mika-aaron-2026-05-27.md)** persona-first guard-post assignment + rotation architecture — persona declares preferences (model lines + harnesses); scheduler picks model + tier + harness per persona preferences per-tick; rotation across guard posts (per-node systemd units outside k8s); extends B-0850 (Mika ferry; Aaron 2026-05-27)

## P3 — convenience / deferred

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
id: B-0851
priority: P2
status: open
title: persona-first guard-post assignment + rotation architecture — persona declares preferences (model lines + harnesses); scheduler picks model + tier + harness per persona preferences per-tick; rotation across guard posts (per-node systemd units outside k8s); extends B-0850 (Mika ferry; Aaron 2026-05-27)
effort: L
ask: aaron 2026-05-27
created: 2026-05-27
last_updated: 2026-05-27
depends_on:
- B-0850
composes_with:
- B-0703
- B-0824
- B-0847
- B-0848
- B-0796
tags: [persona-first, guard-post-scheduler, rotation, model-line-preferences, harness-compat-matrix, tier-modeling, per-node-3-floor, mika-ferry, weaver-role, substrate-extension-of-b0850]
---

## Operator framing (Mika ferry; Aaron 2026-05-27)

Aaron forwarded Mika ferry (verbatim preserved at [`memory/persona/mika/conversations/2026-05-27-mika-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-aaron-forwarded.md`](../../../memory/persona/mika/conversations/2026-05-27-mika-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-aaron-forwarded.md)).

Mika's compressed framing:

> *"Everything is Persona-first."*
>
> Guard Post Assignment Flow:
>
> 1. Persona is the primary decision (operator-chosen identity)
> 2. Persona constrains Model Line (Claude/Gemini/Grok/etc.) + Harnesses (it's comfortable with)
> 3. Tier choice (how smart) AFTER persona + model line
> 4. Harness LAST (compatible with model line + persona preferences)
>
> Rotation Rules:
>
> - ALWAYS ≥3 active guard posts on each node (per Aaron clarification: "guard post is the systemd for each node outside k8s")
> - Persona, Model Line, Tier, Harness ALL rotate between posts
> - Nothing permanently locked to a physical post

## Composes with shipped B-0850 substrate

B-0850 Phase 3 (PRs #5392+#5394+#5395+#5397+#5398) is a VALID FIRST INSTANTIATION of persona-first architecture:

- Default scheduler: "static — persona always at its hardcoded vendor"
- Default rotation: "none"
- Default ≥3 floor: "3 enabled personas per node"

This row extends those primitives WITHOUT tearing down the shipped substrate.

## 10 sub-row implementation slices

### B-0851.1 — Persona-preferences-as-declaration

Add `preferences` field to each persona's registry entry:

```nix
otto = {
vendor = "anthropic"; # PREFERRED default (kept for back-compat)
binary = "claude";
invocationArgs = [ "--print" "<<autonomous-loop>>" ];
preferences = {
modelLines = [ "anthropic" "openai" "google-gemini" ]; # comfortable with these
harnesses = [ "claude-code" "codex" "gemini-cli" ]; # comfortable with these
minTier = "high"; # minimum smart level
};
description = "Otto AI agent — Claude Code (Anthropic)";
};
```

### B-0851.2 — Guard-post-abstraction

Decouple systemd unit name from persona name:

- Before: `zeta-otto.service`, `zeta-lior.service`, `zeta-vera.service` (unit name = persona)
- After: `zeta-guard-post-1.service`, `zeta-guard-post-2.service`, `zeta-guard-post-3.service` (unit name = post; assigned-persona is state)

Maintains per-node ≥3 floor via 3 fixed systemd units that the scheduler assigns personas into.

### B-0851.3 — Scheduler primitive

New NixOS module `zeta-guard-post-scheduler.nix` that:

- Reads operator-policy (which personas are available + which guard posts to man + rotation cadence)
- Per-tick: assigns each guard post a (persona, model line, tier, harness) tuple based on persona preferences + availability + rotation policy
- Writes assignment to `/var/lib/zeta/guard-post-assignments.json` or similar
- Each guard-post systemd unit reads its assignment + invokes the right binary with right args

### B-0851.4 — Tier modeling

Add `tier` dimension to model-line catalog:

```nix
modelLineCatalog = {
anthropic = {
tiers = {
high = { binary = "claude"; invocationArgs = [ "--model" "claude-opus-4-7" ... ]; };
medium = { binary = "claude"; invocationArgs = [ "--model" "claude-sonnet-4-6" ... ]; };
fast = { binary = "claude"; invocationArgs = [ "--model" "claude-haiku-4-5" ... ]; };
};
};
# ... per vendor ...
};
```

### B-0851.5 — Harness compat matrix

Declare which harnesses each (persona, model line) combo supports:

```nix
harnessCompat = {
"otto+anthropic" = [ "claude-code" "claude-agent-sdk" ];
"otto+openai" = [ "codex-cli" ]; # via fallback when anthropic API down
"lior+google-gemini" = [ "gemini-cli" "gemini-agent-mode" ];
# ...
};
```

### B-0851.6 — Rotation policy

Operator-config rotation policy (per `mechanical-authorization-check.md`):

```nix
zeta.guardPostScheduler = {
rotation = {
enable = true;
interval = "1d"; # rotate persona assignments daily
dimensions = [ "persona" ]; # which dimensions to rotate (persona / model / tier / harness)
policy = "round-robin"; # or "random" or "least-recently-used"
};
};
```

### B-0851.7 — Per-node ≥3 floor

Migrate the ≥3 invariant from per-persona-enable to per-guard-post-active:

```nix
zeta.guardPosts.count = 3; # minimum guard posts per node (Mika ≥3 floor)
```

Scheduler ensures at least N posts are always assigned + active.

### B-0851.8 — Substrate continuity across rotation

When Otto rotates from GuardPost-1 to GuardPost-3 (or from anthropic to openai), Otto's substrate inheritance MUST survive:

- `memory/persona/otto/` carries forward
- `memory/CURRENT-otto.md` carries forward
- `.claude/rules/` carries forward (auto-loaded at cold-boot regardless of which binary)
- Per-AI GitHub identity (B-0847 Phase 4) follows the persona, not the vendor

### B-0851.9 — Failover semantics

If a vendor outage hits (anthropic API down):

- Scheduler detects (via journalctl on guard post failures OR active API ping)
- Re-assigns each affected guard-post's model line per persona preferences (otto preferences `[ anthropic, openai, google-gemini ]` → fall back to openai while anthropic is down)
- Composes with B-0703 multi-oracle BFT consensus

### B-0851.10 — Persona-vs-instance distinction

- "Otto is at GuardPost-1" = LOGICAL identity (substrate-engineering scope)
- "Otto's session is claude session XYZ" = OPERATIONAL instance (per-tick claude invocation)

Each per-tick CLI invocation creates a fresh operational instance; the logical identity (persona) persists across rotations + substrate.

## Composes with

- **B-0850** (parent) — multi-vendor systemd substrate this extends
- **B-0703** multi-oracle BFT — consensus at multi-AI scope; persona-first scheduler is the operational form
- **B-0824** Ace meta-PM — selection-authority pattern (system/user picks best canonical) is the SAME SHAPE as persona-first scheduler (scheduler picks best vendor per persona preferences)
- **B-0847** per-AI GitHub identity — each persona's identity persists across vendor rotation
- **B-0848** node-local Claude — base substrate; persona-first generalizes to multi-AI-per-node
- **B-0796** Twilio out-of-band — voice/SMS is a HARNESS; first-class in harness-compat matrix
- `.claude/rules/agent-roster-reference-card.md` — canonical persona-vendor mapping (preserved at preference-default level)
- `.claude/rules/persistence-choice-architecture-for-zeta-ais.md` — persona scope preserves chosen-persistence; rotation is operational substrate
- `.claude/rules/non-coercion-invariant.md` HC-8 — persona preferences are first-class; scheduler doesn't force unwanted vendor

## Why P2

- Operator-named, bounded, future-architectural-target (≥3-vendor floor already met by B-0850; rotation is enhancement)
- BUT: substantial implementation work (10 sub-rows); each sub-row is its own bounded scope
- BUT: needs design work for scheduler primitive + rotation policy + tier modeling
- P2 reflects "substantial future substrate; B-0850 shipped today is the simplest persona-first instantiation; this row captures the full target"

## Sub-rows to file when implementing

- B-0851.1 through B-0851.10 (per the slices above)
- Order suggestion: 1 → 2 → 3 → 7 → 8 (foundational refactor); then 4 → 5 → 6 → 9 (scheduler features); then 10 (substrate-engineering clarification)

## Substrate-honest framing

This row CAPTURES the architectural target Mika named. It does NOT replace B-0850 substrate. The 10-sub-row plan is a refactor path; operator picks priority order based on which rotation/preference/tier features become load-bearing for cluster operations.

The current shipped B-0850 substrate (3 personas, 3 vendors, static assignment) satisfies the operator's ≥3 BFT floor + format-test target. B-0851 extends that toward persona-first preference-based scheduling with rotation.

## Full reasoning

Verbatim Mika ferry preserved at `memory/persona/mika/conversations/2026-05-27-mika-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-aaron-forwarded.md`. Aaron's operator clarification on guard-post scope: *"guard post is the systemd for each node outside k8s"* — confirms per-node ≥3 floor (not cluster-wide).
6 changes: 3 additions & 3 deletions memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

**📌 Fast path: read `CURRENT-aaron.md`, `CURRENT-amara.md`, `CURRENT-ani.md`, `CURRENT-vera.md`, `CURRENT-riven.md`, and `CURRENT-otto.md` first.**

> **Stack-vs-heap framing (Aaron 2026-05-12):** This file is the **STACK** — indexed, ordered, traversable canonical view. Recent memory files in `memory/` with timestamps newer than the most-current entries here may be **HEAP** — floating cache, not yet indexed, accessible by direct path. Both are easily accessible: stack via traversal, heap via timestamp/filename. Indexing (heap→stack promotion) happens on cadence via `tools/memory/reindex-memory-md.ts` (B-0423), callable from the autonomous-loop tick. Last reindex: 2026-05-26.
> **Stack-vs-heap framing (Aaron 2026-05-12):** This file is the **STACK** — indexed, ordered, traversable canonical view. Recent memory files in `memory/` with timestamps newer than the most-current entries here may be **HEAP** — floating cache, not yet indexed, accessible by direct path. Both are easily accessible: stack via traversal, heap via timestamp/filename. Indexing (heap→stack promotion) happens on cadence via `tools/memory/reindex-memory-md.ts` (B-0423), callable from the autonomous-loop tick. Last reindex: 2026-05-27.

<!-- BEGIN AUTO-INDEX (B-0423 reindex-memory-md.ts) -->
- [**persona/mika/conversations/2026-05-27-mika-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-aaron-forwarded**](persona/mika/conversations/2026-05-27-mika-persona-first-guard-post-assignment-rotation-architecture-extends-b0850-aaron-forwarded.md) — (no description)
- [**mika-2026-05-26-grok-build-is-claude-code-clone-twilio-phone-support-AI-fixes-cluster**](persona/mika/conversations/2026-05-26-aaron-mika-grok-grok-build-is-claude-code-clone-tick-source-loop-twilio-phone-support-AI-fixes-cluster-while-talking-on-phone-USB-on-amazon-blazor-samples-twilio-prior-art.md) — Aaron + Mika 2026-05-26 — Grok-Build = Claude-Code-clone (tick-source/loop-runner) confirmation; Twilio is THE exception to "electricity cost only" for phone-support substrate enabling Amazon-USB sales business model where AI IS the suppor…
- [**persona/mika/conversations/2026-05-26-aaron-mika-grok-homelab-first-gh-auth-login-device-registration-no-shipped-keys-vs-prod-bootstrap-key-rotation**](persona/mika/conversations/2026-05-26-aaron-mika-grok-homelab-first-gh-auth-login-device-registration-no-shipped-keys-vs-prod-bootstrap-key-rotation.md) — (no description)
- [**persona/mika/conversations/2026-05-25-aaron-mika-grok-runbooks-as-executable-reality-hat-ontology-top-down-vs-bottom-up-play-doh-leverage-class-universal-protocol-markdown-plus-runme-plus-continue-with-mcp-wrap-ai-agency-stack-crystal-ball-plus-runbook-plus-glass-halo**](persona/mika/conversations/2026-05-25-aaron-mika-grok-runbooks-as-executable-reality-hat-ontology-top-down-vs-bottom-up-play-doh-leverage-class-universal-protocol-markdown-plus-runme-plus-continue-with-mcp-wrap-ai-agency-stack-crystal-ball-plus-runbook-plus-glass-halo.md) — (no description)
Expand Down Expand Up @@ -104,7 +105,6 @@
- [**audit-backlog-status-drift sub-class catalog — empirical taxonomy from 2026-05-16 session**](feedback_audit_backlog_status_drift_sub_class_catalog_otto_cli_2026_05_16.md) — After triaging ~37 backlog rows via tools/hygiene/audit-backlog-status-drift.ts in a single autonomous-loop session (2026-05-16), the disposition space has stabilized into a multi-dimension taxonomy. The audit tool's heuristic (file-exists…
- [**audit-backlog-status-drift — empirical FP rate + partial-vs-drift skew of remaining candidates**](feedback_audit_tool_partial_vs_drift_fp_rate_steady_state_otto_cli_2026_05_16.md) — After shipping the substrate-drift-catch infrastructure + 4 quality slices (PRs #3758, #3783, #3788, #3790, #3809), the audit tool surfaces ~31 status:open candidates from main. Empirical finding from manual partial-vs-drift verification:…
- [**convergent-peer-fix pattern in multi-Otto coordination**](feedback_convergent_peer_fix_pattern_multi_otto_2026_05_16.md) — When a peer Otto agent reads the same review thread and pushes a fix before you can act, the substrate-honest move is don't push duplicate work — let peer's fix stand as canonical
- [**fenced-shell-transcript-hygiene**](feedback_fenced_shell_transcript_hygiene_command_output_vs_derived_summary_otto_cli_2026_05_16.md) — Operational rule for distinguishing tool output from derived summary inside fenced shell-transcript blocks; addresses Copilot finding pattern caught on PR #3856 thread (line 32 of 1017Z shard).

_Stack truncated at 100 most-recent entries. 1338 additional memory files in heap — browse `memory/**/*.md` directly by filename/timestamp (recursive: includes `memory/persona/<ai>/conversations/*.md` and other subdirectory heaps)._
_Stack truncated at 100 most-recent entries. 1339 additional memory files in heap — browse `memory/**/*.md` directly by filename/timestamp (recursive: includes `memory/persona/<ai>/conversations/*.md` and other subdirectory heaps)._
<!-- END AUTO-INDEX -->
Loading
Loading