# Aivyx PA Product — Phase 12.5 Review Drafted 2026-04-15 during the post-Phase-12 product-shape review pass. This document is the **product analogue of [`DESIGN.md`](DESIGN.md)**: the locked decisions about *what Aivyx PA is for and what it is not* that every subsequent phase must respect. `DESIGN.md` answers "how does the agent work" — `PRODUCT.md` answers "who is the agent for, what does it commit to do, and where is the line." The two contracts are siblings, not nested. Editing either one requires an amendment under `docs/amendments/` per the same process. The current phase journal lives in `docs/PHASE_N.md`, and the rolling product-shape entries live in [`docs/PRODUCT_ROADMAP.md`](docs/PRODUCT_ROADMAP.md) (the product analogue of [`docs/ROADMAP.md`](docs/ROADMAP.md)). This document was assembled from a four-cluster question-pinning pass that walked every load-bearing product question surfaced by a read-only inventory of the post-Phase-12 codebase. The cluster-by-cluster pinning rationale is in the appendix at the bottom of this file so a future session can reconstruct the *why* without reading the original working-session transcript. --- ## The one-line pitch (LOCKED 2026-04-15, amended 2026-05-12) > **Aivyx PA is a self-learning, self-improving AI-personal assistant > with a user-defined Profile and Persona, running on your hardware, > talking to cloud or local LLMs under your own credentials, and > never compromising privacy or auditability for the sake of a feature.** > > *See amendment > [`2026-05-12-pitch-reframe.md`](docs/amendments/2026-05-12-pitch-reframe.md) > — the original pitch was reframed in Phase 56 to reflect the > operator's restated vision (self-learning, self-improving > AI-personal assistant with Profile + Persona). The privacy / > auditability / local-first constraints are preserved unchanged.* Every commitment below either supports this sentence or constrains what features the platform may grow without contradicting it. Future phases that find themselves drifting away from this sentence are required to surface the drift as an amendment, not absorb it silently. --- ## Product Commitment 1 — Single Operator, Single Primary Agent (LOCKED 2026-04-15) ### The Rule > **One human operator per Aivyx PA instance. One primary agent the > operator interacts with. Sub-agents exist as a mode the primary > agent switches into mid-session — not as separate processes, not as > parallel sessions, not as independent tool registries.** ### What this commits us to 1. **No multi-tenancy. Ever.** A second human is a second Aivyx PA instance on a different machine (or under a different OS user on the same machine). There is no "shared" mode, no "team" mode, no tenancy primitive at any layer. 2. **Sub-agents are role-switching, not process-spawning.** When the primary agent needs to operate under constrained authority (a child task, a sandboxed exploration, a domain-specific sub-mission), it switches into a child role per **P7** and runs in that role's attenuated capability envelope. When the sub-task completes, it switches back. There is exactly one physical agent process at any moment. 3. **Capability escalation across role-switch boundaries is structurally impossible.** A child role's capability set is strictly attenuated from its parent's per the inheritance rules in **P7**. The primary agent cannot grant a sub-agent authority it doesn't itself hold; the type system enforces this, not a runtime check. 4. **One redb store, one audit chain, one capability ceiling.** Sub-agent turns are tagged with the role active at the time of the turn, the same way Phase 11's role primitive already tags ordinary turns. The audit chain is operator-scoped, not role-scoped. ### What this commitment deliberately does not say - **It does not say sub-agents are easy to use today.** The role-switching primitive needed to support sub-agent mode is a forward commitment; today's foundation has the role primitive but not the mid-session switching machinery. - **It does not say sub-agents are always sequential.** A future phase may explore concurrent sub-agent execution within the single physical process; that's an implementation choice, not a contract change. The contract pins "single physical process," not "single execution pointer." - **It does not say what happens when a mission outlives the operator's session at the keyboard.** That's **P5**'s territory. > *See amendment > [`2026-10-05-named-instances.md`](docs/amendments/2026-10-05-named-instances.md) > (A17) — one operator may run several named instances side by side > (`--instance `); each is a complete instance with exactly one > primary agent, and instances share nothing. P1 holds per instance; > P6 unchanged.* --- ## Product Commitment 2 — Session Legibility and Two Success Modes (LOCKED 2026-04-15) ### The Rule > **Every Aivyx PA session is operator-inspectable in real time and > after the fact. Sessions complete in one of two shapes: a > bounded task with a clear start and end, or an open-ended > mission with operator-approval gates at decision points.** ### What this commits us to 1. **The legibility floor.** The renderer must surface enough of the agent's reasoning, tool calls, and outcomes that the operator can judge what happened without reading source code. This includes a real-time view (during the session) and a post-hoc view (`--verify-only` and any future inspection surfaces). A feature that obscures the agent's actions from the operator is a contract violation, full stop. 2. **Bounded tasks are the default shape.** A session begins when the operator initiates an interaction, runs through one or more turn-loop iterations, and ends when the goal is satisfied or abandoned. This is the shape Aivyx PA ships today and the shape every channel adapter understands. 3. **Open-ended missions are a forward commitment.** A mission is a long-running operator intent that may span multiple sessions, multiple days, multiple agent restarts, and is structured around **operator-approval gates**: the agent runs autonomously between gates, halts at each gate, queues the gate for the operator to resolve asynchronously, and resumes when approval is granted. Missions are the primitive that makes "track this codebase's CI for the next week and tell me when something breaks" a first-class shape. 4. **Approval gates are operator-controlled, not agent-controlled.** The agent identifies decision points where it judges operator approval is warranted (or where the role config requires it). The operator can also pre-declare conditions that always require approval (file writes outside a path, network calls to specific hosts, capability scopes the role doesn't hold, etc.). The mission lifecycle, the gate-resolution UX, and the operator-side queueing are all in **P5**. ### What this commitment deliberately does not say - **It does not pin the mission primitive's shape.** What a mission *is* (a row in redb, a long-lived turn, a tree of sub-sessions) is a future-phase decision. The contract commits that mission semantics exist; the implementation shape is open. - **It does not say a bounded task and a mission are different primitives.** A mission may turn out to be a bounded task with a longer lifetime and approval-gate semantics, or it may turn out to need its own type. The contract is outcome-shaped, not type-shaped. --- ## Product Commitment 3 — Goals and Non-Goals of the Platform (LOCKED 2026-04-15) The product contract takes an explicit position on what Aivyx PA is trying to become and what it explicitly refuses to become. Each goal below is a positive commitment that constrains future-phase work toward a target shape; each non-goal is a constraint that prevents drift away from the target. ### Goals - **G1 — Web interaction.** `web.fetch` is the floor. Future phases extend Aivyx PA to richer web interaction (page rendering, form submission, structured scraping) **gated by role allowlists**. A `researcher` role may have a rich web surface; a `coder` role may have raw HTTP only. The goal is not "a web agent," it is "an agent the operator can configure to interact with the web within a role-defined envelope." - **G2 — Code interaction.** Aivyx PA is a coding agent in addition to being other things. Full CRUD on files via `fs.read` / `fs.write`, shell execution via `shell.exec`, and a future TUI-level code-editing surface that the agent uses *as a tool*. Aivyx PA does not become an IDE — it interacts with code through the same tool family that interacts with everything else. - **G3 — Memory Reflection (outcome-driven self-improvement).** The agent observes outcomes — every `ToolOutcome`, every `TurnOutcome`, every mission-level success or failure — and uses that history to refine its own behavior over time. Memory is *core*, not scratchpad. The substrate (`memory.*`) is the storage layer; the reflection layer is a forward commitment whose properties are pinned in **P8**. - **G4 — Sub-agent orchestration.** The primary agent can switch into a child role mid-session per **P1** and **P7**, run constrained, and switch back. Sub-agents inherit attenuated authority by construction. The contract commits to "sub-agents exist as a first-class mode" without committing to a specific orchestration UX. - **G5 — Autonomous and scheduled execution.** Missions per **P2** may run unattended, between operator interactions, on schedules (cron, systemd timers), in response to triggers (webhooks, file changes), or on agent-initiated continuations. All such execution is attributed to the operator's identity per **P6** and audited against the operator's capability ceiling. - **G6 — Local execution, cloud inference, privacy non-negotiable.** Aivyx PA runs on the operator's hardware. Inference may go to cloud LLM providers (Anthropic today; others as the `LlmProvider` trait grows). Storage is encrypted at rest with an operator-controlled passphrase. Network egress is gated by capability scopes. **Privacy and encryption are never compromised in the name of a feature** — this is the single property that uniquely positions Aivyx PA, and the one a future phase is most likely to be tempted to compromise on. Don't. > *See amendment > [`2026-09-26-cloud-escalation.md`](docs/amendments/2026-09-26-cloud-escalation.md) > (A15) — consent-gated cloud escalation: a local-first > configuration may send a specific conversation's call to a > cloud endpoint the operator configured, under six privacy > rules (e.g. tainted conversations never escalate); N5 > unchanged — no Aivyx-hosted component, key proxying or > telemetry. Model routing Part 3b.* > *See amendment > [`2026-09-27-on-failure-escalation.md`](docs/amendments/2026-09-27-on-failure-escalation.md) > (A16) — authorizes the `on_failure` trigger A15 deferred: a > local model that demonstrably fails a conversation (looping, > tool-call repair exhausted, or, in the autonomous loop, a > Verdict FAIL or Circuit stall) may escalate its next turn > only, under A15's same six privacy rules, consent gate and > audit trail. Model routing Part 3b.* - **G7 — Third-party tool SDK.** Tools follow a documented contract any third party can implement to add new capabilities to Aivyx PA. The SDK contract guarantees policy integration: capability scopes, audit logging, cancellation, role allowlists, input schema enforcement. The SDK shape is pinned in **P11**; the distribution model is pinned in **P12**. Third-party tools are *possible*, but **N3** rules out marketplace dynamics — the SDK contract is open, the registry is not. ### Non-Goals - **N1 — No multi-tenancy or shared instances.** Per **P1**. - **N2 — No hosted-service shape.** Aivyx PA is not a SaaS, has no hosted control plane, has no Aivyx-the-company server in the loop. The operator runs the daemon on their own hardware under their own OS user, period. Per **P6** and **G6**. - **N3 — No marketplace dynamics.** Third-party tools are possible per **G7**, but Aivyx PA core does not host a registry, curate a directory, run a rating system, or distribute third-party tools. Operators install third-party tools the way they install any other software — explicitly, knowing what they are doing. The model is `git`'s relationship with third-party `git-*` subcommands, not Chrome's relationship with the Web Store. - **N4 — Not an IDE.** Per **G2**: Aivyx PA interacts with code via tools. It does not ship LSP integration, syntax highlighting beyond what the renderer already does, project-awareness beyond what the filesystem gives it, or visual diff UI. A future phase may add a TUI-level *code-editing surface that the agent uses as a tool*, but the surface is for the agent, not for the operator to use as an editor. - **N5 — No inference-side compromises for convenience.** No proxying the operator's API key through a hosted service "for setup ease." No batching the operator's prompts on Aivyx servers "to save money." No phone-home telemetry. No cloud-side context store. The operator's API key talks directly to the model provider, the operator's data stays on the operator's hardware, full stop. ### What G3, G4, G5 commit to that the foundation does not yet ship The current foundation (Phase 12) ships a working bounded-task agent on Local CLI and Telegram. **G3 (Memory Reflection), G4 (sub-agent orchestration as a switching mode), and G5 (autonomous/scheduled execution) all require future-phase work to deliver.** The contract pins them as forward commitments; the corresponding phase work is enumerated in `docs/PRODUCT_ROADMAP.md`. --- ## Product Commitment 4 — Daemon-Default Architecture (LOCKED 2026-04-15) ### The Rule > **Aivyx PA runs as a long-running daemon process under the > operator's OS user. The user-facing CLI commands are frontends > that connect to the daemon. If no daemon is running when a > frontend launches, the frontend auto-spawns one and detaches > it; the daemon survives the frontend exit. There is exactly > one operational shape.** ### What this commits us to 1. **The daemon is the only execution shape.** Foreground-only mode, as it exists today, is replaced. The same binary serves as both daemon and frontend depending on how it is invoked, and the operator's normal usage (`aivyx-pa`, `aivyx-pa --channel telegram`, etc.) routes through frontends to a backing daemon. 2. **The daemon holds live agent state.** Active turns, in-flight missions, scheduled-execution timers, IPC connections, loaded role configs, the open redb handle — all live in the daemon's address space and survive frontend disconnections. Restarting a frontend does not restart the agent. 3. **The daemon's IPC surface is the single integration point.** Channel frontends speak to the daemon over IPC. Third-party tool processes (per **P12**) speak to the daemon over the same IPC. Future inspection surfaces (a `aivyx-pa status` subcommand, a localhost web UI, etc.) all attach via IPC. This is one protocol to design, defend, and version. 4. **IPC authentication is OS-level.** The daemon's IPC socket is owned by the operator's OS user with mode 0600. There is no Aivyx PA-level password, token, or auth handshake on the IPC. Anyone who can read the socket file is by definition the operator. Per **P6**. 5. **Auto-spawn is invisible in the common case.** An operator running `aivyx-pa` for the first time on a fresh box should not need to learn the word "daemon" before getting a working agent. The frontend detects no running daemon, spawns one, detaches it, and connects — all transparently. The operator only thinks about the daemon when they explicitly want to manage it (`aivyx-pa daemon stop`, `aivyx-pa daemon status`). ### What this commitment deliberately does not say - **It does not say what the IPC protocol looks like.** Unix domain sockets, named pipes, length-prefixed JSON, msgpack, protobuf — all valid implementation choices. The contract pins that there *is* an IPC, not what it is. - **It does not say the daemon has a network surface.** Per **P6** and **G6**, the daemon's IPC is local-only. A web UI per **P5** is `127.0.0.1:` only, not a service exposed to the network. - **It does not say how the daemon handles crashes.** Crash recovery, in-flight turn replay, mission resumption — all implementation concerns for the daemon-shipping phase. ### Phase impact This is the **largest single architectural commitment** in the product review. The current foundation is process-per-session shaped, and the daemon migration will reshape the binary, the channel adapters, the audit chain wiring, and the storage lifecycle. The migration is enumerated as the first major entry in `docs/PRODUCT_ROADMAP.md` and is expected to span one or more dedicated phases. --- ## Product Commitment 5 — Open First-Party Channel Surface (LOCKED 2026-04-15) ### The Rule > **Aivyx PA commits to a documented channel adapter SDK. First-party > channels are whichever ones are worth shipping in core; the > contract pins the shape, not the count. Third parties can also > implement the adapter contract.** ### What this commits us to 1. **The adapter SDK is a first-class artifact, not internal plumbing.** It is the same kind of contract as the tool SDK from **P11**: documented surface, integration guarantees, stability commitments deferred until real use. A third-party channel author writes a channel against the SDK and gets the turn-loop, audit-chain, and capability machinery for free. 2. **First-party channels grow with the platform.** Today: Local CLI, Telegram. Plausibly tomorrow: a localhost web UI on `127.0.0.1` (made cheap by the daemon IPC from **P4**), voice (made plausible by mobile-side audio), an IDE plugin, email, Discord. The contract does not pre-commit to any specific second-tier channel — it commits to the *shape* of how channels are added. 3. **Local-first applies to channel design.** A first-party channel may not require a hosted relay, a cloud provider's bot infrastructure beyond what an operator-owned key permits, or any third-party service the operator hasn't explicitly opted into. Telegram is acceptable because the operator runs their own bot under their own token; a first-party "Aivyx Hosted Web" channel would not be. 4. **Channel adapters are pluggable at daemon startup, not compile time.** The daemon discovers available channel frontends and registers them. This is consistent with **P4**'s daemon shape and **P12**'s tool-as-process model. ### What this commitment deliberately does not say - **It does not pre-commit to a localhost web UI.** A web UI is a *likely first addition* once the daemon ships, because the IPC layer makes it cheap, but it is not pinned. The decision is made at the phase that opens it, not here. - **It does not commit to a stable adapter SDK version.** Same posture as **P11**: integration guarantees first, stability later when real third-party adapters surface real pressure. --- ## Product Commitment 6 — OS-Level Operator Identity (LOCKED 2026-04-15) ### The Rule > **The operator is the OS user who owns the daemon process and > the redb store. There is no Aivyx PA-level identity primitive, > no Aivyx PA-level authentication, no Aivyx PA-level account.** ### What this commits us to 1. **Identity equals OS user, period.** The operator's "identity" is whatever `id -u` returns. Aivyx PA does not maintain its own user table, does not issue tokens, does not sign audit entries with an Aivyx PA-internal key. Audit chains attribute work to "the OS user the daemon ran under," and that's the identity the contract commits to. 2. **The daemon never grows authentication surface.** Frontends attaching to the daemon authenticate via Unix file permissions on the IPC socket (mode 0600, owned by the operator). There is no password handshake, no token exchange, no challenge-response. If you can `read(2)` the socket, you are the operator. 3. **Triggered runs (cron, systemd, webhooks) inherit OS identity.** A scheduled mission launched by `cron` runs under the operator's OS user. A webhook-triggered run is delivered by a daemon thread already running under the operator's OS user. There is no "service account," no shared identity, no impersonation. 4. **A leaked passphrase is rotated against the redb store alone.** Because Aivyx PA has no separate identity primitive, compromising the passphrase compromises the storage, but it does not require revoking an "Aivyx PA account" or re-issuing certificates. Rotation is a passphrase change on the redb store, full stop. ### What this commitment deliberately does not say - **It does not say the operator cannot use Aivyx PA remotely.** Remote use means SSH'ing into the box and talking to the local daemon — exactly the way `tmux`, `mosh`, and other long-lived per-user daemons work. Aivyx PA itself never grows a network-listening surface; the network surface is `sshd`, which is not Aivyx PA's concern. - **It does not say multi-device sync is impossible.** A future feature may sync Aivyx PA state between two machines the same operator owns, but that sync is a peer-to-peer shape between two operator-owned daemons under one OS identity per box, not a cloud-side identity primitive. Pinning would be a contract amendment. --- ## Product Commitment 7 — Single-Inheritance Role Tree (LOCKED 2026-04-15) ### The Rule > **Roles form a single-inheritance tree rooted at an implicit > `default` role. A child role's authority is strictly attenuated > from its parent's: tool allowlist subset, capability set > subset, deeper memory namespace, contained filesystem ceiling. > Multi-parent composition is explicitly out.** ### What this commits us to 1. **Every role declares an optional `parent`.** A role with no `parent` field inherits from the implicit `default` role. A role with `parent: Some("base")` inherits from `base`. The tree is rooted at `default` and has no cycles (validated at config load time). 2. **Inheritance is strict attenuation along every dimension.** - `tool_allowlist`: child is a subset of parent's. - Capability set (per **P9**): child's capability scopes are each strictly contained within a parent's scope. - `memory_topic_prefix`: child's prefix is a deeper namespace under the parent's (parent `coder/` → child `coder/refactor/`). - `fs_root` (per **P9**): child's root is a path within the parent's root. - Network allowlist (per **P9**): child's allowed origins are a subset of the parent's. - System prompt: child may override entirely; this is the only dimension that is not attenuated, because a prompt-attenuation primitive doesn't exist. 3. **Sub-agent mode (per P1) switches into a child role.** When the primary agent enters sub-agent mode, it switches to a child of its currently-active role. This makes sub-agent capability constraint a property of the type system: the child role's declaration cannot exceed the parent's, so the sub-agent cannot escalate. 4. **Aivyx PA core ships zero default roles.** The `default` role is implicit (synthesized at config load time if absent). The `coder` and `researcher` test fixtures from Phase 11 stay as test fixtures only — operators write their own role tree. Future phases may grow operator-facing role config samples per **N3**'s curation posture, but no role is *shipped* in core. 5. **Multi-parent composition is structurally impossible.** The diamond problem is closed off at the contract level. A role that needs the union of two parents' capabilities should be a sibling of both with its own explicit declarations, not an attempt to merge them. ### What this commitment deliberately does not say - **It does not say the role tree is small.** A complex Aivyx PA deployment may have a deep tree of roles for different sub-tasks, missions, and contexts. The contract does not constrain depth or width. - **It does not say roles are immutable at runtime.** Per **P8**'s reflection commitment, the agent may write to its own role tree under capability gating. Today the role config is load-time-only; the reflection layer phase will grow runtime role mutation. --- ## Product Commitment 8 — Outcome-Driven Audited Reflection (LOCKED 2026-04-15) ### The Rule > **The agent observes outcomes — every `ToolOutcome`, every > `TurnOutcome`, every mission-level success or failure — and > uses that history to refine its own behavior over time. Every > behavior change is an explicit, audited operation with the > same standing as a tool call. There is no silent > self-modification.** ### What this commits us to 1. **The substrate is `memory.*`, unchanged.** Phase 6's memory tools (`memory.read`, `memory.write`, `memory.forget`), Phase 10's wildcard cross-topic recall, Phase 11's role-prefix isolation. This is the storage layer reflection builds on, and it is **not replaced** — extended, never replaced. 2. **Outcome history is first-class data the agent can read.** Every tool call's outcome, every turn's outcome, every mission's success/failure signal is recorded in the audit chain *and* is exposed to the agent through a future Reflection API. Today the audit chain records this data; the future commitment is that the agent can *read* it as structured input to its reasoning, not just produce it as side effects of its actions. 3. **Reflection writes are capability-secured.** The agent needs an explicit capability (e.g., `reflection.write`, exact base name TBD by the implementing phase) to make any change to its own role config, system prompt, memory topics, or other persistent behavior-shaping state. An operator who does not want autonomous self-modification simply does not grant this scope to any role, and the substrate degrades to "outcome history exists but the agent cannot act on it." 4. **Every reflection write lands in the audit chain.** A reflection-driven role-prompt edit is an audited operation the same way a `fs.write` or `memory.write` is. The audit chain remains the single source of truth for "what did this agent do," and reflection is not a side-channel. 5. **The reflection layer's *shape* is deferred.** The contract commits to the *properties* (outcome-driven, audit-logged, operator-inspectable, capability-secured) without specifying the implementation. Whether reflection is one tool, several tools, a separate subsystem, or an emergent property of how the role tree is structured — all open questions for the phase that ships it. ### What this commitment deliberately does not say - **It does not say reflection requires an LLM call.** A reflection step may be as simple as "if this tool's failure rate exceeds N, remove it from the role's allowlist" — pure logic, no inference. Or it may require the LLM to summarize a session's outcomes and write a new prompt. Both shapes are valid. - **It does not say reflection is autonomous by default.** The capability gate from point 3 is the operator's lever: reflection is opt-in per role. - **It does not say reflection is global.** Per **P7**'s attenuation rules, a child role's reflection writes are scoped to the child's own state, not the parent's. ### Why this commitment is the most differentiating This is the single property that distinguishes Aivyx PA from "Claude with a memory store" and from "AutoGPT with self-improvement." Aivyx PA commits to outcome-driven evolution **and** to keeping every step of that evolution legible to the operator. The reflection layer phase is expected to be one of the most consequential in the platform's lifetime, and pinning the audit-chain invariant *now* prevents a future implementation from compromising it for ergonomics. --- ## Product Commitment 9 — Per-Role Full Capability Declaration (LOCKED 2026-04-15) ### The Rule > **Every dimension a role can be attenuated along is declared > in the role config — tool allowlist, capability scopes, > filesystem roots, network allowlists, memory namespacing, > shell cwd ceilings, and any future capability dimension. The > role config is the single declaration site for everything a > role can do. The binary's operator-level capability grants > are removed and replaced with the active role's declarations.** ### What this commits us to 1. **The role config is the single source of truth.** An operator reads one file (their `aivyx-pa.toml` or per-role files) to know what any role can do. There are no hidden capabilities, no operator-level grants that bypass the role, no implicit "the binary always allows X." 2. **Every capability dimension has a role-level field.** The exact field set grows as the platform grows, but every capability the role primitive can attenuate is reachable from the role config. Today's PHaseE-12 dimensions: `tool_allowlist`, `system_prompt`, `memory_topic_prefix`. The expansion adds: `capability_scopes` (full Scope list), `fs_root`, `fs_mode` (read-only / read-write), `net_allowlist` (URL prefix list), `shell_cwd_root`, and `parent` (per **P7**). 3. **Inheritance applies to every dimension.** Per **P7**'s attenuation rules, a child role's value on every dimension must be a strict subset of the parent's. This is how single-inheritance role composition gets its real teeth — the entire capability surface is composable, not just the tool list. 4. **The binary's operator-level grants disappear.** Today the binary unconditionally grants `memory.read`, `memory.write`, `fs.read:/**`, `fs.write:/**`, `net.fetch`, `shell.exec:cwd:/**` to the operator's capability set. Per this commitment, that surface moves *entirely* into the implicit `default` role's declaration. Explicit roles attenuate from the `default` role's declaration, not from a separate operator-level grant. 5. **Validation runs at role-load time.** Capability declarations exceeding the parent's, references to undefined tools, filesystem paths outside the operator's outer sandbox, network allowlist entries that don't parse, inheritance cycles — all fail loud at startup, not at first-use. Operators get a clear error before the agent starts a turn. ### What this commitment deliberately does not say - **It does not pin the field names or the exact TOML shape.** Those are implementation choices for the migration phase. The contract commits to "every capability dimension is reachable from the role config," not "the field is called X." - **It does not say the migration is small.** This is a significant reshape of the binary's capability wiring, comparable in scale to Phase 11's role primitive itself. The migration is enumerated in the product roadmap. - **It does not say new capability dimensions land in the contract.** Adding a new capability base to the role config is an additive change. Removing one or changing inheritance semantics would be an amendment. --- ## Product Commitment 10 — Substrate-Only Core, Fifteen Tools Forever (LOCKED 2026-04-15, amended 2026-04-20, 2026-05-22, 2026-05-28, 2026-06-19) ### The Rule > **Aivyx PA core ships exactly fifteen first-party tools forever: > `fs.read`, `fs.write`, `fs.delete`, `fs.metadata`, > `memory.read`, `memory.write`, `memory.forget`, > `shell.exec`, `web.fetch`, `web.post`, `web.extract`, > `git.status`, `git.diff`, `git.commit`, `net.dns`. > Adding to or removing from this list requires a > `PRODUCT.md` amendment.** > > *See amendments > [`2026-04-20-substrate-tool-count.md`](docs/amendments/2026-04-20-substrate-tool-count.md) > — `web.post` added in Phase 37, amendment filed in Phase 38; > [`2026-05-22-substrate-tool-count-ten.md`](docs/amendments/2026-05-22-substrate-tool-count-ten.md) > — `fs.delete` + `fs.metadata` added and amendment filed in > Phase 100; > [`2026-05-28-substrate-tool-count-thirteen.md`](docs/amendments/2026-05-28-substrate-tool-count-thirteen.md) > — `git.status` + `git.diff` (one new `git.read` scope base > shared between the two) + `net.dns` (existing scope base > since Phase 0) added and amendment filed in Phase 109; > and [`2026-06-19-substrate-tool-count-fifteen.md`](docs/amendments/2026-06-19-substrate-tool-count-fifteen.md) > — `web.extract` (readability over the existing `net.fetch` > base) + `git.commit` (one new `git.write` scope base) added at > Chapter Forge (FG.1 / FG.3), the count + base contract filed > at FG.2.* ### What this commits us to 1. **The substrate is the operator-discoverable surface.** An operator who runs Aivyx PA for the first time finds these fifteen tools available (subject to role allowlists and trust tiers). Every richer capability — browser, LSP, code search, email, calendar, anything domain-specific — is a third-party tool the operator installs explicitly. Git's read primitives (`git.status`, `git.diff`) were added to substrate at A12 (Phase 109) on the rationale that code- read inspection is operator-bootstrap-essential, the same way `fs.read` is; `git.commit` followed at A13b (Chapter Forge) — code-write is the `fs.write` to that `fs.read` — alongside `web.extract`, the readability refinement of `web.fetch`. 2. **The substrate is closed-set.** The contract pins the exact list, not "approximately ten" or "the current set plus reasonable additions." Pressure to add an eleventh tool to core is met with "amendment to **P10** required" — and the amendment must explain why the new tool is substrate rather than third-party. The default answer is "third party," and the burden of proof is on the addition. 3. **The substrate principle is "what every Aivyx PA instance needs to bootstrap."** A tool belongs in core if and only if Aivyx PA without it cannot perform basic operator-useful work. `fs.*` and `memory.*` and `shell.exec` and `web.fetch`, and `web.post` together cover "read, write, delete, inspect, remember, execute, fetch, post" — the minimal set for an agent that does anything useful. Anything richer is curated by the operator's role declarations and tool installations, not by Aivyx PA core. ### Substrate vs. Infrastructure vs. Third-Party — the three-tier taxonomy The ten-tools-forever rule applies only to *substrate tools* — the operator-facing primitives an operator chooses when configuring a role. Aivyx PA is permitted (and expected) to grow two adjacent tool categories that are **not** substrate and therefore **not** counted against the cap: - **Infrastructure tools.** Tools the agent uses to manage itself: reflection writes per **P8**, role updates, outcome reads, sub-agent spawning per **P1**, mission lifecycle operations per **P2**. These are the machinery the agent uses to *be* itself, not the machinery the operator uses to give the agent capabilities. They are not operator-discoverable in the role config the same way substrate tools are; they are wired by the platform and gated by capabilities (often dedicated capability bases like `reflection.write`, `mission.create`, etc.). The infrastructure set is allowed to grow as **G3**, **G4**, and **G5** require, without amendment. - **Third-party tools.** Anything else, implemented against the SDK contract from **P11**, distributed and run per **P12**. Operators install these explicitly. There is no central registry per **N3**. ### Why the cap is at exactly the current count Phase 37 stabilized the substrate set; Amendment A11 (Phase 100) brought it to ten tools; Amendment A12 (Phase 109) brought it to thirteen with the `git.status` + `git.diff` read pair and `net.dns`; Amendment A13b (Chapter Forge) brought it to fifteen with `web.extract` and `git.commit`. Pinning the cap at the current count is a way of saying: **the foundation is done growing the substrate.** Future product phases focus on the daemon (**P4**), the role-config migration (**P9**), the reflection layer (**P8**), missions (**P2**), and the SDK contracts (**P11**, **P12**) — not on cramming more tools into core. ### What this commitment deliberately does not say - **It does not say the existing fifteen tools are frozen in shape.** A future phase may extend `web.fetch` to support HEAD, may extend `shell.exec` to support a process-group kill API, may extend `memory.read` to support new query variants. Tool *internals* are not pinned by this commitment; only the *count of operator-facing substrate tools* is. - **It does not say infrastructure tools are unconstrained.** Each infrastructure tool gets its own capability base, its own audit treatment, and its own role-config integration per **P9**. They are not a back door for capability expansion — they are a separate category for a different purpose. --- ## Product Commitment 11 — SDK Contract: Interface + Integration (LOCKED 2026-04-15) ### The Rule > **Any tool implementing the SDK contract gets the policy > machinery for free: capability scopes are honored exactly as > declared, audit logging is automatic, cancellation is > honored, role allowlists work, input schemas are enforced at > the planner layer. Stability of the SDK API is deferred — > the contract commits to "what the SDK does," not yet to > "the SDK never breaks."** ### What this commits us to 1. **Policy integration is automatic.** A third-party tool author writes a tool against the documented `Tool` trait (and its supporting types: `ToolContext`, `ToolOutcome`, `Scope`, `JsonSchema`), declares a `required_scope`, and gets *all* of Aivyx PA's safety properties as guarantees, not as opt-ins. The author cannot accidentally skip audit logging, cannot accidentally bypass the capability check, cannot accidentally evade cancellation. The SDK contract is closed under safety. 2. **The contract is the public API of the relevant crates.** The crates that constitute the SDK surface (`aivyx-core`'s `Tool` trait and supporting types, `aivyx-capability`'s `Scope` machinery, the future tool-process IPC protocol from **P12**) are the documented surface. Internal helper functions are not part of the contract. 3. **The SDK is the same surface first-party tools use.** Per **P12**, first-party substrate tools speak the same protocol third-party tools speak — they just skip the IPC hop for performance. This means the SDK contract is self-testing: every first-party tool is also a valid third-party tool by construction. A future phase that wants to extract a substrate tool into an out-of-process third-party tool can do so without rewriting it. 4. **Stability is deferred until the SDK has stabilized in real third-party use.** The contract today commits to "policy integration works as documented," not to "the trait surface won't change between phases." A future amendment will pin a stability window (likely versioned, likely with a deprecation policy) once enough third-party tools exist to apply real pressure. ### What this commitment deliberately does not say - **It does not say what language the SDK is in.** Today the SDK is Rust because Aivyx PA is Rust. The IPC protocol from **P12** opens the door to non-Rust tools speaking the same contract; the language-independent surface becomes part of the SDK contract once **P12**'s IPC protocol lands. - **It does not say the SDK ships with a registry, a scaffolding tool, or a starter template.** Those are ergonomic affordances a future phase may add; the contract pins the policy guarantees, not the developer experience. - **It does not commit to backwards compatibility.** A Phase 13 SDK shape may differ from a Phase 14 SDK shape. The commitment to stability is a future amendment. --- ## Product Commitment 12 — Tools as Separate Processes Over Daemon IPC (LOCKED 2026-04-15) ### The Rule > **Third-party tools run as their own OS processes, communicate > with the Aivyx PA daemon over IPC, and are registered at daemon > startup. First-party substrate tools are a special case: they > ship in-process for performance, but they speak the same > protocol third-party tools speak.** ### What this commits us to 1. **Process isolation is the security boundary.** A misbehaving third-party tool cannot crash the Aivyx PA daemon, cannot read the daemon's memory, cannot exfiltrate the redb passphrase from process address space, cannot tamper with audit entries that haven't yet reached disk. The OS process boundary is the defense, not the SDK API. 2. **Tool processes inherit OS-level identity from the daemon.** A third-party tool process runs as the same OS user as the daemon (per **P6**). This means the tool process *can*, at the OS level, read files the daemon reads — including the redb file, including environment variables. The IPC isolation defends against in-memory attacks; OS-level isolation is implicit in the single-operator trust model. **Operators install third-party tools knowing they run under their own OS user.** This is the same trust model as installing any other software on a personal box. 3. **Cross-language tool authoring is unlocked.** Because tools speak a documented IPC protocol rather than a Rust trait, third-party tools may be written in any language that can speak the protocol. A Python data scientist can write an Aivyx PA tool without learning Rust. The IPC protocol becomes the language-independent dimension of the SDK from **P11**. 4. **First-party tools special-case in-process for speed.** The fifteen substrate tools from **P10** ship in-process in the daemon for latency reasons. They speak the same protocol third-party tools speak — the protocol is the contract — but they bypass the IPC hop. This means a substrate tool can be extracted into a separate process later (or vice versa) without rewriting it. The in-process / out-of-process distinction is a performance optimization, not an architectural divide. 5. **Tool registration happens at daemon startup, not at compile time.** The daemon discovers available third-party tool processes (from a known directory, from a config field, or via a discovery protocol), verifies their SDK contract version, and registers them into the tool catalog. Operators can add or remove tools without rebuilding Aivyx PA. ### What this commitment deliberately does not say - **It does not say the tool process protocol uses any particular wire format.** JSON, msgpack, protobuf, Cap'n Proto — all valid implementation choices. - **It does not say tools cannot be sandboxed further.** A future phase may add OS-level sandboxing (seccomp, containers, separate UIDs) on top of the IPC isolation. The contract pins "process isolation is the floor," not "process isolation is the ceiling." - **It does not say first-party tools may never be out-of-process.** A future phase may extract a substrate tool into a separate process for fault-isolation reasons even at a small latency cost. The contract is symmetric. --- ## Product Commitment 13 — Assistant Profile (LOCKED 2026-05-12) > *Added by amendment > [`2026-05-12-product-commitment-p13-profile.md`](docs/amendments/2026-05-12-product-commitment-p13-profile.md) > — filed in Phase 56 alongside A8 (pitch reframe) and A10 > (P14 — Persona).* ### The Rule > **Every Aivyx PA instance carries an operator-declared > Profile that pins who this assistant is for and how it > communicates. Profile is loaded once per daemon lifetime > and injects into every turn's system prompt regardless of > active role. Profile is mutable only by the operator, and > only through operator-facing surfaces (CLI subcommands, > Web UI panes); the agent cannot modify its own Profile.** ### What this commits us to 1. **Profile is a contract-level concept distinct from the role envelope.** A role's `system_prompt` field per **P9** may further specialize the agent's voice for that role's specific task, but Profile is the role-orthogonal identity layer. Switching roles does not switch Profiles. 2. **Profile is single-instance per operator.** Per **P6** (OS-Level Operator Identity) and **P1** (Single Operator, Single Primary Agent), there is exactly one Profile per Aivyx PA daemon. There is no "switch profile" gesture parallel to "switch role." 3. **Profile is operator-declared at install/init time and operator-mutable thereafter.** The agent cannot write to its own Profile. Profile changes are operator-driven through CLI or Web UI surfaces, *not* through the reflection layer (**P8**) or any in-turn mechanism. Reflection writes shape Persona (**P14**), not Profile. 4. **Profile is plain-text-inspectable.** Profile lives in a plain-text operator-readable file. The operator can read their Profile without unlocking the redb store, the same way they read role configurations today. 5. **Profile carries operator-declared identity fields in (at minimum) these categories:** - **Operator profile** — who the operator is (role, expertise level, primary work context). - **Communication style** — verbosity, formality, citation frequency, source referencing, etc. - **Primary use cases** — the 1–3 use-case archetypes the assistant is being shaped around. - **Behavioral preferences** — non-capability defaults that flavor the agent's judgment. - **Behavioral constraints** — non-capability guardrails the agent should respect across every role. - **Assistant name** — what the operator calls this specific assistant (distinct from product name and role names). The contract pins these **categories**, not the field names or the on-disk shape, per the **P9** precedent. 6. **Profile injects into every turn's system prompt.** The system-prompt assembly pipeline at turn start composes Profile alongside (not inside) the role-derived envelope description. 7. **Profile carries no secrets.** Profile must not be used for API keys, passphrases, tokens, or any secret material. Secret storage remains the AEAD-encrypted redb store. ### What this commitment deliberately does not say - **It does not pin the field names or the exact storage shape.** Per **P9** precedent. Phase 57 chooses the on- disk shape and field naming. - **It does not require Profile to be encrypted.** Profile carries no secrets per Commit 7. - **It does not require `aivyx-pa init` to be the only entry point.** Phase 57 extends the init wizard with use-case prompts, but other channels may bootstrap Profile. - **It does not preclude Profile from referencing other state** (memory entries, role names, scheduled tasks). - **It does not commit Profile to the audit chain.** Whether operator-driven Profile changes get audit entries is an implementation decision. ### How Profile composes with roles, capabilities, memory, and Persona - **Role envelope (P7 + P9)** gates capabilities. Profile does not. Profile has no envelope of its own. - **System prompt (P9 dimension)** is the per-role prompt override. Profile injects *alongside* the role's `system_prompt`, not inside it. - **Memory (G3)** is dynamic and observation-driven. Profile is static and operator-declared. - **Persona (P14)** is the dynamic counterpart of Profile. Profile is the static seed; Persona is the evolving voice that grows from Profile + accumulated reflection-approved deltas. Effective voice at turn start = Profile + sum(approved Persona deltas). --- ## Product Commitment 14 — Persona (LOCKED 2026-05-12) > *Added by amendment > [`2026-05-12-product-commitment-p14-persona.md`](docs/amendments/2026-05-12-product-commitment-p14-persona.md) > — filed in Phase 56 alongside A8 (pitch reframe) and A9 > (P13 — Assistant Profile).* > **Terminology note:** The operator's vision uses **"Soul"** > for the evolving character-layer. The contract spelling is > **"Persona"**. Both refer to the same concept; contract > docs, phase journals, and code use "Persona." ### The Rule > **Persona is the reflection-written dynamic identity layer > that grows from Profile (P13) over the assistant's > lifetime. Every Persona modification is a structured delta > proposed by the agent via the P8 reflection layer, > approved by the operator through the P2 mission-gate > machinery, and recorded in an HMAC-chained append-only > delta log audit-verifiable like the existing audit chain. > There is no silent Persona modification, no unaudited > Persona modification, and no operator-bypassed Persona > modification.** ### What this commits us to 1. **Persona modifications are P8-gated and P2-approved.** The agent proposes Persona deltas through the same `reflection.propose` surface that proposes memory and role-config edits today. The operator approves them through the same mission-gate machinery that approves missions today. Silent agent-driven Persona evolution is structurally impossible. 2. **Persona deltas form an append-only HMAC-chained log audit-verifiable like the existing audit chain.** The chain may share the existing audit chain or live as a parallel chain (implementation choice for Phase 59); the contract pins HMAC-chained, append-only, offline-verifiable as load-bearing security properties. 3. **Effective Persona at turn start is `Profile + sum(approved deltas)`.** Persona augments Profile, never overwrites it. The effective-identity layer composed at the start of every turn is Profile plus the deterministic application of every approved delta from the log. 4. **Persona is operator-reversible.** Because the delta log is append-only but the effective Persona is computed by *applying* deltas, the operator can revert to a prior effective Persona by appending a structured revert delta that nullifies one or more previous approved deltas. The audit chain remains immutable; the agent's effective voice returns to a prior state. 5. **Persona is single-instance per operator.** Per **P1** and **P6**, there is exactly one Persona delta log per Aivyx PA daemon, parallel to the single Profile. 6. **Persona writes are capability-secured.** The agent needs an explicit capability (e.g., `persona.propose`, exact base name TBD by Phase 59) to propose a delta. Operators who do not want autonomous voice-evolution simply do not grant this scope to any role; the substrate degrades to "Profile drives the voice, delta log stays empty forever." 7. **Persona is plain-text-inspectable in its effective form.** The operator can view the current effective Persona without unlocking the redb store. The delta log itself may be HMAC-chained and encrypted-at-rest; the *effective* state is operator-readable. ### What this commitment deliberately does not say - **It does not pin the delta categories.** Phase 59 chooses whether deltas cover communication adaptations, learned context, character traits, relationship milestones, or other categories. - **It does not say reflection *must* propose Persona deltas.** An operator may run Aivyx PA for years with an empty delta log. - **It does not pin the storage backend.** Whether the log lives in a new `KeyDomain::Persona`, shares the audit chain's domain, or uses a separate file is implementation choice. - **It does not preclude future delta export/import.** The contract pins the security property, not the locality. - **It does not commit to a specific approval-gate UX.** P2's mission-gate substrate already exists; Persona delta approvals reuse it. - **It does not say Persona changes are autonomous by default.** The capability gate is the operator's lever. - **It does not commit to a global Persona scope.** Per **P7**'s attenuation rules, child roles' Persona writes are scoped to the child's state. ### Why this is the most differentiating commitment after P8 **P8** already commits Aivyx PA to outcome-driven audited self-improvement at the *behavior* level (memory, role overrides). **P14** extends that posture to the *identity* level: the assistant's *voice* itself can evolve, but every evolution step is operator-approved and audit-verifiable. Together P8 and P14 define a single load-bearing property: **the assistant can become more useful over time, and every step of that becoming is legible to the operator and reversible by the operator.** No other agent product in the lane offers both. ### How Persona composes with Profile, roles, memory, and reflection - **Profile (P13)** is the static seed; Persona is the dynamic growth on top. Profile is *who the operator declared the assistant to be*; Persona is *who the assistant becomes*. - **Roles (P7 + P9)** gate capabilities; Persona has no envelope. A Persona delta shapes *how* the agent communicates, never *what* it may do. - **Memory (G3)** captures observations; Persona captures voice refinements. Memory is dynamic substrate; Persona is dynamic identity. - **Reflection (P8)** is the *engine* that proposes Persona deltas. P14 commits to nothing new in reflection machinery beyond a new delta category. - **Effective system prompt at turn start** = Profile + sum(approved Persona deltas) + active-role `system_prompt` + role-derived envelope description. --- ## Status This document is the **locked product contract**. Edits require an amendment under `docs/amendments/` per the same process as [`DESIGN.md`](DESIGN.md). The technical contract in `DESIGN.md` and this product contract are siblings: technical amendments do not require product amendments and vice versa, but a product amendment that requires a technical change necessarily requires an accompanying technical amendment. For the rolling product-shape entries (the product analogue of `docs/ROADMAP.md`), see [`docs/PRODUCT_ROADMAP.md`](docs/PRODUCT_ROADMAP.md). For the current phase journal, see the active `docs/PHASE_N.md` listed in [`docs/README.md`](docs/README.md). For the contract-vs-roadmap split explanation, see [`docs/README.md`](docs/README.md). --- ## Appendix — How this contract was assembled This document is the output of a **product-shape review pass** conducted at the Phase 12 / Phase 13 boundary on 2026-04-15. The pass ran in three stages: 1. **Stage 1 — Read-only inventory.** A targeted walk across five load-bearing seams of the post-Phase-12 codebase: the binary entry surface, the channel adapters, the role primitive and capability ceilings, the seven shipped tools, and the audit chain. The walk produced a factual, non-prescriptive inventory of "what Aivyx PA looks like from outside today." 2. **Stage 2 — Question pinning.** From the inventory, twelve load-bearing product questions were surfaced — places where the implementation had silently made a decision but never written it down, or where no decision had been made at all. The questions were grouped into four clusters and pinned one cluster at a time, with labelled options (A/B/C and variants) and a recommendation for each. The pinning followed the same rhythm as Phase 11 Q1–Q6 and Phase 12 Q1–Q6 in the technical layer. 3. **Stage 3 — This document.** Each pinned answer became one numbered Product Commitment (P1 through P12), drafted in the same shape as `DESIGN.md`'s deliverables: a one-rule north star, a "what this commits us to" list, a "what this deliberately does not say" list, and (where applicable) a "phase impact" note for commitments that require future work to deliver. ### The four clusters - **Cluster 1 — Identity & intent (P1, P2, P3).** Who runs Aivyx PA, what counts as success, what is in scope and what is explicitly out. The single most reframing cluster: the pinned answers expanded the product vision substantially beyond what the foundation today implements, taking the product from "personal CLI agent with eight tools" to "personal autonomous agent platform with daemon, missions, reflection, sub-agents, third-party SDK." - **Cluster 2 — Surfaces & channels (P4, P5, P6).** The daemon-default architecture (the largest single architectural commitment), the open channel adapter surface, OS-level operator identity. The cluster's centrepiece is **P4**'s daemon commitment, which reshapes the binary's lifecycle and unlocks **G5**'s autonomous execution and **P2**'s mission primitive. - **Cluster 3 — Capability and policy model (P7, P8, P9).** Single-inheritance role tree, outcome-driven audited reflection, per-role full capability declaration. Together these form a closed evolution loop: reflection observes outcomes → updates a role's declaration within the parent's attenuation envelope → next session runs under the updated role. This cluster contains **P8**, the single most differentiating commitment in the contract. - **Cluster 4 — Tool suite & SDK (P10, P11, P12).** The substrate-only core principle, the SDK contract's integration guarantees, and the tool-as-process model. Together these define the platform extension surface. **P10** locks the current shape; **P11** and **P12** open the door for third-party expansion without compromising the privacy or audit invariants. ### Internal-consistency check After all twelve commitments were pinned, an explicit internal-consistency check surfaced four implications that needed to be written into the contract explicitly to avoid drift: 1. **One IPC layer carries channels and tools both.** **P4**'s daemon IPC, **P5**'s channel adapter SDK, and **P12**'s tool process protocol all share one IPC surface. This makes the daemon-shipping phase load-bearing for the entire extension story; the IPC protocol designed there becomes the contract third parties speak. 2. **Reflection implies runtime role mutation.** **P8**'s reflection layer + **P9**'s per-role capability declaration together mean role configs become *mutable at runtime*, not just at startup. The reflection-layer phase will need to grow runtime role mutation under capability gating. 3. **Substrate vs. infrastructure tool taxonomy.** **P10**'s seven-tools cap applies only to *substrate* tools. Infrastructure tools (the machinery for **G3**, **G4**, **G5** to work) are a separate category and may grow without amendment. This distinction is written explicitly into **P10** and into the appendix to prevent a future phase from tripping over it. 4. **Tool processes are trusted at the OS-user level, sandboxed at the daemon address-space level.** **P12**'s process isolation defends the daemon's memory; OS-level isolation is implicit in the single-operator model from **P1** and **P6**. A third-party tool can read what the operator can read; it cannot tamper with the daemon's in-memory state or audit chain. This is written into **P12** explicitly. No contradictions surfaced during the consistency check. The four implications above are consequences of the pinned commitments, not unresolved questions. ### Forward commitments enumerated The following Product Commitments require future-phase work to deliver. The corresponding entries in `docs/PRODUCT_ROADMAP.md` give one-paragraph intents per expected phase: - **P4 — Daemon-default architecture.** Major reshape, expected to span one or more dedicated phases. - **P9 — Per-role full capability declaration.** Migration of the binary's operator-level grants into the role config. - **P5 — Open channel adapter SDK.** Likely couples to the daemon-shipping phase. - **P12 — Tool process IPC protocol.** Likely couples to the daemon-shipping phase. - **P11 — SDK documentation surface.** Likely a docs-and- examples phase after the in-tree SDK has stabilized. - **P2 — Mission primitive.** Couples to the daemon and to the role-config migration. - **P1 — Sub-agent role-switching machinery.** Couples to **P9**'s role-config migration. - **G3 / P8 — Reflection layer.** Couples to outcome history exposure and runtime role mutation. The commitments that **do not** require new phase work because the foundation already supports them: - **P3 — Goals and non-goals.** Vision document. - **P6 — OS-level operator identity.** Already true; the commitment is not introducing it. - **P7 — Single-inheritance role tree.** Phase 11's role primitive is the substrate; **P9**'s migration adds the inheritance layer. - **P10 — Substrate-only core.** True at fifteen tools (Amendment A5, Phase 38; Amendment A11, Phase 100; Amendment A12, Phase 109; Amendment A13b, Chapter Forge). --- ## Delivery Status (as of Phase 60, 2026-05-12) A traceability surface mapping each product commitment to its implementation state after 59 phases. The commitment text above carries nine amendments: A5 (P10 seven→eight, Phase 38), A6 (parallel tool execution, Phase 40), A7 (protocol negotiation, Phase 41), A8 (pitch reframe, Phase 56), A9 (P13 — Profile, Phase 56), A10 (P14 — Persona, Phase 56), A11 (P10 eight→ten, Phase 100), A12 (P10 ten→thirteen, Phase 109), A13b (P10 thirteen→fifteen, Chapter Forge). This section records what shipped, what partially shipped, and what remains forward. **Every PRODUCT.md commitment (P1–P14) is fully shipped.** The forward-commitment ledger closes at Phase 60. The original Phase 49 closure covered P1–P12; Chapter A (Phases 50–54) closed Foundation Closeout; Phase 55 demonstrated the post-Chapter-A posture; Phases 56–60 delivered the Profile + Persona forward arc (P13 + P14 amendment + substrate + operator surfaces). After Phase 60, future work is driven by operator feedback or contract amendments rather than scheduled forward commitments. Phase 60 also closes the Phase 59 Q5(a) hot- reload deferral — reflection-approved Persona deltas now take effect on the next turn without daemon restart. ### Fully Delivered - **P1 — Sub-Agent Role-Switching.** Phase 14 (inline sub-session nesting), Phase 33 (multi-level nesting). `OnceLock`-backed `RoleSwitchTool` factory closure with capability-bounded recursive nesting — each child's envelope can only narrow, never widen. Structural impossibility of escalation pinned by integration tests and `--print-role` reachable-targets enumerator. - **P2 — Session Legibility and Two Success Modes.** Phases 21, 23, 28, 35. Mission state machine (six states), `MissionCreateTool`, gate creation from `TurnOutcome::Escalated` (turn loop + daemon + trigger path), `ResolveGate` handler with turn resumption on approval, `mission.list`/`mission.status` read-only tools, gate rendering (CLI + Telegram). - **P4 — Daemon-Default Architecture.** Phases 16–20 (five- phase migration). Protocol settlement, production hardening, REPL wiring, multi-connection + Telegram port, daemon management. Auto-spawn, graceful shutdown, PID file, `daemon run`/`status`/`stop` subcommands, `--no-daemon` flag. The daemon is the sole execution shape in production. - **P6 — OS-Level Operator Identity.** Always true by construction. The daemon's IPC socket is mode `0600`, owned by the operator's effective UID. No Aivyx PA-level identity. - **P7 — Single-Inheritance Role Tree.** Phase 11 (role primitive) + Phase 13 (config migration). `parent_role` in TOML config, strict attenuation along every dimension, validated at config-load time. - **P8 — Outcome-Driven Audited Reflection.** Phases 28–30, extended at Phase 110. Audit introspection via `turn.history` (Phase 28), reflection loop via `reflection.propose`/`.apply` (Phase 29), runtime role mutation via `role.update` + planner factory integration (Phase 30). Phase 110 added the Skills Auto-Creation primitive: `LearnedSkill` as the 11th `PersonaDeltaCategory` variant (Q1a), new `skills.propose` capability scope sibling to `persona.propose` (Q2b), `skills.list` + `skills.invoke` substrate tools, and a `## Learned skills` section in the assembled system prompt (Q3c). Stays inside P8's envelope — the agent proposes through the existing persona-proposal surface, the operator approves through the Phase 70 review flow, the chain records both halves. No P8 amendment needed; the commitment text defines the propose-approve-apply shape and the skills extension fits inside that shape unchanged. Full observe→propose→approve→apply cycle now operational for memory writes, runtime role-config changes, Persona identity refinement, AND learned skills. - **P9 — Per-Role Full Capability Declaration.** Phase 13. `capability_scopes` parsed via `Scope::parse` at config-load time. Four-role worked example in `examples/aivyx-pa.toml`. `--print-role` debug flag for operator introspection. - **P10 — Substrate-Only Core, Fifteen Tools Forever.** Always true. The fifteen substrate tools (`fs.read`, `fs.write`, `fs.delete`, `fs.metadata`, `memory.read`, `memory.write`, `memory.forget`, `shell.exec`, `web.fetch`, `web.post`, `web.extract`, `git.status`, `git.diff`, `git.commit`, `net.dns`) are the closed set. `web.post` added in Phase 37, amendment A5 filed in Phase 38; `fs.delete` + `fs.metadata` added in Phase 100, amendment A11 filed the same phase; `git.status` + `git.diff` (sharing new `git.read` scope) + `net.dns` (existing scope since Phase 0) added in Phase 109, amendment A12 filed the same phase; `web.extract` (over the existing `net.fetch` scope) + `git.commit` (new `git.write` scope) added at Chapter Forge, amendment A13b filed at FG.2. Infrastructure tools and third-party MCP tools are separate categories. - **P5 — Open First-Party Channel Surface.** Phase 48. `docs/CHANNEL_SDK.md` is the v0 third-party contract; `examples/python-channel/` is the worked reference (Python 3, stdlib only, 15-test conformance suite). The substrate was always present (Phase 16 daemon IPC, Phase 19 multi-connection, Phase 39 Web UI proves it works for out-of-Rust adapters) — Phase 48 *published* it. - **P11 — SDK Contract: Interface + Integration.** Phase 48 (channel half) + Phase 49 (tool half). Each SDK's `docs/*_SDK.md` declares integration guarantees (capability gating, audit logging, cancellation) as stable while explicitly deferring API stability per the original P11 posture ("stability deferred until real third-party use"). - **P12 — Tools as Separate Processes Over Daemon IPC.** Phase 49 foundation + Phase 50 closeout. `aivyx-tool` crate (12th workspace member, A4 addendum); `ToolProcessBridge` spawns child processes via tokio with `kill_on_drop`; `ToolProxy` implements `aivyx_core::Tool` over a length- prefixed JSON protocol on the child's stdin/stdout; operator declares tools in `[[tool_process]]`; scope binding at handshake with operator-narrowing overrides; `docs/TOOL_SDK.md` is the v0 contract; `examples/python-tool/` ships the worked wordcount reference. Phase 50 closed the "extractable without rewriting" clause: `run_tool_as_subprocess` wraps any `aivyx_core::Tool` impl as a subprocess, proven equivalent to in-process execute() by the `p12_equivalence.rs` conformance test against `FsReadTool`. Phase 50 also wired the two foundation- phase deferrals: `ToolEvent` frames now relay onto the channel (`Status`/`OutputChunk` → `StreamEvent`), and cancellation is targeted via `CancelInvocation { call_id }` using a caller-supplied id. **Fully delivered.** - **P13 — Assistant Profile.** Phase 57 (Foundation) + Phase 58 (Inspection). Operator-declared static identity layer in `aivyx-config::Profile` with six P13-commit-5 fields (`assistant_name`, `operator_profile`, `communication_style`, `primary_use_cases`, `behavioral_preferences`, `behavioral_constraints`). `[profile]` TOML table per Q1(a). `Profile::default()` synthesizes Q5(b) fallback (`assistant_name = "Aivyx PA"`, all other categories empty) — every pre-Phase-57 `aivyx-pa.toml` keeps working unchanged. `assemble_session_prompt` helper composes Profile + role envelope into a labeled *"## About this assistant"* + *"## Active role: "* system prompt per Q3(c). Operator surface: `aivyx-pa init` extension (Phase 57 Q4(c) — three opt-in prompts), `aivyx-pa profile show` (read aivyx-pa.toml, print labeled), `aivyx-pa profile edit` (toml_edit-driven surgical `[profile]` section update in `$EDITOR` per Q2(a)), Web UI Profile pane via `Query::GetProfile` IPC per Q4(a). Reload semantics: load-time-only per Q5(a) (matches existing role-config behavior). **Fully delivered.** - **P14 — Persona.** Phase 59 (Foundation) + Phase 60 (Visualization). Reflection-written dynamic identity layer growing from Profile via P8-gated, P2-approved, HMAC-chained operator-reversible delta accumulation. Substrate (Phase 59): new `KeyDomain::Persona` (10th storage domain) with parallel HMAC chain (distinct genesis seed from audit), `PersonaDelta` records with 10 `PersonaDeltaCategory` variants (6 Profile-mirror + 4 Persona-specific per Q3(c)), `PersonaDeltaOp` with `SetScalar` / `AppendList` / `RemoveList`, validation + chain verification + replay into `EffectivePersona`, `persona.propose` capability scope, `reflection.propose` schema extension with required_scope escalation, `reflection.apply` writes approved deltas to the chain and the `SharedEffectivePersona` runtime state, and a three-section `assemble_session_prompt` layout per Q6(a) (`## About this assistant` + `## How I have learned to communicate` + `## Active role`). Operator surfaces (Phase 60): per-turn planner-factory refresh closing the Phase 59 Q5(a) deferral (approved deltas take effect on next turn without restart); `PersonaDeltaOp::Revert { target_delta_id }` variant + inverse-apply folder for revert semantics (P14 commit 4) including revert-of-revert restoring the original; `Query::GetEffectivePersona` + `Query::ListPersonaDeltas` IPC envelopes; `FrontendMessage::RevertPersonaDelta` for operator-initiated revert; `aivyx-pa persona show` / `list` / `revert` CLI subcommands; Web UI Persona pane with effective-state rendering and click-to-revert per Q3(a). Reverts are operator-only per Q5(a) — auto-approved since the operator is the proposer. Q4(a) chain shape: reverts append a `Revert` delta rather than mutating the chain in place, preserving the append-only invariant. **Fully delivered.** ### Partially Delivered - **P3 — Goals and Non-Goals.** Vision document — partially realized through implementation: - **G1 (Web interaction):** `web.fetch` shipped (Phase 12), `web.post` (POST/PUT/PATCH/DELETE) shipped (Phase 37), binary body support and redirect following shipped (Phase 37). Rich web interaction (page rendering, form submission) not yet started. - **G2 (Code interaction):** Shipped. `fs.read`, `fs.write`, `shell.exec` all operational with role gating. - **G3 (Memory Reflection):** Shipped (Phases 28–30). Memory substrate, reflection loop, runtime role mutation. - **G4 (Sub-agent orchestration):** Shipped (Phases 14, 33). Multi-level role-switching with capability attenuation. - **G5 (Autonomous/scheduled execution):** Shipped (Phases 26–27). Cron schedules, webhooks, file watchers, trigger unification, mission wrapping. - **G6 (Local execution, privacy):** Shipped (Phase 34). Ollama first-class support with health check. - **G7 (Third-party tool SDK):** Shipped (Phases 48, 49). `docs/CHANNEL_SDK.md` and `docs/TOOL_SDK.md` document the v0 contracts; `examples/python-channel/` and `examples/python-tool/` are the worked references. MCP integration remains as a parallel adapter (Phases 23–24, 32). ### Forward (Not Yet Started) *(Empty as of Phase 60 exit. **The PRODUCT.md forward- commitment ledger is closed.** Every P1–P14 commitment is fully shipped. Future work lands as operator-feedback driven phases or as contract amendments that introduce new commitments; both go through the existing amendment process before opening a phase.)* ### Forward Commitment Candidates — Status Update The following were identified at the Phase 21 boundary as candidates. Several have since been delivered: - **MCP Client Integration.** Delivered (Phases 23–24, 32). `aivyx-mcp` crate with stdio and SSE transports, `McpServerBridge` + `McpToolProxy`, `mcp.call` capability base, `[[mcp_server]]` TOML config, `--mcp-server` and `--mcp-sse` CLI flags. - **Multi-Provider LLM Support.** Delivered (Phases 25, 34). OpenAI-compatible `LlmProvider` adapter, `ProviderKind` enum (`Anthropic`, `OpenAi`, `Ollama`), `--provider` CLI flag. Phase 34 added first-class Ollama support with optional API key, conditional `stream_options`, health check, and worked example. - **Scheduled Execution.** Delivered (Phases 26–27). Cron schedules, webhook triggers (localhost-only), file-change watchers, `TriggerDispatch` unification, opt-in mission wrapping. - **Web UI Channel.** Delivered (Phases 39, 47). Phase 39 shipped the chat surface (localhost-only `127.0.0.1:7843`, `FrontendType::Web`, embedded HTML/CSS/JS, WebSocket bridge to the daemon IPC). Phase 47 extended it into a full operator inspection surface (mission dashboard, audit viewer with verify-chain banner, sessions list) by adding the `Query`/`QueryResponse` IPC envelope. ### Phase 51–55 — Chapter A Foundation Closeout + MCP sandbox After Phase 50 closed P12, the project pivoted from "deliver remaining commitments" to "close out Phase 0–49 loose ends." Phases 51–54 are Chapter A; Phase 55 is the first post-Chapter-A phase. - **Phase 51 — Cleanup.** Closed three pre-existing items: `AivyxError::{Storage,Crypto}` typed nested errors (D6 honored after 50 phases of stub), `handle_connection` parameter-struct lift (`ConnectionContext`), `AIVYX_PASSPHRASE` TOML/env footgun (`PassphraseSource:: FromConfig`). - **Phase 52 — Sandbox layer.** Generic command-wrapper sandbox for `[[tool_process]]`. Operator supplies the policy (bubblewrap / firejail / docker / sandbox-exec). Narrowed THREAT_MODEL.md §5.6. - **Phase 53 — (skipped).** Audit log rotation deferred indefinitely; chain growth is bounded by tool-call frequency × uptime. - **Phase 54 — Final docs sweep.** Root README rewrite, PRODUCT_ROADMAP delivered-section refresh, DAEMON_IPC Phase 47 addendum, A3 amendment scope-base count addendum, walkthrough refresh, cross-doc consistency spot-check. - **Phase 55 — MCP Server Sandbox Layer.** Ported the Phase 52 sandbox pattern from `[[tool_process]]` to `[[mcp_server]]`, closing THREAT_MODEL §5.2. New `aivyx-mcp::SandboxConfig`, parallel `[mcp_server.sandbox]` TOML schema. Demonstrated the post-Chapter-A posture (operator-feedback-shaped trigger + proven-pattern port + small task list). ### Phase 56 — Profile + Persona contract amendments (docs-only) This phase. Three amendments to `PRODUCT.md` filed in a single batch (the second contract amendment batch in project history; Phase 22 was the first): - **A8 — Pitch Reframe.** Narrows the LOCKED 2026-04-15 pitch from "personal autonomous agent platform" to "AI-personal assistant with user-defined Profile and Persona." Updates "cloud LLMs ... your own API key" to "cloud or local LLMs ... your own credentials" (reflecting Ollama support from Phase 34). - **A9 — Product Commitment P13 (Assistant Profile).** Adds P13 as the operator-declared, mostly-static identity layer. Pins seven commitments and pins field *categories* (per P9 precedent) without pinning field names. - **A10 — Product Commitment P14 (Persona).** Adds P14 as the reflection-written, dynamic identity layer growing from Profile under P8-gated, P2-approved, HMAC-chained operator-reversible delta accumulation. Pins both the storage property (HMAC-chained, append-only) and the gating property (P8-proposed, P2-approved). Carries a Terminology Note mapping the operator's "Soul" framing to the contract's "Persona" spelling. Zero code changes. PRODUCT.md byte-identity streak ended at six phases (intentional, via the formal amendment process). DESIGN.md and `aivyx-core/src/lib.rs` streaks held. ### Phase 57–58 — Profile Foundation + Inspection (P13 closed) The Profile arc's two implementation phases, which together deliver P13: - **Phase 57 (Foundation, shipped 2026-05-12).** `aivyx-config::Profile` struct with six P13-commit-5 fields; `[profile]` TOML table parser per Q1(a); `Profile::default()` synthesizing `assistant_name = "Aivyx PA"` + empty rest per Q5(b); `aivyx-channel::assemble_session_prompt` helper per Q3(c) composing Profile + role envelope into a labeled *"## About this assistant"* + *"## Active role: "* layout (with non-invasive passthrough when Profile is at its synthesized default); wiring through both parent and role-switch child planner factories so sub-sessions inherit the same Profile section; `aivyx-pa init` extension with three opt-in Profile prompts per Q4(c); startup-banner `profile` row. - **Phase 58 (Inspection, shipped 2026-05-12).** Closes the milestone with the operator surface: `aivyx-pa profile show` (read `aivyx-pa.toml`, labeled banner-style format per Q3(a)); `aivyx-pa profile edit` (`toml_edit`-driven surgical `[profile]` section update in `$EDITOR` per Q2(a), preserves comments and other sections); Web UI Profile pane via `Query::GetProfile` IPC envelope + `ProfileSummary` wire-shape per Q4(a); restart-required reload semantics per Q5(a). P13 moves to **Fully Delivered**; only P14 (Persona, Phases 59–60) remains forward. `toml_edit = "0.22"` is the first new workspace crate added since Phase 27's `notify`. ### Phases 59–60 — Persona Foundation + Visualization (P14 closed, ledger closed) The Persona arc's two implementation phases, which together deliver P14 and close the forward-commitment ledger. - **Phase 59 (Foundation, shipped 2026-05-12).** `KeyDomain::Persona` (10th storage domain) parallel to `KeyDomain::Audit`, distinct genesis seed; `PersonaDelta` + `PersonaDeltaCategory` (10 variants — 6 Profile-mirror + 4 Persona-specific per Q3(c)) + `PersonaDeltaOp` (`SetScalar` / `AppendList` / `RemoveList`) + `PersonaChainLog` + `PersistentPersonaLog`; `EffectivePersona` runtime state + `compute_effective_persona` pure folder; `SharedEffectivePersona = Arc>`; `persona.propose` capability scope; `reflection.propose` schema extension with `required_scope` escalation when deltas present; `reflection.apply` writes approved deltas to chain + shared state; `assemble_session_prompt` three-section labeled layout per Q6(a); chain key derived from master key (same shape as audit chain key) with startup replay into shared state, plumbed through `ReflectionApplyTool` and the planner-factory snapshot read at session build. - **Phase 60 (Visualization, shipped 2026-05-12).** Closed the forward-commitment ledger. `PersonaDeltaOp::Revert { target_delta_id }` variant + `apply_inverse_of_entry` folder for revert semantics including revert-of-revert restoring the original (P14 commit 4). Per-turn planner-factory refresh — approved deltas take effect on the next turn without restart (closes Phase 59 Q5(a)). `Query::GetEffectivePersona` + `Query::ListPersonaDeltas` IPC envelopes; `FrontendMessage::RevertPersonaDelta` + `DaemonMessage::PersonaRevertResolved` for operator-initiated revert. `aivyx-pa persona show / list / revert` CLI subcommands (daemon-IPC-backed). Web UI Persona pane with effective-state rendering and click-to-revert per Q3(a). Reverts are operator-only per Q5(a) and auto-approved (operator is the proposer). Per Q4(a), reverts append a delta to the append-only chain rather than mutating it. **P1–P14 all fully shipped. The forward-commitment ledger closes here.** Future numbered phases land as operator- feedback-driven work or as amendment-introduced commitments through the existing process. The Profile + Persona arc (Phases 56–60) was the last forward arc; after Phase 60 the project sits at every commitment delivered, every operator surface visible, and every reflection-written change audit-verifiable and operator-reversible.