# openalice

> OpenAlice — Alice character core: Rust binary, Cat-A soul/prompt blocks, per-lane state machine, reflexion scheduler, storage-v2 file-first identity layout, and connector bridge for Telegram / Discord / Matrix / A2A.


## At a glance
| field | value |
|---|---|
| kind | `meta` |
| priority | `P1` |
| default branch | `mvp` |
| last activity | 2026-07-10T16:51:16+00:00 |
| features catalogued | **735** |
| runtime deps declared | **10** |
| operator note | _NAO directive 2026-05-24 — main streaming product (Minsky-owned, P1)_ |

## Manifest
`.atlas-deps.yml` — parsed cleanly: **yes**

### Runtime deps
- `codex-oauth` (external) · `http` · via `CODEX_OAUTH_CLIENT_ID` — Primary LLM provider — Codex OAuth device-flow + in-process token refresh for all assistant turns.
- **`openalice-auth`** · `shared-jwt` · via `SHARED_JWT_SECRET` — Verify oa_session JWTs on every authenticated HTTP route; ALICE_JWT_SECRET shares the same secret.
- `elevenlabs` (external) · `http` · via `ELEVENLABS_API_KEY` · _optional_ — ElevenLabs v3 streaming TTS for MSE-based lipsync-locked voice output (OA_TTS_PROVIDER=elevenlabs).
- **`openalice-a2a`** · `http` · via `A2A_API_KEY` · _optional_ — Agent-to-agent task dispatch and hybrid group chat (A2A connector bridge).
- `openalice-agi-skills` (external) · `other` · via `OPENALICE_VOYAGER` · _optional_ — Voyager curriculum + versioned skill registry (Phase 3 Q6, PR 3.1 scaffold). Default OFF; tick is no-op unless OPENALICE_VOYAGER=on|shadow. Sandbox + Critic gate + LLM goal proposal deferred to PR 3.2+.
- **`openalice-prompt-composer`** · `other` · via `OPENALICE_PROMPT_COMPOSER` · _optional_ — Composer crate reads Cat-A SHA256-pinned .md blocks at boot and assembles prompts via SectionBuilder when OPENALICE_PROMPT_COMPOSER=v2.
- **`openalice-storage-v2`** · `other` · via `OPENALICE_STORAGE_LAYOUT` · _optional_ — File-first identity/session layout (identities/{slug}/, sessions/{conn}-{chat_id}/) read through storage-v2 compat shim when OPENALICE_STORAGE_LAYOUT=v2.
- `openrouter` (external) · `http` · via `OPENROUTER_BASE_URL` · _optional_ — Embedding calls (BGE-M3 / popular model routing) via OpenRouter /api/v1/chat/completions.
- `telegram-bot-api` (external) · `http` · via `BOTLAB_RELAY_TOKEN` · _optional_ — Telegram connector — inbound message relay + outbound send/edit/react via Bot API.
- `youtube-oauth` (external) · `http` · via `YOUTUBE_OAUTH_CLIENT_ID` · _optional_ — YouTube OAuth token exchange for chat-bridge per-broadcast spawn (moderation + stream key flows).

### Consumed env
- `ALICE_DATA_DIR`
- `ALICE_PRIMARY_AGENT_ID`
- `ALICE_CONFIG_DIR`
- `OPENALICE_HOME`
- `OPENALICE_PROMPTS_ROOT`
- `OA_ALICE_BIN`
- `OA_ALICE_CLI_BIN`
- `OPENALICE_ALICE_CLI_BIN`
- `SHARED_JWT_SECRET`
- `ALICE_JWT_SECRET`
- `INTERNAL_BROADCAST_SECRET`
- `A2A_INTERNAL_SECRET`
- `A2A_API_KEY`
- `ALICE_A2A_KEY`
- `CODEX_OAUTH_CLIENT_ID`
- `CODEX_OAUTH_TOKEN_URL`
- `CODEX_DEVICE_VERIFICATION_URL`
- `CODEX_MODELS`
- `CODEX_MODELS_DISCOVERY_PATH`
- `CODEX_DISCOVERY_TTL`
- `CODEX_REFRESH_MARGIN`
- `CODEX_SSE_STALE_TIMEOUT`
- `DEFAULT_CODEX_AUTH_FILE`
- `DEFAULT_CODEX_BASE_URL`
- `OPENROUTER_BASE_URL`
- `OPENROUTER_API_KEY`
- `OPENROUTER_POPULAR_MODELS`
- `ELEVENLABS_API_KEY`
- `ELEVENLABS_API_URL`
- `OA_TTS_PROVIDER`
- `STREAMING_TTS`
- `OPENALICE_STORAGE_LAYOUT`
- `OPENALICE_PROMPT_COMPOSER`
- `BOTLAB_RELAY_TOKEN`
- `BOTLAB_RELAY_CHAT`
- `A2A_API_KEY`
- `ALICE_A2A_ENABLED`
- `ALICE_A2A_PROBE_MS`
- `ALICE_A2A_TIMEOUT_SECS`
- `BROWSE_PUBLIC_WS_BASE`
- `BROWSE_PUBLIC_HOST`
- `PTY_PUBLIC_WS_BASE`
- `OPENALICE_IMAGE_GEN`
- `OPENALICE_IMAGE_GEN_ENV`
- `OPENALICE_GOAL_AUTONOMY`
- `OPENALICE_SKILL_CURATOR`
- `OPENALICE_AGENT_KANBAN`
- `OPENALICE_DURABLE_EXEC`
- `OPENALICE_COALESCE_STRICT_DEDUP`
- `OPENALICE_COALESCE_STRICT_DEDUP_WINDOW_MS`
- `OPENALICE_LANE_SCORER`
- `OPENALICE_KEEP_LEGACY_TOOLS`
- `OPENALICE_OUTBOUND_DELIVERY`
- `OPENALICE_INBOUND_ENVELOPE`
- `OPENALICE_MEMORY_CHAR_WHITELIST_SIZE`
- `OPENALICE_MEMORY_CHAR_WHITELIST`
- `OPENALICE_REQUEST_TIMEOUT_SECS`
- `OPENALICE_REQUEST_TIMEOUT_STREAMING_SECS`
- `OPENALICE_AGENT_MAX_DEPTH`
- `OPENALICE_AGENT_HEARTBEAT_GRACE_MS`
- `OPENALICE_AUXILIARY_BACKFILL_MODEL`
- `ALICE_LINTER_GATE_ENABLED`
- `ALICE_DECAY_JOB_ENABLED`
- `ALICE_CRYSTALLIZE_ENABLED`
- `ALICE_GUARD_PATTERNS`
- `ALICE_MENTION_REGEX`
- `ALICE_MEMORY_CREDENTIAL_POLICY`
- `ALICE_RUN_FEATURE_GATE_CHECKS`
- `OPENALICE_REFLEXION_ENABLED`
- `OPENALICE_REFLEXION_TURN_THRESHOLD`
- `OPENALICE_CRITIC_AGENT`
- `OPENALICE_CRITIC_GATE_TOOL_DISPATCH`
- `OPENALICE_CRITIC_GATE_RESPONSE_DRAFT`
- `OPENALICE_CRITIC_MODEL`
- `OPENALICE_CRITIC_ASYNC_MODEL`
- `OPENALICE_CRITIC_GATE_LIST`
- `OPENALICE_CRITIC_AUDIT_INTERVAL`
- `OPENALICE_CRITIC_DAILY_USD_CAP`
- `OPENALICE_VOYAGER`
- `OPENALICE_VOYAGER_GOALS_PER_CYCLE`
- `OPENALICE_SKILL_REGISTRY_PATH`
- `OPENALICE_ENVELOPE`
- `OPENALICE_ENVELOPE_SIGMA`
- `OPENALICE_ENVELOPE_REFERENCE_PATH`
- `OPENALICE_ENVELOPE_JUDGE_MODEL`
- `OPENALICE_ENVELOPE_JUDGE_DAILY_USD_CAP`
- `OPENALICE_REFLEXION_SYNTH`
- `OPENALICE_REFLEXION_SYNTH_MODEL`
- `OPENALICE_REFLEXION_DAILY_USD_CAP`
- `CODEX_AUTH_FILE`
- `OPENALICE_CODEX_BASE_URL`
- `OA_LANE_DB_PATH`
- `RUST_LOG`
- `OTEL_EXPORTER_OTLP_ENDPOINT`
- `OTEL_SERVICE_NAME`
- `OTEL_DISABLED`
- `YOUTUBE_OAUTH_CLIENT_ID`
- `YOUTUBE_OAUTH_CLIENT_SECRET`
- `OPENALICE_CLI_ALLOW_TOKEN`
- `OPENALICE_CLI_ALLOW_WRITE`

### Owns tables
- `lanes`
- `kv_store`
- `schema_version`

### Events published
- `connector.message`
- `audit.entry`
- `agent.reflection`
- `memory.consolidated`
- `memory.crystallized`
- `task.created`
- `task.completed`
- `agent.spawned`
- `kernel.started`
- `envelope.rollback`

### Events consumed
- `connector.message`
- `task.created`
- `agent.spawned`
- `task.completed`
- `security.anomaly`
- `calendar.reminder`

### Exposes
- `docker_image` — openalice-alice
- `http_endpoint` — https://alice.blal.pro/v1/chat
- `http_endpoint` — https://alice.blal.pro/v1/chat/stream
- `http_endpoint` — https://alice.blal.pro/api/v1/memory/graph
- `http_endpoint` — https://alice.blal.pro/v1/agents/*
- `http_endpoint` — https://alice.blal.pro/v1/a2a
- `http_endpoint` — https://alice.blal.pro/v1/events/stream
- `http_endpoint` — https://alice.blal.pro/metrics
- `http_endpoint` — https://alice.blal.pro/health

## Env drift

**Code reads, manifest omits (72):**
- `A2A_DB_PASSWORD`
- `A2A_SERVICE_URL`
- `ALICE_ENDPOINT`
- `ALICE_HEALTH_BASE_URL`
- `ALICE_MEMORY_BENCH_EMBED`
- `ALICE_URL`
- `BOTLAB_RELAY_CHANNEL`
- `CARGO_MANIFEST_DIR`
- `CARGO_WORKSPACE_DIR`
- `CLAUDE_CONFIG_DIR`
- `COCKPIT_PORT`
- `DOMAIN`
- `ELEVENLABS_MODEL_ID`
- `ELEVENLABS_VOICE_ID`
- `GATEWAY_ANON_RATE_LIMIT`
- `GATEWAY_RATE_LIMIT`
- `HOST_UID`
- `MEMORY_BACKFILL`
- `MEMORY_REEMBED`
- `ML_ADMIN_KEY`
- `NEXT_PUBLIC_API_URL`
- `NEXT_PUBLIC_PLAYGROUND_ONLY`
- `NEXT_PUBLIC_PUBLIC_KEY`
- `OA_BOOT_REPLAY_PENDING`
- `OA_COCKPIT_BIN`
- `OA_PENDING_QUEUE_DB_PATH`
- `OA_SKILL_SCRIPT`
- `OPENALICE_ALERT_TELEGRAM_CHAT_ID`
- `OPENALICE_ALLOW_SOUL_WRITE`
- `OPENALICE_BROWSER_SVC_URL`
- `OPENALICE_CONNECTOR_ENGINE_COMPACT`
- `OPENALICE_DEFAULT_INTERACTION_MODE`
- `OPENALICE_LANE_V2`
- `OPENALICE_MAX_MEMORY_BYTES`
- `OPENALICE_MINIMAL_TOOLS`
- `OPENALICE_ML_KEY`
- `OPENALICE_QUEUE_ACCUMULATOR`
- `OPENALICE_QUEUE_ACCUMULATOR_TTL_MS`
- `OPENALICE_SAFETY_GATE`
- `OPENALICE_SEARCH_SVC_URL`
- `OPENALICE_SYNTH_TO_STEER_CONV_ID`
- `OPENALICE_TEST_TOOLS`
- `OPENALICE_TIMEOUT_SECS`
- `OPENALICE_TOKEN_COMPACTION`
- `OPENALICE_TOOLS_AUTO_COMMIT_EDITS`
- `OPENALICE_TOOL_OUTPUT_COMPACT`
- `OPENALICE_TOOL_OUTPUT_COMPACT_HARD_CAP`
- `OPENALICE_TOOL_OUTPUT_COMPACT_THRESHOLD`
- `OPENALICE_TUI_THEME`
- `OPENALICE_VOYAGER_LLM_MODEL`
- `OPENALICE_VOYAGER_TICK_SECS`
- `OPENALICE_WORKING_LONG_SECS`
- `PLAYWRIGHT_PORT`
- `PTY_INTERNAL_SECRET`
- `RUNPOD_ANIM_TEMPLATE`
- `RUNPOD_API_KEY`
- `RUNPOD_RENDERER_TEMPLATE`
- `S3_ACCESS_KEY`
- `S3_BUCKET`
- `S3_ENDPOINT_URL`
- `S3_PREFIX`
- `S3_REGION`
- `S3_SECRET_KEY`
- `SCHEDULER_ANIM_IMAGE`
- `SCHEDULER_PROVIDERS`
- `SCHEDULER_RENDERER_IMAGE`
- `STATUS_TOKEN`
- `SWE_IPC_DIR`
- `SWE_RUN_TESTS_TIMEOUT`
- `TTS_PROVIDER`
- `VITE_CJS_IGNORE_WARNING`
- `VOICE_CACHE_DIR`

**Manifest declares, code unused (43):**
- `ALICE_JWT_SECRET`
- `ALICE_MENTION_REGEX`
- `ALICE_RUN_FEATURE_GATE_CHECKS`
- `BROWSE_PUBLIC_HOST`
- `BROWSE_PUBLIC_WS_BASE`
- `CODEX_AUTH_FILE`
- `CODEX_DEVICE_VERIFICATION_URL`
- `CODEX_DISCOVERY_TTL`
- `CODEX_MODELS`
- `CODEX_MODELS_DISCOVERY_PATH`
- `CODEX_OAUTH_CLIENT_ID`
- `CODEX_OAUTH_TOKEN_URL`
- `CODEX_REFRESH_MARGIN`
- `CODEX_SSE_STALE_TIMEOUT`
- `DEFAULT_CODEX_AUTH_FILE`
- `DEFAULT_CODEX_BASE_URL`
- `ELEVENLABS_API_URL`
- `OA_TTS_PROVIDER`
- `OPENALICE_AGENT_HEARTBEAT_GRACE_MS`
- `OPENALICE_AGENT_KANBAN`
- `OPENALICE_CODEX_BASE_URL`
- `OPENALICE_CRITIC_ASYNC_MODEL`
- `OPENALICE_CRITIC_DAILY_USD_CAP`
- `OPENALICE_CRITIC_GATE_RESPONSE_DRAFT`
- `OPENALICE_CRITIC_GATE_TOOL_DISPATCH`
- `OPENALICE_ENVELOPE_JUDGE_DAILY_USD_CAP`
- `OPENALICE_ENVELOPE_JUDGE_MODEL`
- `OPENALICE_IMAGE_GEN`
- `OPENALICE_IMAGE_GEN_ENV`
- `OPENALICE_REFLEXION_DAILY_USD_CAP`
- `OPENALICE_REFLEXION_ENABLED`
- `OPENALICE_REFLEXION_SYNTH`
- `OPENALICE_REFLEXION_SYNTH_MODEL`
- `OPENALICE_REFLEXION_TURN_THRESHOLD`
- `OPENALICE_SKILL_CURATOR`
- `OPENALICE_SKILL_REGISTRY_PATH`
- `OPENROUTER_BASE_URL`
- `OPENROUTER_POPULAR_MODELS`
- `PTY_PUBLIC_WS_BASE`
- `RUST_LOG`
- `STREAMING_TTS`
- `YOUTUBE_OAUTH_CLIENT_ID`
- `YOUTUBE_OAUTH_CLIENT_SECRET`

## Live reachability
- last probe: **down** · `https://alice.blal.pro` · HTTP 401 · 68ms
- uptime 24h: **0.0%**

## Features (735)

### agentic
- **`workflow_skills.runtime`** · _experimental_ · since 0.1.0 — Declarative workflow-skills with triggers (timer/call/context-pattern); step = deterministic tool/sub-skill or guarded sub-agent-spawn. Unifies hands + sub-agents; loadable as packs.  
  *openalice_workflow_skills:0*

### agents
- **`agents.agentic_loop.critic_gate_reintegration`** · _experimental_ · since 2026-07-09 — D3 (2026-07-09, docs/design/capabilities-on-framework-2026-07-09.md) — the deferred PR 2.6 Constitutional Critic gate reintegration, as an ASYNC CriticGateStage in the turn's StagePipeline (right after DeliberationStage). Reuses the pure build_review_prompt/parse_verdict logic from agents-safety (widened pub(crate) → pub) but calls the LLM via ctx.llm.complete(...), never the blocking review_sync (whose thread::scope + join would starve a tokio worker). On Veto: publishes a response-draft-soft-veto observer event + injects a [CRITIC HINT: ...] nudge + RetryPasses, capped at 1 (ctx.critic_retry_count); a second veto is log-only (sent as-is). Fail-open (Approve-equivalent) on every LLM/parse error. Default OFF — caps.critic.gate_reintegration / OPENALICE_CRITIC_GATE_REINTEGRATION. Speaker-mismatch pre-check lens (2026-07-10, ports the dormant Q5 derive_speaker_context/build_critic_speaker_hint pair off the deleted api-handlers::chat_tools::agentic_loop::critic — see its old TODO Phase D Step 5c): the SAME single LLM call renders a SPEAKER CHECK block when the trailing user-run has ≥2 distinct speakers; a speaker_mismatch-shaped veto (is_speaker_mismatch_veto) gets the speaker-specific hint instead of the generic one, sharing this SAME retry budget — one combined spend, not a second counter.  
  *openalice_agents::agentic_loop::turn_pipeline::critic_gate:0*
- **`agents.agentic_loop.stage_pipeline`** · _stable_ · since 2026-07-06 — E4b — the agentic loop's phases (turn-start, pre-LLM, LLM-call; response/gate/all-failed phases share the same staged fns unconditionally) run through core::ecs::StagePipeline. DEFAULT-ON 2026-07-06 (lab canary probe_alice 3/3 both ways, byte-identical parity harness); the legacy inline path + its OPENALICE_STAGE_PIPELINE kill-switch were RETIRED 2026-07-08 after 3 green gates + a live-prod bake with zero errors — the staged expression IS the loop's base now.  
  *openalice_agents::agentic_loop::staged:0*
- **`agents.agentic_loop.tool_verify`** · _experimental_ · since 2026-07-09 — Phase M3b (2026-07-02, resurrected + re-hooked 2026-07-09 per docs/design/capabilities-on-framework-2026-07-09.md D1/D2) — OPT-IN tool-result self-verification. When a turn ran a successful mutating tool (any is_artifact_write_tool: workspace write/edit/patch/delete, send_file, git_add/commit/push), `DeliberationStage` injects one [VERIFY] reflection to re-read + confirm the change before finalizing (fixing it if wrong), then RetryPasses. SOTA verify-your-edits pattern; catches silently-wrong edits a tool-ok status misses. Capped at TOOL_VERIFY_CAP=1; only fires when a mutation actually ran. Default OFF — caps.deliberation.tool_verify / OPENALICE_TOOL_VERIFY.  
  *openalice_agents::agentic_loop::turn_pipeline::tool_verify:0*
- **`agents.agentic_loop.turn_pipeline`** · _beta_ · since 2026-07-06 — THE agentic loop — the whole turn as a core::ecs::StagePipeline with declarative StageControl::RetryPass re-entry: every legacy `continue` (overflow recovery, durable resume, force-execute nudge, anti-fallback retry, next tool round) is a RetryPass and MAX_TOOL_ITERATIONS is the run_with_retries pass budget. Stages are thin adapters over the staged phase fns (single source of truth). ENDGAME COMPLETE 2026-07-08: inline monolith retired (morning), E4c default-ON, then the E4b sequencer driver + kill-switch retired (midday) — ONE loop. Every hand-over was pinned byte-identical by the parity harnesses (now loop_golden_pins.rs); the flip gate ran the full 9436-test suite through the pipeline.  
  *openalice_agents::agentic_loop::turn_pipeline:0*
- **`agents.agentic_loop.turn_plan`** · _experimental_ · since 2026-07-09 — Phase M2b (2026-07-02, resurrected + re-hooked 2026-07-09 per docs/design/capabilities-on-framework-2026-07-09.md D1/D2) — OPT-IN live turn-start planner. For a non-trivial request, `run_turn_pipeline` makes one cheap LLM call (turn-start only, never re-run on RetryPass) to decompose the ask into ordered subgoals and injects them as a [PLAN] block into the system message, additive on top of the existing static planning reminder. Fail-open (plan error / trivial request → no plan → normal loop). Default OFF — caps.deliberation.plan / OPENALICE_TURN_PLAN.  
  *openalice_agents::agentic_loop::turn_pipeline::turn_plan:0*
- **`agents.agentic_loop.turn_verify`** · _experimental_ · since 2026-07-09 — Phase M2 (2026-07-02, resurrected + re-hooked 2026-07-09 per docs/design/capabilities-on-framework-2026-07-09.md D1/D2) — OPT-IN live turn-completion verifier. `DeliberationStage` (between LlmCallStage and ResponseStage in the turn's StagePipeline) asks a cheap LLM judge whether the user's request is fully accomplished before the candidate draft is returned; a NO verdict injects a [SELF-CHECK] reflection naming the gap and RetryPasses the turn (capped at TURN_VERIFY_REFLECT_CAP=2). Upgrades termination from 'LLM stopped / cap' to goal-verification. Fail-open (judge error → treat as complete → never blocks a reply). Default OFF — caps.deliberation.verify / OPENALICE_TURN_VERIFY.  
  *openalice_agents::agentic_loop::turn_pipeline::turn_verify:0*
- **`agents.answer_completeness.hybrid_scorer`** · _beta_ · since 2026-05-20 — Phase 8XXX M4 — runtime ANSWER_COMPLETENESS scorer. Hybrid two-phase design: a cheap deterministic heuristic gate (question detection + key-term overlap, RU+EN aware) handles the common all-addressed case with zero LLM cost; an LLM verification phase (gpt-5.4-mini, ~300 input + 50 output tokens) adjudicates ambiguous bundles. Per-bundle retry cap (1) prevents follow-up loops. Conservative: parse failures and scorer errors return `Clear` so a bad scorer never blocks a reply. Consumed by reply.rs to transition the lane to FollowupNeeded when one or more questions in a coalesced bundle were silently skipped.  
  *openalice_agents::answer_completeness:0*
- **`agents.answer_completeness.scorer_caps_bridge`** · _beta_ · since 2026-07-09 — Caps-migration (2026-07-09, tail-close wave) — `install_default_scorer_from_env` is config-first: when a live unified-config handle is installed, `caps.answer_all.scorer` ("off"|"heuristic"|"hybrid", any other value falls back to "hybrid") selects the scorer; uninstalled processes keep the legacy `OPENALICE_LANE_SCORER` env read verbatim, including its "hybrid" default when unset. Schema default is "hybrid" — a deliberate deviation from the all-caps-off convention, matching today's de-facto default (prod already ships hybrid).  
  *openalice_agents::answer_completeness:0*
- **`agents.approval`** · _stable_ · since 0.1.0 — HITL approval queue — hierarchical routing (MEMBER → LEAD → admin), deadline-aware, notification-backed pending list for dangerous tool invocations.  
  *openalice_agents::approval:0*
- **`agents.fingerprint`** · _stable_ · since 0.1.0 — Case fingerprint — SHA-256 over (agent, tool, canonical args) so that standing approvals, JIT grants, and safety audits key off a stable identifier.  
  *openalice_agents::fingerprint:0*
- **`agents.groups`** · _stable_ · since 0.1.0 — GroupRegistry — CRUD, role-based membership, hierarchical tool resolution, group XP tracking, per-group MCP server discovery.  
  *openalice_agents::groups:0*
- **`agents.jit_permissions`** · _stable_ · since 0.1.0 — Just-in-time, time-bounded, task-scoped permission grants that auto-expire — lets agents temporarily reach tools they don't normally have with a TTL safety net.  
  *openalice_agents::jit_permissions:0*
- **`agents.mission_engine`** · _stable_ · since 0.1.0 — Autonomous goal execution — CRUD missions, LLM planner that decomposes goals into task DAGs, reporter that delivers results to the configured channel. Scratchpad + mission.json per mission.  
  *openalice_agents::mission_engine:0*
- **`agents.rank`** · _stable_ · since 0.1.0 — Agent Rank System — 4 metrics (Accuracy / Honesty / Execution / Discipline), hidden MMR (0-3200+), visible Bronze→Apex tiers with five divisions each. Honest failure scored above dishonest success.  
  *openalice_agents::rank:0*
- **`agents.reflexion.b_hybrid_scheduler`** · _experimental_ · since 2026-05-22 — Phase 8MMMM-PPPP follow-up — Reflexion B-hybrid scheduler scaffold. Fast-path triggers when a chat accumulates N completed turns since the last Reflexion (default N=10, env OPENALICE_REFLEXION_TURN_THRESHOLD). 24h daily floor covers chats with no fast-path activity. Activity counter REUSES openalice_coalesce::lane_state turn counts — no parallel counter. Scaffold only: trait + unit tests, NOT wired into the alice runtime yet.  
  *openalice_agents::reflexion::scheduler:0*
- **`agents.reflexion.heuristic_proposal_synth`** · _experimental_ · since 2026-05-22 — Phase 8MMMM-PPPP POC — Reflexion heuristic synthesizer. Detects user follow-ups that match a misunderstanding regex (RU «не…/ты не…/имел в виду…» + EN «no/i meant») within 2 minutes of the prior assistant reply. Emits an overlay YAML proposal to prompts/proposals/ for NAO to manually merge. NEVER auto-applies. No LLM call — heuristic only. The LLM-backed impl is a follow-up wave. Per memory `feedback-alice-free-to-evolve-no-personality-optimization-2026-05-21` this is a SUGGESTION channel, not a tuning loop.  
  *openalice_agents::reflexion::proposal_synth:0*
- **`agents.reflexion.proposal_archive_30d`** · _experimental_ · since 2026-05-22 — Phase 8MMMM-PPPP follow-up — Reflexion proposal archive sweep. Moves `prompts/proposals/*.rejected` older than 30 days into `_archive/YYYY-MM/`. Idempotent. NEVER deletes (per `feedback-memory-archive-not-delete-2026-05-02`). Designed for daily cron co-scheduling with the B-hybrid scheduler. Active (un-suffixed) proposals are not touched.  
  *openalice_agents::reflexion::proposal_store:0*
- **`agents.runtime.steer_mailbox`** · _experimental_ · since 2026-04-26 — Steer mailbox — keyed by (agent_id, conv_id), accepts mid-run user course-corrections that the agentic loop drains at the next safe injection point (between tool calls / before the next LLM call). Bounded at 50 entries per pair; overflow drops the oldest with WARN.  
  *openalice_agents::steer:0*
- **`agents.soul.intent.heuristic_classifier`** · _beta_ · since 0.1.0 — Wave J #1 — regex-only intent classifier. Extracts action vs question vs chat, deliverable kind (file/skill/memory/none), and target_path from the user message. The Task Contract section (Wave J #3) renders only when target_path is present.  
  *openalice_agents_soul::intent:0*
- **`agents.soul.sections.task_contract`** · _beta_ · since 0.1.0 — Wave J #3 — '# Task Contract (this turn)' section. Renders the expected deliverable kind, target path, merge constraint, and success criteria so the model has a load-bearing per-turn contract. Lights up only when the Wave J #1 intent classifier pinned a target_path on the user message. Full mode only.  
  *openalice_agents_soul::sections::task_contract:0*
- **`agents.standing_approvals`** · _stable_ · since 0.1.0 — Pre-approved permissions for specific tool-invocation patterns — exact, pattern, and scope match with TTL + use counting; bypass the HITL gate for known-safe fingerprints.  
  *openalice_agents::standing_approvals:0*
- **`agents.steering.background_note`** · _experimental_ · since 2026-05-07 — Wave R2 BACKGROUND_NOTE renderer — folds a different-speaker mid-stream event into the next turn's prompt as a stable literal `[BACKGROUND_NOTE from speaker @X: "..."]` prefix. Independent of Wave R3's `<speaker>` tag rendering so it survives across rendering changes.  
  *openalice_agents::steering:0*
- **`agents.steering.cancel.mailbox`** · _experimental_ · since 2026-05-07 — Wave R2 cancel mailbox — keyed by (agent_id, conv_id), carries a one-shot signal that tells the agentic loop to abort the current LLM call cleanly at the next safe boundary. Used by the CoalesceRestart / CancelRestart strategies and by `alice-cli steer cancel`.  
  *openalice_agents::steering::cancel_mailbox:0*
- **`agents.steering.facade`** · _experimental_ · since 2026-05-07 — Wave R2 mid-stream steering facade — speaker classifier, intent heuristic, strategy selector, cancel mailbox, pending_after queue, metrics constants. Consumed by the connector bridge's `steer_routing` stage and by the agentic loop's cancel-poll site.  
  *openalice_agents::steering:0*
- **`agents.steering.intent.classify`** · _experimental_ · since 2026-05-07 — Wave R2 heuristic intent classifier (same-speaker case) — redirect vs follow-up vs additional info. RU + EN markers; pure str-match, no LLM, <5ms guaranteed.  
  *openalice_agents::steering::intent:0*
- **`agents.steering.metric.steer_total`** · _experimental_ · since 2026-05-07 — Wave R2 Prometheus constants — `oa_steer_total{strategy=...}` counter and `oa_steer_decision_latency_ms` histogram. Dashboards / alert rules reference these strings; renaming is a breaking change. Master plan §12.1 R2 row.  
  *openalice_agents::steering::metrics:0*
- **`agents.steering.pending.queue`** · _experimental_ · since 2026-05-07 — Wave R2 pending_after_current FIFO — same-speaker follow-up events that arrived during an in-flight turn and must be processed AFTER the turn ends. The connector bridge drains this on in-flight guard drop and re-enters the pipeline with the queued event.  
  *openalice_agents::steering::pending_queue:0*
- **`agents.steering.speaker.classify`** · _experimental_ · since 2026-05-07 — Wave R2 speaker-continuity classifier — same-speaker vs different-speaker comparison of the in-flight event vs the incoming event. Falls back to a (chat_id, user_id) surrogate when R3's speaker_id is not yet populated on Event.  
  *openalice_agents::steering::speaker:0*
- **`agents.steering.strategy.select`** · _experimental_ · since 2026-05-07 — Wave R2 strategy selector — maps (speaker_continuity, intent) to one of {CoalesceRestart, CancelRestart, QueueAfter, ContextInjectForNext}. Pure heuristic, no LLM. Measured by the `oa_steer_decision_latency_ms` histogram.  
  *openalice_agents::steering::strategy:0*
- **`agents.tool_index`** · _stable_ · since 0.1.0 — Semantic tool search via HNSW over tool-description embeddings — core tools always loaded, top-K relevant tools injected per message, tool_search fallback for the long tail (~85% token savings).  
  *openalice_agents::tool_index:0*
- **`agents.tool_manager`** · _stable_ · since 0.1.0 — Central tool registry + execution pipeline: schema validation → policy check → cache → safety drivers → safety gate → budget tick → execute → record usage.  
  *openalice_agents::tools:0*
- **`agents.tool_manager.tool_trace_recorder`** · _beta_ · since 2026-05-07 — Wave V — middleware that appends a JSON line to per-chat tool-calls.jsonl after every dispatch. Records (tool, args, outcome, duration, lesson, error). Skipped when group_id is empty so out-of-band system calls don't pollute scopes.  
  *openalice_agents::tools:0*
- **`agi.delivery.answer_all_cancel_restart`** · _experimental_ · since 2026-07-09 — A1 (2026-07-09, docs/design/capabilities-on-framework-2026-07-09.md D4-DECIDED) — OPT-IN answer_all delivery guarantee at the ONE live CancelRestart drop site: `IterationHeadStage`'s cancel arm (turn_pipeline.rs), which today unconditionally aborts the turn into a dead end (response_extract's cancelled-silently Stop has no re-entry). When `caps.answer_all.enabled` and the reason is CancelRestart: a steer already folded this pass (or ONE extra PerIteration injector poll, race-free against steer_routing's push-before-cancel write order) swallows the abort and folds the `<steer kind="replace"> redirect into the SAME pass — ONE reply, never two (A2: Replace honored literally, not double-answered). No steer materializing falls through to today's abort byte-identically. CoalesceRestart's Phase-8OOO swallow and Operator's cancel are untouched. Default OFF — caps.answer_all.enabled / OPENALICE_ANSWER_ALL.  
  *openalice_agents::agentic_loop::turn_pipeline:0*
- **`openalice.reflexion.codex_synth`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.7 + PR 2.8 — LLM-backed Reflexion proposal synthesizer using Codex gpt-5.4-mini (OPENALICE_REFLEXION_SYNTH_MODEL). PR 2.8 flipped the default to `codex`; set OPENALICE_REFLEXION_SYNTH=heuristic to revert, or `off` to disable synth entirely. Cost-guarded by OPENALICE_REFLEXION_DAILY_USD_CAP (default $0.20). Cat-A block mutations (A-*) are silently dropped before returning — the LLM is instructed to avoid them but the filter is authoritative. On JSON parse error, cost-cap breach, or LLM transport failure the synth auto-falls-back to the heuristic backend and bumps `oa_reflexion_synth_fallback_total{reason}`.  
  *openalice_agents::reflexion::codex_proposal_synth:0*
- **`openalice.reflexion.codex_synth.http_transport`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.8 — `CodexSynthLlm::complete` HTTP transport. Reads the OAuth access_token from `~/.codex/auth.json` (CODEX_AUTH_FILE override), POSTs the Responses-API shape to `chatgpt.com/backend-api/codex/responses`, drains the SSE stream, extracts the assistant text from `output[].content[].text`, and returns it to the synth. Bridges to tokio via a small one-shot single-thread runtime (the synth call site is sync). Auto-falls-back to the heuristic synth on any transport error — never panics, never blocks the runtime.  
  *openalice_agents::reflexion::codex_proposal_synth:0*
- **`openalice.reflexion.metrics.synth_fallback`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.8 — Prometheus counter `oa_reflexion_synth_fallback_total{reason}`. Bumped whenever the Codex-backed Reflexion synth (OPENALICE_REFLEXION_SYNTH=codex, the new default) falls back to the heuristic backend. Reasons: `codex_unavailable` (no OAuth token), `cost_cap_hit` (OPENALICE_REFLEXION_DAILY_USD_CAP would be exceeded), `parse_error` (Codex returned unparseable JSON), `network_error` (HTTP transport failed). Used by Atlas dashboards + Grafana to monitor LLM-synth health without re-running the loop.  
  *openalice_agents::reflexion::reflexion_metrics:0*

### agents-tools
- **`tools.agent_spawn`** · _beta_ · since 2026-05-07 — Wave T — HTTP-tool handler for `agent_spawn`. Forks a fresh alice-cli subprocess that executes the spawn spec; supports budget caps (tokens + wall), scope, parent_id (recursion), and the OPENALICE_AGENT_MAX_DEPTH cap (default 3). Effects: spec written, spawn initiated, audit row appended. Phase 8J hardening: when background=true the parent waits on alice-cli with a 10s wall budget and kills the subprocess on exceed, so a hung CLI / file-watcher / flock cannot burn through the 60s HTTP middleware timeout (RCA of the lab `subagent-spawn-and-watch` 408).  
  *openalice_agents_tools::tools_builtins::handlers_misc::agent_spawn:0*

### agi-core
- **`openalice.agi_core.lane_v2`** · _beta_ · since 2026-05-22 — Phase 1 Q3 — Lane v2 fat struct. Consolidates per-lane state (FSM, turns, bundles, speakers, refs, intent, envelope, reflexion, skills) into a single serializable struct that can be snapshotted and round-tripped through runner blobs.  
  *openalice_asi_core::lane:0*
- **`openalice.agi_core.registry_trait`** · _beta_ · since 2026-05-22 — PR 1.7/1.7.5 — LaneRegistry trait returns native LaneSnapshot. CoalesceLaneRegistry adapter uses snapshot_state_parts / snapshot_all_as_parts — no coalesce::Lane import on read path.  
  *openalice_asi_core::registry:0*

### agi-skills
- **`agi.skills.adapters.sandboxed_executor`** · _experimental_ · since 2026-06-21 — SandboxedSkillExecutor — real SkillSandbox that EXECUTES Voyager bash skills in the capability sandbox (Process/Docker backend), deny-by-default: pre-filter + scratch-tmpdir FileWrite only, no net/env/shell, fuel+30s+16MB limits. Default-OFF — wired via OPENALICE_VOYAGER_SANDBOX=process|docker (default validate = BasicSkillValidator, unchanged).  
  *openalice_asi_skills::adapters::sandboxed_executor:0*
- **`agi.skills.cycle.tick`** · _experimental_ · since 2026-05-23 — VoyagerCycle::tick() — single tick of the curriculum loop. Phase 3.2 runs synth -> sandbox -> Critic-gated promotion; shadow mode stays read-only.  
  *openalice_asi_skills::cycle:0*
- **`agi.skills.persistence.json`** · _experimental_ · since 2026-05-23 — JSON round-trip for VoyagerCurriculum + SkillRegistry to/from ${OPENALICE_HOME}/skills/. Missing files load as Default.  
  *openalice_asi_skills::persistence:0*
- **`agi.skills.registry.versioned_skill`** · _experimental_ · since 2026-05-23 — SkillRegistry + VersionedSkill + SkillVersion + SkillCreator. Append-only versions, NAO-overridable active pointer.  
  *openalice_asi_skills::registry:0*
- **`agi.skills.voyager.curriculum`** · _experimental_ · since 2026-05-23 — VoyagerCurriculum + LearningGoal + FailedAttempt types; pick_next_goal priority (deadline > novelty > revisit).  
  *openalice_asi_skills::voyager:0*
- **`openalice.agi_skills.bootstrap`** · _experimental_ · since 2026-05-23 — Phase 3 PR 3.1 — Voyager curriculum + skill versioning scaffold. Types, JSON persistence, stub cycle. Sandbox + Critic gate + LLM goal proposal deferred to PR 3.2+. Default: OPENALICE_VOYAGER=off.  
  *openalice_asi_skills:0*

### agi/skills
- **`agi.skills.adapters.codex_skill_synth`** — Phase 3.2 production adapter — wraps a Codex `CriticLlm` (typically `CodexHttpCriticLlm`, but the trait is generic) to satisfy `SkillProposalSynth`. Uses gpt-5.4-mini by default for cost. The Codex Responses API requires a top-level `instructions` field (Phase 8LL fix for image_gen, Critic 2026-05-24 fix for review). This adapter passes a synth-specific role declaration as the `instructions` string via the `complete()` prompt context — actual contract is owned by `CodexHttpCriticLlm::complete`, which already pins the required field per the post-fix transport.  
  *crates/asi-skills/src/adapters/codex_skill_synth.rs:1*
- **`agi.skills.adapters.critic_gate`** — Phase 3.2 production adapter — wraps `ConstitutionalCritic` to satisfy `SkillProposalGate`. Reuses `EventKind::ResponseDraft` (no new variant added to agents-safety yet; the skill body travels in the draft slot and the context tags it as a skill proposal via metadata).  
  *crates/asi-skills/src/adapters/critic_gate_adapter.rs:1*
- **`agi.skills.adapters.sandbox_validator`** — Phase 3.2 production adapter — pure-Rust validator that satisfies `SkillSandbox`. Validates skill-body structure WITHOUT executing it: 1. parses YAML frontmatter (between `---` fences) 2. checks required frontmatter fields (`name`, `purpose`) 3. checks `name` matches kebab-case `[a-z][a-z0-9-]*` 4. scans body for obvious dangerous patterns (rm -rf /, curl|sh, eval $(curl, sudo, etc.) — REJECT these on principle 5. checks at least one fenced ```bash code block is present Future PR can swap this for a real WasmSandbox/ProcessSandbox adapter that actually executes the skill. For now, structural validation is the safest first step — Critic will gate the rest.  
  *crates/asi-skills/src/adapters/sandbox_validator.rs:1*
- **`agi.skills.critic_gate`** — Phase 3.2 — Voyager sandbox + Critic-gated promotion. This module defines the Critic review boundary used before skill promotion.  
  *crates/asi-skills/src/critic_gate.rs:1*
- **`agi.skills.sandbox`** — Phase 3.2 — Voyager sandbox + Critic-gated promotion. This module defines the sandbox execution boundary used after proposal synthesis and before Critic review.  
  *crates/asi-skills/src/sandbox_exec.rs:1*
- **`agi.skills.synth`** — Phase 3.2 — Voyager sandbox + Critic-gated promotion. This module defines the proposal synthesis boundary used by [`crate::cycle::VoyagerCycle`] before sandbox execution.  
  *crates/asi-skills/src/skill_proposal.rs:1*

### alice-cli
- **`alice_cli.agent.budget.tokens`** · _beta_ · since 2026-05-07 — Wave T — per-spawn `--budget tokens=N` cap. Worker tracks self-reported tokens via the DSL `tokens:N` step; on cap, writes partial result with outcome=budget_exceeded.  
  *openalice_alice_cli::agent::runner::run_worker:0*
- **`alice_cli.agent.budget.wall`** · _beta_ · since 2026-05-07 — Wave T — per-spawn `--budget wall=M` wall-clock cap (seconds). Worker's tokio timer fires cancel; result lands with outcome=wall_exceeded and elapsed_ms in metadata.  
  *openalice_alice_cli::agent::runner::run_worker:0*
- **`alice_cli.agent.cancel`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent cancel <agent_id>` flips the running/<id>.json `cancel` flag; the worker polls and exits at the next safe boundary, writing a partial result with outcome=cancelled.  
  *openalice_alice_cli::agent::runner::cancel_agent:0*
- **`alice_cli.agent.depth_cap`** · _beta_ · since 2026-05-07 — Wave T — recursion depth cap (master plan §16 risk #9). Each spec carries parent_id + depth; spawn is rejected at $OPENALICE_AGENT_MAX_DEPTH (default 3) with oa_agent_depth_cap_total incremented. Stops malicious self-spawning skills cold.  
  *openalice_alice_cli::agent::runner::spawn_subagent:0*
- **`alice_cli.agent.get`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent get <agent_id>` prints the full spec + current status + (if done) result for a single agent.  
  *openalice_alice_cli::agent::layout::get_agent:0*
- **`alice_cli.agent.kanban`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — `alice-cli agent kanban [--scope S] [--watch] [--json]` renders Hermes-style 7-column Kanban (queued / running / blocked / retrying / done / failed / cancelled) of every known sub-agent. `--watch` runs a heartbeat-watcher pass before rendering so stale runs are surfaced as Failed.  
  *openalice_alice_cli::handle_agent_kanban:0*
- **`alice_cli.agent.kanban.flag`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — `OPENALICE_AGENT_KANBAN=1` feature flag turns on Hermes v0.13.0-style Kanban: heartbeat side-task per worker, atomic state-transition counters, retry budget. Default OFF in prod (additive); ON in lab.  
  *openalice_alice_cli::agent::kanban::is_kanban_enabled:0*
- **`alice_cli.agent.kanban.heartbeat_thread`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — heartbeat side-thread spawned per Kanban worker. Refreshes `last_heartbeat_at` every 5s (default) by reading the running breadcrumb, bumping `heartbeat_count`, and atomic-writing it back. Bumps `oa_agent_heartbeats_total` on every beat. Fire-and-forget — a failed write doesn't kill the worker, only the watcher's perception.  
  *openalice_alice_cli::agent::kanban::spawn_heartbeat_thread:0*
- **`alice_cli.agent.kanban.heartbeat_watcher`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — `evaluate_heartbeats()` scans every running breadcrumb under a layout and declares dead the ones whose `last_heartbeat_at` drifted past the grace window (default 30s). Writes a synthetic `heartbeat_lost` result, bumps `oa_agent_heartbeats_lost_total` + the failed state-transition counter. Returns the lost agent_ids so the caller can chain into `escalate_or_retry`.  
  *openalice_alice_cli::agent::kanban::evaluate_heartbeats:0*
- **`alice_cli.agent.kanban.retry_budget`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — per-job retry budget. `escalate_or_retry()` consults `spec.retry_budget` vs `spec.retries_used`; under budget yields `Retry{retries_used+=1}` + bumps `oa_agent_retry_total{reason}`, at/above budget yields `Escalate` + bumps `oa_agent_retry_exhausted_total`. Pure function (no IO) so callers compose audit + respawn around it.  
  *openalice_alice_cli::agent::kanban::escalate_or_retry:0*
- **`alice_cli.agent.kanban.tui_render`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — `alice-cli agent kanban` verb renders a 7-column ASCII table (queued / running / blocked / retrying / done / failed / cancelled) with one row per known agent. Output is deterministic so the verb can be diff-tested.  
  *openalice_alice_cli::agent::kanban::render_kanban:0*
- **`alice_cli.agent.list`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent list [--scope] [--status]` walks the agents/ tree and emits one JSON object per known sub-agent with its spec + status (running/done/failed).  
  *openalice_alice_cli::agent::layout::list_agents:0*
- **`alice_cli.agent.run_worker`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent _run <agent_id>` is the internal worker hook spawned by `agent spawn`. It loads the spec, evaluates the task (DSL today: sleep:Ns/tokens:N/echo:.../spawn:.../fail), enforces budget caps via tokio timer + token counter, then writes a result.json atomically.  
  *openalice_alice_cli::agent::runner::run_worker:0*
- **`alice_cli.agent.spawn`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent spawn '<task>'` forks a fresh alice-cli subprocess that executes the spawn spec. Returns an agent_id (uuid); spec/running/result files live in ~/.openalice/data/{agent}/agents/. Supports --background, --budget tokens=N,wall=M, --scope chat=<id>, --model, --provider, --parent-id, with $OPENALICE_AGENT_MAX_DEPTH cap.  
  *openalice_alice_cli::agent::runner::spawn_subagent:0*
- **`alice_cli.agent.spawn.retry_budget`** · _experimental_ · since 2026-05-15 — Phase 8FF-4 — `alice-cli agent spawn --retry-budget N` arms Hermes-style retry semantics on the resulting spec. Pairs with `OPENALICE_AGENT_KANBAN=1` to enable the heartbeat watcher.  
  *openalice_alice_cli::handle_agent_spawn:0*
- **`alice_cli.agent.watch`** · _beta_ · since 2026-05-07 — Wave T — `alice-cli agent watch <agent_id>` tails the result file until it appears, then prints the final JSON and exits. Polls every 100ms with a 1s coarse fallback.  
  *openalice_alice_cli::agent::runner::watch_until_done:0*

### alice-control
- **`alice.control.queue.format`** · _beta_ · since 2026-06-09 — MC C1 — ControlCommand + ControlResult wire format, HMAC-SHA256 signing/verification, and JSONL file helpers for the Mission Cockpit command queue. Shared by alice watcher, cockpit writer, and TUI writer. Verbs: Cancel/Pause/Resume/Retry/Spawn.  
  *openalice_core::dataflow::control_queue:0*
- **`alice.control.queue.spawn_verb`** · _experimental_ · since 2026-06-09 — Phase-C — `Spawn` ControlVerb + `SpawnParams` wire type. Adds sub-agent spawn via the signed command queue (HMAC-gated). Depth cap enforced by spawn_subagent; token-budget gate is a FIXME deferred to a future wave. Cockpit POST /v1/agents/{id}/spawn + TUI `s` key behind ConfirmSpawn modal.  
  *openalice_core::dataflow::control_queue:0*

### api
- **`api.handlers.v1.models_list`** · _stable_ · since 0.1.0 — GET /v1/models + GET /v1/models/{id} — public OpenAI-shape model catalog endpoints. Backed by the bundled ModelRegistry loaded from config/models/*.yaml + include_str! defaults. Track F-GPT55 (2026-04-23) confirmed gpt-5.5 surfaces here automatically once the YAML catalog lists it.  
  *openalice_api_handlers::http::routes::router_routes:0*

### audit
- **`core.merkle_audit`** · _stable_ · since 0.1.0 — [DEPRECATED alias — see observability.audit.merkle] SHA-256 hash-chained audit log — typed actions, store persistence, range verification, tamper-evident history.  
  *openalice_observability::audit::merkle:0*

### build
- **`build.cargo_features.a2a`** · _stable_ · since 0.9.0 — Cargo feature `a2a` — gates the A2A inbound long-poll connector auto-start in `alice serve`. Module `openalice_alice::modules::mod_a2a` is only compiled when enabled; the shared agents::protocols::a2a client + MCP bridge remain always-compiled because federation + mod_drivers::DRIVER_A2A_CLIENT consume them regardless.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.browser`** · _beta_ · since 0.9.0 — Cargo feature `browser` — reserves the flag for Chromium / CDP-driven code (map_create screenshot path, browser-rules engine, regression-tests/chrome scenarios). Declared-only today; phase-2 will gate the CDP client + Xvfb env checks.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.full`** · _stable_ · since 0.9.0 — Cargo feature `full` — umbrella that turns on voice + lsp + wasm + browser + tui + a2a in one flag. Default-on. Lets operators opt back into the complete build after --no-default-features with a single toggle.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.lsp`** · _beta_ · since 0.9.0 — Cargo feature `lsp` — reserves the flag for the rust-analyzer / LSP bridge (openalice-lsp). Currently declared-only because AppState wires lsp_registry across ~40 HTTP handlers; phase-2 will flip openalice-lsp to optional and gate the AppState fields. Flag still valid today for CI-matrix intent-signalling.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.tui`** · _beta_ · since 0.9.0 — Cargo feature `tui` — reserves the flag for the ratatui-based terminal Mission Control (openalice-tui + alice tui subcommand). Declared-only today because Commands::Tui still builds unconditionally; phase-2 will gate the CLI variant + crates/api-handlers/.../routes/tui.rs handlers.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.voice`** · _stable_ · since 0.9.0 — Cargo feature `voice` — pulls the Silero-VAD ONNX adapter (openalice-voice-wake/silero) + wake-word intelligence driver. Default ON. Turn off for SaaS worker nodes that never ingest audio; saves ~15 MB of ort / ndarray compile output.  
  *openalice_core::config::cargo_features_registry:0*
- **`build.cargo_features.wasm`** · _stable_ · since 0.9.0 — Cargo feature `wasm` — passes through to openalice-modules/wasm-runtime + openalice-modules-drivers/wasm-runtime. Turns on the wasmtime-backed pack host so signed .wasm skills and connectors load at boot. Disable for binaries that only run native tools.  
  *openalice_core::config::cargo_features_registry:0*

### chat
- **`chat.v1.goal_autonomy`** · _experimental_ · since 2026-05-15 — /goal slash-command — user types `/goal "achieve X by Y"` and Alice decomposes + executes subtasks autonomously, reporting progress + surfacing blockers. Snipes Hermes v0.13.0 + Claude Code v2.1.143. Gated by OPENALICE_GOAL_AUTONOMY env var; default OFF in prod, ON in lab.  
  *openalice_agents_soul::goal_engine:0*
- **`chat.v1.goal_runner`** · _experimental_ · since 2026-05-15 — Goal Runner — OODA-shaped autonomous executor for /goal entities. Decomposes the goal text, walks subtasks linearly, charges LLM call counter, checkpoints after each step, surfaces blockers. Sibling to mission_executor but slash-command friendly.  
  *openalice_agents_soul::goal_runner:0*

### connector
- **`connector.a2a`** · _beta_ · since 0.1.0 — Google A2A protocol — Agent-Card discovery, 8-state task model, JSON-RPC 2.0 (message/send, tasks/get, tasks/cancel), server + client roles.  
  *openalice_agents::protocols::a2a:0*
- **`connector.discord`** · _stable_ · since 0.1.0 — Discord bot — raw Gateway v10 WebSocket + REST; channel allowlist, DM pairing, reply threading, Russian mention patterns. No heavy framework dep (tokio-tungstenite + reqwest only).  
  *openalice_modules::connectors::discord_bot:0*
- **`connector.email`** · _beta_ · since 0.1.0 — Email connector skeleton — poll loop with exponential backoff, transport-agnostic so SMTP/IMAP can be swapped for provider APIs.  
  *openalice_modules::connectors::email:0*
- **`connector.email_smtp`** · _beta_ · since 0.1.0 — Raw-TCP SMTP + IMAP transport — EHLO/STARTTLS/AUTH LOGIN send, LOGIN/SELECT/SEARCH/FETCH/STORE poll; no heavyweight framework.  
  *openalice_modules::connectors::email_smtp:0*
- **`connector.mcp.dynamic_registry`** · _experimental_ · since 2026-06-21 — Runtime MCP tool registry — discovered MCP tools (mcp.<server>.<tool>) with list_changed + dynamic add_server + tool-poisoning detection (sanitize/quarantine, untrusted-by-default). The dispatcher consults it; trust is granted out-of-band (SafetyGate/HITL), never by the remote server.  
  *openalice_agents_tools::protocols::mcp_dynamic_registry:0*
- **`connector.telegram`** · _stable_ · since 0.1.0 — Telegram bot — long-polling, pairing, inline keyboards, streaming typing indicator, HTML formatting, callback queries, file upload, per-chat message dedup, voice message support.  
  *openalice_modules::connectors::telegram:0*
- **`connector.telegram.bot_to_bot_metrics`** · _beta_ · since 2026-05-18 — Phase 8KKK — Prometheus counters for Telegram bot-to-bot traffic: `oa_telegram_bot_to_bot_messages_received_total` (raw inbound), `oa_telegram_bot_to_bot_loop_blocked_total` (guard drops by reason), `oa_telegram_bot_to_bot_replied_total` (Alice's outbound reply). Lets us alert on runaway chains, saturated chats, and silent drops without scraping logs.  
  *openalice_modules::connectors::telegram::bot_to_bot_metrics:0*
- **`connector.telegram.rich_formatting`** · _beta_ · since 2026-06-14 — #517 v1 — Telegram rich-message formatting. Outbound text replies go through a unified decision layer (`outbound.rs`): rich ON by default (global `OPENALICE_TG_RICH` kill-switch + per-chat `settings/tg_rich` override) builds `InputRichMessage{markdown}` and POSTs Bot API 10.1 `sendRichMessage` (Telegram renders headings/tables/lists/code/quotes/ LaTeX natively, 32768-char cap); on any error or when disabled it falls back to an improved legacy HTML floor (headings→<b>, lists→•/n., tables→aligned <pre>, ---→rule, tasks→☐/☑) with a tag-aware 4096 chunker that never orphans a tag and re-opens open tags across chunk boundaries. Removes the old double `markdown_to_telegram_html` call.  
  *openalice_modules::connectors::telegram::rich:0*
- **`connector.wasm`** · _experimental_ · since 0.1.0 — WASM connector adapter — loads a `.wasm` module implementing the connector protocol (send_message / poll_messages) and dispatches through `openalice_sandbox::WasmSandbox`.  
  *openalice_modules::connectors::wasm:0*
- **`connector.web`** · _stable_ · since 0.1.0 — Web UI connector — WebSocket transport abstraction for the in-browser chat UI (Mission Control, embedded widget).  
  *openalice_modules::connectors::web:0*
- **`delivery.adapter`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `DeliveryAdapter` trait per platform. Adapters declare which channels they serve (`channels()`), which modalities they support (`supports()`), and the actual send path (`deliver()`). Object-safe; the typed inner client (e.g. `Arc<TelegramHost>`) lives in an `Any`-typed slot via `raw_client()` + `client_as::<T>()` downcast.  
  *openalice_delivery::adapter:0*
- **`delivery.adapter.a2a`** · _experimental_ · since 2026-05-21 — Phase 8CCCC Phase B2 — `A2aDeliveryAdapter` implements the canonical `openalice_delivery::DeliveryAdapter` trait for the `a2a` channel. POSTs `{"result": text, "status": "completed"}` to `{base}/internal/tasks/{task_id}/complete` with the optional `X-Internal-Secret` header. Capability matrix: Text only (A2A task results are JSON-RPC text strings). task_id is taken from `envelope.reply_to.platform_id` first, then `options.raw_extras["a2a_task_id"]`. Gated by `OPENALICE_OUTBOUND_DELIVERY=v2`.  
  *openalice_modules_connectors::connectors::a2a::delivery_adapter:0*
- **`delivery.adapter.discord`** · _experimental_ · since 2026-05-21 — Phase 8CCCC Phase B2 — `DiscordDeliveryAdapter` implements the canonical `openalice_delivery::DeliveryAdapter` trait, translating `OutboundEnvelope`s into the existing `DiscordRestClient::send_*` calls. Capability matrix: Text + Reaction + TypingIndicator + Edit. Photo / Voice / File modalities short-circuit to Unsupported until the upstream REST client grows multipart attachment surfaces. Embeds + components remain on the rich-embed reply-stage branch (Phase B-late will surface them via DeliveryOptions::raw_extras). Gated by `OPENALICE_OUTBOUND_DELIVERY=v2`.  
  *openalice_modules_connectors::connectors::discord_bot::delivery_adapter:0*
- **`delivery.adapter.telegram`** · _experimental_ · since 2026-05-21 — Phase 8CCCC Phase B1 — `TelegramDeliveryAdapter` implements the canonical `openalice_delivery::DeliveryAdapter` trait, translating `OutboundEnvelope`s into the existing `TelegramRestClient::send_*` calls. Capability matrix: Text + Photo + Voice + File + Reaction + TypingIndicator + Edit (every modality the enum currently models). Gated by `OPENALICE_OUTBOUND_DELIVERY=v2`; default unset → legacy direct path stays in force (byte-identical to pre-8CCCC). Phase B1.5 lands the global router install + the actual reply.rs dispatch switch.  
  *openalice_modules_connectors::connectors::telegram::delivery_adapter:0*
- **`delivery.envelope`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `OutboundEnvelope { channel, modality, payload, reply_to, options }` value type mirroring the inbound shape in modules-connectors `InboundEnvelope` (8GGGG). `DeliveryModality` enum: Text, Photo, Voice, File, Reaction, TypingIndicator, Edit. `DeliveryPayload` tagged-union covers every payload type; `validate()` catches modality/payload mismatches. `DeliveryOptions` carries cross-platform hints (silent, parse_mode, scheduled_at_ms, link_preview, thread_id) that adapters honour opportunistically.  
  *openalice_delivery::envelope:0*
- **`delivery.error`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `DeliveryError` enum classifies every failure mode: AdapterUnavailable, RateLimited (retryable), Unsupported (terminal), PayloadTooLarge (terminal), RemoteFailure (terminal), TransportError (retryable), InvalidEnvelope (terminal), RetryBudgetExhausted (terminal wrap of a retryable inner). `is_retryable()` drives the router's retry loop; `kind()` provides low-cardinality metric labels.  
  *openalice_delivery::error:0*
- **`delivery.global_router`** · _experimental_ · since 2026-05-21 — Phase 8CCCC Phase B1.5 — process-global `DeliveryRouter` slot (`std::sync::OnceLock`). `install_global_router(Arc<dyn DeliveryRouter>)` is called once from `alice::main` boot right after Telegram (and future Discord/Matrix/A2A) adapters are registered. Dispatch sites (currently: connector_bridge `reply.rs`) read via `global_router()` and fall back to the legacy per-platform `rest_client::send_*` direct path when `None`, so a flag-on / router-missing process is non-breaking. Gated alongside `OPENALICE_OUTBOUND_DELIVERY=v2` via `is_v2_enabled()`.  
  *openalice_delivery::global:0*
- **`delivery.metrics`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `DeliveryMetrics`: atomic counters for `deliveries_total`, `no_adapter_total`, `unsupported_total`, `retries_total`, `budget_exhausted_total`, `registered_adapters`. Phase B exposes these as Prometheus counters via `linkme::distributed_slice(METRICS_EXPORTERS)` in the `observability` crate.  
  *openalice_delivery::metrics:0*
- **`delivery.registration_slice`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `linkme::distributed_slice(DELIVERY_ADAPTERS)` collects every `AdapterRegistration` declared across the workspace. `InMemoryDeliveryRouter::from_registrations()` walks the slice and builds a router without per-crate boot glue. The slice is empty in Phase A; Phase B adds one registration per concrete adapter (telegram, discord, matrix, web, voice, a2a).  
  *openalice_delivery::router:0*
- **`delivery.router.in_memory`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — `InMemoryDeliveryRouter`: per-platform adapter HashMap + exponential-backoff retry on retryable errors (RateLimited / TransportError) + audit hook placeholder. Unsupported modalities short-circuit without retry; classification errors (AdapterUnavailable, PayloadTooLarge, InvalidEnvelope) are terminal. Cost-aware (optional) via `DeliveryAdapter::cost_estimate`.  
  *openalice_delivery::router:0*
- **`delivery.router.trait`** · _experimental_ · since 2026-05-20 — Phase 8CCCC Phase A — canonical `DeliveryRouter` trait. Single outbound entry point that answers `given ChannelRef + DeliveryModality + DeliveryPayload, which DeliveryAdapter should the caller invoke?`. Object-safe (no generic methods on the trait). Dark in Phase A: no existing connector send path is migrated. Phase B routes telegram, discord, matrix, web-sse, voice, and a2a onto this trait.  
  *openalice_delivery::router:0*

### connector-core
- **`modules.connectors.core.avatars`** · _experimental_ · since 2026-05-15 — Phase 8WW — AvatarProvider trait + AvatarBytes / AvatarMeta value types + decide_avatar_fetch cache gatekeeper. Connector-agnostic contract for inbound-triggered avatar auto-fetch into the refs registry (`refs/people/{slug}/`).  
  *openalice_modules_connectors::core::avatars:0*
- **`modules.connectors.core.bot_pairing`** · _experimental_ · since 0.3.0 — BotPairingFlow — generic 'is_bot ? -> uppercase 6-char check -> redeem -> whitelist -> persist' helper that collapses the byte-identical pairing-attempt blocks in telegram::host::handle_update and discord_bot::handle_message_create.  
  *openalice_modules_connectors::core::bot_pairing:0*
- **`modules.connectors.core.http_retry`** · _experimental_ · since 0.3.0 — Shared 429-Retry-After HTTP retry helper — RateLimitError, parse_retry_after, do_request_with_retry. Replaces the byte-identical 429 blocks that Track 4 left inline in Telegram + Discord REST clients.  
  *openalice_modules_connectors::core::http_retry:0*
- **`modules.connectors.core.lifecycle`** · _experimental_ · since 0.2.0 — ConnectorStatus state machine — boot → connecting → connected → reconnecting → stopped, with reasoned transitions for operator UI.  
  *openalice_modules_connectors::core::lifecycle:0*
- **`modules.connectors.core.messaging`** · _experimental_ · since 0.3.0 — TypingPing — persistent 'user is typing…' indicator that loops every N seconds until cancelled. Both Telegram and Discord plug their own send-action closure in.  
  *openalice_modules_connectors::core::messaging:0*
- **`modules.connectors.core.pairing`** · _experimental_ · since 0.2.0 — GenericPairingManager<K> — 6-char codes, 15-min expiry, single-use, store-backed paired-user set. Backs Telegram + Discord pairing flows.  
  *openalice_modules_connectors::core::pairing:0*
- **`modules.connectors.core.pipeline`** · _experimental_ · since 0.2.0 — ConnectorPipeline trait + run_pipeline driver — unified receive→decode→authorize→dedup→dispatch→ack stages shared across Telegram, Discord, and future connectors.  
  *openalice_modules_connectors::core:0*
- **`modules.connectors.core.policy`** · _stable_ · since 0.2.0 — BotAntiLoop (4 exchanges / 30s / 60s cooldown) + ChannelRateLimiter (leaky-bucket, configurable max/s). Byte-for-byte identical to the former Telegram + Discord inline copies.  
  *openalice_modules_connectors::core::policy:0*
- **`modules.connectors.core.streaming`** · _experimental_ · since 0.2.0 — StreamingAdapter trait + PlaceholderEditController + OnceReply — abstracts placeholder-then-edit flows (Telegram, Discord) vs. single-shot (A2A, SMTP, WebSocket ack).  
  *openalice_modules_connectors::core::streaming:0*

### core
- **`chat_folders.audit_log`** · _beta_ · since 2026-05-07 — Wave S — _audit.jsonl append-only change log. Every migration / folder mutation records one JSON line with {ts, action, ...} so operators can replay layout history without git scraping.  
  *openalice_core::storage::chat_folders:0*
- **`chat_folders.layout`** · _beta_ · since 2026-05-07 — Wave S — canonical per-chat folder layout helpers. Every channel (TG/Discord/Matrix/A2A/browser/voice) writes inbox/outbox/voice/ browser/traces/dossiers/skills under ~/.openalice/data/{agent}/chat/{scope}/ via this module.  
  *openalice_core::storage::chat_folders:0*
- **`chat_folders.migration_s1`** · _beta_ · since 2026-05-07 — Wave S — folder layout migration runner. Snapshots the data dir (cp -al hardlink), creates canonical dirs for every detected chat scope, stamps schema.json: {version: s1}, audits each step. Idempotent + dry-run-able via OPENALICE_CHAT_FOLDERS_MIGRATION_DRY_RUN.  
  *openalice_core::storage::chat_folders_migration:0*
- **`chat_folders.migration_s1_step`** · _beta_ · since 2026-05-07 — Wave U — `WaveSChatFoldersStep` adapter that exposes the Wave S migration as a `memory_migration::MigrationStep` so the generic framework can drive it alongside future wave migrations.  
  *openalice_core::storage::chat_folders_migration:0*
- **`chat_folders.schema_version`** · _beta_ · since 2026-05-07 — Wave S — schema.json version stamp at ~/.openalice/data/{agent}/chat/{scope}/schema.json. Migration runner reads this to decide whether to re-run; absent => pre-S layout.  
  *openalice_core::storage::chat_folders:0*
- **`chat_folders.traces`** · _beta_ · since 2026-05-07 — Wave V — traces_dir() + tool_calls_jsonl() path helpers. Append-only tool-call memory log lives at ~/.openalice/data/{agent}/chat/{scope}/traces/tool-calls.jsonl. Per-chat scope, never crossed for privacy.  
  *openalice_core::storage::chat_folders:0*
- **`core.budget`** · _stable_ · since 0.1.0 — 7-dimension budget tracker — tokens, cost, iterations, wall time, tool calls, bytes, requests. Thresholds + warn/block hooks plumbed into the event bus.  
  *openalice_core::runtime::budget:0*
- **`core.context_budget.goal_preserve`** · _experimental_ · since 2026-07-02 — OPT-IN goal-preserving compaction (OPENALICE_GOAL_PRESERVE, 2026-07-02): when the context budget compacts, the ORIGINAL task (first user message) is re-pinned right after the system message so the goal survives. Closes the naive recency-drop gap where compaction silently discards the original request — the 4-team convergent `/goal` pattern. Default off → recency-only compaction byte-identical.  
  *openalice_core::runtime::context_budget:0*
- **`core.context_budget.smart_compact`** · _experimental_ · since 2026-07-02 — OPT-IN agent-authored smart-compaction (OPENALICE_SMART_COMPACT, 2026-07-02): sets the CompactionEngine's summarize_dropped mode so the messages about to be dropped are folded into an LLM summary (authored by the agents-loop via the Summarizer seam) instead of silently discarded. Default off → the engine keeps the plain recency notice (byte-identical). Fail-open: no summarizer / summary error → plain notice.  
  *openalice_core::runtime::context_budget:0*
- **`core.embedding`** · _stable_ · since 0.1.0 — Embedding service for Memory Engine v2 — configurable provider (OpenAlice ML gateway BGE-M3 1024-dim or off); keyed by text hash to reuse rerank cache entries.  
  *openalice_core::memory::embedding:0*
- **`core.hnsw`** · _stable_ · since 0.1.0 — f32 HNSW index — O(log(n)·d) approximate nearest neighbour search backing memory preload, tool index, and the rerank cache.  
  *openalice_core::memory::hnsw:0*
- **`core.kernel`** · _stable_ · since 0.1.0 — Kernel — composes budget, config, events, identity, merkle audit, gate pipeline, and policy engine into the OpenAlice runtime core.  
  *openalice_core::kernel:0*
- **`core.pipeline`** · _stable_ · since 0.1.0 — 6-anchor gate pipeline with 2 plugin slots — pre-context, context, pre-plan, plan, pre-act, act phases with ordered gate execution and shared gate state.  
  *openalice_core::runtime::pipeline:0*
- **`core.policy`** · _stable_ · since 0.1.0 — Default-deny policy engine — pattern-based path + tool rules keyed on agent id with explicit effect (allow/deny).  
  *openalice_core::security::policy:0*
- **`core.runtime.live_config_bridge`** · _beta_ · since 2026-07-08 — Caps-migration Phase 2 — the unified-config ConfigHandle is installed into core at boot (it used to be dropped), and the zero-arg flag helpers (goal_preserve/smart_compact/stuck_fuzzy) read the live snapshot when installed: oa.yaml edits hot-reload these caps without a restart. Uninstalled processes (alice-cli, unit tests) keep the legacy direct-env reads — byte-identical.  
  *openalice_core::runtime::live_config:0*
- **`core.runtime.live_config_bridge.phase3_legacy_caps`** · _beta_ · since 2026-07-08 — Caps-migration Phase 3 (adoption-ladder rung 3) — the 7 original Phase 9a caps now read this SAME live-config bridge first, falling back to their legacy direct-env read when uninstalled: openalice_agents_image_gen::feature_flag_enabled (caps.image_gen.enabled), openalice_router (private codex::image_gen_feature_flag_enabled duplicate, kept in sync — caps.image_gen.enabled), openalice_agents_soul::goal_engine::autonomy_enabled (caps.goal_autonomy.enabled), openalice_agents_memory::skills::curator::curator_enabled (caps.skill_curator.enabled), openalice_alice_cli::agent::kanban::is_kanban_enabled (caps.agent_kanban.enabled), openalice_agents::agentic_resume::is_enabled (caps.durable_exec.enabled), openalice_coalesce (private config::strict_dedup, surfaced via pub is_strict_dedup_enabled — caps.coalesce.strict_dedup), openalice_agents_memory::memory_preload (private read_char_whitelist_floor — caps.memory.char_whitelist_size, u32→usize cast). Three scalar knobs were documented OUT of scope here and closed 2026-07-09 (tail-close wave): openalice_agents_memory::skills::curator::cadence_hours (caps.skill_curator.hours, u32→u64 cast, `< 1` floor preserved), openalice_agents::agentic_resume::ResumeBudget::new (caps.durable_exec.max_resumes, u32→u8 clamp), and coalesce's private config::strict_dedup window_ms (caps.coalesce.strict_dedup_window_ms, `0` ⇒ `None` ⇒ platform default, same as the pre-existing enabled/window_ms split).  
  *openalice_core::runtime::live_config:0*
- **`core.scheduler`** · _stable_ · since 0.1.0 — Combined agent/task/calendar scheduler — tracks plans, plan progress, calendar events; the backbone for mission + hand orchestration.  
  *openalice_core::scheduler:0*
- **`core.session`** · _stable_ · since 0.1.0 — Session management — TTL, absolute max lifetime, per-user limits, MFA-aware expiry for authenticated users.  
  *openalice_core::security::session:0*
- **`core.validators.skill_name`** · _beta_ · since 2026-05-07 — Phase 8Y-T0 — single `validate_skill_name` shared by every skill-touching crate (agents-tools, agents-memory, modules-intelligence, alice-cli). Returns identical human-friendly errors with kebab-case suggestions so the LLM self-corrects the same way no matter which code path dispatched the tool.  
  *openalice_core::security::validators::skill:0*
- **`dataflow.turn_feedback`** · _experimental_ · since 2026-07-08 — TurnFeedback state machine + FeedbackRenderer trait — one seen→answered/failed ack registry connectors render (e.g. 👀 on inbound, cleared exactly once at the turn's terminal state). Pure + platform-less; per-connector renderers live in modules-connectors. Replaces ~7 scattered per-path bookkeeping sites that let mid-turn steers leak a stale 👀 forever.  
  *openalice_core::dataflow::feedback:0*
- **`dataflow.turn_feedback.working_long`** · _experimental_ · since 2026-07-10 — WORKING_LONG progress tier (2026-07-10, docs/design/turn-feedback-state-machine-2026-07-08.md "Future" section) — an optional escalation on TurnFeedback for long-running turns: once a turn's elapsed time crosses caps.feedback.working_long_secs (default 0 = off; env back-compat OPENALICE_WORKING_LONG_SECS), the connector renderer sends ONE progress-artifact message (FeedbackRenderer::working_long_start), edits it at most every 30s with elapsed time (working_long_tick), and deletes it the INSTANT the turn reaches ANSWERED/FAILED (working_long_clear, driven synchronously from TurnFeedback::finish — never a delayed poll). Default no-op trait methods keep every existing FeedbackRenderer (NoopRenderer, DiscordFeedback, external test mocks) byte-identical without touching them — only TelegramFeedback overrides the three methods for v1 (Discord parity deferred). The pure escalation decision (TurnFeedback::poll_working_long) is driven by an async watcher spawned alongside the existing typing-heartbeat loop (connector_bridge::stages::typing_loop), sharing its typing_cancel flag — the heartbeat's own spawn block is untouched.  
  *openalice_core::dataflow::feedback:0*
- **`migration.dry_run`** · _beta_ · since 2026-05-07 — Wave U — `MigrationCtx::dry_run` flag flips the framework into a planner that returns plans without touching disk; per-step env flags (e.g. OPENALICE_CHAT_FOLDERS_MIGRATION_DRY_RUN) still honoured for back-compat.  
  *openalice_core::storage::memory_migration:0*
- **`migration.framework`** · _beta_ · since 2026-05-07 — Wave U — generic memory migration framework. Versioned, idempotent, dry-run-able, rollback-able driver. Steps implement MigrationStep (detect/plan/apply/verify/rollback); the framework handles snapshot (cp -al), global audit (_migrations.jsonl), and re-run safety.  
  *openalice_core::storage::memory_migration:0*
- **`migration.global_log`** · _beta_ · since 2026-05-07 — Wave U — every apply() appends one JSONL row to ~/.openalice/data/_migrations.jsonl (ts, step_id, namespace, from→to, items, errors, dry_run).  
  *openalice_core::storage::memory_migration:0*
- **`migration.rollback`** · _beta_ · since 2026-05-07 — Wave U — `MigrationFramework::rollback_to(namespace, version)` walks steps in reverse and invokes `MigrationStep::rollback`. Default impl restores the cp -al snapshot dir wholesale.  
  *openalice_core::storage::memory_migration:0*
- **`migration.step_trait`** · _beta_ · since 2026-05-07 — Wave U — `MigrationStep` trait every memory-namespace migration implements (id/from_version/to_version/namespace + lifecycle hooks).  
  *openalice_core::storage::memory_migration:0*
- **`speaker.continuity_tracker`** · _beta_ · since 2026-05-07 — Wave R3 — sliding-window (N=3) per-scope tracker of the most recent speaker turns. In-memory only (no persistence). Backs the `<speaker>` prompt-tag renderer + the Wave R2 steering classifier + the Wave R4 multi-speaker turn-bundle builder.  
  *openalice_core::runtime::speaker:0*
- **`speaker.metrics`** · _beta_ · since 2026-05-07 — Wave R3 — Prometheus counters `oa_speaker_resolved_total{source=dossier|platform_fallback|unknown}` and `oa_speaker_continuity_total{result=same|switch}`. Cardinality-bounded: three + two label values total.  
  *openalice_core::runtime::speaker:0*
- **`storage_v2.crate`** · _experimental_ · since 2026-05-21 — Phase 8storage-B file-first storage compat-shim. Dormant in B-1 (no caller wires it yet) — mirrors `agents-refs` + `core::dossier` + `connector_history/` + `memory/relations/` reads against the new `identities/` + `sessions/` + `identities/_graph/` layout. Phase B-2 gates ~18 audited read-sites on `OPENALICE_STORAGE_LAYOUT=v2`.  
  *openalice_storage_v2:0*
- **`storage_v2.wire.edges`** · _experimental_ · since 2026-05-21 — Phase 8storage-B2-1 read-site wire-up. Routes memory_relations::{find_relations, find_connected_entities, count_relations, all_relations} and /v1/knowledge/graph edge enumeration through openalice_storage_v2::edges when OPENALICE_STORAGE_LAYOUT=v2. Status quo preserved when flag unset / != "v2".  
  *openalice_agents_memory::storage_v2_wire:0*
- **`storage_v2.wire.identities`** · _experimental_ · since 2026-05-21 — Phase 8storage-B2-2 read-site wire-up. Routes RefsStore::{get, list_all, list_kind} + resolve_ref through openalice_storage_v2::identities when OPENALICE_STORAGE_LAYOUT=v2. Status quo preserved when flag unset / != "v2".  
  *openalice_agents_refs::storage_v2_wire:0*
- **`store.factory`** · _stable_ · since 0.1.0 — Pluggable storage backends (FS / SQLite / Postgres) behind `Store` trait — hot-swap via config, per-backend migrations, export + factory entry points.  
  *openalice_store:0*
- **`store.impls.fs`** · _stable_ · since 0.1.0 — Filesystem `StorageProvider` impl — atomic temp+rename writes, fsync durability, hierarchical keys with `_doc` sentinel, fsnotify-based watch. Production default.  
  *openalice_store::fs:0*
- **`store.impls.in_memory`** · _stable_ · since 0.1.0 — In-memory `StorageProvider` impl backed by `HashMap` behind `tokio::sync::RwLock`. Zero-disk, deterministic, ideal for unit tests and ephemeral caches.  
  *openalice_store::mem:0*
- **`store.impls.postgres`** · _stable_ · since 0.1.0 — PostgreSQL `StorageProvider` impl — async sqlx pool, configurable connection settings, TIMESTAMPTZ-based polling watch. Behind cargo feature `store-postgres`.  
  *openalice_store::postgres:0*
- **`store.impls.s3`** · _experimental_ · since 0.1.0 — S3 `StorageProvider` impl — `aws-sdk-s3` backed, compatible with AWS S3 / MinIO / R2 / B2 / Wasabi / SeaweedFS via `S3StoreConfig::endpoint_url`. Behind cargo feature `s3` (default off).  
  *openalice_store::s3:0*
- **`store.impls.s3.real`** · _experimental_ · since 0.1.0 — S3 `StorageProvider` real client wiring (Track F6) — get/put/delete/list paginated, exists via HeadObject, 404 → Ok(None)/Ok(false). Tested against MinIO. Cargo feature `s3`.  
  *openalice_store::s3:0*
- **`store.impls.sqlite`** · _stable_ · since 0.1.0 — SQLite `StorageProvider` impl — async sqlx pool, WAL mode, forward-only schema migrations, polling watch. Behind cargo feature `store-sqlite`.  
  *openalice_store::sqlite:0*
- **`store.trait.storage_provider`** · _stable_ · since 0.1.0 — `StorageProvider` public alias for the kernel `Store` trait — lets callers accept `Arc<dyn StorageProvider>` and swap the backend at boot without touching a single call site.  
  *openalice_store:0*

### dataflow
- **`dataflow.loop_injector`** · _stable_ · since 2026-07-02 — The LoopInjector contract + InjectorRegistry — one uniform seam through which every source (connector / calendar / memory / webhook / sub-agent / WASM pack) feeds the agentic loop. Typed + immutable injections, fail-open polling, explicit per-seam ordering. Default-ON 2026-07-08 after the P0 hardening wave: apply_injections now returns the folded UserMessage count (fixes turn_pipeline's IterationHeadStage hard-coding injected=0, which had silently disabled the Phase-8OOO stale-CoalesceRestart swallow and risked reproducing the 2026-05-19 silent-drop incident); Scheduler::list_events now honors CalendarEventFilter.agent_id and excludes terminal-status events (was leaking every agent's calendar into every conversation); the CalendarInjector is now a shared process-wide singleton behind per-agent opt-in (injectors.calendar, default off) instead of a fresh instance per turn (was resetting its notice-dedup set every turn — infinite re-notify). RETIRED 2026-07-09 (adoption-ladder end state, same-day precedent as turn_pipeline::turn_pipeline_enabled): the OPENALICE_LOOP_INJECTORS kill-switch is gone and every call-site is unconditional — the injector path is simply how the loop works now.  
  *openalice_core::dataflow::injector:0*

### ecs
- **`ecs.component`** · _experimental_ · since 2026-07-03 — The Component trait — one uniform seam for the framework's composable data blocks (AgentConfig blocks, injectors, tools). Enables uniform introspection + a single ECS vocabulary across crates, without a type-erased World.  
  *openalice_core::ecs:0*

### federation
- **`federation.sync`** · _beta_ · since 0.1.0 — Event replication between federated peers — dedup + vclock merge on inbound, LWW for memory entries; pluggable `SyncTransport`.  
  *openalice_modules::federation::sync:0*

### hands
- **`hands.worker_manager`** · _stable_ · since 0.1.0 — Autonomous workers framework — cron-scheduled agents (research, digest, monitor, …) that tick independently of user prompts, managed by `WorkerManager`.  
  *openalice_modules::hands:0*

### hands/workers
- **`hands.workers.pre_flight`** — Pre-flight handlers -- pure-Rust health checks that run before the LLM agentic loop. Used to skip expensive LLM calls when a cheap check already determines the state. Phase 3 cost optimization (2026-05-24): Sentinel infra-monitor was burning high token volume to confirm "healthy" most of the time. Pre-flight reduces that to LLM calls only on real anomalies.  
  *crates/modules-hands/src/hands/pre_flight.rs:1*

### intelligence
- **`intelligence.browser`** · _stable_ · since 0.1.0 — Native CDP browser automation — direct WebSocket to a headless Chromium, no Playwright/Node dep. SSRF check, text-length cap, per-process cleanup, 30s load / 10s eval timeouts.  
  *openalice_modules::intelligence::browser:0*
- **`intelligence.browser_rules`** · _stable_ · since 0.1.0 — Three-level self-improving rules engine for cookie/banner dismissal (EasyList CSS → text pattern click → LLM DOM fallback), results persisted so next visit is free.  
  *openalice_modules::intelligence::browser_rules:0*
- **`intelligence.knowledge_graph`** · _stable_ · since 0.1.0 — Knowledge graph — entity/relation extractor, in-memory graph, JSON persistence, Obsidian exporter, Memgraph backend option.  
  *openalice_modules::intelligence::knowledge:0*
- **`intelligence.rag`** · _stable_ · since 0.1.0 — RAG pipeline — hybrid keyword + vector retrieval, multimodal chunking, router for source selection; foundation for grounded answers.  
  *openalice_modules::intelligence::rag:0*
- **`intelligence.web_search`** · _stable_ · since 0.1.0 — Cascading web search — Direct APIs (wttr, Wikipedia) → DuckDuckGo HTML → agent-browser. Provider-aware with rate limiting and URL decoding.  
  *openalice_modules::intelligence::web_search:0*

### lsp
- **`lsp.diagnostics_cache`** · _stable_ · since 0.1.0 — Live diagnostics store — subscribes once to LSP `textDocument/publishDiagnostics` notifications and serves synchronous lookups by URI, mirroring editor-style caching.  
  *openalice_lsp::diagnostics:0*
- **`lsp.multi_lang_registry`** · _stable_ · since 0.1.0 — Multi-language LSP session registry — file extension → server mapping, one session per (language, workspace), lazy startup. Ships Rust, Python, TypeScript, JavaScript bindings.  
  *openalice_lsp::registry:0*
- **`lsp.rust_analyzer_client`** · _stable_ · since 0.1.0 — High-level rust-analyzer client — typed methods (hover_at, definition_at, references_at, document_symbols, workspace_symbols) over JSON-RPC with lifecycle + didOpen management.  
  *openalice_lsp::rust:0*

### memory
- **`agents.memory.ab_benchmark`** · _experimental_ · since 2026-04-25 — Memory v4 A/B benchmark — env-gated baseline switches (ALICE_MEMORY_BASELINE_V3 / ALICE_MEMORY_DISABLE_M3 / _M4 / _M5) that flip M3 mode-classification, M4 history-search, and M5 intent-aware boosts off so a benchmark can compare v3 vs v4 retrieval inside one process. Default off — production path unchanged. See benches/memory_v4_ab.rs.  
  *openalice_agents::memory_preload:0*
- **`agents.memory.bench.history_search`** · _experimental_ · since 2026-04-25 — Wave G6 — criterion benchmark for `memory_preload::history_search::lexical_rank` (BM25-lite). Measures small (50-turn / 5-token) and large (500-turn / 30-token) cases. Audit gap: claim was sub-ms at 500 turns, this bench is the first measurement.  
  *openalice_agents_memory::benches::history_search_perf:0*
- **`agents.memory.bench.live_embeddings`** · _experimental_ · since 2026-04-26 — Memory v4 G8 — Wave G8 A/B harness wires a real EmbeddingService (provider=`bench`, deterministic n-gram embedder in openalice-core) so the benchmark exercises the HNSW vector channel hermetically without an ML gateway dependency. See benches/memory_v4_ab.rs and crates/core/src/embedding.rs.  
  *openalice_agents::memory_preload:0*
- **`agents.memory.bench.preload`** · _experimental_ · since 2026-04-25 — Wave G6 — criterion benchmark for `memory_preload::preload_memory_context` end-to-end. Small (5 cards / 50 turns) and large (30 cards / 500 turns / M3+M4+M5 engaged) cases. Audit gap: claim was sub-10ms — first measurement.  
  *openalice_agents_memory::benches::memory_preload_perf:0*
- **`agents.memory.budget.compact_mode`** · _experimental_ · since 2026-04-26 — Memory v4 G8 tuning — opt-in `compact_budget_for` allocator that shrinks rerank pool ~30 % and clamps Active Characters to 3. Toggled via ALICE_MEMORY_COMPACT_MODE; default off so production budget remains unchanged.  
  *openalice_agents::memory_preload::budget:0*
- **`agents.memory.budget.quality_threshold`** · _experimental_ · since 2026-04-26 — Memory v4 G8 tuning — drop scored candidates below ALICE_MEMORY_QUALITY_THRESHOLD (default 0.0 = no-op). Trims the cold-tier noise tail so Precision@10 stops bleeding under v4-full.  
  *openalice_agents::memory_preload:0*
- **`agents.memory.decay`** · _experimental_ · since 2026-04-25 — Memory v4 M5 — importance auto-decay. Half-life-based decay on MemoryUnit.importance (default 14 days) with a permanent floor (1.0) so units never disappear, just deprioritise. Correction-flagged units decay 4x faster.  
  *openalice_agents::memory_preload::decay:0*
- **`agents.memory.decay.archive`** · _beta_ · since 2026-05-07 — Wave Q5 — archive layout: `dossiers/{type}/_archive/{YYYY-MM-DDTHH-MM}/{slug}.md`. Survives `gather_candidates` filtering (Q4 `_archive/` skip rule) yet remains greppable on disk. Curator `archive_resurrect` path can re-load any archived dossier whose slug is explicitly pinned.  
  *openalice_agents_memory::decay::job:0*
- **`agents.memory.decay.audit.archive`** · _beta_ · since 2026-05-07 — Wave Q5 — append `actor=decay, action=archive` row to `_audit.jsonl` after every decay rename. Carries slug, reason ('60d_no_access' default), source path, and destination path.  
  *openalice_agents_memory::decay::audit:0*
- **`agents.memory.decay.job.archive_window`** · _beta_ · since 2026-05-07 — Wave Q5 — default archive_after_days = 60 (matches `feedback-memory-archive-not-delete-2026-05-02`). Configurable per invocation; production cron is expected to keep the default.  
  *openalice_agents_memory::decay::job:0*
- **`agents.memory.decay.job.dry_run`** · _beta_ · since 2026-05-07 — Wave Q5 — `cfg.dry_run = true` produces a DecayReport listing the slugs that *would* be archived without touching the disk or appending audit rows. Surfaced via `alice-cli memory decay run --dry-run`.  
  *openalice_agents_memory::decay::job:0*
- **`agents.memory.decay.job.run`** · _beta_ · since 2026-05-07 — Wave Q5 — `run_decay(agent, scope, cfg)`: walks dossiers, archives any whose freshness age exceeds cfg.archive_after_days. Atomic per-file rename via std::fs::rename inside the lockfile guard. Returns a DecayReport with per-slug outcomes.  
  *openalice_agents_memory::decay::job:0*
- **`agents.memory.decay.lockfile`** · _beta_ · since 2026-05-07 — Wave Q5 — fs4 advisory exclusive lock on `dossiers/_decay.lock`. Prevents two concurrent decay sweeps from racing on the same (agent, scope). Independent of Scribe lockfile — a Scribe run and a decay sweep are allowed to interleave (atomic renames keep the tree consistent).  
  *openalice_agents_memory::decay::lockfile:0*
- **`agents.memory.decay.lockfile.acquire`** · _beta_ · since 2026-05-07 — Wave Q5 — `acquire_decay_lock` opens (creating if needed) the per-(agent, scope) `dossiers/_decay.lock` and takes an exclusive fs4 advisory lock. RAII via `DecayLockGuard`: lock released on drop.  
  *openalice_agents_memory::decay::lockfile:0*
- **`agents.memory.decay.run`** · _beta_ · since 2026-05-07 — Wave Q5 — `run_decay(agent, scope, cfg)` scans dossiers and archive-moves any whose last_accessed_at (fallback updated_at) is older than archive_after_days (default 60). Atomic per-file rename to `_archive/{ts}/{slug}.md`; no hard deletes. Best-effort per file — partial failures don't abort the sweep.  
  *openalice_agents_memory::decay::job:0*
- **`agents.memory.decay.status`** · _beta_ · since 2026-05-07 — Wave Q5 — `decay_status(agent, scope)` walks `_archive/` and returns counts of archived dossiers in the trailing 30d, 90d and all-time. Surfaced via `alice-cli memory decay status`.  
  *openalice_agents_memory::decay::status:0*
- **`agents.memory.decay.status.scan`** · _beta_ · since 2026-05-07 — Wave Q5 — `decay_status(agent, scope)` walks `_archive/` and returns counts of archive folders in trailing 30d/90d/all-time, plus the list of distinct archive batch timestamps. Read-only; safe to call without the decay lock.  
  *openalice_agents_memory::decay::status:0*
- **`agents.memory_dedup`** · _stable_ · since 0.1.0 — Memory Engine v2 — three-step write pipeline (hash dedup → semantic dedup > 0.85 → bi-temporal contradiction resolution) inspired by Graphiti + Mem0.  
  *openalice_agents::memory_dedup:0*
- **`agents.memory.history_search.fts5`** · _experimental_ · since 2026-04-25 — Memory v4 M4 — opt-in FTS5 lexical fast-path. Currently a no-op shim because the Store trait is kv-only; the lexical layer falls back to in-Rust BM25 over the JSON-encoded history. Schema + FtsMessageIndex extension trait will land in M4.1.  
  *openalice_agents::memory_preload::history_search:0*
- **`agents.memory.history_search.lexical`** · _experimental_ · since 2026-04-25 — Memory v4 M4 — pure-Rust BM25-lite ranker over per-chat connector_history. Surfaces older turns lexically matching the user query without requiring an embedder. Sub-ms at 500 turns.  
  *openalice_agents::memory_preload::history_search:0*
- **`agents.memory.history_search.merge`** · _experimental_ · since 2026-04-25 — Memory v4 M4 — score-normalised, dedup-by-message-id merge of lexical + semantic hits. Tags each survivor with HitSource {Lexical|Semantic|Both}.  
  *openalice_agents::memory_preload::history_search:0*
- **`agents.memory.history_search.prompt_slot`** · _experimental_ · since 2026-04-25 — Memory v4 M4 — `## Relevant past discussion (history search)` prompt slot. Gated by ModeBudget::history_search_slot; widens Coding / Research / Personal / Roleplay chats with full-history callbacks.  
  *openalice_agents::memory_preload::history_search:0*
- **`agents.memory.history_search.semantic`** · _experimental_ · since 2026-04-25 — Memory v4 M4 — cosine-similarity ranker over cached per-turn embeddings at connector_history/{conv_id}/embeddings.json. Cache-on-write, sliding-window for chats > 100 turns.  
  *openalice_agents::memory_preload::history_search:0*
- **`agents.memory.intent_classifier`** · _experimental_ · since 2026-04-25 — Memory v4 M5 — heuristic intent classifier (Question / Recall / Correction / NewFact / Emotion / TaskRequest / Smalltalk / Other). Cheap regex-only path, runs every turn. The classification is written *inline* on `Message::intent` (single source of truth in connector_history) and consumed by the scorer + reinforcement engine. The proxy boundary strips it before any LLM ever sees it.  
  *openalice_agents::memory_preload::intent:0*
- **`agents.memory.reflection.audit.apply`** · _beta_ · since 2026-05-07 — Wave Q7 — append `actor=reflection, action=...` row to `_audit.jsonl` for every auto-applied proposal (archive_stale, backlink_cleanup, index_refresh) and for every gated proposal enqueued for NAO approval. Carries the run_id so operators can group + replay.  
  *openalice_agents_memory::reflection::audit:0*
- **`agents.memory.reflection.detect.emerging`** · _beta_ · since 2026-05-07 — Wave Q7 — `detect_emerging_clusters` flags observation references to entity slugs that appear ≥ 3 times across `observations/` JSON but have no dossier on disk. Risk Medium → Gated.  
  *openalice_agents_memory::reflection::detectors:0*
- **`agents.memory.reflection.detect.merge`** · _beta_ · since 2026-05-07 — Wave Q7 — `detect_mergeable_pairs` flags two dossiers as candidates for merge when their alias sets share ≥ 2 entries OR their slug basenames are sub-string matches (e.g. `person/nao` vs `person/bassel-nao`). Risk Medium → Gated. Never auto-applied — operator approves in the CLI.  
  *openalice_agents_memory::reflection::detectors:0*
- **`agents.memory.reflection.detect.stale`** · _beta_ · since 2026-05-07 — Wave Q7 — `detect_stale` flags dossiers whose freshness age exceeds `stale_after_days` (default 30) AND importance < 0.9. Risk Low → Auto. Cross-validates the Q5 decay sweep; intentional overlap so an operator-skipped decay run is still caught.  
  *openalice_agents_memory::reflection::detectors:0*
- **`agents.memory.reflection.detect.tool_trace_concepts`** · _beta_ · since 2026-05-07 — Wave V → Q7 — scan tool-calls.jsonl, find recurring lesson patterns (same lesson text 3+ times across ≥ 2 distinct days). Emit one `EmergingCluster` proposal per pattern with a suggested concept slug. Risk Medium → Gated — NAO approves dossier creation in the CLI.  
  *openalice_agents_memory::reflection::detectors:0*
- **`agents.memory.reflection.llm.budget`** · _beta_ · since 2026-05-07 — Wave Q7 — `TokenBudget` enforces `OPENALICE_REFLECTION_MAX_TOKENS_PER_RUN` (default 20000) via pre-check + post-debit. Hitting the cap emits the `oa_reflection_budget_exceeded_total` Prometheus counter and aborts the run cleanly with a partial report.  
  *openalice_agents_memory::reflection::llm:0*
- **`agents.memory.reflection.llm.trait`** · _beta_ · since 2026-05-07 — Wave Q7 — `ReflectionLlm` trait abstracts the router/codex call surface so the reflection runner is testable without a live endpoint. Default model `gpt-5.4-mini` (fallback `gpt-5.4`). Production wiring injects a thin sync adapter over the existing `LlmProvider`.  
  *openalice_agents_memory::reflection::llm:0*
- **`agents.memory.reflection.lockfile.acquire`** · _beta_ · since 2026-05-07 — Wave Q7 — `acquire_reflection_lock` opens (creating if needed) the per-(agent, scope) `dossiers/_reflection.lock` and takes an exclusive fs4 advisory lock. RAII via `ReflectionLockGuard`: lock released on drop.  
  *openalice_agents_memory::reflection::lockfile:0*
- **`agents.memory.reflection.metrics.budget`** · _beta_ · since 2026-05-07 — Wave Q7 — Prometheus counter `oa_reflection_budget_exceeded_total`. Emitted once per reflection run whose accumulated tokens would cross `OPENALICE_REFLECTION_MAX_TOKENS_PER_RUN`. The run aborts cleanly after emission and writes a partial report.  
  *openalice_agents_memory::reflection::metrics:0*
- **`agents.memory.reflection.metrics.proposals`** · _beta_ · since 2026-05-07 — Wave Q7 — Prometheus counter `oa_reflection_proposals_total{kind, applied}`. `kind` ∈ {stale, merge, emerging_cluster, contradiction, backlink_cleanup, index_refresh}. `applied` ∈ {auto, queued, rejected, dry_run}.  
  *openalice_agents_memory::reflection::metrics:0*
- **`agents.memory.reflection.metrics.runs`** · _beta_ · since 2026-05-07 — Phase 8BB-1 — Prometheus counter `oa_reflection_runs_total{outcome}`. One bump per `run_reflection` completion. `outcome` ∈ {completed, budget_exceeded, skipped_locked, dry_run}. Pre-8BB-1 the runner reported its outcome on the JSON response only — `/metrics` had no aggregate view of how many runs finished and in which state.  
  *openalice_agents_memory::reflection::metrics:0*
- **`agents.memory.reflection.metrics.tokens`** · _beta_ · since 2026-05-07 — Wave Q7 — Prometheus counter `oa_reflection_tokens_used_total`. Bumped after every successful reflection LLM call.  
  *openalice_agents_memory::reflection::metrics:0*
- **`agents.memory.reflection.module`** · _beta_ · since 2026-05-07 — Wave Q7 — reflection submodule root. Coordinates sampler + detectors + LLM cross-check + auto-apply + queue + audit + markdown report. Lock + budget + archive-not-delete safety rails live inside; see module docs.  
  *openalice_agents_memory::reflection:0*
- **`agents.memory.reflection.proposals.risk`** · _beta_ · since 2026-05-07 — Wave Q7 — risk classification (Low / Medium / High). Only Low auto-applies. Permanent deletes are always Gated regardless of classifier verdict, per `feedback-memory-archive-not-delete-2026-05-02`.  
  *openalice_agents_memory::reflection::proposals:0*
- **`agents.memory.reflection.proposals.types`** · _beta_ · since 2026-05-07 — Wave Q7 — `Proposal` shape: kind ∈ {Stale, Merge, EmergingCluster, Contradiction}, target slugs, reason, suggested action, risk, disposition (Auto | Gated). Stable proposal id is sha256 over (run_id, kind, sorted targets) so CLI approve/reject is idempotent.  
  *openalice_agents_memory::reflection::proposals:0*
- **`agents.memory.reflection.queue.append`** · _beta_ · since 2026-05-07 — Wave Q7 — append a Proposal as a JSON line to `reflection/_pending/{kind}.jsonl`. Used by the runner for any proposal whose disposition is Gated.  
  *openalice_agents_memory::reflection::queue:0*
- **`agents.memory.reflection.queue.list`** · _beta_ · since 2026-05-07 — Wave Q7 — read all pending Proposals of a kind from the queue. Used by `alice-cli memory reflect list` and `alice-cli memory reflect status`.  
  *openalice_agents_memory::reflection::queue:0*
- **`agents.memory.reflection.queue.take`** · _beta_ · since 2026-05-07 — Wave Q7 — `take_by_id` removes one Proposal from the queue atomically (read all → filter → tmp + rename). Used by `alice-cli memory reflect approve|reject <id>`.  
  *openalice_agents_memory::reflection::queue:0*
- **`agents.memory.reflection.report.render`** · _beta_ · since 2026-05-07 — Wave Q7 — `render_report` returns the markdown body for one reflection run, grouped by proposal kind with auto vs gated clearly tagged. Used by both the writer and by tests.  
  *openalice_agents_memory::reflection::report:0*
- **`agents.memory.reflection.report.write`** · _beta_ · since 2026-05-07 — Wave Q7 — `write_report` persists the markdown to `reflection/{run_ts}.md` atomically. Directories are created on demand.  
  *openalice_agents_memory::reflection::report:0*
- **`agents.memory.reflection.runner.auto_apply`** · _beta_ · since 2026-05-07 — Wave Q7 — auto-apply path: low-risk proposals only (Stale archives + backlink cleanup + MEMORY-INDEX refresh). Hard delete is NEVER auto- applied. Calls into Q5's `archive_stale_dossier` so the rename-not- delete invariant holds in one place.  
  *openalice_agents_memory::reflection::runner:0*
- **`agents.memory.reflection.runner.gate`** · _beta_ · since 2026-05-07 — Wave Q7 — gated path: medium/high-risk proposals (Merge, EmergingCluster, Contradiction) write to `reflection/_pending/<kind>.jsonl`. Operator approves or rejects via `alice-cli memory reflect approve|reject <id>`.  
  *openalice_agents_memory::reflection::runner:0*
- **`agents.memory.reflection.runner.run`** · _beta_ · since 2026-05-07 — Wave Q7 — `run_reflection` is the single entrypoint that ties sampler, heuristic detectors, the budget-capped LLM cross-check, auto-apply, pending-queue enqueue, audit append, and the per-run markdown report. Goes through the `_reflection.lock` fs4 advisory lock; second concurrent run returns SkippedLocked.  
  *openalice_agents_memory::reflection::runner:0*
- **`agents.memory.reflection.runner.skill_pass`** · _beta_ · since 2026-05-07 — Wave Q7 — optional skill-library reflection pass (Voyager). Gated behind `OPENALICE_REFLECTION_INCLUDE_SKILLS=true` (default false). Walks `chat/{scope}/skills/*.md`; emits one informational EmergingCluster proposal per skill unused in 60+ d. Wave P owns the deeper skill refactor logic — Q7 is the visibility layer.  
  *openalice_agents_memory::reflection::runner:0*
- **`agents.memory.reflection.sampler.scan`** · _beta_ · since 2026-05-07 — Wave Q7 — `scan` walks `dossiers/{type}/*.md` (skipping `_archive/` and `MEMORY-INDEX.md`), parses each via `Dossier::parse_markdown`, and returns a `Vec<SampledDossier>` carrying the parsed dossier, its full on-disk path, the computed weight and the age in days.  
  *openalice_agents_memory::reflection::sampler:0*
- **`agents.memory.reflection.sampler.weight`** · _beta_ · since 2026-05-07 — Wave Q7 — `compute_weight` = 0.5 * importance + 0.5 * exp(-Δdays/14). Δdays is age since `last_accessed_at` (fallback `updated_at`). The constant matches the curator's β-axis.  
  *openalice_agents_memory::reflection::sampler:0*
- **`agents.memory.reinforcement`** · _experimental_ · since 2026-04-25 — Memory v4 M5 — intent-aware importance reinforcement. Each retrieved unit gets an importance bump scaled by the user-turn intent (Recall largest, Smalltalk smallest). Cooldown 30 min, write-through every 10 bumps + on flusher tick.  
  *openalice_agents::memory_preload::reinforce:0*
- **`agents.memory.scope_isolation_fix`** · _experimental_ · since 2026-04-26 — Wave G9 fix — `candidates::select_candidates` now applies `scope_retains` to vector-prefilter cold-keys before reinjecting them, closing a `MemoryScope::Isolated` bypass that leaked global `people/` and other globally-scoped units into per-chat Isolated rooms. Strictly tightening: Full / Curated scopes are unchanged.  
  *openalice_agents_memory::memory_preload::candidates:0*
- **`agents.memory.scribe.audit.promote`** · _beta_ · since 2026-05-07 — Wave Q3 — append `actor=scribe, action=promote` row to `_audit.jsonl` after every Scribe write. Carries slug, source observation ids, model, tokens, trigger and outcome for downstream replay + accountability.  
  *openalice_agents_memory::scribe::audit:0*
- **`agents.memory.scribe.caps.daily_tokens`** · _beta_ · since 2026-05-07 — Wave Q3 — sliding 24-hour cap on Scribe LLM tokens per agent. Default 100000. Env: OPENALICE_SCRIBE_MAX_TOKENS_PER_DAY. Cap-hit pauses Scribe for the agent until the window rolls; emits oa_scribe_paused_total{reason=daily_tokens}.  
  *openalice_agents_memory::scribe::caps:0*
- **`agents.memory.scribe.caps.hourly_calls`** · _beta_ · since 2026-05-07 — Wave Q3 — sliding 1-hour cap on Scribe LLM calls per agent. Default 10. Env: OPENALICE_SCRIBE_MAX_CALLS_PER_HOUR. Cap-hit pauses Scribe for the agent until the window rolls; emits oa_scribe_paused_total{reason=hourly_cap}.  
  *openalice_agents_memory::scribe::caps:0*
- **`agents.memory.scribe.caps.status`** · _beta_ · since 2026-05-07 — Wave Q3 — `ScribeStatus` snapshot exposed via `CostState::status_for` and `alice-cli memory scribe status`: last-run timestamp, hourly calls used, daily tokens used, current pause state.  
  *openalice_agents_memory::scribe::caps:0*
- **`agents.memory.scribe.conflict_cascade`** · _beta_ · since 2026-05-07 — Wave Q5 — once the contradiction journal hits CASCADE_THRESHOLD (default 3) entries, Scribe sets `t_invalid` on the old dossier and creates a successor dossier with `t_valid = latest contradiction timestamp` and `superseded_by` pointing back. The journal is truncated. Old dossier remains greppable on disk for as_of queries.  
  *openalice_agents_memory::scribe::conflict_tracker:0*
- **`agents.memory.scribe.conflict_invalidate_metric`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_contradiction_invalidate_total`. Bumped every time the Q5 cascade fires and `t_invalid` is set on the prior dossier (after CASCADE_THRESHOLD consistent contradictions). Always reaches `/metrics` via the observability exporter registry.  
  *openalice_agents_memory::scribe::conflict_tracker:0*
- **`agents.memory.scribe.conflict_tracker`** · _beta_ · since 2026-05-07 — Wave Q5 — per-dossier contradiction journal at `dossiers/{type}/{slug}.contradictions.jsonl`. Append-only; one row per Scribe-detected contradiction event with observation id, observed_at timestamp and explanation.  
  *openalice_agents_memory::scribe::conflict_tracker:0*
- **`agents.memory.scribe.dry_run`** · _beta_ · since 2026-05-07 — Wave Q3 — dry-run mode: produces a `PromotePlan` describing the would-be LLM call (model, prompt char count, target dossier path, source-hash) without invoking the LLM, writing the dossier or touching the audit log. Surfaced via `alice-cli memory scribe run --dry-run`.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.lockfile.acquire`** · _beta_ · since 2026-05-07 — Wave Q3 — `acquire_scribe_lock` opens (creating if needed) the per-(agent, scope) `dossiers/_scribe.lock` file and takes an exclusive fs4 advisory lock. RAII via `LockGuard`: lock released on drop.  
  *openalice_agents_memory::scribe::lockfile:0*
- **`agents.memory.scribe.lockfile.try`** · _beta_ · since 2026-05-07 — Wave Q3 — non-blocking `try_lock` semantics: returns `LockOutcome::Busy` when another Scribe run already holds the lock, instead of stalling. Caller can audit + skip cleanly.  
  *openalice_agents_memory::scribe::lockfile:0*
- **`agents.memory.scribe.metrics.calls`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_scribe_calls_total{outcome}` per master plan §12.1. Recorded once per `ScribeRunner::run` invocation with outcome label (`success` / `fail` / `budget_exceeded`). The SideEffectScorer in the lab harness asserts on this counter.  
  *openalice_agents_memory::scribe::metrics:0*
- **`agents.memory.scribe.metrics.paused`** · _beta_ · since 2026-05-07 — Wave Q3 — Prometheus counter `oa_scribe_paused_total{reason}`. Emitted by `CostState::check_and_reserve` when a cap is hit.  
  *openalice_agents_memory::scribe::metrics:0*
- **`agents.memory.scribe.metrics.runs`** · _beta_ · since 2026-05-07 — Wave Q3 — Prometheus counter `oa_scribe_runs_total{trigger, outcome}`. Recorded once per ScribeRunner::run call.  
  *openalice_agents_memory::scribe::metrics:0*
- **`agents.memory.scribe.metrics.tokens`** · _beta_ · since 2026-05-07 — Wave Q3 — Prometheus counter `oa_scribe_tokens_used_total{model}`. Updated after each Scribe LLM call.  
  *openalice_agents_memory::scribe::metrics:0*
- **`agents.memory.scribe.promote`** · _beta_ · since 2026-05-07 — Wave Q3 — promotion pipeline: render prompt from candidate observations + optional prior dossier, call gpt-5.4-mini (fallback gpt-5.4) via LlmCall, write dossier with `source_observations_hash` set, append `actor=scribe` row to `_audit.jsonl`.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.runner`** · _beta_ · since 2026-05-07 — Wave Q3 — Scribe runner orchestrates trigger detection, idempotency check, lock acquisition, LLM call, dossier write and audit append. Public entry point is `ScribeRunner::run` (per (agent, scope, slug)) plus `run_status`.  
  *openalice_agents_memory::scribe:0*
- **`agents.memory.scribe.trigger.cluster`** · _beta_ · since 2026-05-07 — Wave Q3 — embedding-cluster trigger: fires when ≥ CLUSTER_THRESHOLD_COUNT observations belong to the same cluster id reported by `ClusterApi::cluster_size`. The real bge-m3 + cluster-detection wiring is mocked at the trait boundary so the trigger is testable without an embedding service.  
  *openalice_agents_memory::scribe::triggers:0*
- **`agents.memory.scribe.trigger.importance`** · _beta_ · since 2026-05-07 — Wave Q3 — importance-signal trigger: fires the moment any candidate observation carries `important: true` (M5 intent classifier) OR the observation was emitted by the `memory_pin` tool (source contains `memory_pin`). Single-observation fire.  
  *openalice_agents_memory::scribe::triggers:0*
- **`agents.memory.scribe.trigger.mention`** · _beta_ · since 2026-05-07 — Wave Q3 — mention-threshold trigger: fires when an entity slug appears in ≥ MENTION_THRESHOLD_COUNT observations within MENTION_THRESHOLD_WINDOW (default 3 / 7 days, env-overridable).  
  *openalice_agents_memory::scribe::triggers:0*
- **`agents.memory.scribe.trigger.pin`** · _beta_ · since 2026-05-07 — Wave Q3 — explicit-user-pin trigger: fires when an observation carries `nli_pin = true` (set by the NLI detector for phrases like «запомни это про X» / «remember this about X»). Always fires immediately.  
  *openalice_agents_memory::scribe::triggers:0*
- **`agents.memory.scribe.trigger.post_action`** · _beta_ · since 2026-05-07 — Wave Q3 — post-action-reflection trigger: fires when a candidate observation has source = `task_execute:<task_id>` AND `outcome` field is set. Scribe writes an `event/<date>-<slug>.md` dossier.  
  *openalice_agents_memory::scribe::triggers:0*
- **`agents.memory.scribe.worker.conflict_pipeline`** · _beta_ · since 2026-05-07 — Wave Q5 — after a Scribe consolidation lands, `run_conflict_pipeline` scans the candidate observations for negation patterns that overlap with tokens in the prior dossier body. Each detected conflict appends a row to the contradiction journal and a marker to the dossier's `## Contradictions` section. After CASCADE_THRESHOLD (3) consistent events, the worker sets `t_invalid` on the old dossier and creates a successor dossier with `t_valid` + `superseded_by` populated.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.contradiction_linter_audit`** · _beta_ · since 2026-05-15 — Phase 8DDD-2 — `run_conflict_pipeline` now appends a canonical `{actor: "contradiction_linter", action: "invalidate", slug, t_invalid, events_total}` audit row when the cascade fires. The lab probe scorer (`memory-contradiction-cascade`) requires a STRICT actor/action match; the pre-8DDD-2 pipeline only wrote `actor=scribe, action=promote` rows, which the integration test allow-listed but the real probe rejected. Best-effort: failure is logged at debug level, never rolls back the cascade.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.explicit_correction_fast_cascade`** · _beta_ · since 2026-05-15 — Phase 8DDD-2 — when the candidate observations carry an EXPLICIT correction phrase («поправка», «correction:», «на самом деле», «I was wrong», «scratch that», …) the cascade fires once the journal holds at least one event, instead of waiting for the conservative CASCADE_THRESHOLD = 3 consensus rule. The `memory-contradiction-cascade` probe only sends two corrections after the initial fact, so the strict threshold rule never tripped under realistic probes. Backwards-compatible: paraphrased / accidental contradictions still honour the threshold.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.idempotency`** · _beta_ · since 2026-05-07 — Wave Q3 — Scribe idempotency rule: skip the LLM call when the prior dossier has a matching `source_observations_hash` AND its mtime is younger than DOSSIER_MTIME_FRESH_WINDOW (default 1 h). New observations or stale dossiers re-arm the call.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.llm_call_trait`** · _beta_ · since 2026-05-07 — Wave Q3 — `LlmCall` trait abstracts the codex/router call surface so Scribe remains testable without a live gpt-5.4-mini endpoint. Production wiring injects a thin `LlmProvider`-backed adapter; tests use `mock_llm_call`.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.prompt_render`** · _beta_ · since 2026-05-07 — Wave Q3 — `render_prompt` deterministically produces the consolidation prompt from candidate observations + optional prior dossier body. Pure function — no time / no randomness — so the same input renders byte-identical output (prompt-cache friendly).  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.run`** · _beta_ · since 2026-05-07 — Wave Q3 — `ScribeRunner::run` orchestration: lock → idempotency check → cost cap reservation → LLM call → dossier write → audit append → metrics. Single entry point for both background runs and the `alice-cli memory scribe run` CLI verb.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.source_observations_section`** · _beta_ · since 2026-05-07 — Phase 8AA-1 — after the LLM emits the consolidated dossier body, the Scribe worker appends a `## Source observations` section with one bullet per candidate `ObservationRef` that carries verbatim user text. Preserves locality phrases ("Германии", "Мюнхен") and other literal phrasing that derivative summaries strip out. Probes grep this section for exact user statements.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.text_contradiction_detector`** · _beta_ · since 2026-05-15 — Phase 8DDD-2 — `looks_like_contradiction` now inspects `obs.text` (in addition to `obs.outcome`) for correction / negation markers and falls back to a capitalised-token overlap check when the entity slug is in the canonical Latin form but the prior dossier body holds the Cyrillic spelling. Without this the conflict journal stayed empty on plain-chat turns built by `worker_hooks::build_observation_for_turn` (which leaves `outcome` empty unless `task_execute` ran), so the cascade never fired on the `memory-contradiction-cascade` probe.  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory.scribe.worker.verbatim_phrase_blockquote`** · _beta_ · since 2026-05-15 — Phase 8CC-2 — after the LLM body is rendered and before the `## Source observations` section is appended, Scribe injects a `> «{text}» — {date} from {source}` blockquote into the H1 region of the dossier body. The curator digest extractor stops at the next H1/H2 boundary by design, so prior to this fix the verbatim user phrase under `## Source observations` was truncated out of the curator paste. Lifting the quote into H1 lets `expected_response_contains:["Германии"]` probes pass end-to-end (dossier → curator → system prompt).  
  *openalice_agents_memory::scribe::worker:0*
- **`agents.memory_search`** · _stable_ · since 0.1.0 — Semantic search over agent memory — in-memory embedding index with cosine similarity for fast nearest-neighbour retrieval of memory entries.  
  *openalice_agents::memory_search:0*
- **`agents.memory.skills.audit.append`** · _beta_ · since 2026-05-07 — Wave P — emit one `_audit.jsonl` row per skill mutation (create / update / archive / run). Reuses Wave S's append_audit so dossier + skill history sit in one tail.  
  *openalice_agents_memory::skills::audit:0*
- **`agents.memory.skills.curator.grade`** · _experimental_ · since 2026-05-15 — Phase 8FF-3 — `SkillGrader` trait + heuristic + LLM impls. The heuristic grader maps frontmatter (`use_count`, `success_rate`, `last_used_at`) to a 1-5 quality + 1-5 usage score. The LLM grader (gpt-5.4-mini → gpt-5.4 fallback) augments the heuristic on the same single-writer Codex OAuth path as Scribe + Reflection.  
  *openalice_agents_memory::skills::curator:0*
- **`agents.memory.skills.curator.metrics`** · _experimental_ · since 2026-05-15 — Phase 8FF-3 — Prometheus counters: `oa_skill_curator_runs_total{outcome}`, `oa_skill_curator_skills_graded_total`, `oa_skill_curator_proposals_total{kind}` (kind = delete / consolidate). Exporter registers via `METRICS_EXPORTERS`.  
  *openalice_agents_memory::skills::curator:0*
- **`agents.memory.skills.curator.module`** · _experimental_ · since 2026-05-15 — Phase 8FF-3 — Autonomous Skill Curator (Hermes v0.12.0 snipe). Background worker that walks per-chat + global skill libraries, grades each skill (quality / usage / overlap), and proposes deletions + consolidations into the existing pending-skills queue. Gated behind `OPENALICE_SKILL_CURATOR=1`; default OFF in prod.  
  *openalice_agents_memory::skills::curator:0*
- **`agents.memory.skills.curator.proposals`** · _experimental_ · since 2026-05-15 — Phase 8FF-3 — curator emits `delete` proposals (quality < 2 AND usage < 2 AND age > 14 d) and `consolidate` proposals (body overlap > 70 %) into `reflection/_pending/skills.jsonl`. NEVER deletes a skill directly — every proposal requires explicit `alice-cli memory reflect approve <id>` to take effect.  
  *openalice_agents_memory::skills::curator:0*
- **`agents.memory.skills.curator.report`** · _experimental_ · since 2026-05-15 — Phase 8FF-3 — curator writes one JSONL row per run to `reflection/skill_curator_runs/{run_ts}.jsonl`. Each row records the per-skill grade + per-proposal verdict + timing so operators can audit / replay every curator pass.  
  *openalice_agents_memory::skills::curator:0*
- **`agents.memory.skills.frontmatter.q1`** · _beta_ · since 2026-05-07 — Wave P — per-chat skill `.md` YAML frontmatter (q1 schema): name, purpose, created_at, last_used_at, use_count, success_rate, tags, schema_version. Mirrors the Q1 dossier serde pattern so the skill loader + LLM authoring path share one struct.  
  *openalice_agents_memory::skills::frontmatter:0*
- **`agents.memory.skills.frontmatter.validate`** · _beta_ · since 2026-05-07 — Wave P — strict validation for SkillFrontmatter (`name` non-empty, `purpose` non-empty, `schema_version=q1`, `use_count >= 0`, `success_rate ∈ [0.0, 1.0]`). Rejects on write so a broken skill never leaks to disk; the error string is shaped for LLM self-correction on the next turn.  
  *openalice_agents_memory::skills::frontmatter:0*
- **`agents.memory.skills.global_fallback`** · _beta_ · since 2026-05-07 — Wave P — global cross-scope skills at `~/.openalice/data/{agent}/skills/` are visible in every per-chat listing as a fallback. Per-scope skills shadow globals on name collision so a chat can locally override a recipe.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.metrics.create`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_skill_create_total`. Bumped once per `PerChatSkillManager::new_skill` invocation.  
  *openalice_agents_memory::skills::extra_metrics:0*
- **`agents.memory.skills.metrics.proposals`** · _beta_ · since 2026-05-07 — Phase 8I — Prometheus counter trio for skill-reflection proposals: `oa_skill_merge_proposal_total` (the 8E SideEffectScorer probe), `oa_skill_archive_proposal_total`, `oa_skill_review_proposal_total`. Incremented at proposal-write time (not approval). 8H wires the exposition into `/metrics`; 8I owns the storage + record sites.  
  *openalice_agents_memory::skills::metrics:0*
- **`agents.memory.skills.metrics.run`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_skill_run_total{outcome}`. Bumped once per `PerChatSkillManager::run` invocation with outcome label (`success` / `fail` / `timeout`).  
  *openalice_agents_memory::skills::extra_metrics:0*
- **`agents.memory.skills.module`** · _beta_ · since 2026-05-07 — Wave P — per-chat skill submodule. Hosts the PerChatSkillManager + q1 frontmatter + self-improving reflection. Coexists with Wave I's global SkillManager (which owns the cross-scope SKILL.md library).  
  *openalice_agents_memory::skills:0*
- **`agents.memory.skills.per_chat.archive`** · _beta_ · since 2026-05-07 — Wave P — move `{name}.md` + `{name}.sh` into `_archive/<ts>/`. Per `feedback-memory-archive-not-delete-2026-05-02`: never delete outright — old versions stay recoverable.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.list`** · _beta_ · since 2026-05-07 — Wave P — list every skill (`.md`) under the per-chat skills folder plus the global fallback. Each entry returns its parsed frontmatter + scope tag so the CLI / prompt builder can merge them.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.merge`** · _beta_ · since 2026-05-07 — Phase 8I — `merge_skills(slug_a, slug_b, target)` consumes a merge proposal: concatenates purposes + bodies + .sh under section headers, archives both originals to `_archive/<ts>/`, writes the new merged skill. Never auto-applies; only callable from the `memory reflect approve <id>` path.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.new`** · _beta_ · since 2026-05-07 — Wave P — scaffold a new skill: writes `{name}.md` with q1 frontmatter + an executable `{name}.sh` stub (chmod 755, shebang, `set -euo pipefail`). Refuses to overwrite an existing skill.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.run`** · _beta_ · since 2026-05-07 — Wave P — execute `{name}.sh` synchronously via std::process::Command under `timeout(1)`. Captures stdout/stderr/exit_code, bumps use_count + success_rate, updates last_used_at. Runs in agent's working dir under `~/.openalice/data/{agent}/`.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.show`** · _beta_ · since 2026-05-07 — Wave P — render a single skill's full body (frontmatter + recipe markdown). Used by `alice-cli skill show` + the `skill_create / skill_update` audit step.  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.per_chat.update`** · _beta_ · since 2026-05-07 — Wave P — update an existing skill body (markdown) and/or selected frontmatter fields (purpose, tags). Frontmatter timestamps + counters are NOT mutated by this verb (run() owns them).  
  *openalice_agents_memory::skills::manager:0*
- **`agents.memory.skills.reflection.duplicates`** · _beta_ · since 2026-05-07 — Wave P — detect skill pairs with ≥ 80 % byte overlap in their `.sh` bodies. Output: SkillProposal{action=merge}. NAO approves; never auto-merge.  
  *openalice_agents_memory::skills::reflection:0*
- **`agents.memory.skills.reflection.failing`** · _beta_ · since 2026-05-07 — Wave P — detect skills with success_rate < 0.5 AND use_count ≥ 5. Output: SkillProposal{action=review}. NAO reviews + decides whether to rewrite, archive, or accept as-is.  
  *openalice_agents_memory::skills::reflection:0*
- **`agents.memory.skills.reflection.queue`** · _beta_ · since 2026-05-07 — Wave P — append SkillProposals to `chat/{scope}/reflection/_pending/skills.jsonl`. Re-uses Q7's pending-queue convention (one JSON per line, stable id over (scope, action, targets)).  
  *openalice_agents_memory::skills::reflection:0*
- **`agents.memory.skills.reflection.stale`** · _beta_ · since 2026-05-07 — Wave P — detect skills with last_used_at > 90 days ago AND use_count ≤ 1. Output: SkillProposal{action=archive}. Archive is reversible (`_archive/`) so the proposal is auto-applyable, but Wave P keeps it gated for the first release per master plan §9.5.  
  *openalice_agents_memory::skills::reflection:0*
- **`agents.memory_tags`** · _stable_ · since 0.1.0 — Tag-based memory indexing — fast tag lookups, multi-tag intersection, prefix filtering, JSON serialisation.  
  *openalice_agents::memory_tags:0*
- **`agents.memory.tool_trace.lesson.heuristic`** · _beta_ · since 2026-05-07 — Wave V — derive_lesson: deterministic mapping from (tool, args, error, outcome, duration) to a one-line lesson string. No LLM. Recognises 403/429, 5xx, Cloudflare, timeouts, connection refused; falls back to a truncated error preview.  
  *openalice_agents_memory::tool_trace::lesson:0*
- **`agents.memory.tool_trace.lookup.cosine`** · _beta_ · since 2026-05-07 — Wave V — token-cosine similarity over JSON args. Extracts keys + primitive values into a token bag, computes cos(θ) = dot / (|a| · |b|). Threshold 0.7 picks 'similar enough that the past lesson still applies'.  
  *openalice_agents_memory::tool_trace::lookup:0*
- **`agents.memory.tool_trace.lookup.find_lessons`** · _beta_ · since 2026-05-07 — Wave V — find_relevant_lessons(agent, scope, tool, args). Scans last 50 entries (or 7d, whichever shorter), keeps same-tool entries with cosine ≥ 0.7, returns top-K most-recent lessons. De-duplicates lesson text so the same lesson never appears twice in one surface.  
  *openalice_agents_memory::tool_trace::lookup:0*
- **`agents.memory.tool_trace.metrics.duration`** · _beta_ · since 2026-05-07 — Wave V — Prometheus histogram `oa_tool_call_duration_ms{tool}`. Buckets: 10, 50, 100, 250, 500, 1000, 2500, 5000, 10000, +Inf.  
  *openalice_agents_memory::tool_trace::metrics:0*
- **`agents.memory.tool_trace.metrics.recorded`** · _beta_ · since 2026-05-07 — Wave V — Prometheus counter `oa_tool_call_recorded_total{tool, outcome}`. Bumped once per append.  
  *openalice_agents_memory::tool_trace::metrics:0*
- **`agents.memory.tool_trace.metrics.rotations`** · _beta_ · since 2026-05-07 — Wave V — Prometheus counter `oa_tool_call_rotations_total{scope}`. Bumped once per rotation event; pair with the trace_size gauge to detect chats that rotate too often (sign of an upstream bug-loop).  
  *openalice_agents_memory::tool_trace::metrics:0*
- **`agents.memory.tool_trace.metrics.surfaced`** · _beta_ · since 2026-05-07 — Wave V — Prometheus counter `oa_tool_call_lesson_surfaced_total{tool}`. Incremented once per lesson the section surfaces into the system prompt before a tool call.  
  *openalice_agents_memory::tool_trace::metrics:0*
- **`agents.memory.tool_trace.metrics.trace_size`** · _beta_ · since 2026-05-07 — Wave V — Prometheus gauge `oa_tool_call_trace_size_bytes{scope}`. Set on every append so retention monitoring can detect runaway scopes before rotation kicks in.  
  *openalice_agents_memory::tool_trace::metrics:0*
- **`agents.memory.tool_trace.module`** · _beta_ · since 2026-05-07 — Wave V — per-chat append-only tool-call memory (lessons-learnt jsonl). Captures every tool invocation with outcome + duration + heuristic lesson; surfaces relevant lessons before similar future calls. Privacy: per-chat scope, never cross-streamed.  
  *openalice_agents_memory::tool_trace:0*
- **`agents.memory.tool_trace.record.append`** · _beta_ · since 2026-05-07 — Wave V — append one TraceEntry as a JSON line to tool-calls.jsonl via O_APPEND. Single line per call; atomic at the OS level for sub-PIPE_BUF writes. Bumps oa_tool_call_recorded_total{tool,outcome} + duration histogram + trace_size gauge. Triggers retention rotation check.  
  *openalice_agents_memory::tool_trace::record:0*
- **`agents.memory.tool_trace.record.tail`** · _beta_ · since 2026-05-07 — Wave V — read_recent_entries: tails the trace file and returns up to N most-recent entries as parsed TraceEntry rows. Skips malformed lines (forward-compat for new fields).  
  *openalice_agents_memory::tool_trace::record:0*
- **`agents.memory.tool_trace.rotation.gzip`** · _beta_ · since 2026-05-07 — Wave V — lazy rotation of tool-calls.jsonl when it crosses 10k lines OR 10 MB. Rotated file is renamed to tool-calls.YYYY-MM-DD.jsonl.gz (gzipped in place). Archive-not-delete: rotated logs are NEVER removed.  
  *openalice_agents_memory::tool_trace::rotation:0*
- **`agents.memory.user_model`** · _experimental_ · since 2026-04-26 — Wave G8 — Honcho-style per-chat user model. Persists identity / belief / goal claims with confidence + provenance under memory/{agent}/user_models/{scope}.json. Read at preload time, rendered into the system prompt under `## User Model (live dialectic)`.  
  *openalice_agents_memory::user_model:0*
- **`agents.memory.user_model.contradiction_detection`** · _experimental_ · since 2026-04-26 — Wave G8 — strict contradiction detector. Files a Contradiction when a new claim is the direct negation of an existing same-kind claim, or sits on a known mutually-exclusive identity axis (citizenship, employment-status). Never auto-resolves — the rendered block surfaces unresolved counts to Alice for clarification.  
  *openalice_agents_memory::user_model::update:0*
- **`agents.memory.user_model.dialectic`** · _experimental_ · since 2026-04-26 — Wave G8 — dialectic update path. Reinforces same-claim turns with a small confidence bump, files Contradictions on negation pairs, updates the per-chat EmotionalState from a bilingual keyword bag + MessageIntent hint. Heuristic-only; LLM escalation hook reserved.  
  *openalice_agents_memory::user_model::update:0*
- **`agents.memory.v4.active_chars`** · _beta_ · since 0.1.0 — Memory v4 M2.D — dedicated `## Active Characters` system-prompt slot for Isolated/RP chats. Compact card-format table; suppresses duplicate names from `## People Profiles`.  
  *openalice_agents::profile_cards:0*
- **`agents.memory.v4.budget_allocator`** · _beta_ · since 0.1.0 — Memory v4 M3 — per-mode budget allocator. Maps (ChatMode, MessageComplexity) → top-N tuple + Active Characters slot policy. General falls through to legacy v3 retrieval_depth (zero regression).  
  *openalice_agents::memory_preload::budget:0*
- **`agents.memory.v4.chat_mode_classifier`** · _beta_ · since 0.1.0 — Memory v4 M3 — universal ChatMode classifier (Roleplay / Coding / Research / Personal / Automation / Education / General). Replaces the M2 Isolated-as-RP heuristic. Combines explicit override + keyword-density + persona + tool-use proxies via weighted vote.  
  *openalice_agents::memory_preload::mode:0*
- **`agents.memory.v4.entities_field`** · _beta_ · since 0.1.0 — Memory v4 M1.I — Use MemoryUnit.entities[] structured field in scoring for precise entity matching. Falls back to text_lower.contains for legacy units with empty entities[].  
  *openalice_agents::memory_preload:0*
- **`agents.memory.v4.graph_khop`** · _beta_ · since 0.1.0 — Memory v4 M2.F — entity-graph k-hop traversal. Extends graph expansion from 1-hop to 2-hops with hop-aware GRAPH_BOOST decay (×0.5 per hop). Capped at 30 entities to bound recall noise.  
  *openalice_agents::memory_preload:0*
- **`agents.memory.v4.mode_persistence`** · _beta_ · since 0.1.0 — Memory v4 M3 — chat-scoped ChatMode cache at chat/{scope}/mode.json. Re-detected every 10 turns or 7 days; explicit override at chat/{scope}/settings/mode wins immediately at confidence 1.0.  
  *openalice_agents::memory_preload::mode:0*
- **`agents.memory.v4.recent_access`** · _beta_ · since 0.1.0 — Memory v4 M2.C — recent-access multiplier. Units accessed in the last 24 h with access_count > 0 get a +0.20 score boost. Makes yesterday's-conversation units sticky for follow-up turns.  
  *openalice_agents::memory_preload:0*
- **`agents.memory.v4.topn_widening`** · _beta_ · since 0.1.0 — Memory v4 M1.B — Top-N widening for Isolated/RP chats. Normal (10,25,35) → (10,40,55); Complex (10,40,50) → (10,60,75). Full / Curated unchanged.  
  *openalice_agents::memory_preload::classify:0*
- **`agents.memory.v4.whitelist`** · _beta_ · since 0.1.0 — Memory v4 M1.A — active character whitelist. Top-K cards (by 24h access_count + last_accessed) injected regardless of similarity ranking. Solves narrow-query character-context drop.  
  *openalice_agents::profile_cards:0*
- **`agents.memory_versions`** · _stable_ · since 0.1.0 — Version history for memory entries — rollback, version retrieval, automatic pruning of old versions.  
  *openalice_agents::memory_versions:0*
- **`agents.profile_cards`** · _stable_ · since 0.1.0 — Entity Profile Cards — compact JSON dossiers per person/topic, consolidated from memory facts. Loaded instantly on mention via direct key lookup (no scoring); refreshed by Night Synthesis.  
  *openalice_agents::profile_cards:0*
- **`anchors.curator_boost`** · _beta_ · since 2026-05-07 — Wave Q8 — Curator integration. The matcher's per-slug bonus is added on top of the existing Q4 score; with the default multi_anchor_bonus=0.15 and base_per_kind_bonus=0.05, a dossier matching both a text anchor and a voice anchor on the same turn ranks above the same dossier matching only text — even when text alone is the only Q4 entity_match hit.  
  *openalice_agents_memory::anchors::matcher:0*
- **`anchors.feature_flags`** · _beta_ · since 2026-05-07 — Wave Q8 — three env-var feature flags gate per-kind anchor LOOKUP only (registration is always allowed): OPENALICE_EMBEDDING_KIND_TEXT (default ON), OPENALICE_EMBEDDING_KIND_IMAGE (default OFF, CLIP plugin), OPENALICE_EMBEDDING_KIND_VOICE (default OFF, ECAPA plugin). Flags OFF make matcher::score_anchor_matches return zero bonus for that kind — no panic, no Prometheus spam.  
  *openalice_agents_memory::anchors::flags:0*
- **`anchors.matcher`** · _beta_ · since 2026-05-07 — Wave Q8 — per-turn anchor matcher. Returns a slug→bonus map that the Curator adds onto the Q4+Q5+Q6 base score. Text/url/phone/email match via lowercased substring. Image and voice match via cosine similarity against the on-disk embedding store. Each kind contributes a small bonus; multi-anchor matches (>=2 distinct kinds) get an extra multi_anchor_bonus. Gated on OPENALICE_EMBEDDING_KIND_* flags — flag OFF for a kind ⇒ that kind contributes 0.  
  *openalice_agents_memory::anchors::matcher:0*
- **`anchors.metrics`** · _beta_ · since 2026-05-07 — Wave Q8 + Phase 8BB-1 — oa_dossier_anchor_match_total{kind="text|image|voice"} counter. Increments once per dossier→anchor match picked up by the Curator. No slug label (cardinality safe). Per master plan §12.1 row Q8. Pre-8BB-1 the bump only fired when caller passed a `MetricsCollector` (None in production) — 8BB-1 mirrors the bump into a process-global OnceLock that registers via the METRICS_EXPORTERS slice, so the counter always reaches `/metrics`.  
  *openalice_agents_memory::anchors::metrics:0*
- **`anchors.similarity`** · _beta_ · since 2026-05-07 — Wave Q8 — pure cosine-similarity over f32 slices. No LLM, no async. Mismatched-dim inputs return 0.0 (treat model/dim divergence as a non-match). Zero-norm inputs (all zeros) return 0.0 — degenerate vectors cannot be ranked.  
  *openalice_agents_memory::anchors::similarity:0*
- **`anchors.store`** · _beta_ · since 2026-05-07 — Wave Q8 — file-backed vector store under ~/.openalice/data/{agent}/embeddings/{kind}/{embedding_id}.bin (raw f32 little-endian) + .meta.json sidecar with {model, dim, source_path?, created_at, sha256?}. Writes go through *.tmp + rename so partial files are never observed. Registration is always allowed regardless of OPENALICE_EMBEDDING_KIND_* flags.  
  *openalice_agents_memory::anchors::store:0*
- **`curator.access_bump`** · _beta_ · since 2026-05-07 — Wave Q5 — after the per-turn Curator picks a dossier into Tier-1, it atomically rewrites the dossier's `last_accessed_at` frontmatter field to now and appends `actor=curator, action=access` to `_audit.jsonl`. This bumps the forgetting-curve weight back to ~1.0 so frequently-used facts stay surface-able.  
  *openalice_agents_memory::curator:0*
- **`curator.always_include`** · _beta_ · since 2026-05-07 — Wave Q4 — manually-pinned slugs that override Curator scoring and always paste at the top of the Tier-1 digest block. Capped at ALWAYS_INCLUDE_MAX (5). Unioned with the legacy OPENALICE_MEMORY_CHAR_WHITELIST env var.  
  *openalice_agents_memory::curator::config:0*
- **`curator.anchor_boost`** · _beta_ · since 2026-05-07 — Wave Q8 — applies anchor-matcher bonuses (text/file/image/voice/url/phone/email) onto ScoredCandidate.score and re-sorts. Per (slug, kind) match bumps oa_dossier_anchor_match_total{kind=...}. Multi-anchor boost is configurable (default 0.15) and applied when a single dossier matches ≥2 distinct kinds in one turn. Phase 8J hardening: image/voice query + resolver closures are dropped BEFORE the matcher runs when the corresponding feature flag is OFF, and the matcher call is wall-budgeted (250ms) so a slow resolver can never stall the per-turn HTTP handler.  
  *openalice_agents_memory::curator::anchor_boost:0*
- **`curator.archive_resurrect`** · _beta_ · since 2026-05-07 — Wave Q5 — pinned slug not found in active dossiers? Walk `dossiers/{type}/_archive/**/{slug}.md` and surface the most recent archived copy. Lets operators force-load an archived dossier by pinning its slug; non-pinned archived dossiers stay hidden from Curator scoring.  
  *openalice_agents_memory::curator:0*
- **`curator.budget_shrink`** · _beta_ · since 2026-05-07 — Wave Q4 — adaptive Top-K. Selection greedily walks scored candidates and stops when the next digest would exceed the Tier-1 token budget (default 2000) or when K hits the configured cap (default 5). Always-include slugs are added first and bypass the K cap but still respect the budget.  
  *openalice_agents_memory::curator:0*
- **`curator.config.load`** · _beta_ · since 2026-05-07 — Wave Q4 — load CuratorConfig from ~/.openalice/data/{agent}/config/curator.json. Missing or partial file falls back to research-tuned defaults; never panics.  
  *openalice_agents_memory::curator::config:0*
- **`curator.config.save`** · _beta_ · since 2026-05-07 — Wave Q4 — atomically persist CuratorConfig (used by `alice-cli memory curator weights --set ...` and `pin/unpin`). Writes to *.tmp and renames so partial files are never observed.  
  *openalice_agents_memory::curator::config:0*
- **`curator.digest.extract`** · _beta_ · since 2026-05-07 — Wave Q4 — pull the first ~N tokens of a dossier body (after frontmatter) for Tier-1 prompt injection. Stops at the next H1 / H2 heading so digests never bleed across sections.  
  *openalice_agents_memory::curator::digest:0*
- **`curator.digest.tokenise`** · _beta_ · since 2026-05-07 — Wave Q4 — fast whitespace-and-punctuation token counter. ~10 % of GPT BPE accuracy at 100x the speed; used for soft-budget gating.  
  *openalice_agents_memory::curator::digest:0*
- **`curator.gather_candidates`** · _beta_ · since 2026-05-07 — Wave Q4 — walk dossiers/{type}/*.md for the (agent, scope), parse each via Dossier::parse_markdown, extract digest text. Skips _archive/ subtrees and the MEMORY-INDEX.md file. Falls back gracefully on parse errors.  
  *openalice_agents_memory::curator:0*
- **`curator.metrics.alias_match`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_entity_alias_match_total`. Bumped once per alias hit during `curator::score::entity_match`. Always reaches `/metrics` via the observability exporter registry.  
  *openalice_agents_memory::curator::extra_metrics:0*
- **`curator.metrics.dossier_load_total`** · _beta_ · since 2026-05-07 — Wave Q4 — `oa_dossier_load_total{tier}` counter. Bumps on every dossier injected into the prompt, broken down by Tier 0 (always-on MEMORY-INDEX), Tier 1 (curator digest), or Tier 2 (full body via dossier_read tool).  
  *openalice_agents_memory::curator::metrics:0*
- **`curator.metrics.dossier_resurrect`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_dossier_resurrect_total`. Bumped once per _archive/-resident dossier force-loaded via the `always_include` pin path (Wave Q5 override).  
  *openalice_agents_memory::curator::extra_metrics:0*
- **`curator.metrics.latency_seconds`** · _beta_ · since 2026-05-07 — Wave Q4 — `oa_curator_latency_seconds` histogram. End-to-end curator latency per turn. Master plan §5.4 acceptance: p99 < 30 ms on a 500-dossier corpus.  
  *openalice_agents_memory::curator::metrics:0*
- **`curator.metrics.score`** · _beta_ · since 2026-05-07 — Wave Q4 — `oa_curator_score{slug}` gauge. Last raw curator score per dossier slug. Drives Grafana dashboards and ad-hoc debugging via `alice-cli memory curator score`.  
  *openalice_agents_memory::curator::metrics:0*
- **`curator.metrics.score_distribution`** · _beta_ · since 2026-05-07 — Wave Q4 — `oa_curator_score_distribution` histogram. Distribution of every curator score this turn (cardinality-safe — no slug label). Surfaces drift in the score distribution over time.  
  *openalice_agents_memory::curator::metrics:0*
- **`curator.metrics.top_k_paste`** · _beta_ · since 2026-05-07 — Wave Q4 — `oa_curator_top_k_paste_total{slug}` counter. Increments every turn a slug ends up in the Tier-1 digest paste — proxy for "how often is this dossier surfaced?".  
  *openalice_agents_memory::curator::metrics:0*
- **`curator.neighbor_expand`** · _beta_ · since 2026-05-07 — Wave Q6 — when a dossier ranks into Top-K, optionally pull its 1-hop graph neighbours into the paste at half-weight. Capped at neighbor_cap (default 3) per turn so the prompt cannot blow up. Increments oa_dossier_load_total{tier="2"} for every neighbour loaded.  
  *openalice_agents_memory::curator:0*
- **`curator.render_paste`** · _beta_ · since 2026-05-07 — Wave Q4 — render the selected digests into a single markdown block headed `# Curator Dossiers — chat:{scope}`. Empty when no dossiers selected so the section self-skips.  
  *openalice_agents_memory::curator:0*
- **`curator.render_paste.aliases_line`** · _beta_ · since 2026-05-15 — Phase 8GG-3 — when a DigestEntry carries `aliases:` from the dossier frontmatter (Wave R3 identity-name field) AND/OR `tags:` the curator surfaces them as a `**Aliases:** A · B · C` line in the rendered paste immediately after the entry header. Aliases that match the slug basename are deduped out; the line itself self-skips when no distinct alias remains, so dossiers without identity-name metadata see zero surface drift. Up to 6 aliases per entry to keep Tier-1 token budget bounded. Steers the LLM toward the canonical name spelling the user originally used (e.g. Latin `Katya` when answering in Russian).  
  *openalice_agents_memory::curator:0*
- **`curator.run`** · _beta_ · since 2026-05-07 — Wave Q4 — top-level Curator entry point. Loads candidates from the dossiers dir, scores them via the Q4 heuristic, applies the always-include override list, trims to Top-K under the Tier-1 token budget, and renders the digest paste. No LLM.  
  *openalice_agents_memory::curator:0*
- **`curator.score`** · _beta_ · since 2026-05-07 — Wave Q4 — pure-function dossier scorer. Combines five heuristic components (entity match / recency / importance / scope_fit / length penalty) into a single rank. No LLM. p99 < 30 ms on a 500-dossier corpus per master plan §5.4.  
  *openalice_agents_memory::curator::score:0*
- **`curator.score.entity_match`** · _beta_ · since 2026-05-07 — Wave Q4 — entity_match component. Checks slug + tags + first body heading against turn text (lowercased substring + transliteration- friendly normalisation). 1.0 on direct mention, 0.5 on partial token overlap, 0.0 otherwise.  
  *openalice_agents_memory::curator::score:0*
- **`curator.score.forgetting_curve`** · _beta_ · since 2026-05-07 — Wave Q5 — γ-modulator: the importance component is multiplied by exp(-Δdays / decay_tau_days), where Δ is measured from frontmatter.last_accessed_at (Curator pick history), not updated_at. τ defaults to 14d and is configurable per agent via curator.json `decay_tau_days`. Stale dossiers naturally rank lower without being deleted.  
  *openalice_agents_memory::curator::score:0*
- **`curator.score.recency`** · _beta_ · since 2026-05-07 — Wave Q4 — recency component. exp(-Δdays / 14). A 14-day-old dossier scores ~0.37; a fresh one scores 1.0; a 60-day-old one scores ~0.014.  
  *openalice_agents_memory::curator::score:0*
- **`curator.score.scope_fit`** · _beta_ · since 2026-05-07 — Wave Q4 — scope_fit component. Private dossier matching the current chat scopes 1.0, Public/SharedWithAgents (treated as globally-readable) scores 0.7, Private dossier from a different chat scopes 0.0 — blocks cross-chat leakage.  
  *openalice_agents_memory::curator::score:0*
- **`dossier.aliases`** · _beta_ · since 2026-05-07 — Wave R3 — additive frontmatter field `aliases: [..]` carries human-readable nicknames for the entity. The `<speaker>` tag renderer resolves a `speaker_id` back to a dossier and then prettifies the display name out of aliases + slug + body heading, so `Бассель` and `Bassel` both surface as `name="Bassel"`.  
  *openalice_core::memory::dossier:0*
- **`dossier.anchors`** · _beta_ · since 2026-05-07 — Wave Q8 — multi-modal anchors. Extends EntityAnchor with optional per-kind fields: path+sha256 for `file`; embedding_id+model for `image`/`voice`; value for `text`/`url`/`phone`/`email`. Validation rejects malformed sha256 (must be 64 lowercase hex), malformed embedding_id (must be [A-Za-z0-9_-]+), and missing required fields. YAML field renamed from `kind:` to `type:`; legacy `kind:` accepted via serde alias for backwards compat.  
  *openalice_core::memory::dossier:0*
- **`dossier.as_of_view`** · _beta_ · since 2026-05-07 — Wave Q5 — `Dossier::is_valid_at(date)` filters by t_valid/t_invalid: a dossier is visible at `as_of` iff `t_valid <= as_of` (or t_valid is null) AND `(t_invalid IS NULL OR t_invalid > as_of)`. Powers `dossier_read --as-of` and the historical-view CLI verbs.  
  *openalice_core::memory::dossier:0*
- **`dossier.edge_confidence`** · _beta_ · since 2026-05-07 — Wave Q6 — `EntityEdge` extended with `confidence: Option<f32>` (0..1) and `created_at: Option<String>` (RFC3339).  Both fields are skipped on serialise when None so legacy Q2 dossiers keep round-tripping.  Validation rejects confidence outside [0,1] — see `ValidationError::EdgeConfidenceOutOfRange`.  
  *openalice_core::memory::dossier:0*
- **`dossier.frontmatter_schema`** · _beta_ · since 2026-05-07 — Wave Q2 — q1 frontmatter schema for dossiers (slug, schema_version, timestamps, share, tags, importance, t_valid/t_invalid, encrypted, anchors[], edges[]). Round-trips via parse_markdown / render_markdown.  
  *openalice_core::memory::dossier:0*
- **`dossier.index.read`** · _beta_ · since 2026-05-07 — Wave Q1 — read MEMORY-INDEX.md for an (agent, scope). Lists every dossier under chat_root/dossiers/, separated into active + archived. Always-injected Tier-0 of the memory hierarchy.  
  *openalice_agents_memory::dossier_index:0*
- **`dossier.index.rebuild`** · _beta_ · since 2026-05-07 — Wave Q1 — walk chat_root/dossiers/, parse each .md file's frontmatter, and produce a MemoryIndex. Idempotent; safe to call on every turn.  
  *openalice_agents_memory::dossier_index:0*
- **`dossier.index.render`** · _beta_ · since 2026-05-07 — Wave Q1 — render a MemoryIndex into the canonical MEMORY-INDEX.md markdown. Stable byte-output for prompt cache friendliness.  
  *openalice_agents_memory::dossier_index:0*
- **`dossier.last_accessed_at`** · _beta_ · since 2026-05-07 — Wave Q5 — additive frontmatter field `last_accessed_at` (RFC3339). The Curator bumps this every time the dossier is picked into the Tier-1 paste, and the forgetting-curve scorer uses it as the freshness signal. Backwards compatible — older dossiers omit the field; consumers fall back to `updated_at`.  
  *openalice_core::memory::dossier:0*
- **`dossier.share_modes`** · _beta_ · since 2026-05-07 — Wave Q2 — ShareMode (Private | SharedWithAgents([..]) | Public) ACL field stored in dossier frontmatter. Q2 validates + round-trips; enforcement lands with A2A.  
  *openalice_core::memory::dossier:0*
- **`dossier.source_observations_hash`** · _beta_ · since 2026-05-07 — Wave Q3 — additive frontmatter field `source_observations_hash` carries a sha256 over the observation ids that produced the current dossier body. The Scribe promotion worker uses it for idempotency: if the candidate set hashes the same on a re-trigger, the LLM call is skipped. Backwards compatible — older dossiers omit the field.  
  *openalice_core::memory::dossier:0*
- **`dossier.speaker_ids`** · _beta_ · since 2026-05-07 — Wave R3 — additive frontmatter field `speaker_ids: [..]` carries the platform-scoped speaker ids (e.g. `tg:670376626`, `discord:123`, `a2a:agent-alice-bf3a`) that map to this dossier. The speaker resolver scans every person dossier for an exact-equality match on this field. Set by `alice-cli speaker bind` or by Scribe when promoting a person.  
  *openalice_core::memory::dossier:0*
- **`dossier.superseded_by`** · _beta_ · since 2026-05-07 — Wave Q5 — additive frontmatter field `superseded_by: <slug>` set by the Scribe conflict-cascade pipeline once an old dossier's t_invalid flips and a successor is created. Allows as_of consumers to walk to the current view by chasing the link.  
  *openalice_core::memory::dossier:0*
- **`dossier.types`** · _beta_ · since 2026-05-07 — Wave Q2 — universal entity types: person/project/object/concept/event/fact_cluster. Phase 8Z-A added `location` (additive, no migration) so Alice can write `location/<canonical>` slugs for places referenced by `located_in` edges. Phase 8GG-3 added `topic` as a read-only serde alias for `concept` so externally-seeded dossier fixtures (lab `memory-anchor-multi` probe at `dossiers/topic/hermes-overview.md` with frontmatter `kind: topic`) parse cleanly. Round-trip via `render_markdown` always emits `concept`. The DossierType enum drives directory layout and forward-compat curator filters.  
  *openalice_core::memory::dossier:0*
- **`dossier.validate`** · _beta_ · since 2026-05-07 — Wave Q2 — Dossier::validate() enforces slug kebab-case, importance range, tag count + length caps, and t_valid <= t_invalid temporal ordering. Called on write; lenient on read to tolerate future schema_version drift.  
  *openalice_core::memory::dossier:0*
- **`graph.add_edge_with_inverse`** · _beta_ · since 2026-05-07 — Wave Q6 — insert an edge X→Y and the inverse Y→X atomically. Both dossier writes use tempfile+rename; the original write is rolled back if the inverse write fails. Enforces the 12-edge cap per dossier (lowest-confidence eviction, oldest-first tiebreak) and writes an audit row on every insert + every eviction.  
  *openalice_agents_memory::graph::edges:0*
- **`graph.bfs.load_corpus`** · _beta_ · since 2026-05-07 — Wave Q6 — load all dossiers under (agent, scope) into a slug → edges adjacency map. Walks the same dirs as the curator (skips _archive/ and MEMORY-INDEX.md).  
  *openalice_agents_memory::graph::bfs:0*
- **`graph.bfs.neighbors`** · _beta_ · since 2026-05-07 — Wave Q6 — 1-hop neighbour list for a slug. Returns Vec<Neighbor> with target_slug, edge_type, confidence. Used by the curator neighbour expansion + the alice-cli `graph neighbors` verb.  
  *openalice_agents_memory::graph::bfs:0*
- **`graph.bfs.path`** · _beta_ · since 2026-05-07 — Wave Q6 — BFS shortest-path between two dossier slugs. Default max_hops 6. Returns Vec<String> of slugs (start..=end) or None when no path exists within the hop limit.  
  *openalice_agents_memory::graph::bfs:0*
- **`graph.cap.enforce`** · _beta_ · since 2026-05-07 — Wave Q6 — 12-edge per-dossier cap. Lowest-confidence edge (oldest-first tiebreak) is evicted when a new edge pushes the count past the cap. Deterministic so replay-debugging converges on stable state.  
  *openalice_agents_memory::graph::cap:0*
- **`graph.edge_type`** · _beta_ · since 2026-05-07 — Wave Q6 — closed enum of 10 edge types (child_of/parent_of, works_on/worked_on_by, references/referenced_by, contradicts, similar_to, located_in, belongs_to) with explicit inverse map. Symmetric types (contradicts/similar_to/located_in/belongs_to) keep the same label on the inverse side; the four active types flip.  
  *openalice_agents_memory::graph::edges:0*
- **`graph.metrics.edge_count`** · _beta_ · since 2026-05-07 — Wave Q6 — `oa_edge_count` gauge tracks the most recent dossier edge count seen by add_edge_with_inverse. Coarse signal — pairs with `oa_edge_eviction_total` to flag dossiers under cap pressure.  
  *openalice_agents_memory::graph::metrics:0*
- **`graph.metrics.edge_eviction`** · _beta_ · since 2026-05-07 — Wave Q6 — `oa_edge_eviction_total` counter increments each time the 12-edge cap forces an eviction. A non-zero rate indicates a hot dossier; ops should consider raising the cap or merging the entity.  
  *openalice_agents_memory::graph::metrics:0*
- **`graph.metrics.traversal_seconds`** · _beta_ · since 2026-05-07 — Wave Q6 — `oa_graph_traversal_seconds` histogram (min/max/sum). Per-call wall time of `bfs::path` traversal. Master plan §6.4 acceptance: p99 < 100 ms on a 500-dossier corpus.  
  *openalice_agents_memory::graph::metrics:0*
- **`graph.remove_edge_with_inverse`** · _beta_ · since 2026-05-07 — Wave Q6 — delete an edge X→Y and the inverse Y→X. Atomic: if the inverse delete fails the original is restored. No-op on missing edges; returns whether the edge existed.  
  *openalice_agents_memory::graph::edges:0*
- **`memory.access_reinforcement`** · _beta_ · since 0.1.0 — Buffered access_count reinforcement. Retrieval paths register bumps in a DashMap; background flusher (30s interval) persists deltas to disk with atomic writes. Enables ACT-R activation scoring, tier promotion (Cold→Warm→Hot), and RLHF feedback loops that were starved by missing record_access calls.  
  *openalice_agents::access_reinforcement:0*
- **`memory.confidence_updater`** · _beta_ · since 0.1.0 — ConfidenceUpdater — typed confirm/doubt application with audit deltas that closes the Brain v3 M11 write-time loop (triggers: DuplicateSeen, UpdateRefinement, Contradiction, LinterWarning, UserCorrection, AccessReinforcement).  
  *openalice_agents::confidence_updater:0*
- **`memory.consolidation`** · _stable_ · since 0.1.0 — Bi-temporal invalidation — when a new fact contradicts an older one (cosine 0.6-0.85, same entity), the older fact's invalid_at / expired_at are set and the new fact is written alongside.  
  *openalice_agents::memory_dedup:0*
- **`memory.contradiction_linter`** · _beta_ · since 0.1.0 — Write-time automated contradiction detector (key/semantic/temporal/entity checks) producing LintReport with Clean/Warn/Block severity.  
  *openalice_agents::contradiction_linter:0*
- **`memory.crystallize`** · _beta_ · since 0.2.0 — Post-conversation crystallization pipeline — distills a window of turns into a structured Procedural digest (question / findings / entities / lessons) and persists it both as JSON and as a MemoryUnit so the memory engine can retrieve it later.  
  *openalice_agents::memory_crystallize:0*
- **`memory.crystallize_window`** · _beta_ · since 0.3.0 — Post-session crystallization sweep — scans connector_history/* every 5 minutes and crystallises any chat with ≥ 20 new messages that has been idle ≥ 10 minutes, persisting a Procedural digest per window. Controlled by env `ALICE_CRYSTALLIZE_ENABLED` (default: on).  
  *openalice_alice::modules::mod_memory_crystallize_window:0*
- **`memory.decay_job`** · _beta_ · since 0.3.0 — Nightly retention decay job — iterates the primary agent's memories at 04:00 local, applies DecaySweep outcomes (Keep / MarkLowConfidence / Forget) with a 5000-unit budget, and emits `memory.decay.ran` with per-run counters. Controlled by env `ALICE_DECAY_JOB_ENABLED` (default: off in prod for rollout safety).  
  *openalice_alice::modules::mod_memory_decay_job:0*
- **`memory.entity_typed_edges`** · _beta_ · since 0.1.0 — RelationEdge v2 schema — optional `relation_type` carrying the classifier kind (extends/supersedes/…) alongside the free-form `predicate`. Legacy v1 JSON loads as untyped via serde defaults.  
  *openalice_schemas::memory:0*
- **`memory.forgetting_curve`** · _beta_ · since 0.1.0 — Ebbinghaus retention model with confidence reinforcement — retention_score(unit, now) in [0,1].  
  *openalice_agents::forgetting_curve:0*
- **`memory.identity_md`** · _beta_ · since 2026-05-02 — Phase 2 Week 5 — single per-chat identity.md replaces eight per-chat memory keys (onboarding, settings, persona). Read with legacy-fallback for one release; subsequent edits always produce identity.md.  
  *openalice_core::config::identity_md:0*
- **`memory.linter_gate`** · _beta_ · since 0.3.0 — Write-path linter gate — runs DefaultLinter against the top-K nearest neighbours before persisting a newly-extracted MemoryUnit. Block refuses persist, Warn persists + doubts conflicting neighbours, Clean persists as-is. Controlled by env `ALICE_LINTER_GATE_ENABLED` (default: off in prod for rollout safety).  
  *openalice_alice::modules::mod_memory_extractor:0*
- **`memory.per_chat_scope`** · _stable_ · since 0.1.0 — 3-level per-chat scope (Full / Curated / Isolated) with scope_retains SSOT — chat/ RPG rooms don't leak global people/ or project/ memory.  
  *openalice_agents::memory_preload::scope:0*
- **`memory.persona_loader`** · _beta_ · since 2026-05-02 — Phase 2 Week 5 — unified Persona loader. Reads identity.md when present, otherwise falls back to the legacy per-chat keys (chat/{scope}/onboarding/*, settings/memory_scope, persona). Caller-facing surface for SectionBuilder + per-chat prompt injection.  
  *openalice_agents_soul::persona:0*
- **`memory.preload`** · _stable_ · since 0.1.0 — 6-channel scored preloader with hot/warm/cold tiering, HNSW vector pre-filter, cross-encoder reranking, per-chat scope isolation.  
  *openalice_agents::memory_preload:0*
- **`memory.relation_classifier`** · _beta_ · since 0.1.0 — Deterministic heuristic classifier that types the link between a new MemoryUnit and its prior target (Supersedes/Contradicts/Fixed/Extends/Uses/Caused/Related) so `relation_type` stops being empty.  
  *openalice_agents::relation_classifier:0*
- **`memory.retention_decay`** · _beta_ · since 0.1.0 — Pure-function decay sweep that classifies memories Keep/MarkLowConfidence/Forget based on retention score.  
  *openalice_agents::retention_decay:0*
- **`memory.threat_filter`** · _beta_ · since 2026-05-02 — Phase 2 Week 6 — port of Hermes _MEMORY_THREAT_PATTERNS plus codex_auth + tool_directive_hijack additions. Scans memory recall lines for prompt-injection / exfiltration / persistence / credential-leak patterns. On match: drop the line, emit warn log. Read-side blocks; write-side warns only.  
  *openalice_agents_memory::memory_preload::threat_filter:0*
- **`speaker.identity_aliases_reader`** · _beta_ · since 2026-05-21 — Phase 8WWW — read `~/.openalice/data/{agent}/identities/{slug_dir}/aliases.yaml` and return the merged `addressee_anchors ∪ nicknames` list, dedup'd (case-insensitive, case-preserving). Pure FS, no caching. Returns empty Vec on missing file / parse error so callers can silently degrade. Surfaces alias data to the per-turn prompt assembly so Alice merges NAO = Bassel = Бассель = NeuroAstralOwl in the `ActiveSpeakersSection` + `CurrentAddresseeSection` bullets.  
  *openalice_agents_memory::speaker:0*
- **`speaker.metrics_emit`** · _beta_ · since 2026-05-07 — Wave R3 — Prometheus counter emit helpers for `oa_speaker_resolved_total{source=...}` and `oa_speaker_continuity_total{result=...}`. Layered above `openalice_core::speaker` (which only defines the label strings) so the dep graph stays acyclic.  
  *openalice_agents_memory::speaker:0*
- **`speaker.resolver`** · _beta_ · since 2026-05-07 — Wave R3 — heuristic speaker_id → dossier resolver. Walks per-scope person dossiers for an exact match on `frontmatter.speaker_ids`. No LLM call; pure FS scan + string compare. Falls back to the platform display name + `unknown` source on miss.  
  *openalice_agents_memory::speaker:0*

### middleware
- **`middleware.auth`** · _stable_ · since 0.1.0 — JWT / Session / API-Key authentication middleware — multi-scheme principal extraction, signed-cookie session, HMAC API keys.  
  *openalice_middleware::auth:0*
- **`middleware.metrics`** · _stable_ · since 0.1.0 — [DEPRECATED alias — see observability.metrics.collector] HTTP metrics middleware — per-route counters, latency histograms, Prometheus text-format exporter for scrape.  
  *openalice_observability::metrics:0*
- **`middleware.ratelimit`** · _stable_ · since 0.1.0 — Per-user/IP token-bucket rate limit — configurable capacity + refill rate, emits standard `Retry-After` and `X-RateLimit-*` headers.  
  *openalice_middleware::ratelimit:0*

### modules
- **`alice.bridge.coalesce.shared`** · _beta_ · since 2026-05-07 — Phase 8W-4 — coalescer extracted into `openalice-coalesce` so /v1/chat (web platform) and the connector_bridge pipeline share one implementation and one `oa_coalesce_total` metric family.  
  *openalice_coalesce:0*
- **`alice.bridge.coalesce.strict_dedup`** · _beta_ · since 2026-05-15 — Phase 8EE-D — opt-in strict-dedup gate. When `OPENALICE_COALESCE_STRICT_DEDUP=1`, requests landing on a `(scope, speaker)` key within `2 × platform_window` of a prior drain are converted to Followers without entering the buffer. Collapses sequentially-fired probe traffic (rapid-fire-tg) and connector self-echo (discord double-reply) into one LLM call. OFF by default — prod chat flows behave exactly as today. Surfaces `oa_coalesce_strict_dedup_total{platform}` for operator dashboards.  
  *openalice_coalesce:0*
- **`alice.coalesce.lane_key_canon`** · _beta_ · since 2026-06-12 — Lane v2 M0 — canonical LaneKey derivation. One pure fn family (`canonical_scope` / `canonical_speaker` / `canonical_lane_key` / `lane_key_from_conv_id`) replaces the four divergent producer/consumer derivations that made commit_answer miss the writer's lane record (lanes wedged Processing → 2026-06-08 mass-replay class; eyes-sweep + eager-retry dead; scorer forced Clear). Canon: scope='{connector}--{source}', speaker=bare uid.  
  *openalice_coalesce::lane_key_canon:0*
- **`alice.coalesce.lane_persist`** · _beta_ · since 2026-05-19 — Phase 8XXX M5 — durable SQLite WAL persistence for the lane state machine. Every successful transition (on_inbound, begin_processing, commit_answer, mark_followup, reset_to_idle) is mirrored into a `lanes` table with WAL journaling. On boot `lane_state::boot_recovery` hydrates the registry and drains any Processing lane older than the orphan threshold, so a crash mid-LLM-turn cannot leave a lane wedged. OFF in unit tests (no persist hook); ON in `alice` boot via `install_lane_persist`.  
  *openalice_coalesce::lane_persist:0*
- **`alice.coalesce.lane_persist_v2`** · _beta_ · since 2026-06-12 — Lane v2 M1 — SQLite WAL persistence for the v2 lane model. `lanes_v2` table in the same db file as v1, slim discriminant rows (bundle/pending/turn_history as JSON columns, NULLable bundle), PER-ROW salvage on load (one corrupt row can no longer abort the whole hydrate) and a per-lane monotonic seq guard on upsert (stale fire-and-forget writes are skipped with a WARN).  
  *openalice_coalesce::lane_persist_v2:0*
- **`alice.coalesce.lane_registry_v2`** · _beta_ · since 2026-06-12 — Lane v2 M1/M4d — in-memory registry for the v2 lane model. LazyLock singleton constructed unconditionally with the persist layer swappable inside the shared handle (8ZZZ race class impossible by construction), v1-semantics mutators with the payload in current_bundle, per-lane monotonic seq stamped under the write lock, persisted pending-steer queue, and boot_recovery_v2 (unconditional Processing drain + process_epoch stamp + no-clobber hydrate). M4d recovery triple: boot moves a crashed Processing `current_bundle` into pending_queue (speaker preserved) instead of dropping it, and `drain_pending` re-injects parked items on the next natural inbound — superseding the v1 spontaneous pending-eyes replay under read_v2().  
  *openalice_coalesce::lane_registry_v2:0*
- **`alice.coalesce.lane_state`** · _beta_ · since 2026-05-19 — Phase 8XXX M1 — per-(agent, scope, speaker) lane state machine. Tracks Idle → Bundling → Processing → Answered ↘ FollowupNeeded so multi-speaker group chats run parallel lanes, restart-safety drops orphaned Processing lanes, and ANSWER_COMPLETENESS can mark unaddressed messages for retry per lane instead of chat-wide. Data layer only — wiring lives in M2 (coalesce), M3 (hot inject), M4 (scorer), M5 (persist + orphan drain).  
  *openalice_coalesce::lane_state:0*
- **`alice.coalesce.lane_v2_ack`** · _beta_ · since 2026-06-12 — Lane v2 M4b — commit-side ack lifecycle helpers (the Katya hanging-👀 cure). `covered_message_ids_for_clear` returns the FULL covered-id set (active bundle ids UNION parked pending_queue ids) so the reply / empty-response clear iterates EVERY message that got a 👀 this turn, not just the bundle anchor; `terminal_silence_sweep` is the 8OOO Invariant B tripwire (oa_lane_terminal_silence_total — metered WARN only, never blocks). All gated on read_v2(); a strict None / zero-report no-op under Off|DualWrite (byte-identical mvp).  
  *openalice_coalesce::lane_v2_ack:0*
- **`alice.coalesce.lane_v2_backfill`** · _beta_ · since 2026-06-12 — Lane v2 M2 — one-time idempotent v1→v2 migration. Reads every v1 `lanes` row, converts LaneState→LaneV2 (Bundling/Processing fold the bundle, FollowupNeeded folds the carry subset addressed=false, Answered/Waiting/Idle = discriminant), stamps process_epoch=0 so boot_recovery_v2 drains backfilled Processing rows, and upserts into lanes_v2. Idempotent: a key already live in lanes_v2 (process_epoch>0) is skipped. Pending-queue.db backfill runs in the alice boot path (cross-crate).  
  *openalice_coalesce::lane_v2_backfill:0*
- **`alice.coalesce.lane_v2_mirror`** · _beta_ · since 2026-06-12 — Lane v2 M2 — gated dual-write mirror. Pure fns wired at every v1 lane write site that mirror the transition onto the v2 registry ONLY when LaneV2Mode::write_v2() (DualWrite|V2Read|V2Only); a strict no-op under Off (byte-identical mvp). Best-effort: a v2 mutator reject (or a post-op state/bundle-id mismatch vs v1) bumps oa_lane_v2_divergence_total{site} + WARN, never propagates. The read path stays v1 in M2 — v2 is write-shadow-only.  
  *openalice_coalesce::lane_v2_mirror:0*
- **`alice.coalesce.lane_v2_mode`** · _beta_ · since 2026-06-12 — Lane v2 M0 — shared 4-value parser for OPENALICE_LANE_V2 (off|dual_write|v2_read|v2_only; legacy "v2" aliases to v2_read; unknown → Off with a once-per-process WARN). All seven pre-M0 exact-match `== "v2"` gates converge on this parser via `LaneV2Mode::current()` + the read_v2/write_v2/write_legacy helpers.  
  *openalice_coalesce::lane_v2_mode:0*
- **`alice.coalesce.lane_v2_read`** · _beta_ · since 2026-06-12 — Lane v2 M3/M4c — read-path projection helpers. `processing_bundle_for_read` (M3) projects a Processing lane's v2 current_bundle into the v1-shaped (Vec<LaneMessage>, BundleId) the scorer + eyes-sweep consumers expect, ONLY under LaneV2Mode::read_v2() (V2Read|V2Only); returns None under Off|DualWrite so reply/eager_retry keep the byte-identical v1 read path. `drain_payload_from_owned_bundle` (M4c buffer ownership) reproduces the v1 coalescer drain `(merged_text, coalesced_from)` from the OWNED v2 bundle ONLY under V2Only — the V2Only-only FollowupNeeded→Bundling carry-over delta (carried unaddressed + new in merged_text vs the v1 fresh-window's new-only) is pinned by the M5 parity tests. Returns None off-V2Only (v1 buffer drains). Mirror keeps v2==v1 (M2), so M3/M4c are byte-identical under Off|DualWrite.  
  *openalice_coalesce::lane_v2_read:0*
- **`alice.coalesce.lane_v2_types`** · _beta_ · since 2026-06-12 — Lane v2 M1/M4a/M4d — write-model data types for Lane-as-SoT v2. Discriminant-only LaneStateV2 (payload in current_bundle), BundleV2 (messages + steer_injected + reply_message_id + completeness_verdict + retry budget), persisted PendingSteerV2 queue, capped turn_history, process_epoch + per-lane seq. LaneMessageV2 carries the M4a per-message `addressed` flag (serde-default true; the FollowupNeeded→Bundling fold carries exactly the `addressed == false` subset). add_inbound implements the M4d Processing-inbound → pending_queue park (replacing the v1 IllegalTransition) so a message that arrives mid-flight rides the next natural inbound. Pipeline wiring lands in M2 (dual-write) / M3 (v2 read) / M4 (ownership + ack).  
  *openalice_coalesce::lane_v2_types:0*
- **`alice.coalesce.queue_accumulator_v2`** · _beta_ · since 2026-05-22 — Phase AGI P1.1 §4.1 — Q2 queue accumulator (turn-skip live fix). Adds Waiting(TTL=4s) state to the lane FSM. When OPENALICE_QUEUE_ACCUMULATOR=v2, a reply commit transitions the lane to Waiting instead of Answered; any follow-up inbound within the TTL immediately opens a new Bundling window, eliminating the 3-month turn-skip UX bug where consecutive user messages triggered N separate LLM calls. Default OFF — bit-identical to v1 when unset.  
  *openalice_coalesce::lane_state:0*
- **`delivery.boot_recovery.unified`** · _experimental_ · since 2026-07-10 — NAO 2026-07-10 — ONE orchestrator (run_boot_recovery) + ONE policy point (BootReplayPolicy / boot_replay_policy) replacing four scattered boot-time replay/recovery call sites (v1 PendingAfterQueue restore, pending_queue.db→lanes_v2 backfill, boot_recovery_v2's frozen-bundle carry, and Telegram's recover_pending_eyes crash renderer). Default policy is Drop (a crash clears the ack and does NOT re-answer); ReplayOnce re-delivers exactly once, deduped via a shared BootRecoveryReport so the v2 carry and a connector's own orphan scan can never both answer the same crashed message.  
  *openalice_coalesce::boot_recovery:0*
- **`plugin_host.bench.dispatch`** · _experimental_ · since 2026-04-25 — Wave G6 — criterion benchmark for `PluginHost::invoke` dispatch path using a no-op stub plugin. Measures the floor latency the host itself adds (registry lookup + RwLock + invoke). Adapters layer their own subsystem cost on top.  
  *openalice_plugin_host::benches::dispatch_perf:0*

### observability
- **`observability.audit.http`** · _stable_ · since 0.1.0 — Per-request HTTP audit channel — non-blocking mpsc, structured events for each request/response.  
  *openalice_observability::audit::http:0*
- **`observability.audit.merkle`** · _stable_ · since 0.1.0 — Merkle-chained audit log — typed AuditAction entries, SHA-256 hash chain, tamper detection (re-exported from openalice-core).  
  *openalice_observability::audit::merkle:0*
- **`observability.core.bootstrap`** · _stable_ · since 0.1.0 — Unified observability bootstrap — initializes tracing, OTLP export, metrics registry, and audit chain in one call.  
  *openalice_observability:0*
- **`observability.macros.span_meter_audit`** · _stable_ · since 0.1.0 — Unified macros — `alice_span!`, `alice_meter!`, `alice_audit!` — single grep target for span/metric/audit conventions.  
  *openalice_observability::macros:0*
- **`observability.metrics.collector`** · _stable_ · since 0.1.0 — In-process Prometheus metrics registry — counters, gauges, histograms, text exposition format.  
  *openalice_observability::metrics:0*
- **`observability.metrics.exporter_registry`** · _beta_ · since 2026-05-07 — Phase 8H — process-global Prometheus exporter registry. Each subsystem registers `fn() -> String` via `linkme::distributed_slice(METRICS_EXPORTERS)`. The /metrics handler walks the slice — no compile-time dep direction problem.  
  *openalice_observability::exporters:0*
- **`observability.metrics.http`** · _stable_ · since 0.1.0 — Canonical Prometheus metric + label constants — dashboards and alert rules reference a single source of truth.  
  *openalice_observability::prom_labels:0*
- **`observability.tracing.otel`** · _stable_ · since 0.1.0 — OpenTelemetry OTLP/gRPC exporter → Tempo — graceful degradation when endpoint unreachable, honours OTEL_DISABLED env. Compiled only when the `otlp` Cargo feature is enabled (default on).  
  *openalice_observability::otel:0*
- **`observability.tracing.subscriber`** · _stable_ · since 0.1.0 — Global tracing subscriber — JSON stdout fmt layer, optional OTLP layer, double-init safe.  
  *openalice_observability::tracing:0*

### openalice/agi_core
- **`openalice.agi_core`** — OpenAlice AGI Core — Phase 1 Q3 Lane v2 fat struct. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 **Audit reference**: `docs/q3-lane-v2-consumer-audit-2026-05-22.md` # PR sequence - **PR 1.2** (this crate): `Lane` definition + unit tests, no consumers. - **PR 1.3** (this crate): `From<coalesce::Lane>` backwards-compat shim. - **PR 1.4**: migrate `prompt_assembly.rs` behind `OPENALICE_LANE_V2=v2`. - **PR 1.5**: migrate remaining stages, flip env default. - **PR 1.6**: delete `coalesce::Lane` / `LaneSnapshot` / `ChatScope`. # Usage (post PR 1.4 consumer) ```ignore use openalice_asi_core::{Lane, LaneKey}; let lane = Lane::default(); let snapshot = lane.snapshot(); let blob = lane.to_runner_blob().unwrap(); let restored = Lane::from_runner_blob(&blob).unwrap(); ```  
  *crates/asi-core/src/lib.rs:1*
- **`openalice.agi_core.coalesce_compat_v1`** — Backwards-compat coalesce ↔ agi_core type conversions. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 # PR history - PR 1.3: added `From<CoalesceLane> for Lane` fat-struct bridge. - PR 1.4-1.5: bridge used by prompt_assembly + eager_retry + reply stages. - PR 1.7 step 5: `From<CoalesceLane> for Lane` deleted — zero production callers remain after the LaneRegistry trait was updated to return native `LaneSnapshot` directly. Only `LaneState` conversions remain, used by `registry::coalesce_lane_to_snapshot()`. # What remains - `From<CoalesceLaneState> for LaneState` — used by the adapter to build `LaneSnapshot.state` from a coalesce snapshot. - `From<LaneState> for CoalesceLaneState` — kept for symmetry and future write-path use (e.g. LanePersist migration).  
  *crates/asi-core/src/compat.rs:1*
- **`openalice.agi_core.cot_trace`** — Chain-of-thought trace types — Phase 1 PR 1.8 wired. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.3 (Q7) # Dual-type design Two structs live here: - [`CotTrace`] — typed, Lane v2 native. Uses `Uuid` + `DateTime<Utc>`. Used by `agi-safety`'s `Critic` trait and future Lane v2 turn records. - [`CotWireTrace`] — string-typed, sessions.jsonl-friendly. Parsed directly from the LLM's `<cot_trace>` JSON output. All optional fields for backward-compat with old turns. Persisted into `TurnRecord.meta["cot_trace"]` by the agentic loop. # PR sequence - **PR 2.1**: `CotTrace` type definitions only, no wiring. - **PR 1.8 (this)**: add `CotWireTrace` + `ContextSource` extensions. Wire `CotWireTrace` extraction + persistence in `agentic_loop.rs`. - **PR 2.7+ (Reflexion)**: reads `cot_trace` from sessions.jsonl to synthesise meta-learning signals. Converts `CotWireTrace → CotTrace`. - **PR 2.x Q7+2**: wire `CotTrace` into `Lane.turns` per turn record.  
  *crates/asi-core/src/cot.rs:1*
- **`openalice.agi_core.cot_trace`** — [derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] [serde(rename_all = "snake_case")]  
  *crates/asi-core/src/cot.rs:67*
- **`openalice.agi_core.cot_trace`** — [derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]  
  *crates/asi-core/src/cot.rs:104*
- **`openalice.agi_core.lane_key`** — Lane identity key — `(agent_id, chat_scope, user_id)` triple. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 `LaneKey` is the stable identity of a lane. It outlives any in-flight bundle and is used as the HashMap key in the registry and as the serialization identity in runner blobs. Unlike `coalesce::LaneKey` (which uses `scope` + `speaker`), Lane v2 uses the more explicit `chat_scope` + `user_id` naming to match the master-plan spec and the consumer audit field map.  
  *crates/asi-core/src/lane_key.rs:1*
- **`openalice.agi_core.lane_snapshot`** — `LaneSnapshot` — read-only projection of `Lane` state. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 # Why a separate snapshot type? `Lane` is the mutable source of truth. Consumers that need a stable read-only view (metrics exporters, `ReflexionWorker`, `LanePersist` write-through, runner blob construction) take a `LaneSnapshot` so: - They cannot accidentally mutate the live lane. - Snapshot can cross async `.await` points without holding the lane lock. - JSON representation is stable (subset of fields; no VecDeque churn). # Fields Snapshot omits raw `turns` / `bundles` / `scorer_history` VecDeques to keep the snapshot small and stable. Those are available on the full `Lane` when deep inspection is needed. # PR 1.7 addition `state: LaneState` — the native agi_core FSM state. Added so that `LaneRegistry::snapshot` callers can pattern-match on the state (e.g. `Processing { bundle_id }`) without going through `CoalesceLane`. The `state_name` string field is preserved for backwards-compat metrics.  
  *crates/asi-core/src/snapshot.rs:1*
- **`openalice.agi_core.lane_state_native`** — Lane state FSM — native agi_core enum (PR 1.6 sub-step 5). **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 + §4.1 # PR history - PR 1.2-1.4: was a transparent re-export of `openalice_coalesce::LaneState`. - PR 1.6 sub-step 5: replaced with a native enum that mirrors all coalesce variants (including Q2 `Waiting`) but sheds the raw message payloads — those stay in coalesce and are not part of the AGI-layer state. # Design rationale The AGI layer needs to reason about FSM state (e.g. "is the lane waiting?", "was the last bundle answered?") but does NOT need the raw `Vec<LaneMessage>` carried inside coalesce variants. Those live in the coalesce layer and are accessed via `coalesce::LaneRegistry::snapshot`. The native enum here is deliberately slim: it carries only the discriminant-level data needed for AGI decisions (bundle IDs, timestamps, TTL). # Conversion `From<coalesce::LaneState> for LaneState` is in `crates/agi-core/src/compat.rs` alongside the other coalesce→v2 conversion logic.  
  *crates/asi-core/src/lane_state.rs:1*
- **`openalice.agi_core.runner_blob`** — Runner blob — serialization helpers for `openalice-runner` forward-compat. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 # Purpose `openalice-runner` (future crate, deferred per NAO directive) will spawn isolated Alice instances and checkpoint their lane state across restarts. The runner blob format is a deterministic JSON bytes representation of `Lane` that: - Roundtrips losslessly (all fields, bounded collections included). - Uses stable field ordering (struct serialization = declaration order). - Carries `schema_version` so the runner can detect and reject or migrate blobs from older Lane definitions. # Determinism `serde_json::to_vec` on a struct serializes fields in declaration order (Rust struct order = JSON key order). This is stable across serde_json versions for `Serialize` on named fields. The blob is NOT pretty-printed to minimize size. # Forward-compat with openalice-storage-v2 Sessions are stored as `.jsonl` files under `sessions/{connector}-{chat_id}/{date_range}_{ulid}.jsonl` per the v2 storage layout. Runner blobs are NOT session records — they are in-memory checkpoints. The storage path is referenced here only so the runner knows where to write blobs during future wiring (PR 1.4+).  
  *crates/asi-core/src/runner.rs:1*

### openalice/agi_safety
- **`openalice.agi_safety.bootstrap`** — OpenAlice AGI Safety — Phase 2 Q5 Constitutional Critic scaffold. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.1 # Architecture This crate provides the `Critic` trait and two implementations: - [`ConstitutionalCritic`] — LLM-backed critic using Codex OAuth gpt-5.4-mini. Currently a **stub**: all verdicts return [`Verdict::Approve`] until PR 2.2 wires the actual LLM call. - [`ShadowCritic`] — observation-only critic. Records all events via structured tracing and always returns [`Verdict::Approve`]. Used when `OPENALICE_CRITIC_AGENT=off` or `=shadow` (default: `off`). # Environment variables | Variable | Values | Default | Effect | |---|---|---|---| | `OPENALICE_CRITIC_AGENT` | `on\|off\|shadow` | `off` | Selects critic impl | | `OPENALICE_CRITIC_MODEL` | model string | `gpt-5.4-mini` | LLM model (PR 2.2) | | `OPENALICE_CRITIC_GATE_LIST` | comma-separated | `tool_dispatch_mutating,response_draft` | Sync-gated event kinds | # PR sequence - **PR 2.1** (this crate): scaffold — types, trait, stubs, ShadowCritic, tests. - **PR 2.2**: wire `ConstitutionalCritic` → actual Codex LLM call. - **PR 2.3**: wire `review_sync` into `agentic_loop.rs` for mutating tools. - **PR 2.4**: wire `review_sync` for `ResponseDraft` before TG send. - **PR 2.5**: wire `periodic_audit` scheduler (every 20 turns per lane). # Usage (post PR 2.2 wiring) ```ignore use openalice_asi_safety::{build_critic_from_env, SyncEvent, Verdict}; let critic = build_critic_from_env(); let verdict = critic.review_sync( SyncEvent::ToolDispatch { tool_name: "shell".into(), args: serde_json::json!({}), is_mutating: true }, &lane, &trace, ).await; match verdict { Verdict::Approve => { /* proceed */ } Verdict::Veto { reason, .. } => { /* abort + log */ } Verdict::AskHuman { summary, .. } => { /* TG escalation */ } } ```  
  *crates/asi-safety/src/lib.rs:1*
- **`openalice.agi_safety.constitutional_critic`** — `ConstitutionalCritic` — LLM-backed Critic (Codex OAuth gpt-5.4-mini). **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.1 # Status: STUB — PR 2.1 This file defines the struct, env-loading, and [`Critic`] trait impl but does **NOT** make any LLM calls. All methods return placeholder verdicts until PR 2.2 wires the Codex OAuth client. # PR 2.2 TODO - Import `openalice_codex_oauth` (or equivalent HTTP client). - Replace `review_sync` stub with actual Codex API call using `OPENALICE_CRITIC_MODEL` (default `gpt-5.4-mini`). - Replace `periodic_audit` stub with LLM-based pattern analysis. - Add retry logic + circuit breaker (fall back to `ShadowCritic` on LLM timeout/error so the primary loop is never blocked indefinitely). # Env knobs | Variable | Default | Description | |---|---|---| | `OPENALICE_CRITIC_AGENT` | `"off"` | Must be `"on"` for this impl to be built | | `OPENALICE_CRITIC_MODEL` | `"gpt-5.4-mini"` | LLM model for critic calls | | `OPENALICE_CRITIC_GATE_LIST` | `"tool_dispatch_mutating,response_draft"` | Sync-gated event kinds | # Safety guarantee `ConstitutionalCritic` MUST NEVER modify Cat-A prompts (§5.1 kill list). Its LLM prompts (PR 2.2) are pure Cat-B instrumental — strictly input classification, not personality mutation.  
  *crates/asi-safety/src/constitutional_critic.rs:1*
- **`openalice.agi_safety.critic_trait`** — `Critic` trait — the core safety contract for the Constitutional Critic Agent. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.1 # Design The `Critic` trait has three methods: 1. **`review_sync`** — synchronous gate: called BEFORE executing a mutating tool or sending a response draft. Returns a [`Verdict`] that MUST be checked before proceeding. Blocking. 2. **`observe_async`** — fire-and-forget observer: called AFTER memory writes, proposal accepts, lane transitions. Does NOT block the primary loop. 3. **`periodic_audit`** — scheduled audit: called every N turns per lane (default 20). Returns findings that can be escalated. # PR note PR 2.1 defines types and trait. PR 2.2 wires actual LLM calls in `ConstitutionalCritic`. PR 2.3+ wires call sites in `agentic_loop.rs`.  
  *crates/asi-safety/src/critic.rs:1*
- **`openalice.agi_safety.envelope_judge`** — Behavioral Envelope LLM Judge — Phase 2 PR 2.10 (Q4 second half). **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.3 # Purpose When the variance gate ([`crate::envelope::check_envelope`]) returns [`crate::envelope::EnvelopeStatus::Collapsed`], we want a second-opinion check before triggering any rollback. The variance gate is fast + free but can produce false positives on legitimate stylistic shifts (vacation mode, formal register, etc.). The LLM judge is the slow + expensive confirmation gate that decides whether the collapse is real. # Design Mirrors `crates/agents-safety/src/constitutional_critic.rs`: - A [`EnvelopeJudge`] trait abstracts the LLM call so tests can inject mocks. - Concrete [`CodexEnvelopeJudge`] uses gpt-5.4-mini via Codex OAuth (production wiring deferred — initial impl returns `Unavailable` so callers fall back to the conservative `Acquitted` default). - JSON parse with markdown-fence strip; `Confirmed { reason }` vs `Acquitted { reason }`. - Daily USD cap (`OPENALICE_ENVELOPE_JUDGE_DAILY_USD_CAP`, default `0.10`) tracked in a process-global ledger. # Safety - Default `EnvelopeJudge` trait impl returns `Acquitted` → gate is conservative when no judge is configured (no false rollbacks). - LLM transport errors → `Acquitted` (fail-open: do nothing rather than rollback on stale evidence). - This module NEVER mutates Cat-A prompts. It only emits a [`crate::rollback::RollbackSignal`] structured event that the overlay layer reads.  
  *crates/asi-safety/src/judge.rs:1*
- **`openalice.agi_safety.envelope_reference_backfill`** — Backfill `prompts/envelope/reference.json` from Alice's sessions corpus. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.3 **PR**: Phase 2 PR 2.10 (Q4 second half) # Usage ```text cargo run -p openalice-asi-safety --bin build_envelope_reference -- \ --sessions-dir data/sessions \ --output prompts/envelope/reference.json \ --max-replies 200 ``` Defaults: - `--sessions-dir`: `data/sessions` (relative to cwd) - `--output`: `prompts/envelope/reference.json` - `--max-replies`: `200` # Behaviour 1. Walks `--sessions-dir` recursively for `*.jsonl` files. 2. Parses each line as JSON; selects records where `role == "assistant"` and `content` is a non-empty string. 3. Computes `ReplyFeatures` for each reply and feeds them into a `RunningStats` per dimension. 4. Writes the resulting `EnvelopeReference` to `--output` (pretty JSON). # Safety - **READ-ONLY** for sessions. This binary NEVER writes to `data/sessions/`. - If the sessions dir is missing or empty, the binary exits with a clear message and DOES NOT overwrite the output file. This preserves the PR 2.9 placeholder until real corpus data exists. - Pure stdlib + the agi-safety crate. No async runtime, no LLM, no network.  
  *crates/asi-safety/src/bin/build_envelope_reference.rs:1*
- **`openalice.agi_safety.envelope_rollback_signal`** — Envelope auto-rollback signal — Phase 2 PR 2.10 (Q4 second half). **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.3 # Purpose When the variance gate flags a reply as `Collapsed` AND the LLM judge `Confirmed` the collapse, this module emits a structured [`RollbackSignal`] event. The overlay-management layer subscribes to these signals and decides which Cat-B overlay (if any) should be rolled back. # Strict invariants 1. **Never touches Cat-A**: this module emits SIGNALS only. The actual rollback is performed by the overlay layer, which already refuses Cat-A targets (see `crates/prompt-composer/src/overlays.rs` `OverlayError::CatARefusal`). 2. **Pure data** — this is a serializable struct + a tracing helper. No I/O, no LLM calls, no state mutation. 3. **Hook is optional**: when no overlay layer is wired the signal is logged via tracing and dropped (no panic, no error). # Integration contract Consumers wire a [`RollbackSink`] implementation into the [`EnvelopeGate`](crate::envelope::EnvelopeGate) via [`EnvelopeGate::with_rollback_sink`](crate::envelope::EnvelopeGate::with_rollback_sink). When the gate runs in `judge` mode and the judge returns `Confirmed`, it builds a `RollbackSignal` and calls `sink.emit(signal)`. The default sink ([`LoggingRollbackSink`]) logs via tracing and never mutates anything — this is what production gets in PR 2.10 until the follow-up overlay-management PR wires a real consumer.  
  *crates/asi-safety/src/rollback.rs:1*
- **`openalice.agi_safety.envelope_variance_gate`** — Behavioral Envelope Variance Gate — Phase 2 PR 2.9 (Q4). **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.3 **Q4 decision**: B+C hybrid — variance gate first, LLM judge on alarm (LLM judge deferred to PR 2.10). # Design The envelope gate measures five behavioral dimensions on each reply and compares them against a reference distribution (loaded from a JSON corpus snapshot). If any dimension's z-score exceeds `alarm_threshold` σ, the gate trips and returns [`EnvelopeStatus::Drifting`] or [`EnvelopeStatus::Collapsed`]. ## Dimensions | Field | Description | |---|---| | `token_length` | Character count of the reply | | `russian_ratio` | Fraction of Cyrillic characters in [0, 1] | | `emoji_rate` | Emoji characters per 100 chars | | `wit_density` | Proxy: `?!` + `😄`-class chars per 100 chars | | `softener_freq` | Hedge words ("ну", "вот", "кстати" …) per 100 words | ## Thresholds (Q4 spec §5.3) - **`Drifting`**: 1–2 dimensions with `|z| > alarm_threshold` (default 3σ) - **`Collapsed`**: 3+ dimensions OR any dimension with `|z| > 5σ` `Collapsed` flags only **catastrophic** personality loss — sustained drift into robot-formal territory. Mood swings and chill-vacation tone are intentionally tolerated (they're legit shifts per Q4 decision). ## Env knobs | Variable | Values | Default | Effect | |---|---|---|---| | `OPENALICE_ENVELOPE` | `on\|off\|shadow` | `off` | Gate mode | | `OPENALICE_ENVELOPE_SIGMA` | float | `3.0` | Alarm threshold σ | | `OPENALICE_ENVELOPE_REFERENCE_PATH` | path | `prompts/envelope/reference.json` | Reference corpus | ## PR sequence - **PR 2.9**: variance gate + types + reference loading. Default `off`. - **PR 2.10** (this PR): LLM judge on `Collapsed` + structured [`RollbackSignal`](crate::rollback::RollbackSignal) emission via a pluggable [`RollbackSink`](crate::rollback::RollbackSink). The actual overlay rollback action is performed by the overlay-management layer (out of scope for `agi-safety`). # Safety guarantee - Default `OPENALICE_ENVELOPE=off` → zero behavioral change (bit-identical). - This module NEVER modifies Cat-A prompts. Rollback signals are scoped to `Cat-B` only (see [`RollbackSignal::target_layer`](crate::rollback::RollbackSignal)). - LLM calls only happen in `judge` mode AND only when the variance gate has already returned `Collapsed`. Cost-capped via `OPENALICE_ENVELOPE_JUDGE_DAILY_USD_CAP` (default $0.10).  
  *crates/asi-safety/src/envelope.rs:1*
- **`openalice.agi_safety.gating_policy`** — Gating policy config — which events are sync-gated vs async-observed. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.1 # Policy semantics The `GatingPolicy` is loaded from environment variables at startup and determines which `SyncEvent` kinds trigger a blocking Critic call vs which are just async-observed. Default policy (per spec §5.1): | Event kind | Behavior | |---|---| | `tool_dispatch_mutating` | SYNC-GATE (blocking) | | `response_draft` | SYNC-GATE (blocking) | | `tool_dispatch_readonly` | ASYNC-OBSERVE only | | `memory_write` | ASYNC-OBSERVE | | `proposal_accepted` | ASYNC-OBSERVE | | `lane_transition` | ASYNC-OBSERVE | # Env knobs - `OPENALICE_CRITIC_GATE_LIST` — comma-separated list of event kind keys that are sync-gated. Default: `tool_dispatch_mutating,response_draft`. - `OPENALICE_CRITIC_AUDIT_INTERVAL` — turns per lane between periodic audits. Default: `20`.  
  *crates/asi-safety/src/policy.rs:1*
- **`openalice.agi_safety.shadow_critic`** — `ShadowCritic` — observe-only Critic that always returns `Approve`. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §5.1 (env knobs) # Design `ShadowCritic` is the default implementation when: - `OPENALICE_CRITIC_AGENT=off` (unset or explicitly disabled) - `OPENALICE_CRITIC_AGENT=shadow` (run but don't enforce) It records all events via structured tracing without any side-effects. This makes it safe to deploy first, collect logs/metrics about what events the Critic *would* have seen, and verify the wiring before activating the `ConstitutionalCritic` in `on` mode. # Metrics `ShadowCritic` uses `tracing::info!` for every event so that the structured log exporter (Grafana/Tempo via OTLP) can surface event rates without any additional counter wiring in this PR. PR 2.2 may add explicit Prometheus counters once the call sites are wired.  
  *crates/asi-safety/src/shadow.rs:1*

### openalice/cot
- **`openalice.cot.emission`** — no description  
  *crates/agents/src/agentic_loop/helpers.rs:132*
- **`openalice.cot.emission`** — no description  
  *crates/api-handlers/src/http/routes/chat_tools/agentic_loop/cot.rs:71*
- **`openalice.cot.emission`** — [allow(dead_code)] // TODO Phase D Step 5c — CoT trace will be in agents  
  *crates/api-handlers/src/http/routes/chat_tools/agentic_loop/cot.rs:31*
- **`openalice.cot.emission`** — no description  
  *crates/api-handlers/src/http/routes/chat_tools/agentic_loop/cot.rs:15*
- **`openalice.cot.emission`** — no description  
  *crates/api-handlers/src/http/routes/chat_tools/agentic_loop/cot.rs:88*
- **`openalice.cot.emission`** — no description  
  *crates/agents/src/agentic_loop/helpers.rs:120*
- **`openalice.cot.emission`** — no description  
  *crates/agents/src/agentic_loop/helpers.rs:99*
- **`openalice.cot.emission`** — no description  
  *crates/agents/src/agentic_loop/helpers.rs:94*

### openalice/delivery
- **`openalice.delivery.router`** — Universal typed DeliveryRouter trait + in-memory router + per-(platform, modality) adapter dispatch + retry policy + audit hook. Phase 8CCCC-A scaffold — dark until Phase B wires all 6 connectors × 7 modalities. Existing per-platform send paths keep current code; MIGRATION (8CCCC) markers at each site guide Phase B. Gated by OPENALICE_OUTBOUND_DELIVERY. ═══════════════════════════════════════════════════════ CRATE: openalice-delivery PURPOSE: Phase 8CCCC — Universal Unification §3.7. Canonical typed `DeliveryRouter` trait + in-memory router + per-(platform, modality) adapter dispatch + retry policy + audit hook (Phase B will wire 8LLLL bus). Phase A scaffold ONLY: zero migrations, zero call-site changes. Existing connector send paths keep their current per-platform send code; this crate is dark until Phase B (pending NAO). FEATURES (this file): - delivery.router.trait        (linkme: delivery.router.trait        | phase: 8CCCC) - delivery.router.in_memory    (linkme: delivery.router.in_memory    | phase: 8CCCC) - delivery.envelope            (linkme: delivery.envelope            | phase: 8CCCC) - delivery.adapter             (linkme: delivery.adapter             | phase: 8CCCC) - delivery.error               (linkme: delivery.error               | phase: 8CCCC) - delivery.metrics             (linkme: delivery.metrics             | phase: 8CCCC) - delivery.registration_slice  (linkme: delivery.registration_slice  | phase: 8CCCC) LAST VERIFIED: 2026-05-20 (Phase 8CCCC Phase A) ═══════════════════════════════════════════════════════ AUDIT (8CCCC Phase A) — 2026-05-20 ═══════════════════════════════════════════════════════════════════ Scope: every outbound delivery call-site across connectors + chat reply pipeline. Phase A leaves a one-line `// MIGRATION (8CCCC):` marker at each site; Phase B migrates them to `router.send(envelope).await`. SUMMARY: 6 channels (telegram, discord, matrix, web, voice, a2a) × up to 7 modalities (text, photo, voice, file, reaction, typing, edit). The send paths today are fragmented: * Telegram is the richest surface — text + photo + document + voice + media_group + edit + reaction + typing_action, all dispatched through `TelegramRestClient::send_*` directly. The reply.rs pipeline stage in `crates/alice/src/connector_bridge/stages/reply.rs` hardcodes a Telegram-specific edit-then-fallback flow. * Discord uses `DiscordRestClient::send_message` / `send_message_with_components` / `edit_message` / `edit_message_rich` / `send_typing` / `send_embed`. `crates/alice/src/discord_response.rs::send_rich_response` wraps the rich-embed/button path the reply.rs stage uses. * Matrix landed in Wave M (8GGGG context) — currently `MatrixClient::send_text` only (Text modality). Photo / voice / edit / reaction are TODO at the adapter and so Phase B Matrix adapter advertises `supports(Text) == true` only. * Web SSE / WebSocket is **not** outbound delivery in the same shape — chat responses stream via SSE from `api-handlers/src/http/routes/chat.rs` while the request is in-flight; this is full-duplex per-request, not an address-and-fire-message surface like Telegram. Modelling it as a `DeliveryAdapter` is a Phase-B-or-later design decision (see "design choices flagged for NAO review" below). * Voice room delivery (TTS audio → SFU peer) lives in `openalice-voice-agent` (a SEPARATE repo, sibling to this one — see memory `reference-voice-stack-three-layers.md`). The voice agent process JOINS rooms rather than being imported; the `voice` channel in this catalogue is a placeholder for the future case where Alice produces a Voice envelope from the reply pipeline (e.g. "speak this in room X"), which today goes via a separate HTTP call into the voice agent's internal API. * A2A (bot-to-bot) outbound goes through `api-handlers/src/http/routes/v2.rs` /tasks/{id}/complete + federation.rs send-task. The reply.rs stage already has an A2A-specific branch that POSTs to /internal/tasks/{id}/complete. ┌──────────┬──────────────────────┬──────────────────────────────────────────────────────────────────────┬──────────────────────────────────────┬───────────────────────────────┐ │ Channel  │ Surface              │ Current call site                                                    │ Reply-to / threading                 │ Failure handling              │ ├──────────┼──────────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────────────────────────┼───────────────────────────────┤ │ telegram │ text                 │ modules-connectors/src/connectors/telegram/rest_client.rs:1025       │ `reply_to_message_id` i64 in body    │ anyhow::Result; bridge logs   │ │          │                      │ telegram/host.rs:892,987,1004,1021,1032,1047,1050,1061,1093,…       │                                      │ + warn! on send_response fail │ │          │ photo                │ telegram/rest_client.rs:1148, 1410 (send_photo_path)                 │ reply_to_message_id                  │ warn! + best-effort fallback  │ │          │ document             │ telegram/rest_client.rs:1178, 1433 (send_document_path)              │ reply_to_message_id                  │ warn! + best-effort fallback  │ │          │ voice                │ telegram/rest_client.rs:1228 (send_voice)                            │ reply_to_message_id                  │ warn! + best-effort fallback  │ │          │ media_group          │ telegram/rest_client.rs:1465 (send_media_group_paths)                │ reply_to_message_id on cover         │ warn! + tail-split fallback   │ │          │ edit                 │ telegram/rest_client.rs:1115 (edit_message_text); reply.rs:74        │ N/A (target msg_id in path)          │ warn! + send-as-new fallback  │ │          │ reaction             │ telegram/rest_client.rs::set_message_reaction; host.rs:690,713,1281  │ N/A (target msg_id in body)          │ `let _ =` (silent)            │ │          │ typing               │ telegram/rest_client.rs:1106 (send_chat_action); host.rs:1295,1555   │ N/A                                  │ `let _ =` (silent)            │ │ discord  │ text                 │ modules-connectors/src/connectors/discord_bot/rest_client.rs:65,127  │ message_reference in JSON body       │ anyhow::Result                │ │          │ embed                │ discord_bot/rest_client.rs:292,357 (send_embed, edit_message_rich)   │ message_reference                    │ anyhow::Result                │ │          │ components (buttons) │ discord_bot/rest_client.rs:304 (send_message_with_components)        │ message_reference                    │ anyhow::Result                │ │          │ edit                 │ discord_bot/rest_client.rs:188 (edit_message)                        │ N/A (target id in path)              │ anyhow::Result                │ │          │ reaction (add)       │ discord_bot/rest_client.rs::add_reaction (called from reply.rs:43)   │ N/A (msg_id in path)                 │ `let _ =`                     │ │          │ reaction (remove)    │ reply.rs:42 (remove_own_reaction)                                    │ N/A (msg_id in path)                 │ `let _ =`                     │ │          │ typing               │ discord_bot/rest_client.rs:232 (send_typing)                         │ N/A                                  │ anyhow::Result                │ │ matrix   │ text                 │ modules-connectors/src/connectors/matrix/client.rs:313 (send_text)   │ m.relates_to.in_reply_to             │ anyhow::Result                │ │          │ (photo/voice/edit)   │ NOT IMPLEMENTED in Phase A — adapter `supports()` returns false      │                                      │                               │ │ web      │ text (SSE chunk)     │ api-handlers/src/http/routes/chat.rs (Sse::stream + chat_tools)      │ N/A (in-flight req/resp)             │ stream-level error frames     │ │          │ ws frames            │ api-handlers/src/http/routes/v2.rs (Ws upgrade)                      │ N/A                                  │ ws-level error                │ │ voice    │ tts speech in room   │ openalice-voice-agent (sibling repo, joined-not-imported)            │ N/A (TTS one-shot)                   │ external process              │ │ a2a      │ task completion      │ api-handlers/src/http/routes/v2.rs::tasks_complete; reply.rs:173-201 │ task_id (carries reply linkage)      │ warn! on POST failure         │ │          │ task message         │ api-handlers/src/http/routes/federation.rs                           │ task_id                              │ Result                        │ └──────────┴──────────────────────┴──────────────────────────────────────────────────────────────────────┴──────────────────────────────────────┴───────────────────────────────┘ Migration markers planted in Phase A (one comment per send-call-site, no behaviour change): * crates/modules-connectors/src/connectors/telegram/rest_client.rs: - send_message (above pub async fn) - send_chat_action - edit_message_text - send_photo - send_document - send_voice - send_photo_path - send_document_path - send_media_group_paths - set_message_reaction * crates/modules-connectors/src/connectors/discord_bot/rest_client.rs: - send_message - send_message_with_id - edit_message - send_typing - send_embed - send_message_with_components - edit_message_rich * crates/modules-connectors/src/connectors/matrix/client.rs: - send_text * crates/modules-connectors/src/connectors/discord.rs: - send (generic BaseConnector path) * crates/alice/src/connector_bridge/stages/reply.rs: - top of stage: notes the whole stage is the migration target * crates/alice/src/connector_bridge/mod.rs: - send_to_connector (the generic dispatcher) * crates/api-handlers/src/http/routes/chat_tools/tools_media.rs: - the TTS provider arm (this is provider routing — see 8IIII — but the audio bytes are then delivered through Telegram/Discord which IS a delivery surface; the marker notes the linkage). Files added in Phase A (this PR): * crates/openalice-delivery/Cargo.toml          — NEW crate * crates/openalice-delivery/src/lib.rs          — AUDIT + feature registry entries * crates/openalice-delivery/src/envelope.rs     — NEW * crates/openalice-delivery/src/adapter.rs      — NEW * crates/openalice-delivery/src/error.rs        — NEW * crates/openalice-delivery/src/router.rs       — NEW (trait + impl) * crates/openalice-delivery/src/metrics.rs      — NEW * crates/openalice-delivery/tests/phase_8cccc_router.rs — NEW (integration tests) * Cargo.toml                                    — add workspace member + dep alias * `// MIGRATION (8CCCC): …` markers at each call-site listed above Phase B migration order (recommended, easiest → hardest): 1. Matrix — single surface (send_text); the adapter advertises Text-only `supports()` and the migration is mechanical. 2. Web SSE — actually a request-response pattern, may not be a DeliveryAdapter at all (see "design choices for NAO" below). If it IS, the surface is small (one streaming text path). 3. A2A — task complete is HTTP POST. Wrap as Adapter::deliver and retire the inline reqwest call in reply.rs:173-201. 4. Discord — text + embed + reaction + edit + typing. Component buttons are an embed-flavoured Text variant; map cleanly. 5. Voice — only if Alice's reply pipeline starts producing Voice envelopes directly (today it's the voice agent that pulls messages, not us pushing audio). 6. Telegram — LAST. Largest surface, most platform-specific quirks (parse_mode, inline keyboards, media groups, reaction removal-by-empty-string, send_response w/ choice-button HTML extraction). The reply.rs Telegram branch is the heaviest migration target — but by then the other 5 channels have validated the trait shape. END AUDIT ═══════════════════════════════════════════════════════════════════  
  *crates/openalice-delivery/src/lib.rs:1*

### openalice/events
- **`openalice.events.dispatcher`** — Event handler registration for cross-module communication. Wires: TOPIC_TASK_CREATED → calendar sync, TOPIC_AGENT_SPAWNED → soul/XP init, TOPIC_CONNECTOR_MESSAGE → connector bridge (64-task semaphore, 3-30s LLM turns), TOPIC_TASK_COMPLETED → XP award, TOPIC_SECURITY_ANOMALY → alerting. Also provides derive_speaker_id helper that stamps tg:{user_id} onto Message.speaker_id for identity resolution (Phase 8WWW). ═══════════════════════════════════════════════════════ MODULE: mod_events.rs PURPOSE: Event handler registration for cross-module communication. Wires event subscriptions that connect Alice's subsystems: task→calendar sync, router reload, connector init, alert escalation, mission completion, federation sync, etc. LAST VERIFIED: 2026-04-13 ═══════════════════════════════════════════════════════  
  *crates/alice/src/modules/mod_events.rs:1*

### openalice/lane
- **`openalice.lane.eager_retry`** — @feature openalice.stages.eager_retry_v2_gate SOTA eager-retry for ANSWER_COMPLETENESS: runs INSIDE the same pipeline turn after the first-pass agentic loop. Synthesises a second-pass User message from carry-over (unaddressed) messages, re-enters run_agentic_loop with byte-identical persona/soul context, concatenates both replies into ONE merged message. Sets followup_handled_eagerly=true so reply stage commits the lane as Answered without a redundant scorer re-run. ═══════════════════════════════════════════════════════ MODULE: stages::eager_retry PURPOSE: Phase «turn-skip eager-retry fix» (2026-05-22, NAO directive) — SOTA eager-retry consumer for the ANSWER_COMPLETENESS scorer. Runs INSIDE the same pipeline turn, AFTER the first-pass agentic loop and BEFORE the `reply` stage. When the scorer flags one or more messages in the coalesced bundle as unaddressed by Alice's first-pass reply, this stage: 1. Synthesises a second-pass User message containing JUST the carry-over subset (the messages the LLM skipped). 2. Re-enters `run_agentic_loop` with the SAME tools list + the SAME conversation history (system prompt, prior history, first User, first Assistant) + the new carry-over User. NO ad-hoc prompt: the second pass sees the same byte-identical persona / soul / connector context as the first. 3. Extracts the second-pass assistant text and CONCATENATES it to the first-pass `ctx.response_text` so the user sees ONE merged message containing all N answers. 4. Sets `ctx.followup_handled_eagerly = true` so the downstream `reply` stage skips its (now-redundant) scorer block and commits the lane as `Answered`. DESIGN NOTES: - Per NAO's personality-preservation directive (`feedback-prompt-byte-identical-preservation-2026-05-21`), the second-pass call MUST reuse the same prompt assembly. We do this by appending the carry-over User to the FULL message list from the first turn's `resp.messages` — that list already contains `[System(personality+soul+connector), …history, User(first), Assistant(first), Tool…]` — and re-using `ctx.tools_for_retry` (snapshot from `prompt_assembly`). No `assemble_for_connector_*` re-call is needed because the system prompt rides on resp[0]. - Per-lane isolation: each PipelineCtx instance owns its own pipeline invocation. Two concurrent lanes both in `FollowupNeeded` run their eager retries on independent tokio tasks (one task per inbound). No shared state across lanes; no deadlock risk. - Retry-budget cap = 1 is enforced by `answer_completeness` `retry_table()` keyed on `BundleId`. Budget-relocation fix (2026-07-10): the budget is spent HERE, at this stage's LAUNCH site (right before the second-pass `run_agentic_loop` call) — NOT inside the scorer the moment it decides `Incomplete`. A structurally-failed attempt (no LLM driver registered, or `ctx.resp` unexpectedly absent) never reaches the launch site, so it never spends the bundle's one shot; the `reply` stage's own fallback scorer call (gated on `followup_handled_eagerly`) then gets a fair, unburned look at the SAME bundle instead of finding a budget some earlier, launch-less pass already exhausted. See `answer_completeness::bump_retry_budget`'s doc for the full rationale. The second-pass call inside this stage still does NOT re-invoke the scorer, so the cap remains structurally honoured — one bundle gets at most one eager retry per turn. - Conservative-by-default: any error in the retry path (scorer failure, LLM error, parse error, empty second-pass body) falls back to `Clear` semantics — the first-pass `ctx.response_text` remains, the lane transitions to `Answered`, and the user sees the original (partial) reply. A bad retry must NEVER block delivery of an existing first-pass answer. FEATURES: - alice.connector_bridge.stages.eager_retry (linkme: eager-retry consumer | phase: turn-skip 2026-05-22) ═══════════════════════════════════════════════════════ Phase «turn-skip eager-retry fix» (2026-05-22) — eager consumer of `ScorerVerdict::Incomplete` that runs a second-pass agentic loop on the carry-over subset in the SAME turn, merges the two replies, and sets `ctx.response_text` to the merged text before `reply` delivers.  
  *crates/alice/src/connector_bridge/stages/eager_retry.rs:1*
- **`openalice.lane.inbound_aliases`** — Opportunistic inbound-triggered aliases.yaml bootstrap (Phase 8WWW). On first sighting of an unknown user, seeds identities/{slug_dir}/aliases.yaml from connector-supplied metadata (TG first_name + username). Slug derives as {platform}-{native_id} matching derive_speaker_id in mod_events.rs. NEVER overwrites hand-curated files. Fail-open: IO errors log warn only. Runs AFTER inbound_avatar, BEFORE prompt_assembly so the new file is readable on the same turn. ═══════════════════════════════════════════════════════════════════════════ MODULE: inbound_aliases PURPOSE: Phase 8WWW follow-up — opportunistic, inbound-triggered `identities/{slug_dir}/aliases.yaml` bootstrap. WHAT When a connector message arrives for a previously-unseen user and no hand-curated `aliases.yaml` exists, seed a minimal one from the connector-supplied metadata (TG `first_name`, optionally `username`): 1. Derive slug_dir = `{platform}-{native_id}` (matches the `sid.replace(':','-')` shape that `openalice_agents_memory::speaker::read_identity_aliases` expects — see `derive_speaker_id` in `mod_events.rs`). 2. If `aliases.yaml` already exists, no-op (NEVER overwrite a hand-curated file — NAO's `tg-670376626/aliases.yaml` is the canonical example we MUST preserve). 3. Otherwise, build a minimal YAML body from `ctx.msg.name` (TG `first_name` mapped onto `Message.name` upstream) and write it atomically (tempfile + rename). WHEN Position: AFTER `inbound_avatar` (avatar is the heavier work, this piggy-backs the same "first sighting" path) and BEFORE `prompt_assembly` (so `read_identity_aliases` finds the new file on the same turn). WHY OPPORTUNISTIC Fail-open: every IO error logs `warn` and continues. The user's inbound message must NEVER be blocked by an aliases bootstrap. WHY ATOMIC WRITES Half-written YAML poisons the read path (`serde_yml::from_str` returns an empty Vec, the prompt section silently loses anchors). Tempfile + rename gives crash-safety on the persistence path. SCOPE / TODO Today this stage seeds the bootstrap for TG only. The connector event payload currently puts `update.from` (first_name + last_name) under both `Message.name` and `ctx.username` — the TG `@handle` is NOT propagated through, so we cannot fill `handles.telegram.username` reliably. Once mod_drivers wiring forwards the @handle on the `connector.message` payload, we can extend the seed shape. TODO(discord): wire when Discord users supply `username` field reliably on `connector.message`. ═══════════════════════════════════════════════════════════════════════════  
  *crates/alice/src/connector_bridge/stages/inbound_aliases.rs:1*
- **`openalice.lane.state_machine`** — Per-(agent, scope, speaker) lane state machine — replaces the implicit one-bundle-per-chat assumption. States: Idle → Bundling → Processing → Answered → FollowupNeeded. In-memory LaneRegistry is source of truth; LanePersist trait hooks SQLite WAL via lane_state.db for crash recovery. Turn counts from this registry drive the B-hybrid reflexion scheduler.  
  *crates/coalesce/src/lane_state/mod.rs:1*

### openalice/prompt
- **`openalice.prompt.composer`** — Lego-block prompt assembly with SHA256 integrity guard on all 22 Cat-A blocks. Composer::open verifies every .md file against manifest.lock at boot — any drift is a loud panic (silent personality drift is worse than a crash). assemble_full(ctx) is gated by OPENALICE_PROMPT_COMPOSER=v2; unset = byte-identical legacy path. Cat-B bodies are composable; Cat-A is immutable and refuses every overlay attempt. `openalice-prompt-composer` — lego-block prompt assembly crate. # Phase 8NNNN-B status: B.3 wire-up ## What changed in B.3 The composer now actually reads the 22 Cat-A `.md` files from `prompts/blocks/{soul,modes,few-shot}/` at boot, computes SHA256 over each file, and verifies the result against the pinned hash in `manifest.lock`. Any mismatch is a FAIL-LOUD panic at `Composer::open` — silent personality drift is the one thing worse than a crash. `Composer::assemble_full(ctx)` is gated by the env flag `OPENALICE_PROMPT_COMPOSER`. Two values are recognised: - `"v2"` — route through the composer's verified-bytes path. The composer renders via `SectionBuilder::default_sections().build(ctx)` (the same path that read the Cat-A Rust string constants). Because `Composer::open` already proved every Cat-A `.md` is byte-identical to its Rust source via SHA256, the rendered output is BYTE-IDENTICAL to the legacy path. The composer's value here is the SHA256 guard on boot: the moment a `.md` or a Rust constant drifts, boot fails. - anything else (incl. unset) — legacy path, byte-for-byte unchanged. ## Why same-renderer-different-source achieves byte-identity The 22 Cat-A `.md` files were extracted byte-for-byte from the Rust string constants in B.2 (with SHA256 receipts in `manifest.lock`). At runtime today both paths read the same bytes: - The legacy path reads from the `&'static str` constants compiled into the binary. - The v2 path reads from the `.md` files via `std::fs::read` and verifies sha256 == lock pin == rust-source bytes. Both feed the identical `SectionBuilder` renderer. Output is identical by construction. The composer scaffolds the future `.md`-as-source-of-truth migration (B.4 hot-reload + B.5 lab cutover) without changing what the model actually sees. ## B.4 / B.5 roadmap (not in B.3) - **B.4** — Cat-B extraction: pull the 42 Cat-B blocks out of their `.rs` sources into `.md` files. SectionBuilder Block sections will call `Composer::assemble_section(slug, ctx)` instead of inlining string constants. Adds `notify`-based hot-reload + overlay layering. - **B.5** — Lab verification (NAO sign-off gate). Replay ~20-30 turns from NAO's recent chat history; warmth + 9-trait acceptance test; speaker-disambig probes. Single prod cutover after sign-off. ## Contracts - `docs/prompt-block-matrix-2026-05-21.md` — 63-row coverage matrix. - `docs/cat_a_hashes-2026-05-21.txt` — 22 Cat-A SHA256 pins. - `docs/prompt-composer-design-2026-05-21.md` — full design doc. - `feedback-no-ab-canary-on-prod-chats-2026-05-21.md` — why the env flag is the only B.3 fork (no per-chat A/B canary).  
  *crates/prompt-composer/src/lib.rs:1*
- **`openalice.prompt.overlays`** — YAML overlay system for Cat-B blocks — layers per-chat / per-agent / global YAML diffs on top of Cat-B block bodies at render time. Cat-A bodies are SHA-pinned and refuse every overlay (loud error). Wire-up into Composer::assemble_full is a follow-up wave (8MMMM-PPPP POC scaffold, wired and tested, pending SectionBuilder integration). Overlay system — Phase 8MMMM-PPPP POC. Layers per-chat / per-agent / global YAML overlays ON TOP of Cat-B block bodies at render time. Cat-A bodies are SHA-pinned and refuse every overlay attempt (loud error) so personality drift through this channel is impossible. See `docs/prompt-evolution-design-2026-05-22.md` for the full design. # Status POC scaffold. The `YamlOverlayLoader` impl is wired and tested; the Composer-facing `apply_overlays_to_cat_b` function is a pure transform that the existing renderer can call AFTER fetching a Cat-B body. The wire-up into `Composer::assemble_full` is a follow-up (per-block call sites in SectionBuilder Block sections), so this module is self-contained for testing.  
  *crates/prompt-composer/src/overlays.rs:1*

### openalice/reflexion
- **`openalice.reflexion.bhybrid_scheduler`** — B-hybrid reflexion scheduling policy: fast-path keyed on completed-turn count since last reflection (OPENALICE_REFLEXION_TURN_THRESHOLD, default N=10) AND 24h daily floor backstop for quiet chats. Pure decision-logic scaffold — no I/O, no tokio; the tokio wiring lives in mod_reflexion.rs. Reuses lane_state LaneRegistry for turn counts (no parallel counter). ═══════════════════════════════════════════════════════ MODULE: reflexion::scheduler PURPOSE: Phase 8MMMM-PPPP follow-up — Reflexion scheduling strategy. Implements the B-hybrid policy NAO locked on 2026-05-22: fast-path scaled by chat activity (turn-count threshold) AND a 24h daily floor so quiet chats still get touched. The scheduler is a SCAFFOLD — wiring into the live tokio loop ships in a later phase. This module only owns the decision logic + unit tests. DESIGN: Two-input policy. (1) Activity counter — REUSES the existing per-(agent, scope, speaker) lane state in `openalice_coalesce::lane_state`. We count bundle transitions out of `Processing` (i.e. completed assistant turns) since the last Reflexion tick for the chat. No parallel counter: lane state is the source of truth (see `feedback-organic-evolution`). (2) Daily floor — backstop. If a chat hasn't been touched by fast-path within `daily_floor_window` (default 24h) of its last Reflexion run, the cron path triggers it. SAFETY: Pure scaffold. The trait surface returns a `Decision` enum; calling code (a future tokio worker) executes the decision. No I/O here, no live wiring into the Alice binary. FEATURES: - agents.reflexion.b_hybrid_scheduler (linkme: 8MMMM-PPPP B-hybrid scheduler scaffold | wave: 8MMMM-PPPP) ═══════════════════════════════════════════════════════ Reflexion scheduling — B-hybrid policy (activity + daily floor). See `docs/prompt-evolution-design-2026-05-22.md` §5 Q3 for the locked decision. NAO 2026-05-22: «B-hybrid» — fast-path triggers when a chat accumulates `N` turns since last Reflexion (default `N=10`, env-tunable), and a 24h cron sweep covers quiet chats. # Non-goals - Wiring into the alice runtime tokio loop. The decision logic is pure; the spawn site is a follow-up wave. - Persistence of the per-chat last-tick timestamps. The default impl carries an in-memory `BTreeMap`; a later wave can graft a durable store behind the `SchedulerStore` trait if needed.  
  *crates/agents/src/reflexion/scheduler.rs:1*
- **`openalice.reflexion.proposal_store`** — Filesystem-only retention sweeps for the Reflexion proposal directory. Implements NAO's locked Q4 decision: *.rejected proposals older than 30 days move into prompts/proposals/_archive/YYYY-MM/. Idempotent, never deletes (archive-not-delete policy). Active (unsuffixed) proposals are never touched — those are NAO's review queue. Pure helper, no tokio. ═══════════════════════════════════════════════════════ MODULE: reflexion::proposal_store PURPOSE: Phase 8MMMM-PPPP follow-up — retention sweeps for the Reflexion proposal directory. Implements NAO's locked Q4 decision (2026-05-22): rejected proposals older than 30 days move into `prompts/proposals/_archive/YYYY-MM/`. Archival is filesystem-level only (move + create dirs); deletion is forbidden per `feedback-memory-archive-not-delete`. DESIGN: Pure filesystem helper. No tokio, no schedule — the wiring wave drives this from a daily cron (same cadence as the B-hybrid scheduler's daily floor). Idempotent: re-running against an already-archived layout is a no-op. SAFETY: Only `*.rejected` files are touched. Active (unsuffixed) proposals are never moved — those are NAO's review queue. Per the memo, NO file is ever deleted. FEATURES: - agents.reflexion.proposal_archive_30d (linkme: 8MMMM-PPPP proposal archive | wave: 8MMMM-PPPP) ═══════════════════════════════════════════════════════ Proposal archive sweep — see module docs above. See `docs/prompt-evolution-design-2026-05-22.md` §5 Q4 for the locked decision. The proposal file lifecycle is: 1. `write_proposal()` lands `YYYYMMDDTHHMMSSZ-{scope}.yaml` in `prompts/proposals/`. NAO reviews; either renames to `.yaml.rejected` (or anything ending `.rejected`) or `mv`s into `prompts/overlays/`. 2. The `_archive` sweep here moves `*.rejected` older than the threshold (default 30 days) into `_archive/YYYY-MM/`. The bucket is keyed on the file's mtime year-month so a year of sweeps builds a tidy by-month browser. Active (un-suffixed) proposals are NEVER touched. They live until NAO acts on them.  
  *crates/agents/src/reflexion/proposal_store.rs:1*
- **`openalice.reflexion.proposal_synth`** — Heuristic-only proposal synthesizer for the Reflexion loop. Detects user follow-ups matching a "misunderstanding" regex (RU+EN) within a short window of the prior assistant reply, emits a YAML overlay PROPOSAL to prompts/proposals/. NEVER auto-applies — NAO is the review gate. LLM-backed synth (Q1) is a planned follow-up gated on NAO greenlighting token spend (OPENALICE_REFLEXION_LLM_SYNTH env, not yet wired). ═══════════════════════════════════════════════════════ MODULE: reflexion::proposal_synth PURPOSE: Phase 8MMMM-PPPP POC — heuristic-only proposal synthesizer for the Reflexion loop. Detects user follow-ups that match a "misunderstanding" regex (RU + EN) within a short window of the prior assistant reply, then emits a YAML overlay PROPOSAL to prompts/proposals/. NEVER auto-applies; NAO is the gate (per feedback-no-ab-canary-on-prod-chats and feedback-alice-free-to-evolve-no-personality-optimization). DESIGN: Source-trait + Synth-trait. The runtime injects the source (which reads chat_folders_outbox + answer-completeness audit log + recent inbox). The synth is pure: given the three feeds, return Option<ProposalDraft>. The writer serializes the draft to YAML and atomically writes to prompts/proposals/{ts}-{chat_scope}.yaml. SAFETY: Heuristic-only in this scaffold. No LLM call, no personality inference. The output is a flag for NAO ("this chat had N misunderstandings, here's the verbatim text"), not an autonomous tuning step. FEATURES: - agents.reflexion.heuristic_proposal_synth (linkme: 8MMMM-PPPP heuristic proposal synth | wave: 8MMMM-PPPP) ═══════════════════════════════════════════════════════ Reflexion proposal synthesizer — see module docs above.  
  *crates/agents/src/reflexion/proposal_synth.rs:1*
- **`openalice.reflexion.scheduler`** — Tokio spawn surface for the BHybridScheduler — maps per-lane ChatActivity from lane_state snapshots, drives heuristic proposal synth → disk write, and runs the daily 30-day archive sweep for rejected proposals. Off by default; opt in via OPENALICE_REFLEXION_ENABLED=true. Cat-A untouched: proposals target Cat-B block IDs only; composer refuses Cat-A overlays. Phase 8MMMM-PPPP — Reflexion B-hybrid scheduler boot wiring + end-to-end pipeline closure. Plumbs `openalice_agents::reflexion::scheduler::BHybridScheduler` into the alice runtime. The scheduler scaffold ships in `crates/agents/src/reflexion/scheduler.rs`; this module owns the tokio-side spawn surface, the per-lane → `ChatActivity` mapping, the heuristic synth → disk write step, and the daily archive sweep for rejected proposals (NAO Q4 lock: keep 30d, then move to `_archive/`). # Decisions honoured * **Q3 (NAO 2026-05-22)** — B-hybrid: fast-path at `N` turns since last reflection (default `N=10`, env `OPENALICE_REFLEXION_TURN_THRESHOLD`) + 24h daily floor backstop. * **Reuse lane_state** — turn counts come from `openalice_coalesce::lane_state::lane_registry().snapshot_all()`, no parallel counter. * **Q4 (NAO 2026-05-22)** — `*.rejected` proposals live flat for 30 days under `prompts/proposals/`, then the archive sweep moves them into `_archive/YYYY-MM/`. Never deletes (per `feedback-memory-archive-not-delete-2026-05-02`). # Safety posture * **Off by default** — `OPENALICE_REFLEXION_ENABLED` must be set to a truthy value before any tokio task spawns. When the flag is off the helper logs `reflexion: disabled` and returns immediately, so the synth / write / archive paths stay completely inert on production deploys until an operator opts in. * **No LLM** — the only synth used here is [`openalice_agents::reflexion::proposal_synth::HeuristicProposalSynth`] (pure regex + lane snapshot). Live LLM-backed synth is a separate wave gated on NAO greenlighting token spend. * **Cat-A untouched** — the proposals this module writes target Cat-B block ids only (`B-*`). The composer's overlay loader refuses any Cat-A target loudly at index time, so even a misconfigured synth cannot reach Cat-A through this channel.  
  *crates/alice/src/modules/mod_reflexion.rs:1*

### openalice/runtime
- **`openalice.runtime.boot`** — Alice binary entry point — boots HTTP server, connector bridge, event bus, reflexion scheduler, and all registered modules. Supports subcommands: serve (full stack), kernel (no HTTP), router (LLM proxy), cli (REPL), doctor, health, export, migrate, version. Env flags gate every experimental subsystem at startup (reflexion, storage-v2, composer-v2). OpenAlice CLI entry point. Full translation of Go `cmd/alice/main.go` (1,086 lines). Supported commands: ```text alice serve   --config path/to/config.yaml    Start the full API server --component all|core|router|worker  (default: all) alice kernel  --config path/to/config.yaml    Start the kernel (no HTTP) alice router  --config path/to/router.yaml    Start the LLM router proxy (standalone) alice cli     --config path/to/config.yaml    Interactive REPL mode alice init    [dir]                            Scaffold a new project alice doctor  --config path/to/config.yaml    Run self-diagnostics alice health  --addr http://localhost:8080     Check server health alice export  --config ... --format json       Export store data alice migrate --from URL --to URL              Migrate data between stores alice version                                  Print version ```  
  *crates/alice/src/main.rs:1*

### openalice/sessions
- **`openalice.sessions.cost_usd`** — no description  
  *crates/alice/src/storage_v2_session_wire.rs:222*
- **`openalice.sessions.cost_usd`** — no description  
  *crates/alice/src/storage_v2_session_wire.rs:142*
- **`openalice.sessions.cost_usd`** — no description  
  *crates/alice/src/storage_v2_session_wire.rs:171*
- **`openalice.sessions.cot_persistence`** — @feature openalice.sessions.meta_model_latency @feature openalice.sessions.cost_usd persist helper; struct refactor deferred [allow(clippy::too_many_arguments)]  
  *crates/alice/src/conversation_persist.rs:45*
- **`openalice.sessions.cot_persistence`** — no description  
  *crates/agents/src/agentic_loop/types.rs:98*
- **`openalice.sessions.cot_persistence`** — [allow(clippy::too_many_arguments)] [allow(dead_code)] // superseded by dual_write_v2_with_meta for new callers; kept for external callers without meta data.  
  *crates/alice/src/storage_v2_session_wire.rs:409*
- **`openalice.sessions.meta_model_latency`** — @feature openalice.sessions.cost_usd  
  *crates/alice/src/storage_v2_session_wire.rs:191*
- **`openalice.sessions.meta_model_latency`** — @feature openalice.sessions.cost_usd [allow(clippy::too_many_arguments)]  
  *crates/alice/src/storage_v2_session_wire.rs:449*

### openalice/stages
- **`openalice.stages.prompt_assembly_v2_gate`** — Stage: assemble the system prompt, tools list, and per-chat context. Preserves behavior from the pre-refactor monolith (lines 218-742): query embedding → `assemble_for_connector` → skill injection → per-chat persona context → the giant "Connector Context" prompt block (extracted to [`super::super::prompt_block`] for readability) → load people memory + per-user memory. The memory preload itself + emotion detection are done in the next stage ([`super::memory_preload`]) because they run in parallel and read values this stage sets. # Phase AGI P1.4 — Lane v2 env-gate When `OPENALICE_LANE_V2=v2` is set, this stage constructs a `Lane v2` (`openalice_asi_core::Lane`) from the pipeline context at entry and derives `preassemble_chat_scope` + `ctx.chat_scope` from the Lane v2 key. **Default (env unset / any value != "v2")**: existing path, bit-identical to pre-P1.4 behavior. No change to any downstream caller. **v2 path (`OPENALICE_LANE_V2=v2`)**: same derivation as the legacy path but via `Lane::key.chat_scope`. Produces byte-identical strings. The acceptance test `scope_derivation_byte_identical_across_env_gate` pins this contract. **Spec reference**: `docs/agi-master-plan-2026-05-22.md` §4.2 PR 1.4 **Audit reference**: `docs/q3-lane-v2-consumer-audit-2026-05-22.md` §PR 1.4  
  *crates/alice/src/connector_bridge/stages/prompt_assembly.rs:1*
- **`openalice.stages.reply_v2_gate`** — Stage: send the final response via the appropriate connector adapter. Preserves behavior from the pre-refactor monolith (lines 1243-1349): * Discord — rich embed/button path via `send_rich_response` * Telegram — edit the placeholder with HTML + inline keyboard, fallback to `send_response` or plain-text on failure * A2A — complete the task via the internal a2a service endpoint * other connectors — `send_to_connector` fallback (Slack, generic, …) Phase 8JJ-3 — also delivers `ctx.outbound_message_attachments` through the Telegram adapter via [`telegram::TelegramHost::send_attachments_with_caption`]. Discord / persona / voice are intentionally deferred to a follow-up phase; the field is read but only Telegram acts on it for now. MIGRATION (8CCCC): TODO this entire stage is the prime migration target — Phase B replaces each per-platform branch with `router.send(envelope)` over the canonical `DeliveryRouter`. The current shape (discord-then- telegram-then-a2a-then-generic if/else cascade) becomes a single `router.send(envelope_for_text)` + optional follow-up envelopes for attachments. Reply-edit semantics map to `DeliveryModality::Edit` with the placeholder's `MessageRef` in the payload.  
  *crates/alice/src/connector_bridge/stages/reply.rs:1*

### openalice/storage
- **`openalice.storage.v2`** — File-first storage compat-shim — mirrors the read API of legacy agents-refs + core::dossier + connector_history/ + memory/relations/ paths against the v2 on-disk layout: identities/{slug}/ + sessions/. Gated by OPENALICE_STORAGE_LAYOUT=v2; legacy paths untouched when unset. 18 read-site migration markers (docs/storage-shim-audit-2026-05-21.md). Re-enabling = spin ner container + set env flag; zero code work. ═══════════════════════════════════════════════════════════════════════════ CRATE: openalice-storage-v2 PURPOSE: Phase 8storage-B file-first storage compat-shim. Mirrors the read API of the legacy `agents-refs` + `core::dossier` + `connector_history/` blob + `memory/{agent}/relations/` paths against the NEW on-disk layout designed in `feedback-storage-file-first-simplified-2026-05-20.md`: identities/{folder}/profile.yaml identities/{folder}/aliases.yaml identities/{folder}/dossier.md identities/{folder}/by-chat/{conn}-{chat_id}.md identities/{folder}/avatar.* sessions/{conn}-{chat_id}/{date_range}_{ulid}.jsonl identities/_graph/edges.jsonl AUDIT (8storage-b1 scaffold) ────────────────────────────────────────────── Inputs:  data_root + agent_id + slug / chat_id / handle Outputs: Identity, Session, Edge values + iterators. This crate is **standalone** in Phase B-1 — no other crate imports it yet. Phase B-2 will add ~4 lines per audited read-site (gated on the `OPENALICE_STORAGE_LAYOUT=v2` env flag) to route reads through here while the legacy paths keep serving v1. See `docs/storage-shim-audit-2026-05-21.md` for the full read-site inventory (18 markers, 5 domains). THREAD SAFETY: every public type is `Send + Sync`. No interior mutability; the loaders are pure functions over `&Path`. FEATURE-REGISTRY ENTRY: this crate ships ONE `storage_v2.crate` marker so operators can `cargo xtask features --grep storage_v2` to find the dormant scaffold. The marker is `Experimental` until Phase B-2 wires it. ═══════════════════════════════════════════════════════════════════════════  
  *crates/openalice-storage-v2/src/lib.rs:1*

### openalice/tools
- **`openalice.tools.search_unified`** — Phase 8P register_tool! bridges for master-plan + bash-first stdlib tools whose handlers lived in agents::tools_builtins but were missing from ToolRegistry (Phase 8O gap: LLM emitted valid tool_use blocks, executor returned "unknown tool"). Covers: agent_spawn, dossier_read/link/anchor, tool_trace_read, memory_crystallize, skill_manage, and unified search actions dispatched through execute_builtin_tool → BUILTIN_TOOLS_MAP. ═══════════════════════════════════════════════════════ MODULE: tools_builtin_bridge.rs PURPOSE: Phase 8P — register_tool! bridges for master-plan + bash-first stdlib + utility tools whose handlers live in `openalice_agents::tools_builtins::handlers_misc::*` but were never wired into the `ToolRegistry` (the agentic loop's only dispatch path). Phase 8O proved the gap: Alice's LLM correctly emitted tool_use blocks for `skill_create`, `skill_run`, `agent_spawn`, `glob`, etc., but `execute_tool()` returned `"unknown tool: <name>"` because no `register_tool!` invocation existed. The handlers themselves are correct (Phase 7 + 8H/I/J). Each registration delegates to `super::dispatcher::execute_builtin_tool(name, &args)` which looks the tool up in `BUILTIN_TOOLS_MAP` and invokes its stateless sync handler. The dispatcher path already emits `TOPIC_TOOL_EXECUTED` + `TOPIC_AUDIT_ENTRY` via `finalize_tool_result`, and `is_mutating_tool` was widened in Phase 8N3 to flag the destructive master-plan tools. Wave coverage: - skill_manage  (Phase 8Y-T1, unified hermes-pattern surface; skill_create/update/run/list/activate registered separately in `tools_skills.rs` — this bridge is for the OTHER tools) - agent_spawn                                (Wave T) - dossier_read / dossier_link / dossier_link_anchor (Wave Q1/Q6/Q8) - tool_trace_read                            (Wave V) - memory_crystallize                         (Wave 8I) - bash / view / edit / write / glob / grep   (bash-first stdlib) - workspace_grep_essential - play_sound                                 (Wave K11) SEE: docs/phase-8p-dispatcher-arms.md  (this commit's design note) ═══════════════════════════════════════════════════════ Phase 8P transport-layer bridge for builtin master-plan tools. The legacy match-block dispatcher was retired in Track 5 in favour of the `register_tool!` linkme distributed slice. Tools that lived only in `BUILTIN_TOOLS` (with stateless handlers in `agents-tools::handlers_misc::*`) and never received a `register_tool!` invocation became invisible to the HTTP dispatcher — every call landed on the `"unknown tool: …"` fallback in `chat_tools::mod::execute_tool`. This file owns the bridge: each `register_tool!` here is a thin adapter that forwards to `dispatcher::execute_builtin_tool` (which consults `BUILTIN_TOOLS_MAP`). Adding a new master-plan tool that lives in `agents-tools::handlers_misc::*` only needs: 1. Append a `BuiltinTool { … handler: handle_foo, … }` entry to `agents-tools/src/tools_builtins/handlers_misc/mod.rs::BUILTIN_TOOLS`. 2. Append a `register_tool! { name: "foo", … }` invocation here so `TOOL_REGISTRY` discovers it on startup. Skipping step (2) reproduces the Phase 8O "unknown tool" regression. # Phase 8R — nested-runtime fix Phase 8P bridged sync `execute_builtin_tool(name, &args)` directly from the async `ChatToolHandler::execute` body. That worked for the pure-sync handlers (dossier_*, memory_crystallize, tool_trace_read, play_sound) but blew up for the bash-first stdlib: `handle_bash_command` in `agents-tools/src/tools_builtins/handlers_misc/bash_tool.rs:1197-1214` builds its own `tokio::runtime::Builder::new_current_thread()` and calls `rt.block_on(run_bash_async(...))`. Calling that from inside a running tokio reactor panics with `SIGABRT`: ```text thread 'tokio-runtime-worker' panicked: "Cannot start a runtime from within a runtime." ``` Phase 8Q's smoke chat surfaced this the first time the LLM emitted a `bash` tool_use block — the whole alice process crashed. Fix: every bridge entry whose inner handler is *blocking* (real CPU work, file I/O, nested runtime) now runs through [`run_builtin_blocking`] which dispatches the sync handler on the `spawn_blocking` thread pool. The thread pool is NOT a tokio runtime, so `rt.block_on(...)` inside `handle_bash_command` is safe. The pure-sync, fast handlers (no nested runtime, no large file I/O — dossier_*, memory_crystallize, tool_trace_read, play_sound) stay on the direct sync path. They never panic in 8Q and wrapping them in `spawn_blocking` would only add a thread-pool round-trip per call. `agent_spawn` uses `std::process::Command` (synchronous fork + wait) but does NOT construct a new tokio runtime — so it does not hit the panic. It runs sync; the latency cost is the subprocess itself, not the bridge.  
  *crates/api-handlers/src/http/routes/chat_tools/tools_builtin_bridge.rs:1*
- **`openalice.tools.tts_unified`** — TTS configuration tools — auto-inject ElevenLabs v3 emotion tags into plain text for anime-style delivery, and TTS config tool handlers extracted from chat_tools/mod.rs. Works with both REST first-byte and MSE streaming TTS paths (STREAMING_TTS=1 enables frame-locked lipsync via ElevenLabs WS stream-input). OA_TTS_PROVIDER selects the backend. TTS configuration tools — extracted from chat_tools/mod.rs.  
  *crates/api-handlers/src/http/routes/chat_tools/tools_tts.rs:1*

### ops
- **`config.caps`** · _beta_ · since 2026-05-19 — Phase 9a — composable capability blocks (image_gen / goal_autonomy / skill_curator / agent_kanban / durable_exec / coalesce / memory). Each block has an `enabled` flag plus cap-specific options. Replaces ad-hoc OPENALICE_* env-var feature flags as the preferred surface.  
  *openalice_config::caps:0*
- **`config.cli`** · _beta_ · since 2026-05-19 — Phase 9a — `alice-cli config init|get|set|validate|diff` verbs. Init writes a starter oa.deploy.yaml from a template; get/set drives the runtime overlay; validate runs the boot-time invariant validator; diff shows per-layer caps provenance.  
  *openalice_config::cli:0*
- **`config.compat`** · _beta_ · since 2026-05-19 — Phase 9a — back-compat shim that reads OPENALICE_* env vars iff the corresponding caps.* field is at its struct default. Emits a one-shot INFO log per env-resolved cap with a migration hint pointing to the oa.yaml key. Zero-disruption for existing prod deployments.  
  *openalice_config::compat:0*
- **`config.hot_reload`** · _stable_ · since 0.1.0 — fsnotify watcher on `alice.yaml` — applies changes to a narrow SAFE_FIELDS allowlist (log_level, timeout_per_attempt, admission rps/burst, cache TTL, safety caps). Unsafe diffs logged WARN and ignored until restart.  
  *openalice_config::hot_reload:0*
- **`config.loader.layered`** · _stable_ · since 0.1.0 — Layered loader with deterministic precedence: defaults ← yaml ← env ← cli. Each layer emits a DEBUG resolution log so field provenance is grep-able.  
  *openalice_config::loader:0*
- **`config.migration`** · _stable_ · since 0.1.0 — Legacy-yaml migrator — drops deprecated top-level secret keys (bot_token, jwt_secret, admin_cidrs, …) with a deprecation warning so stray historical yaml files don't leak secrets into logs or serialized snapshots.  
  *openalice_config::migration:0*
- **`config.schema.alice`** · _stable_ · since 0.1.0 — `AliceConfig` — canonical config root wrapping yaml `RuntimeConfig` + env overlay with redacted Debug for secrets. Replaces 4 prior config sources.  
  *openalice_config::schema:0*
- **`config.validator`** · _stable_ · since 0.1.0 — Boot-time invariant checks: require_auth needs jwt_secret, codex enabled needs credentials, memory.scope_default ∈ {full,curated,isolated}, observability.otel_endpoint must be a valid URI.  
  *openalice_config::validator:0*
- **`config.watcher`** · _beta_ · since 2026-05-19 — Phase 9a — `ConfigHandle` wrapping `tokio::sync::watch::Receiver<Arc<AliceConfig>>`. Pull-based snapshot + `rx.changed().await` subscribe API for AppState consumers. Layers in repo `oa.yaml` ← `oa.deploy.yaml` ← `~/.openalice/config/oa.yaml`.  
  *openalice_config::watcher:0*
- **`deploy.pipeline`** · _stable_ · since 0.1.0 — `alice-deploy` — six-layer deployment pipeline (lab tests, pre-deploy gates, atomic swap, auto-rollback, continuous monitor, self-heal). Separate binary from `alice` to break the chicken-and-egg.  
  *openalice_deploy::lab:0*
- **`xtask.features`** · _stable_ · since 0.1.0 — `cargo xtask features` regenerates `docs/FEATURES.md` + `features.json` from the `#[distributed_slice(FEATURES)]` registry. Deterministic output; `--check` fails CI on drift.  
  *openalice_schemas::features:0*

### packs
- **`packs.manager`** · _stable_ · since 0.1.0 — Pack lifecycle manager — install, enable, disable WASM packs keyed on manifest id/version with authored tools + prompts.  
  *openalice_modules::packs::manager:0*
- **`packs.wasm_loader`** · _stable_ · since 0.1.0 — Pack directory scanner — enumerates `.wasm` modules and registers them as `WasmSkill` / `WasmConnector` instances at `alice serve` startup.  
  *openalice_modules::packs::wasm_loader:0*
- **`packs.wasm_sandbox`** · _stable_ · since 0.1.0 — Pack-level WASM sandbox on wasmtime — memory limits, fuel-metered CPU, OOM detection, spawn/kill lifecycle, synchronous `execute_function`.  
  *openalice_modules::packs::wasm_sandbox:0*
- **`packs.wasm_skill`** · _stable_ · since 0.1.0 — WASM skill adapter — loads a `.wasm` module and executes it through `openalice_sandbox` with JSON in/out, capability-scoped host calls, and typed sandbox errors.  
  *openalice_modules::packs::wasm_skill:0*
- **`sandbox.backends`** · _stable_ · since 0.1.0 — Pluggable sandbox backends (Wasm / Process / Docker) behind a unified `SandboxBackend` trait with automatic fallback; Wasmtime-based default with deny-by-default capability checks.  
  *openalice_sandbox:0*

### plugin-host
- **`plugin_host.adapters.connector`** · _experimental_ · since 0.2.0 — ConnectorPluginAdapter — wraps a connector host's run loop + outbound function; start() spawns, stop() signals + bounded-await.  
  *openalice_plugin_host::adapters::connector:0*
- **`plugin_host.adapters.mcp`** · _experimental_ · since 0.2.0 — McpPluginAdapter — wraps a single MCPBridge-registered server; start() triggers discovery, invoke() calls bridge.execute.  
  *openalice_plugin_host::adapters::mcp:0*
- **`plugin_host.adapters.soul`** · _experimental_ · since 0.2.0 — SoulPackPluginAdapter — wraps an AgentTemplate; invoke("descriptor") materializes an AgentDescriptor for spawn.  
  *openalice_plugin_host::adapters::soul:0*
- **`plugin_host.adapters.wasm`** · _experimental_ · since 0.2.0 — WasmPluginAdapter — wraps openalice_sandbox::WasmSandbox modules as Plugins; capability list extracted from ModuleManifest.  
  *openalice_plugin_host::adapters::wasm:0*
- **`plugin_host.adapters.worker`** · _experimental_ · since 0.2.0 — WorkerPluginAdapter — wraps a single Hand registered with WorkerManager; start/stop = enable/disable, invoke("run_now") = run_now.  
  *openalice_plugin_host::adapters::worker:0*
- **`plugin_host.bootstrap.workers`** · _experimental_ · since 0.2.0 — Supplemental PluginHost wiring for the Worker adapter from alice::main, gated by ALICE_PLUGIN_HOST_WORKERS=1. Default OFF — the existing WorkerManager driver stays primary. Track D1.  
  *openalice_alice::modules::mod_plugin_host:0*
- **`plugin_host.lifecycle.ordering`** · _experimental_ · since 0.2.0 — Canonical start order Soul → Wasm → Mcp → Worker → Connector (stop = reverse) avoids boot races between subsystems.  
  *openalice_plugin_host::lifecycle:0*
- **`plugin_host.trait.plugin`** · _experimental_ · since 0.2.0 — Unified Plugin trait — id/kind/capabilities/initialize/start/stop/invoke/health — implemented by adapters wrapping WASM, MCP, soul packs, connectors, workers.  
  *openalice_plugin_host::plugin:0*

### prompt
- **`prompt.capability_prefs.per_agent`** · _experimental_ · since 2026-07-09 — Per-AGENT override of the 5 global turn-pipeline capability flags (`caps.deliberation.{verify,plan,tool_verify}`, `caps.critic.gate_reintegration`, `caps.answer_all` — crates/agents/src/agentic_loop/turn_pipeline/live_caps.rs), exactly mirroring the injectors.calendar/injectors.packs tri-state pattern: `resolve_agent_capability_prefs` reads the agent's descriptor `config."caps.*"` markers, EACH resolved INDEPENDENTLY by its own key's presence — an absent key yields `None` ("no opinion", falls through to the global live_config/env cap), a present key yields `Some(bool)` (malformed value -> false), and a markerless agent (or a config map that carries other markers but none of these 5 keys) resolves to `CapabilityPrefs::default()` (all `None`) — byte-identical to today's global-only cap resolution. Threaded onto `AgenticLoopServices::capability_prefs` by `agentic_loop_services_from_appstate`; consumed by `live_caps::*_for` at every stage call-site (DeliberationStage, CriticGateStage, the turn-start turn_plan call, the answer_all arm in IterationHeadStage).  
  *openalice_api_handlers::http::routes::chat_prompt::assembler::agent_meta:0*
- **`prompt.capability_prefs.per_chat`** · _experimental_ · since 2026-07-10 — Per-CHAT override of the 5 global turn-pipeline capability flags, layered ON TOP of prompt.capability_prefs.per_agent: `resolve_chat_capability_prefs` reads a per-chat JSON settings file at `memory/{agent}/chat/{connector}-{chat_id}/settings/capability_prefs` (same store-key shape as the interaction_mode per-chat setting; same `caps.*` marker keys the agent descriptor's config map uses), each key resolved INDEPENDENTLY by its own presence — absent file/key -> `None` ("no opinion"). `chat_tools::agentic_loop::run_agentic_loop` resolves both layers every turn (no caching, no restart to flip) and merges via `CapabilityPrefs::merge_over`: chat-override beats agent-marker beats the global cap, per key independently. A markerless chat (no file, or a file carrying none of the 5 keys) resolves to `CapabilityPrefs::default()` — byte-identical to the per-agent-only resolution that existed before this layer did. No CLI/API affordance exists (mirrors interaction_mode, which also has none outside its `/mode` chat command) — flipping a chat's capability prefs is a direct file write; see the design-doc addendum for the exact key + JSON-shape runbook.  
  *openalice_api_handlers::http::routes::chat_prompt::assembler::agent_meta:0*
- **`prompt.execution_guidance.model_keyed`** · _experimental_ · since 2026-05-07 — Phase 8Y-T3 — Hermes-style OPENAI_MODEL_EXECUTION_GUIDANCE block (XML <tool_persistence>, <mandatory_tool_use>, <act_dont_ask>, <verification>, <missing_context>) keyed on ModelFamily. Big gpt-5 models render the full set; small (mini/codex) variants render only the two most load-bearing blocks; Unknown / legacy callers default to the full set.  
  *openalice_agents_soul::sections::blocks::execution_guidance:0*
- **`prompt.few_shot_traces.addressee_anchoring_8mmm`** · _beta_ · since 2026-05-19 — Phase 8MMM — post-gap addressee anchoring few-shot trace. Teaches the canonical recovery shape for the 3-month prod bug NAO reported: Alice talked with @sasha for 5 turns, then @danil sends one message after a time gap → Alice must open her reply addressing Danil (not Sasha). Cross-references the `## CURRENT ADDRESSEE` per-turn anchor + the doctrine ADDRESSEE INVARIANT callout.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.bare_generate_8jjj_a`** · _experimental_ · since 2026-05-18 — Phase 8JJJ-A — bare image-generation few-shot traces. Two new worked examples (RU «нарисуй круг» → image_gen, EN «draw a sunset» → image_gen) showing the no-refs path explicitly. Pairs with the IMAGE_GENERATE_DIRECTIVE trigger: model sees a concrete pattern for translating a bare object word into a structured English prompt + calling image_gen with NO reference_images. Closes the cognition gap where bare draw / generate requests previously got answered textually (e.g. «Вот круг: ⚪») instead of via a real PNG attachment.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.cognition_8uu`** · _experimental_ · since 2026-05-15 — Phase 8UU — image-gen cognition glue traces. Four worked examples (self-portrait, self+other composite, style transfer on attached photo, background swap) that pair the 8UU context triggers with the refs-registry slugs (`self` / `person/<name>`). Uses generic placeholders so no real names leak into the prompt.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.edit_mode_8vv1`** · _experimental_ · since 2026-05-15 — Phase 8VV-1 — image-gen edit-mode trigger reliability traces. Updates the four 8UU cognition-glue traces to use the FULL structured prompt-strategy text from the matching skill templates (preserve clauses, photoreal skin guard, brushwork + palette, cutout edges, negative-prompt tails) and adds a fifth REGRESSION trace that calls out the paraphrase-without-`reference_images` anti-pattern explicitly with the correct structured replacement.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.hermes_pattern`** · _experimental_ · since 2026-05-15 — Phase 8EE-A — Hermes-style few-shot agentic traces. Worked examples (memory_crystallize + dossier_link, skill_manage author, agent_spawn background, dossier_link_anchor, contradiction handling) showing exact user-message → thought → tool sequence → reply patterns. Addresses lab-probe regression where the LLM did not invoke high-value tools on natural prompts despite the doctrine block describing them.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.multi_question_8uuu`** · _beta_ · since 2026-05-19 — Phase 8UUU — multi-question single-speaker few-shot traces (RU + EN variants). Shows the canonical reply shape when a single user message contains 2-N distinct questions: answer EACH, never silently drop one. Pairs with the ANSWER COMPLETENESS doctrine fragment. Targets the ~20% turn-skip rate NAO observed.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.probe_shape_8ii1`** · _beta_ · since 2026-05-16 — Phase 8II-1 — probe-shape few-shot traces. Four new worked examples covering the still-RED lab probes after 8HH-1: skill-run (`skill_manage(action="run")`), skill-merge-proposal (reflection pipeline), subagent-depth-cap (depth_cap_exceeded path with literal "глубин" reply), speaker-katya-bort (Latin-script speaker echo). Each trace quotes the EXACT lab-probe user message and the EXACT expected tool-call shape so the model has a probe-aligned concrete pattern to match.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.few_shot_traces.speaker_correction_8xx`** · _beta_ · since 2026-05-15 — Phase 8XX — speaker mis-attribution correction trace. Teaches the graceful-correction reflex when a participant pushes back with "это не я говорила" / "ты меня перепутала": apologize by canonical Latin name, re-attribute to the actual speaker by canonical Latin name, pivot to address the correcting speaker's real concern. Closes the failure mode where Alice doubled down on the wrong attribution instead of repairing it.  
  *openalice_agents_soul::sections::blocks::few_shot_traces:0*
- **`prompt.generated_images`** · _experimental_ · since 2026-05-15 — Phase 8BBB — GeneratedImagesSection. Surfaces the per-chat catalog of previously-generated images (the top-N most recent entries from `image_index.jsonl`) inside the system prompt so Alice can re-share them via `send_file` (bash-first recall) without regenerating. FS-backed via ImageIndex::load, rendered at priority 140. Self-skips on PromptMode::None, empty agent_id, missing chat_scope, or an empty index.  
  *openalice_agents_soul::sections::generated_images:0*
- **`prompt.refs_surface`** · _experimental_ · since 2026-05-15 — Phase 8UU — RefsSurfaceSection. Surfaces the per-agent refs catalog (self / people / places / objects) inside the system prompt so the model knows which `reference_images` slugs it can pass to `image_gen`. FS-backed via RefsStore::for_agent, rendered at priority 141. Self-skips on PromptMode::None, !has_tools, or an empty registry.  
  *openalice_agents_soul::sections::refs_surface:0*
- **`prompt.tool_surface.agent_tool_mode`** · _stable_ · since 2026-07-03 — Dynamic-agent ToolProfile CONSUMPTION (web path): the agent's descriptor tool_mode (minimal|full|custom) selects the advertised tool schema set per agent instead of the global OPENALICE_MINIMAL_TOOLS env; a markerless agent resolves to no-opinion → byte-identical to the global path. Unconditional since 2026-07-09 — the OPENALICE_AGENT_CONFIG kill-switch (retired adoption-ladder rung, default-ON since 2026-07-08) is gone. (Landed 40dd4ca5f 2026-07-03; registry entry backfilled.)  
  *openalice_api_handlers::http::routes::chat_prompt::assembler::agent_meta:0*
- **`prompt.tool_surface.connector_parity`** · _stable_ · since 2026-07-08 — Per-agent tool surface applies to CONNECTOR-originated turns (Telegram/Discord/…) too: assemble_for_connector_with_context resolves the descriptor tool_mode via the store-only sibling resolve_agent_tool_surface_from_store — before this, Minimal/Custom profiles only shaped WEB-originated turns. Unconditional since 2026-07-09 — the OPENALICE_AGENT_CONFIG kill-switch is gone; a markerless agent still resolves to no-opinion → byte-identical to the global path.  
  *openalice_api_handlers::http::routes::chat_prompt::assembler::agent_meta:0*
- **`prompt.tool_surface.custom_profile`** · _beta_ · since 2026-07-06 — Completes the dynamic-agent ToolProfile trio on the ADVERTISE side: an agent whose descriptor carries tool_mode=custom gets its prompt tool schemas filtered by the first-class allowed_tools/denied_tools lists (non-empty allowed keeps the intersection; denied always drops) — mirroring the dispatch-level enforcement in agents/agent.rs + chat_tools dispatch + workflow_backend, so the LLM never sees tools it cannot call. Minimal/Full advertise paths were already live; per-agent, no global flag.  
  *openalice_api_handlers::http::routes::chat_prompt::tool_schemas:0*

### registry
- **`registry.named`** · _stable_ · since 2026-07-03 — NamedRegistry<T> — the canonical name-keyed component registry (agent configs / templates / presets). The keyed sibling of the ordered InjectorRegistry; one uniform registration primitive for the modular framework.  
  *openalice_core::registry:0*

### router
- **`codex.oauth_device_flow`** · _stable_ · since 0.1.0 — Inline RFC 8628 device-code OAuth flow against auth.openai.com — no CLI, no cron, no subprocess; works in Docker. Atomic auth.json write, serialised refresh with 5-min coalesce window + circuit breaker.  
  *openalice_router::providers::codex_oauth:0*
- **`provider.anthropic`** · _stable_ · since 0.1.0 — Anthropic Messages API provider — Claude model family, native tool use, streaming via SSE.  
  *openalice_router::providers::anthropic:0*
- **`provider.codex`** · _stable_ · since 0.1.0 — Codex OAuth subscription provider — OpenAI Responses API format with auto token refresh before expiry and request/response translation for gpt-5.x-codex and gpt-5.x families.  
  *openalice_router::providers::codex:0*
- **`provider.codex.http_request_parity`** · _beta_ · since 2026-05-15 — Phase 8OO — `chatgpt_http::build_chatgpt_codex_client` builds the reqwest client used for every chatgpt.com/backend-api/codex/* call (Responses POST, /codex/models discovery, image_gen). Mirrors Codex CLI's `codex_login::default_client::build_reqwest_client`: Cloudflare cookie jar enabled, `User-Agent: openalice_codex/<v>`, `originator: openalice_codex` default header. Closes the empty-200 body gap where the Cloudflare WAF was dropping bodies for our vanilla reqwest client.  
  *openalice_router::providers::chatgpt_http:0*
- **`provider.google`** · _stable_ · since 0.1.0 — Google Generative Language API provider — Gemini family (generateContent + streamGenerateContent).  
  *openalice_router::providers::google:0*
- **`provider.openai`** · _stable_ · since 0.1.0 — OpenAI Chat Completions API provider — GPT-4/5 family with streaming SSE, tool calling, and the canonical v1/chat/completions schema.  
  *openalice_router::providers::openai:0*
- **`provider.openai_compat`** · _stable_ · since 0.1.0 — Shared `BaseProvider` — pooled HTTP client, SSE streaming parser, and per-provider API-key + model-list plumbing reused by every OpenAI-compatible provider (Together, Fireworks, Groq, …).  
  *openalice_router::providers::base:0*
- **`router.auxiliary_backfill`** · _beta_ · since 2026-05-02 — Phase 2 Week 6 — Hermes PR #5730 mirror. After primary tier exhausts retries on EmptyStream / Timeout, race a parallel call to a fast auxiliary model (default gpt-5.4-mini) against one final primary attempt before tier-downgrading. RateLimit and Other failure kinds skip the backfill and go straight to tier downgrade. Disable by unsetting OPENALICE_AUXILIARY_BACKFILL_MODEL or setting it equal to the primary model.  
  *openalice_router::fallback::auxiliary_backfill:0*
- **`router.core.crate`** · _stable_ · since 0.1.0 — Provider-neutral half of the old openalice-router crate — traits, EffortRouter, FallbackChain, CircuitBreaker, TokenManager, shared provider infrastructure. Introduced by Track 8 / Phase C split, consolidated back with the vendor crates by Wave K7.  
  *openalice_router:0*
- **`router.core.fallback`** · _stable_ · since 0.1.0 — Post-split alias for the fallback cascade. Same logic as router.effort_fallback, re-registered under the router-core namespace after the Track 8 split.  
  *openalice_router::fallback:0*
- **`router.core.token_manager`** · _stable_ · since 0.1.0 — Codex OAuth TokenManager lives in this crate so every vendor adapter can reuse it. Preserves the single-writer file lock guard (task #208) verbatim.  
  *openalice_router::providers::token_manager:0*
- **`router.device_flow_provider`** · _stable_ · since 0.1.0 — `DeviceFlowProvider` trait + `CodexDeviceFlow` adapter — abstracts RFC 8628 device-code steps (request_user_code / poll / complete) so new OAuth providers plug in without re-implementing the flow.  
  *openalice_router::providers::device_flow:0*
- **`router.effort_fallback`** · _stable_ · since 0.1.0 — 6-level fallback cascade: in-tier providers → key rotation → tier downgrade → semantic cache → degraded response with full error chain.  
  *openalice_router::fallback:0*
- **`router.metrics.codex_empty_stream`** · _beta_ · since 2026-05-23 — Counter `oa_codex_empty_stream_total{model}` bumped each time Codex returns HTTP 200 + opens SSE but emits no meaningful output (empty CompletionResult OR aggregator-side empty-stream error). Lets ops track the frequency of the transient Codex empty-stream glitch so retry budgets can be tuned to upstream baseline.  
  *openalice_router::llm_metrics:0*
- **`router.metrics.codex_reauth_needed`** · _beta_ · since 2026-06-03 — Counter `oa_codex_reauth_needed_total` bumped once each time the Codex refresh circuit flips `needs_reauth` true (token REVOKED server-side — persistent invalid_grant / 'refresh token already used'). Unlike a normal expiry (auto-refresh recovers), a revoked token needs a human re-login, so this counter is the Grafana alert signal that Alice is silently failing Codex calls until someone re-auths.  
  *openalice_router::llm_metrics:0*
- **`router.metrics.llm_calls`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_llm_calls_total{provider,model,outcome}`. Bumped once per `FallbackChain::try_tier` attempt: `success` on `Ok(Ok(_))`, `fail` on `Ok(Err(_))`, `timeout` on the `tokio::time::timeout` expiry arm.  
  *openalice_router::llm_metrics:0*
- **`router.metrics.llm_calls.turn_dedup`** · _beta_ · since 2026-05-15 — Phase 8GG-1 — opt-in per-turn dedup of `oa_llm_calls_total`. When the coalesce strict-dedup gate is ON and a /v1/chat holder turn enters `run_agentic_loop`, the handler wraps the loop in `with_turn_dedup_scope(...)`. Inside the scope, the FIRST `record_call(...)` bumps the counter; subsequent attempts inside the same turn (tool iterations, fallback retries, auxiliary backfill) skip the counter so one chat turn = one counter increment. Stays OFF outside the scope — prod chat flows (gate OFF) behave exactly as today and the counter still ticks per provider attempt.  
  *openalice_router::llm_metrics:0*
- **`router.providers.anthropic.crate`** · _stable_ · since 0.1.0 — Anthropic Messages API adapter. Track 8 / Phase C extracted it into a separate crate; Wave K7 folded it back into openalice-router.  
  *openalice_router::providers::anthropic:0*
- **`router.providers.codex.crate`** · _stable_ · since 0.1.0 — Codex provider. Track 8 / Phase C extracted it into a separate crate; Wave K7 folded it back into openalice-router.  
  *openalice_router::providers::codex:0*
- **`router.providers.codex.empty_stream_retry`** · _stable_ · since 0.1.0 — Codex SSE empty-stream and truncated-payload retry — detects zero-token and cut-off responses from the Responses API and retries with exponential backoff. Preserved verbatim from commit b3fc9048 by the Track 8 split and Wave K7 consolidation.  
  *openalice_router::providers::codex:0*
- **`router.providers.codex.gpt_5_5_support`** · _stable_ · since 0.1.0 — GPT-5.5 (released 2026-04-23, surfaced via Hermes 0.11.0) is wired into the Codex OAuth provider. Listed first in CODEX_MODELS so the empty-model default falls back to gpt-5.5; tier mapping defaults to Max + High effort. gpt-5.4 + gpt-5.4-mini routing is preserved verbatim — no behavioural change for callers that pin an older model.  
  *openalice_router_providers_codex::codex:0*
- **`router.providers.codex.live_model_discovery`** · _stable_ · since 0.1.0 — Live model discovery: `CodexProvider::discover_models` polls the OAuth-authed `GET /codex/models` endpoint on chatgpt.com and caches the result for 1h. Lets newly-shipped OpenAI models (e.g. gpt-5.5 on 2026-04-23) light up in the picker without a catalog edit. Falls back to the bundled static list on any transport error to preserve the truncation/empty-stream invariant.  
  *openalice_router_providers_codex::codex:0*
- **`router.providers.codex.stale_partial_salvage`** · _beta_ · since 2026-07-06 — The codex SSE reader KEEPS a substantial partial (>= CODEX_SALVAGE_MIN_CHARS chars of text deltas) when the stream goes stale (silent >= CODEX_SSE_STALE_TIMEOUT) instead of discarding it as a retryable error; the aggregation salvage policy then returns it tagged Length + truncation notice. Closes the silent-cut variant of the long-reply truncation class (the closed-socket variant shipped 2026-06 in aggregate_codex_stream_with_items). A trickle partial below the threshold keeps the Wave J #0c retryable contract.  
  *openalice_router_providers_codex::codex:0*
- **`router.providers_common.compat_macro`** · _stable_ · since 0.1.0 — `compat_provider!` macro — generates a thin wrapper struct around CompatProvider with auto-derived LLMProvider impl + Deref<BaseProvider>. Used by OpenRouter.  
  *openalice_router::providers::compat_macro:0*
- **`router.providers_common.crate`** · _stable_ · since 0.1.0 — Tiny DRY layer that owns the `compat_provider!` macro. Eliminates ~120 LOC × 6 of identical wrapper boilerplate across the OpenAI- compat providers. Track E2 introduced it as a separate crate; Wave K7 folded it into openalice-router::providers::compat_macro.  
  *openalice_router::providers::compat_macro:0*
- **`router.providers.gemini.crate`** · _stable_ · since 0.1.0 — Google Gemini / Vertex AI adapter. Track 8 / Phase C extracted it into a separate crate; Wave K7 folded it back into openalice-router.  
  *openalice_router::providers::google:0*
- **`router.providers.openai.crate`** · _stable_ · since 0.1.0 — OpenAI + Responses API adapters. Track 8 / Phase C extracted them into a separate crate; Wave K7 folded them back into openalice-router.  
  *openalice_router::providers::openai:0*
- **`router.providers.openrouter.crate`** · _stable_ · since 0.1.0 — OpenRouter adapter. Track 8 / Phase C extracted it into a separate crate; Wave K7 folded it back into openalice-router. Uses CompatProvider.  
  *openalice_router::providers::openrouter:0*
- **`router.proxy.intent_stripper`** · _stable_ · since 2026-04-25 — Memory v4 / M5 — proxy-boundary helper that serializes a CompletionRequest to JSON for an OpenAI-compatible LLM endpoint and strips the OpenAlice-internal `intent` field from every message. Single seam used by every OpenAI-compat provider so the classification label cannot leak into outbound payloads.  
  *openalice_router_core::providers::base:0*
- **`router.proxy.speaker_id_stripper`** · _beta_ · since 2026-05-07 — Wave R3 — proxy-boundary helper also strips the OpenAlice-internal `speaker_id` field (e.g. `tg:670376626`, `discord:123`) from every message before serialization to an OpenAI-compatible endpoint. The field is consumed UPSTREAM by the `<speaker>` prompt-tag renderer and the continuity tracker; sending the raw id to the LLM would bloat payloads and could trip strict-mode validators.  
  *openalice_router_core::providers::base:0*
- **`router.semantic_cache`** · _stable_ · since 0.1.0 — Embedding-based response cache with cosine-similarity lookup, TTL eviction, and configurable threshold — used as the last-ditch fallback when all providers fail.  
  *openalice_router::cache:0*
- **`router.token_manager`** · _stable_ · since 0.1.0 — Owns OAuth token state, auth-file path, and background refresh task for any OAuth-based provider. Reactive 401 refresh + proactive pre-expiry refresh; reusable across Codex/Anthropic/Gemini.  
  *openalice_router::providers::token_manager:0*

### safety
- **`agents.goal_drift`** · _stable_ · since 0.1.0 — Goal-drift detector — sliding window over tool call history; auto suspends agents that diverge from their declared goal beyond a configurable threshold.  
  *openalice_agents::goal_drift:0*
- **`agents.novelty`** · _stable_ · since 0.1.0 — Tracks (agent, tool) first-execution timestamps so the safety gate can require approvals for novel tool calls even when the risk profile alone would allow them.  
  *openalice_agents::novelty:0*
- **`agents.safety_gate`** · _stable_ · since 0.1.0 — Critical enforcement point for tool execution — combines risk level, novelty, standing approvals, and destructive/irreversible flags into a block/pass decision the LLM cannot bypass.  
  *openalice_agents::safety_gate:0*
- **`agi.safety.constitutional_critic.caps_bridge`** · _beta_ · since 2026-07-09 — Caps-migration (2026-07-09, tail-close wave) — the 4 critic env vars actually read at runtime in this crate (grep OPENALICE_CRITIC inventory) go config-first: `ConstitutionalCritic::{new,with_llm}` (caps.critic.{agent,model,async_model}), `critic_async::is_critic_agent_enabled` (caps.critic.agent), and `cost_guard::{cost_guard_can_spend,cost_guard_snapshot}` (caps.critic.daily_usd_cap) all read a live unified-config handle first, falling back to the legacy direct-env read (OPENALICE_CRITIC_AGENT/_MODEL/_ASYNC_MODEL/_DAILY_USD_CAP) when uninstalled. Three more OPENALICE_CRITIC_* vars (_GATE_LIST/_AUDIT_INTERVAL in the separate, test-fixture-only `asi-safety` crate; _GATE_RESPONSE_DRAFT/_GATE_TOOL_DISPATCH/_SPEAKER_REPROMPT in `api-handlers::chat_tools::critic_gate`) are NOT read here and were left out of this wave — see CapCritic's doc comment in `openalice-config`.  
  *openalice_agents_safety::constitutional_critic:0*
- **`agi.safety.constitutional_critic.codex_oauth_transport`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.2 finalization — `CodexHttpCriticLlm::complete` HTTP transport. Reads the OAuth access_token from `~/.codex/auth.json` (CODEX_AUTH_FILE override), POSTs the Responses-API shape to `chatgpt.com/backend-api/codex/responses`, drains the SSE stream, extracts the assistant text from `output[].content[].text`, and returns it to the critic. Bridges to tokio via a small one-shot single-thread runtime (the critic call site is sync). On any transport / auth failure returns `CriticLlmError::Unavailable`, which the critic translates into a fail-open `Verdict::Approve` — never blocks the pipeline.  
  *openalice_agents_safety::codex_oauth_client:0*
- **`agi.safety.constitutional_critic.cost_guard`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — Daily USD cap guard for ConstitutionalCritic. OPENALICE_CRITIC_DAILY_USD_CAP (default $0.50). When hit, all LLM calls fall back to Approve + log WARNING. Tracked via `openalice_critic_cost_cap_total` Prometheus counter.  
  *openalice_agents_safety::constitutional_critic:0*
- **`agi.safety.constitutional_critic.observe_async`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — `ConstitutionalCritic::observe_async` logs + emits `openalice_critic_observed_total{event_type}`. Hybrid model (Q5 polish 2026-05-23): async observer surfaces (periodic_audit today, future pattern detector) call the LLM with OPENALICE_CRITIC_ASYNC_MODEL (default gpt-5.5) — smarter model, off-hot-path. Sync gate (`review_sync`) keeps OPENALICE_CRITIC_MODEL (default gpt-5.4-mini). Pattern-based LLM escalation (3+ memory writes / 60s) deferred to PR 2.3.  
  *openalice_agents_safety::constitutional_critic:0*
- **`agi.safety.constitutional_critic.periodic_audit`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — `ConstitutionalCritic::periodic_audit` walks the lane snapshot + recent N turns + CoT traces, calls the async-observer model (default gpt-5.5 via OPENALICE_CRITIC_ASYNC_MODEL, Q5 polish 2026-05-23) for pattern detection, and returns Vec<AuditFinding>. Cost-guarded at the async-model rate; returns empty Vec when cap hit or OPENALICE_CRITIC_AGENT=off.  
  *openalice_agents_safety::constitutional_critic:0*
- **`agi.safety.constitutional_critic.review_sync`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — `ConstitutionalCritic::review_sync` calls gpt-5.4-mini with a structured JSON verdict prompt (Approve / Veto+reason / AskHuman+uncertainty). Active only when OPENALICE_CRITIC_AGENT=on. Falls back to Approve on parse error or cost-cap breach. Previously a stub returning Approve unconditionally.  
  *openalice_agents_safety::constitutional_critic:0*
- **`agi.safety.critic.askhuman_escalation_channel`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.5 — secondary MPSC channel that surfaces AskHuman findings produced by the async observer for downstream connectors (TG bot drains it + posts to NAO's chat_id 670376626). Capacity 64, drop-oldest with `openalice_critic_askhuman_dropped_total`. Optional — when no consumer drains it, items are logged + dropped.  
  *openalice_agents_safety::critic_async:0*
- **`agi.safety.critic.async_observer`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.5 — bounded MPSC channel + single tokio drainer task that pulls AsyncEvent items (memory writes, lane transitions, response-draft soft vetos) and calls `ConstitutionalCritic::observe_async`. Default OFF when OPENALICE_CRITIC_AGENT != on.  
  *openalice_agents_safety::critic_async:0*
- **`agi.safety.critic.async_observer.overflow_drop`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.5 — drop-oldest backpressure on the async observer MPSC channel (capacity 256). Each drop bumps `openalice_critic_async_dropped_total`. Protects callers from blocking on a stuck drainer.  
  *openalice_agents_safety::critic_async:0*
- **`agi.safety.critic.metrics.audit`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — Prometheus counter `openalice_critic_audit_total{outcome}`. Bumped on every `ConstitutionalCritic::periodic_audit` call.  
  *openalice_agents_safety::critic_metrics:0*
- **`agi.safety.critic.metrics.cost_guard`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — Prometheus counter `openalice_critic_cost_cap_total`. Bumped whenever the daily USD cap is hit and the critic gracefully degrades to Approve without an LLM call.  
  *openalice_agents_safety::critic_metrics:0*
- **`agi.safety.critic.metrics.observed`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — Prometheus counter `openalice_critic_observed_total{event_type}`. Bumped on every `ConstitutionalCritic::observe_async` call.  
  *openalice_agents_safety::critic_metrics:0*
- **`agi.safety.critic.metrics.review`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.2 — Prometheus counter `openalice_critic_review_total{verdict}`. Bumped on every `ConstitutionalCritic::review_sync` call.  
  *openalice_agents_safety::critic_metrics:0*
- **`agi.safety.critic.response_draft_retry_hint`** · _experimental_ · since 2026-05-23 — Phase 2 PR 2.5 — when `gate_response_draft` returns VetoedLogOnly (the per-gate flag is off), the async observer records a response-veto retry hint via `openalice_critic_response_retry_hint_total`. The actual prompt-overlay injection (soft hint into Cat-B for the next turn) is deferred to PR 2.6 because the overlay system is not reachable from the observer context.  
  *openalice_agents_safety::critic_async:0*
- **`codex.reauth_alert_hook`** · _beta_ · since 2026-06-03 — When the refresh circuit flips `needs_reauth` true (token revoked — auto-refresh cannot recover), fire a decoupled, edge-debounced alert: loud ERROR log + `oa_codex_reauth_needed_total` metric + an optional runtime-registered hook (set via `set_reauth_alert_hook`) so the host can proactively notify the operator (e.g. Telegram) with a re-login link instead of failing silently. One fire per revocation until `reset_refresh_circuit` clears the flag.  
  *openalice_router::providers::codex_oauth:0*
- **`codex.refresh_circuit_breaker`** · _stable_ · since 0.1.0 — After 3 consecutive 401/invalid-grant responses, stop probing the OAuth endpoint for 10 min and flag needs_reauth. Prevents log spam when the user's refresh token is truly dead.  
  *openalice_router::providers::codex_oauth:0*
- **`core.loop_guard`** · _stable_ · since 0.1.0 — Outcome-aware loop detector for the agentic loop — tracks hashes of (tool, args, result), identifies ping-pong patterns, warn/block escalation, relaxed thresholds for poll-style tools.  
  *openalice_core::runtime::loop_guard:0*
- **`core.loop_guard.stuck_fuzzy`** · _experimental_ · since 2026-07-02 — OPT-IN fuzzy stuck-detection (OPENALICE_STUCK_FUZZY, 2026-07-02): the outcome-repetition signature collapses VOLATILE digit-runs (timestamps, ids, counts, offsets) before hashing, so two semantically identical results that differ only by such tokens count as the SAME outcome and trip the existing warn/block escalation. Closes the exact-hash gap where a repeated failure differing by a timestamp evaded detection. Default off → outcome hashing is byte-identical.  
  *openalice_core::runtime::loop_guard:0*
- **`openalice.critic.gate_response_draft`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.6 — Constitutional Critic sync gate on the final response draft in `run_agentic_loop` before it is returned to the caller. ENABLED BY DEFAULT (PR 2.6 flip). Set OPENALICE_CRITIC_AGENT=off (master kill switch) or OPENALICE_CRITIC_GATE_RESPONSE_DRAFT=off to disable. On Veto → response logged + sent as-is (PR 2.5 records retry hint via critic_async). On AskHuman → logged + sent as-is.  
  *openalice_api_handlers::http::routes::chat_tools::critic_gate:0*
- **`openalice.critic.gate_response_draft_speaker_reprompt`** · _experimental_ · since 2026-05-23 — Q5 polish round 2 (2026-05-23) — Critic-driven re-prompt for speaker-mismatch detection in multi-speaker bundles. When the recent user-bundle contains ≥2 distinct speakers, `gate_response_draft_speaker_aware` renders a SPEAKER CHECK block in the critic prompt asking the critic to Veto with reason `speaker_mismatch` if the draft answers an earlier speaker's question. The agentic loop catches that veto reason and re-prompts the LLM once with a disambiguation hint (cap 1 per turn). ENABLED BY DEFAULT (Q5 round 2 flip); set OPENALICE_CRITIC_SPEAKER_REPROMPT=off to disable. Surfaces metric `oa_critic_reprompt_speaker_mismatch_total`.  
  *openalice_api_handlers::http::routes::chat_tools::critic_gate:0*
- **`openalice.critic.gate_tool_dispatch`** · _experimental_ · since 2026-05-22 — Phase 2 PR 2.6 — Constitutional Critic sync gate on `execute_tool` for mutating tool dispatches. ENABLED BY DEFAULT (PR 2.6 flip). Set OPENALICE_CRITIC_AGENT=off (master kill switch) or OPENALICE_CRITIC_GATE_TOOL_DISPATCH=off to disable. On Veto → tool blocked with reason. On AskHuman → logged + treated as Veto.  
  *openalice_api_handlers::http::routes::chat_tools::critic_gate:0*
- **`safety.kill_switch`** · _stable_ · since 0.1.0 — Permission-checked agent termination with engage/disengage persistence. Rules: system/user kill any; spawner kills child; agent kills self.  
  *openalice_agents::killswitch:0*
- **`safety.untrusted_tool_gate`** · _experimental_ · since 2026-06-21 — Routes UNTRUSTED-origin tool calls (mcp.* / sandbox.*) through the SafetyGate (standing-approvals → HITL → JIT) + dispatches MCP tools via the kernel-driver MCPBridge. Trusted built-in tools keep today's path. Default SHADOW (OPENALICE_SAFETY_GATE=on to enforce) → prod byte-identical.  
  *openalice_api_handlers::http::routes::chat_tools::untrusted_gate:0*

### soul
- **`agents.soul.skills.section.global`** · _beta_ · since 2026-04-27 — Wave I — render the global Wave I SKILL.md catalog (name + description + when_to_use) inline in the system prompt. Eager-loaded from `~/.openalice/skills/{name}/SKILL.md`.  
  *openalice_agents_soul::sections::skills:0*
- **`agents.soul.skills.section.per_chat`** · _beta_ · since 2026-05-07 — Wave P — render per-chat skills (name + purpose + tags + use_count) inline in the same `# Skills` section. Top-K by use_count desc, capped at PER_CHAT_SKILLS_TOP_K (10) so the prompt token budget stays bounded.  
  *openalice_agents_soul::sections::skills:0*
- **`speaker_tags.metrics.block_render`** · _beta_ · since 2026-05-07 — Phase 8H — Prometheus counter `oa_speaker_block_render_total{source}`. Bumped once per `wrap_message_for_prompt` invocation with the resolve source label (`dossier` / `platform_fallback` / `unknown`). Surfaces on `/metrics` via the observability exporter registry.  
  *openalice_agents_soul::sections::speaker_tags:0*
- **`speaker_tags.slug_pinned_render`** · _beta_ · since 2026-05-15 — Phase 8XX — richer per-message speaker block that pins the dossier slug (`slug="person/nao"`) and an optional ISO-minute timestamp into the open tag alongside the existing `id` + `name` attributes. Grounds the model in "this speaker is the same entity the dossier paste describes" so 3+ participant group chats stop blurring identities. Old `<speaker id name>` shape is preserved when no slug resolves (R3 regression tests stay byte-identical).  
  *openalice_agents_soul::sections::speaker_tags:0*
- **`speaker_tags.wrap_message`** · _beta_ · since 2026-05-07 — Wave R3 — `<speaker id="..." name="...">…</speaker name="...">` wrapper applied to every rendered message that carries a speaker_id. The CLOSING-tag-with-attribute is the load-bearing fix for the `Alice answers the wrong person` bug (`feedback-speaker-confusion.md`).  
  *openalice_agents_soul::sections::speaker_tags:0*

### storage_v2/wire
- **`storage_v2.wire.sessions.ambient`** — Tested reference implementation of the ambient dual-write (test14/test15). The LIVE Telegram path inlines an equivalent in `modules-connectors::telegram::host::save_group_context` because modules-connectors sits BELOW the alice crate and cannot call up into it — so this helper is exercised only by the in-crate test suite. Both build the same `alice: None` ambient TurnRecord; the host adds a `tg_from_id` meta field. [allow(dead_code)]  
  *crates/alice/src/storage_v2_session_wire.rs:521*

### tools
- **`agents.builtin_tools_lazylock`** · _stable_ · since 0.1.0 — Process-wide `LazyLock<HashMap<&'static str, &'static BuiltinTool>>` built exactly once so hot-path dispatchers skip HashMap reconstruction on every tool call.  
  *openalice_agents::tools_builtins::tool_definitions:0*
- **`agents.image_gen.crate`** · _experimental_ · since 2026-05-15 — Phase 8II-2 — image generation crate. ImageGenerator trait + CodexHostedGenerator impl (Codex Responses API hosted image_generation tool) + ImageStore re-send-by-prompt cache. OOP-shaped, provider-agnostic, behind OPENALICE_IMAGE_GEN env flag (default OFF in prod).  
  *openalice_agents_image_gen:0*
- **`agent_spawn.metrics`** · _beta_ · since 2026-05-07 — Phase 8BB-1 — Prometheus counter `oa_agent_spawn_total{depth,outcome}`. Bumped once per `handle_agent_spawn` invocation in the api-router process: alice-cli's canonical counter lives in the child subprocess where /metrics can never see it. Labels: outcome ∈ {success, fail}, depth = `?` (parent never knows the runtime spawn depth — alice-cli surfaces it in its own counter once both processes share a /metrics aggregator).  
  *openalice_agents_tools::tools_builtins::handlers_misc::agent_spawn_metrics:0*
- **`agents.refs.auto_fetch`** · _experimental_ · since 2026-05-15 — Phase 8WW — inbound-triggered avatar auto-fetch into refs. Provides slug derivation (`tg-{user_id}` / `dc-{user_id}` / …), `avatar.meta` sidecar IO with 24h staleness + sha256 dedup, `apply_avatar_to_refs` that creates the bundle / archives the old file when content changed, and a smart-usage gate so participant refs only surface when the prompt explicitly mentions them.  
  *openalice_agents_refs::auto_fetch:0*
- **`agents.refs.auto_fetch.metadata_fix`** · _experimental_ · since 2026-05-19 — Phase 8VVV — fix for the 8WW pipeline bug where `apply_avatar_to_refs` round-tripped through `add_image` with a `.avatar.jpg.staging` source path, leaking the staging name into `metadata.yaml` as `file: .avatar.jpg.staging`. The staging file got cleaned up while metadata pointed at a non-existent path. Fix: splice the image entry directly with the canonical filename (`avatar.jpg`), no staging dance.  
  *openalice_agents_refs::auto_fetch::apply_avatar_to_refs:0*
- **`agents.refs.crate`** · _experimental_ · since 2026-05-15 — Phase 8SS — refs registry. Canonical FS-backed store for Alice's reference images (self / people / places / objects) at `~/.openalice/data/{agent}/refs/`. Foundation for image_gen multi-photo scenarios — image_gen resolves names like 'me' / 'Katya' / 'person/nao' to concrete files via `resolve_ref`.  
  *openalice_agents_refs:0*
- **`agents.refs.resolve`** · _experimental_ · since 2026-05-15 — Phase 8SS — `resolve_ref(store, name)` smart resolver. Maps 'me' / 'self' / 'myself' / 'я' / 'Алиса' / 'alice' to the self bundle; bare names like 'Katya' to `person/katya`; slug-shaped inputs (`person/nao`, `place/voronezh`) to their bundles.  
  *openalice_agents_refs::resolve::resolve_ref:0*
- **`agents.refs.resolve.sota`** · _experimental_ · since 2026-05-19 — Phase 8VVV — SOTA multi-key resolver. Three new match arms: (1) prefix-strip (`person/nao` retries as bare `nao`), (2) user-defined `aliases:` list in metadata.yaml (case-insensitive equality, e.g. `bassel` → `person/tg-...`), (3) display-name extracted from the 8WW auto-fetch description pattern `Auto-fetched from <connector> (<NAME>, user_id=...)`. Fixes the live NAO finding where `image_gen{refs: ["person/nao"]}` returned None despite the bundle existing under `person/tg-670376626`.  
  *openalice_agents_refs::resolve::resolve_ref:0*
- **`agents.refs.store`** · _experimental_ · since 2026-05-15 — Phase 8SS — `RefsStore` handle. `new` / `for_agent` ctor, `list_all` / `list_kind` / `get` reads, `create` / `add_image` / `remove` writes. Metadata.yaml is the source of truth; image files are referenced by bundle-relative name.  
  *openalice_agents_refs::store::RefsStore:0*
- **`agents.refs.store.aliases`** · _experimental_ · since 2026-05-19 — Phase 8VVV — `RefsStore::add_alias` / `RefsStore::remove_alias` mutate the `aliases:` list on a bundle's metadata.yaml. Aliases are case-insensitive lookup keys consumed by `resolve_ref` so a single bundle can answer to multiple names without renaming the canonical slug.  
  *openalice_agents_refs::store::RefsStore:0*
- **`agents.tools.workspace_glob.essential`** · _experimental_ · since 2026-04-27 — workspace_glob promoted to preloaded + essential so Alice can find files by name without spending tool-discovery tokens first.  
  *openalice_agents_tools::tools_builtins::handlers_misc:0*
- **`agents.tools.workspace_grep.essential`** · _experimental_ · since 2026-04-27 — workspace_grep promoted to preloaded + essential so Alice can grep large attachments before reading them — pairs with workspace_stat and workspace_read_range as the large-file SOTA toolkit.  
  *openalice_agents_tools::tools_builtins::handlers_misc:0*
- **`agents.tools.workspace_grep_essential`** · _experimental_ · since 2026-05-02 — Returns markdown/code outline + optional regex matches for a workspace file in one call. Lets Alice navigate a 500K-line attachment by TOC instead of dumping it. Pairs with workspace_read_range for selective deep-dive after the outline scan. Closes the 2026-04-27 large-file gap (572 KB book = 80K tokens per turn).  
  *openalice_agents_tools::tools_builtins::handlers_workspace:0*
- **`api.handlers.chat_tools.a2a`** · _stable_ · since 0.1.0 — A2A send/check/channel_info + collab (group/broadcast/subscribe/channels).  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.agent`** · _stable_ · since 0.1.0 — Agent create/discover/send — scheduler-backed.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.appstore`** · _stable_ · since 0.1.0 — Appstore search/install/info/list_installed.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.calendar`** · _stable_ · since 0.1.0 — Calendar CRUD + today/upcoming/search/conflicts/export.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.canvas`** · _stable_ · since 0.1.0 — Canvas create + add_node — per-chat scoped.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.git`** · _stable_ · since 0.1.0 — Git status/diff/log/show/add/commit/push with agent-scoped dispatch.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.group`** · _stable_ · since 0.1.0 — Group form + invite.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.hybrid`** · _stable_ · since 0.1.0 — Hybrid room create/add/list (humans + agents in one thread).  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.knowledge`** · _stable_ · since 0.1.0 — Knowledge graph + RAG (kg_add_entity/search/traverse, rag_search/ingest).  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.lsp`** · _stable_ · since 0.1.0 — LSP hover/definitions/references/document_symbols/diagnostics.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.map`** · _stable_ · since 0.1.0 — Leaflet maps — create, search, list, delete, screenshot.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.memory`** · _stable_ · since 0.1.0 — Memory read/write/list/delete/search/decay + chat_history_search + tool_search.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.microagent`** · _stable_ · since 0.1.0 — Microagent spawn/list_templates + trajectory replay/list.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.mission`** · _stable_ · since 0.1.0 — Mission create/status/list/stop + consolidation_run.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.multimodal`** · _stable_ · since 0.1.0 — Image + audio generation, send_selfie, minimax_usage.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.planning`** · _stable_ · since 0.1.0 — Goal set, plan+decompose, replan, project_rename, reflect.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.rank`** · _stable_ · since 0.1.0 — Rank status/leaderboard/audit.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.registry`** · _beta_ · since 0.1.0 — Compile-time ToolDescriptor registry — linkme distributed_slice + LazyLock HashMap<&str, &ToolDescriptor>. Every chat tool self-registers via register_tool! macro; dispatcher is O(1) lookup.  
  *openalice_api_handlers::http::routes::chat_tools::registry:0*
- **`api.handlers.chat_tools.router`** · _stable_ · since 0.1.0 — Router get_config/set_effort/list_providers/list_models.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.search_unified`** · _stable_ · since 0.1.0 — Unified `search(kind=…)` tool dispatching to glob / grep / workspace_grep_essential / memory_search. Diamond Wave 3 consolidation; legacy names remain registered as aliases.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.sop`** · _stable_ · since 0.1.0 — SOP list/get/create/execute/status/delete/enable/disable/history.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.soul`** · _stable_ · since 0.1.0 — Soul read/update — agent identity persistence + versioned archive.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.sys`** · _stable_ · since 0.1.0 — Security recording count + TUI session tools.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.task`** · _stable_ · since 0.1.0 — Task CRUD + assign/block/unblock/comment/progress + autonomous execute.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.telegram`** · _stable_ · since 0.1.0 — Telegram reaction + manage_triggers.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.tts`** · _stable_ · since 0.1.0 — TTS — unified `tts(action=…)` + deprecated aliases (set_provider, set_voice, set_tone, get_config, list_voices). Diamond Wave 3 consolidation.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.tunnel`** · _stable_ · since 0.1.0 — Tunnel start/stop/status.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.web`** · _stable_ · since 0.1.0 — Web search/fetch + browser_navigate + mcp_discover + a2a_call.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.worker`** · _stable_ · since 0.1.0 — Worker CRUD + enable/disable/run/history/rename/batch/archive/restore.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`api.handlers.chat_tools.workspace`** · _stable_ · since 0.1.0 — Workspace read/write + list/delete/glob/grep/edit/patch with agent+chat scope enrichment.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`dossier.link`** · _beta_ · since 2026-05-07 — Wave Q6 — dossier_link HTTP tool. Mutating, audited; inserts a bidirectional graph edge between two dossiers via the agents-memory graph layer. KEEP-DEDICATED per master plan §10. Returns JSON with edges_count_from/to and an `evicted` field if the cap forced an eviction.  
  *openalice_agents_tools::tools_builtins::handlers_misc::dossier_link:0*
- **`dossier.link_anchor`** · _beta_ · since 2026-05-07 — Wave Q8 — dossier_link_anchor HTTP tool. Adds one multi-modal anchor (text/file/image/voice/url/phone/email) to a dossier's frontmatter. Atomic rewrite via Dossier::write_to_disk; one `_audit.jsonl` row per call (`actor=anchor, action=link, slug, anchor_summary`).  
  *openalice_agents_tools::tools_builtins::handlers_misc::dossier_link_anchor:0*
- **`dossier.link.auto_upsert`** · _beta_ · since 2026-05-07 — Phase 8W-2 — when `dossier_link` is called with a `from`/`to` slug whose dossier doesn't yet exist on disk, the handler now lazily writes a minimal frontmatter-only stub (importance 0.5, empty body) before delegating to the graph layer. Each stub is audited (`actor=dossier_link, action=auto_upsert, reason=link_target_missing`) and counted by the Prometheus counter `oa_dossier_auto_upsert_total`. Idempotent: existing dossiers are never overwritten. Strict slug validation still applies — a missing/unknown type prefix still errors.  
  *openalice_agents_tools::tools_builtins::handlers_misc::dossier_link:0*
- **`dossier.link.auto_upsert.metrics`** · _beta_ · since 2026-05-07 — Phase 8W-2 — Prometheus counter `oa_dossier_auto_upsert_total`. Bumped once per stub dossier the `dossier_link` handler had to lazily materialise because a `from`/`to` slug pointed at a missing dossier. Registered via METRICS_EXPORTERS distributed slice so `/metrics` picks it up without an explicit dep edge.  
  *openalice_agents_tools::tools_builtins::handlers_misc::auto_upsert_metrics:0*
- **`dossier.read`** · _beta_ · since 2026-05-07 — Wave Q1 — dossier_read HTTP tool. Returns the full markdown body (frontmatter + body) of a dossier identified by slug + scope. Pairs with the always-injected MEMORY-INDEX.md so the LLM can look up only the bodies it actually needs.  
  *openalice_agents_tools::tools_builtins::handlers_misc::dossier:0*
- **`dossier.read.as_of`** · _beta_ · since 2026-05-07 — Wave Q5 — `dossier_read(slug, as_of=YYYY-MM-DD)` filters by t_valid/t_invalid so callers can fetch the historical view of a dossier at any point in time. When as_of is omitted the current view is returned (legacy behaviour).  
  *openalice_agents_tools::tools_builtins::handlers_misc::dossier:0*
- **`skill.create`** · _beta_ · since 2026-05-07 — Wave P — skill_create HTTP tool. Scaffolds a per-chat skill: writes `.md` (q1 frontmatter + body) + executable `.sh` stub under `chat_folders::skills_dir(agent, scope)`. Audited; refuses overwrite.  
  *openalice_agents_tools::tools_builtins::handlers_misc::skill_per_chat:0*
- **`skill.run`** · _beta_ · since 2026-05-07 — Wave P — skill_run HTTP tool. Synchronously executes the sibling `.sh` with a wall-clock timeout (default 60 s). Bumps use_count + success_rate; updates last_used_at. Audited.  
  *openalice_agents_tools::tools_builtins::handlers_misc::skill_per_chat:0*
- **`skill.update`** · _beta_ · since 2026-05-07 — Wave P — skill_update HTTP tool. Refines an existing per-chat skill: replaces body / purpose / tags / sh_body, leaves run counters untouched. Audited.  
  *openalice_agents_tools::tools_builtins::handlers_misc::skill_per_chat:0*
- **`tools.auto_commit_edits`** · _experimental_ · since 2026-06-02 — Opt-in (default OFF) aider-style checkpoint: after a SUCCESSFUL workspace edit/write/patch, auto `git add <file> && git commit` so every AI edit is one `git reset` from revert. Jail-guarded to the agent workspace; pure composition of the existing handle_git_add / handle_git_commit handlers; resilient (non-git or failed commit logs and continues, never breaking the edit). Toggle via env OPENALICE_TOOLS_AUTO_COMMIT_EDITS=1.  
  *openalice_agents_tools::tools_builtins::helpers:0*
- **`tools.bash`** · _beta_ · since 0.1.0 — bash tool — production-grade shell execution with cwd jail, env scrub, NFKC + ANSI normalisation, 40-pattern destructive-command validator, prompt-injection guard, optional network isolation, 100 KiB output cap, and SIGTERM→SIGKILL timeout. The load-bearing primitive of the bash-first refactor.  
  *openalice_agents::tools_builtins::handlers_misc::bash_tool:0*
- **`tools.chat_handler_registry`** · _stable_ · since 0.1.0 — ChatToolHandler trait + ToolRegistry — O(1) name lookup fed by the `register_tool!` macro's linkme distributed_slice. Tools self-register per-file; the central dispatcher has no match arms.  
  *openalice_api_handlers::http::routes::chat_tools::handler:0*
- **`tools.connector.send_file`** · _beta_ · since 0.1.0 — send_file connector tool — auto-routes a workspace file to the active connector (Telegram sendPhoto/sendDocument; Discord/Matrix/A2A stubs). Stub handler at agents-tools layer; transport-layer execution lives in api-handlers chat_tools::tools_send_file.  
  *openalice_agents::tools_builtins::handlers_misc::connector_send_file:0*
- **`tools.edit`** · _beta_ · since 0.1.0 — edit tool — bash-first str_replace primitive. Refuses if path wasn't viewed first (read-tracker), if old==new, if old is empty, or if the actual occurrence count diverges from expected_replacements. Wave J #6 + #7 guards apply to post-edit content.  
  *openalice_agents::tools_builtins::handlers_misc::edit_tool:0*
- **`tools.glob`** · _beta_ · since 0.1.0 — glob tool — workspace-jailed file-name pattern search. 200-result cap; `..` and absolute-path arguments rejected.  
  *openalice_agents::tools_builtins::handlers_misc::glob_tool:0*
- **`tools.grep`** · _beta_ · since 0.1.0 — grep tool — workspace-jailed regex search with optional glob filter and 0-5 lines of surrounding context. Returns column-accurate match records up to a configurable cap (default 50, max 200).  
  *openalice_agents::tools_builtins::handlers_misc::grep_tool:0*
- **`tools.image_gen.stub`** · _experimental_ · since 2026-05-15 — Phase 8II-2 — image_gen builtin tool. Stub handler at the agents-tools layer (schema-side prompt validation only); real generation + ImageStore cache + connector attachment happen at the transport layer where AppState carries the Codex client + ConvContext.  
  *openalice_agents::tools_builtins::handlers_misc::image_gen:0*
- **`tools.read_tracker`** · _beta_ · since 0.1.0 — Per-conversation read-tracker — records which paths `view` has opened so `edit` can refuse to mutate unread files (claw-code FileEditTool's `view-before-edit` invariant).  
  *openalice_agents::tools_builtins::handlers_misc::read_tracker:0*
- **`tools.repo_map`** · _beta_ · since 0.1.0 — repo_map tool — token-capped codebase symbol map. Enumerates git-tracked source files (git ls-files), aggregates LSP document_symbols per file, and renders a ranked markdown outline (path → fn/struct/trait signatures). Hard-capped on file count, per-file symbol count, and total output bytes (~6k tokens default); truncation is announced inline.  
  *openalice_agents::tools_builtins::handlers_lsp:0*
- **`tools.skill_manage`** · _beta_ · since 2026-04-27 — Phase 8Y-T1 — single self-evolution tool with action enum (create / read / patch / edit / delete / run / list) per hermes skill_manager_tool. Lets Alice grow, refine, invoke, and prune her own SKILL.md library at ~/.openalice/skills/{name}/ AND the per-chat `.md` + `.sh` library at chat_folders::skills_dir(agent, scope). Validation errors are designed to be self-correcting (helpful messages so Alice can fix on the next call).  
  *openalice_agents_tools::tools_builtins::handlers_misc::skills:0*
- **`tools.skill_read`** · _deprecated_ · since 2026-04-27 — DEPRECATED (Phase 8Y-T1) — use `skill_manage(action="read", name=…)`. Thin alias retained one release for backward compatibility.  
  *openalice_agents_tools::tools_builtins::handlers_misc::skills:0*
- **`tools.view`** · _beta_ · since 0.1.0 — view tool — bash-first read primitive. cat -n style line-numbered output, optional 1-indexed line range, 2000-line cap, binary-file refusal, records the read in the per-conversation tracker.  
  *openalice_agents::tools_builtins::handlers_misc::view_tool:0*
- **`tools.write`** · _beta_ · since 0.1.0 — write tool — bash-first wrapper over the Wave I.3 / J #6 / J #7 destructive-write protected workspace_write. Gives the model a consistent verb set (view/edit/write) without re-implementing any guard.  
  *openalice_agents::tools_builtins::handlers_misc::write_tool:0*
- **`tool_trace.read`** · _beta_ · since 2026-05-07 — Wave V — tool_trace_read HTTP tool. Returns recent trace entries (last_n, default 20) for the current chat scope only. Optional `tool` filter narrows to one tool name; optional `outcome` filter narrows to a single outcome bucket (success/fail/partial/timeout). Cross-chat isolation enforced: scope defaults to the caller's chat group, never another's.  
  *openalice_agents_tools::tools_builtins::handlers_misc::tool_trace:0*

### transport
- **`api_handlers.agentic_loop.durable_execution`** · _experimental_ · since 2026-05-15 — Phase 8FF-5 — durable execution + auto-resume layer for the agentic loop. Writes per-step checkpoints under `~/.openalice/agentic_runs/{run_id}/checkpoint-{step:03}.json`; on transient failure (empty SSE / silent finish / retryable 5xx) the orchestrator loads the latest checkpoint and replays from that step. Bounded by `router.fallback.max_attempts`. Gated by env `OPENALICE_DURABLE_EXEC=1` (default OFF in prod, ON in lab).  
  *openalice_agents::agentic_resume:0*
- **`api_handlers.agentic_loop.resume_counter`** · _experimental_ · since 2026-05-15 — Phase 8FF-5 — Prometheus counter `oa_agentic_resume_total{reason}`. Bumped once per accepted resume from `ResumeOrchestrator::try_resume`. Reason labels: empty_sse, silent_finish, provider_transient.  
  *openalice_agents::agentic_resume::metrics:0*
- **`api_handlers.chat.coalesce_discord_platform`** · _beta_ · since 2026-05-15 — Phase 8DD-4 — discord platform routes through coalesce with its own first-class label. Before this wave, `normalize_platform("discord")` returned the canonical string but the shared `platform_label` re-mapped it to "other", erasing the discord bucket from `oa_coalesce_total{platform=...}`.  
  *openalice_api_handlers::http::routes::chat_coalesce:0*
- **`api_handlers.chat.coalesce_hook`** · _beta_ · since 2026-05-07 — Phase 8W-4 — `/v1/chat` POSTs run through `openalice-coalesce` with `platform="web"` (overridable via the `platform` request field). Rapid-fire requests on one conversation collapse into one LLM call.  
  *openalice_api_handlers::http::routes::chat_coalesce:0*
- **`api_handlers.chat.coalesce_speaker_key`** · _beta_ · since 2026-05-07 — Phase 8BB-2 — `chat_coalesce::resolve_speaker` reads the `metadata.speaker_id` envelope (lab probes, Voice/SDK transports). Restores the R1 invariant that two distinct speakers in the same chat land in separate coalesce buffers, even when speaker identity arrives at the request envelope level rather than per-message.  
  *openalice_api_handlers::http::routes::chat_coalesce:0*
- **`api.v2.framework_caps_patch`** · _beta_ · since 2026-07-09 — POST /v2/framework/caps — patches one caps.<key> leaf in the runtime-overlay oa.yaml layer (~/.openalice/config/oa.yaml, created on first write) via an atomic tmp+rename write, preserving unrelated yaml keys via a serde_json::Value round-trip. Key is validated against a static allowlist derived from CapsConfig's field names — no arbitrary yaml injection. Polls the live_config hot-reload bridge for up to 3s and reports applied:bool. STATUS_TOKEN-gated (same pattern as codex_setup's mutation routes).  
  *openalice_api_handlers::http::routes::v2_framework:0*
- **`api.v2.framework_state`** · _beta_ · since 2026-07-09 — GET /v2/framework/state — read-only snapshot of the live layered oa.yaml config (CapsConfig from openalice_core::live_config) plus which of the 3 config layers (repo/deploy/runtime-overlay) exist on disk. STATUS_TOKEN-gated. Powers the cockpit Framework page.  
  *openalice_api_handlers::http::routes::v2_framework:0*
- **`chat.speaker_metadata_lift`** · _beta_ · since 2026-05-07 — Phase 8AA-2 — when `/v1/chat` request body carries a top-level `metadata.speaker_id` (lab probe / Voice / future SDK shape) but the trailing user `Message` lacks one, lift the request-level `speaker_id` (and optional `speaker_name`) onto the last user message so `wrap_speaker_blocks` actually fires + the `oa_speaker_block_render_total` counter increments. Eliminates the silent no-op on lab speaker probes.  
  *openalice_api_handlers::http::routes::chat_tools::speaker_wrap:0*
- **`chat.speaker_wrap`** · _beta_ · since 2026-05-07 — Phase 8W-3 — `/v1/chat` and `/v1/chat/stream` invoke R3's `<speaker>`-tag wrapper on every user message that carries a `speaker_id`. Increments `oa_speaker_block_render_total{source}` per wrap; appends `_audit.jsonl` row on `Unknown` resolves so ops can chase down chronic dossier misses.  
  *openalice_api_handlers::http::routes::chat_tools::speaker_wrap:0*
- **`codex.setup_ui`** · _beta_ · since 0.1.0 — First-run Codex OAuth setup UI — /setup/codex HTML + JSON endpoints for status, auth_upload, device_start, device_poll. Drives the in-server device-flow without the codex CLI.  
  *openalice_api_handlers::http::routes::codex_setup:0*
- **`curator.digests.section`** · _beta_ · since 2026-05-07 — Wave Q4 — CuratorDigestsSection renders the per-turn Tier-1 dossier digest paste produced by `agents_memory::curator::run`. Sits between Wave Q1's MemoryIndexSection (233) and the per-turn block (235) at priority 234.  
  *openalice_agents_soul::sections::curator_digests:0*
- **`dossier.index.section`** · _beta_ · since 2026-05-07 — Wave Q1 — MemoryIndexSection renders pre-built MEMORY-INDEX.md into the per-turn unstable suffix. Always-injected Tier-0 of the memory hierarchy; full bodies via dossier_read.  
  *openalice_agents_soul::sections::memory_index:0*
- **`prompt.active_speakers.preamble`** · _beta_ · since 2026-05-15 — Phase 8XX — `## Active speakers in this conversation` preamble. Pins display name + dossier slug + turn count + last-seen timestamp per speaker so Alice has at-a-glance grounding in WHO is in the chat. Renders in Full + Minimal modes at priority 233 (between memory-index and curator-digests). Closes the 3+ participant TG group chat name-confusion gap that Wave R3 `<speaker>` tags alone didn't cover.  
  *openalice_agents_soul::sections::active_speakers:0*
- **`prompt.context_reactive_directive`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — keyword-triggered MANDATORY workflow directive. Reads ctx.latest_user_message and injects a step-by-step directive when the user's intent matches a known trigger phrase (запомни / что ты знаешь / запиши как / делегируй). One directive per turn, ~250 tokens worst case. Sits at priority 232 in the unstable suffix.  
  *openalice_agents_soul::sections::context_reactive_directive:0*
- **`prompt.context_reactive_directive.crystallize`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — MANDATORY_CRYSTALLIZE_DIRECTIVE injected when the user says 'запомни' / 'remember' / 'сохрани' / 'save'.  
  *openalice_agents_soul::sections::context_reactive_directive:0*
- **`prompt.context_reactive_directive.dossier_first`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — DOSSIER_FIRST_DIRECTIVE injected when the user says 'что ты знаешь' / 'what do you know'.  
  *openalice_agents_soul::sections::context_reactive_directive:0*
- **`prompt.context_reactive_directive.skill_create`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — SKILL_CREATE_DIRECTIVE injected when the user says 'запиши как' / 'remember how' / 'save procedure'.  
  *openalice_agents_soul::sections::context_reactive_directive:0*
- **`prompt.context_reactive_directive.spawn_agent`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — SPAWN_AGENT_DIRECTIVE injected when the user says 'делегируй' / 'delegate' / 'в фоне'.  
  *openalice_agents_soul::sections::context_reactive_directive:0*
- **`prompt.context_triggers_8ee_b`** · _beta_ · since 2026-05-15 — Phase 8EE-B — additive context-reactive trigger map extending T4. Adds SKILL_TEACH / SKILL_REFLECT / SUBAGENT_WATCH / ATTACHED_FILE / CORRECTION directives covering lab-probe shapes (skill-author, skill-merge-proposal, subagent-watch, memory-anchor-multi, memory-contradiction-cascade). Sits at priority 232 alongside T4 (last in registration order). Tool-availability gated: self-skips when has_tools == false.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.attached_file`** · _beta_ · since 2026-05-15 — Phase 8EE-B — ATTACHED_FILE_DIRECTIVE injected when the user says 'вот файл', 'attached file', 'here is the doc'. Phase 8GG-3 widened to also match the recall-verb shape 'помнишь (тот|этот) (файл|документ)' / 'remember (that|the|this) (file|doc|document)' so the lab `memory-anchor-multi` probe shape ('Помнишь тот файл с описанием проекта Hermes? hermes-overview.md — что в нём было?') surfaces the anchor_match + dossier_read workflow to the model. Surfaces anchor_match + dossier_link workflow.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.correction`** · _beta_ · since 2026-05-15 — Phase 8EE-B — CORRECTION_DIRECTIVE injected when the user signals a correction ('поправка', 'correction', anchored 'actually' / 'на самом деле'). Surfaces contradiction_invalidate + dossier re-write.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.edit_mode_polish_8vv1`** · _experimental_ · since 2026-05-15 — Phase 8VV-1 — edit-mode trigger reliability polish. The five 8UU image-gen directives now (a) inline a 6-line recap of the matching skill template's prompt strategy, (b) ship a structured copy-paste JSON example whose `prompt` field carries the preserve clause + photoreal/style guards + negative tail (no more 3-word paraphrases), and (c) carry an explicit ANTI-PATTERN block showing the exact failure mode (paraphrase without `reference_images`) and labelling it as a regression. Goal: when refs are in scope AND the user says 'me / myself / я', the model picks edit-mode + populates `reference_images` consistently, NOT a generic text-to-image paraphrase.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_bg_swap`** · _experimental_ · since 2026-05-15 — Phase 8UU — IMAGE_BG_SWAP_DIRECTIVE injected on background-swap requests ('поменяй фон', 'change background', 'swap the background', 'new backdrop'). Mandates the image-edit-bg-swap skill, demanding the source image as the single `reference_images` entry and a clear new-backdrop description in the prompt.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_composite`** · _experimental_ · since 2026-05-15 — Phase 8UU — IMAGE_COMPOSITE_DIRECTIVE injected when the user asks to merge / composite / combine multiple images ('композит', 'composite', 'merge these images', 'combine these'). Mandates the image-edit-compose skill and asks the model to enumerate every available reference (inbox + refs registry slugs) into a single `reference_images` array.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_gen`** · _experimental_ · since 2026-05-15 — Phase 8II-2 — IMAGE_GEN_DIRECTIVE injected when the user says 'нарисуй', 'сгенерируй картинку', 'draw me', 'generate an image', 'create a picture', 'make a picture/image/sprite/mockup'. Surfaces image_gen(prompt=...) as MANDATORY this turn.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_generate`** · _experimental_ · since 2026-05-18 — Phase 8JJJ-A — IMAGE_GENERATE_DIRECTIVE injected for bare text-only image-generation requests («нарисуй круг», «draw a cat», «generate a sunset», «сделай мне картинку дерева»). Differs from the ref-based shapes (self-portrait / with-other / style-transfer / composite / bg-swap) by explicitly telling the model NO refs are needed — just call image_gen with a prompt. Closes the bare-generate cognition gap that left Alice replying textually to «нарисуй круг» despite IMAGE_GEN matching: the existing directive emphasised edit-mode + reference_images, which under-cued the bare path. Tool-availability gated.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_recall`** · _experimental_ · since 2026-05-15 — Phase 8BBB — IMAGE_RECALL_DIRECTIVE injected when the user asks to re-send a previously-generated image (`скинь то фото`, `verни картинку с …`, `find that image of …`, `recall the picture …`, `вспомни картинку`). Surfaces the bash-first workflow: read `chat/<scope>/image_index.jsonl`, grep by subject, then call `send_file({path})`. NO new image generation — re-use the catalog the GeneratedImagesSection preloaded.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_self_portrait`** · _experimental_ · since 2026-05-15 — Phase 8UU — IMAGE_SELF_PORTRAIT_DIRECTIVE injected when the user asks for a portrait OF THE AGENT ('нарисуй меня', 'draw me as ...', 'self portrait', 'portrait of me'). Refines IMAGE_GEN by mandating `reference_images=["self"]` so the result is the agent's canonical face / body, not a generic person. Inlines the image-portrait-photoreal skill's prompt strategy so a single agentic turn covers selection + call.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_style_transfer`** · _experimental_ · since 2026-05-15 — Phase 8UU — IMAGE_STYLE_TRANSFER_DIRECTIVE injected on style- transfer requests ('в стиле …', 'in the style of …', 'like <artist> art', 'painting style'). Mandates the appropriate skill template (image-portrait-painting / image-portrait-anime / image-edit-stylize depending on the style word) and surfaces the source-image reference_images requirement when an inbox/* path is present in the turn.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.image_with_other`** · _experimental_ · since 2026-05-15 — Phase 8UU — IMAGE_WITH_OTHER_DIRECTIVE injected when the user asks for a composite OF THE AGENT WITH ANOTHER PERSON ('нарисуй меня с …', 'me and …', 'composite of me and …', 'meня и …'). Mandates `reference_images=["self", "person/<name>"]`, where `<name>` is the resolved refs-registry slug for the person the user named. Inlines the image-edit-compose skill's prompt strategy.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.skill_reflect`** · _beta_ · since 2026-05-15 — Phase 8EE-B — SKILL_REFLECT_DIRECTIVE injected when the user asks for skill reflection / merge proposal (саморефлекси +  навык, reflect + skill).  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.skill_run`** · _beta_ · since 2026-05-16 — Phase 8HH-1 — SKILL_RUN_DIRECTIVE injected when the user asks Alice to invoke an existing skill (`запусти навык`, `запусти skill`, `run the skill`, `выполни навык`). Surfaces the canonical `skill_manage(action="run")` workflow with MANDATORY enforcement language and a JSON tool-call example, steering the model off `bash` / `memory_read` fallbacks.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.skill_teach`** · _beta_ · since 2026-05-15 — Phase 8EE-B — SKILL_TEACH_DIRECTIVE injected when the user says 'научи меня', 'teach me how to', 'давай создадим skill' and tools are available. Surfaces skill_manage(create).  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.context_triggers_8ee_b.subagent_watch`** · _beta_ · since 2026-05-15 — Phase 8EE-B — SUBAGENT_WATCH_DIRECTIVE injected when the user says 'параллельно сделай', 'spawn agent', 'watch agent'. Surfaces agent_spawn + agent_status polling + depth-cap awareness.  
  *openalice_agents_soul::sections::context_triggers_8ee_b:0*
- **`prompt.current_addressee.anchor`** · _beta_ · since 2026-05-19 — Phase 8MMM — `## CURRENT ADDRESSEE` section. First-class structural anchor for the identity of the sender of the latest user message. Priority 237 (tail of unstable suffix, immediately before the user message). Closes the 3-month post-gap addressee bug where Alice addresses a historically salient speaker (@sasha after 5 prior turns) instead of the actual current sender (@danil after a single new message). Self-skips when `ctx.current_addressee` is None.  
  *openalice_agents_soul::sections::current_addressee:0*
- **`prompt.doctrine.answer_completeness`** · _beta_ · since 2026-05-19 — Phase 8UUU — `Answer Completeness` doctrine fragment. When a user message contains MULTIPLE distinct questions, Alice must answer EACH of them — no silent skips. Targets the ~20% turn-skip rate NAO observed where bundled questions produced partial replies. Pairs with the multi-question few-shot trace. Renders in Full mode (lives inside AUTONOMOUS_DOCTRINE_BODY).  
  *openalice_agents_soul::sections::blocks::doctrine_block:0*
- **`prompt.doctrine.contradiction_echo`** · _beta_ · since 2026-05-15 — Phase 8AAA — `Contradiction Resolution Echo` doctrine fragment. After a correction signal ("на самом деле", "поправка", "actually", "я ошиблась", "correction"), Alice's reply MUST echo the NEW named value verbatim — never just say "обновила" / "noted" without naming it. Targets the 8DD-2 memory-contradiction-cascade probe (storage 3/4 → final reply must contain «Мюнхен» / new location verbatim).  
  *openalice_agents_soul::sections::blocks::doctrine_block:0*
- **`prompt.doctrine.delivery_invariant`** · _beta_ · since 2026-05-19 — Phase 8QQQ-B2 — `Delivery Invariant` doctrine fragment. Teaches Alice that any tool result carrying a `next_required_action` envelope names an explicit follow-up tool call (typically `send_file`) that MUST fire BEFORE the user-facing reply. Tool-agnostic — covers image_gen, future audio_gen / sprite_gen / file_write artifact producers. Renders in Full + Minimal modes when tools are available.  
  *openalice_agents_soul::sections::blocks::doctrine_block:0*
- **`prompt.doctrine.literal_retrieval`** · _beta_ · since 2026-05-16 — Phase 8HH-1 — `Literal Retrieval` doctrine fragment. Instructs Alice to echo named values (places, dates, people, brands) VERBATIM from her dossier/memory paste instead of paraphrasing. Targets lab probes (speaker-nao-mercury, speaker-katya-bort) where the model paraphrased instead of surfacing the exact word the scorer expects. Renders in Full + Minimal modes.  
  *openalice_agents_soul::sections::blocks::doctrine_block:0*
- **`prompt.doctrine.visual_identity_curation`** · _experimental_ · since 2026-05-19 — Phase 8PPP — `Visual Identity Curation` doctrine fragment. Steers Alice to ask for user consent before saving a generated self-portrait into the refs gallery, then run `alice-cli refs add --slug self --image <path> --role gallery` via bash. Maintains visual consistency across future image_gen calls without auto-saving every output. Renders in Full mode when tools are available.  
  *openalice_agents_soul::sections::blocks::doctrine_block:0*
- **`prompt.recent_failures.cap_per_turn`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — hard cap of 3 recent failures rendered per turn (token budget).  
  *openalice_agents_soul::sections::recent_failures:0*
- **`prompt.recent_failures.loader`** · _beta_ · since 2026-05-07 — Phase 8Z-D — load_recent_failure_hints: tails tool-calls.jsonl, filters to outcome=fail + lesson.is_some() within RECENT_WINDOW (7 days), reverses to newest-first, caps at MAX_FAILURES_RENDERED, and projects each TraceEntry into a RecentFailureHint (tool, lesson, age_label). Pure file read + CPU shaping; no kernel/store dependency.  
  *openalice_agents_soul::recent_failures_loader:0*
- **`prompt.recent_failures.section`** · _beta_ · since 2026-05-07 — Phase 8Y-T4 — RecentFailuresSection renders the last N tool failures with lessons from the current chat's tool-calls.jsonl. Complements Wave V's per-tool ToolCallLessonsSection with a broad cross-tool surface.  
  *openalice_agents_soul::sections::recent_failures:0*
- **`tool_call_lessons.cap_per_turn`** · _beta_ · since 2026-05-07 — Wave V — hard cap of 3 lessons rendered per turn (token budget). Section truncates silently if the orchestrator passes more; the metric `oa_tool_call_lesson_surfaced_total` only increments for what actually got surfaced.  
  *openalice_agents_soul::sections::tool_call_lessons:0*
- **`tool_call_lessons.metric_surfaced`** · _beta_ · since 2026-05-07 — Wave V — every surfaced lesson bumps `oa_tool_call_lesson_surfaced_total{tool}` via the shared counter in `agents_memory::tool_trace::metrics`.  
  *openalice_agents_soul::sections::tool_call_lessons:0*
- **`tool_call_lessons.section`** · _beta_ · since 2026-05-07 — Wave V — ToolCallLessonsSection. Renders up to 3 lesson hints the orchestrator pre-computed via `agents_memory::tool_trace::find_relevant_lessons`. Sits at priority 235 (insertion-ordered after PerTurnBlock 235, before TurnBundle 236) — master plan §9.3 reserved 235.5; the i32 space rounds to 235 with positional tiebreak.  
  *openalice_agents_soul::sections::tool_call_lessons:0*
- **`transport.a2a_turn`** · _experimental_ · since 2026-06-18 — Alpha-Alice A2A turn endpoint — POST /v1/a2a/turn. Env-gated (OA_A2A_TURN_ENABLED=1) + bearer-secret auth (OA_A2A_TURN_SECRET). ATLAS's @alice bot calls this; it returns the assistant reply text without posting or polling itself. Reuses the existing agentic-loop pipeline; never touches prod memory/agent-id.  
  *openalice_api_handlers::http::routes::a2a_turn:0*
- **`transport.agentic_loop.agent_injector_set`** · _beta_ · since 2026-07-03 — Dynamic-agent InjectorSet CONSUMPTION: under OPENALICE_AGENT_CONFIG (+ OPENALICE_LOOP_INJECTORS) the agent's descriptor injectors.calendar opts the CalendarInjector in/out and injectors.packs restricts which WASM LoopInjector packs register for this agent's loop. Uniform for web AND connector turns (lives in the shared run_agentic_loop). Default off → byte-identical registration. (Landed 3b4fd9349 + af1174ec8 2026-07-03; registry entry backfilled.)  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agentic_loop.anti_fallback_gate`** · _beta_ · since 2026-05-07 — Phase 8Y-T8 — gates the all-tools-failed escape valve in the agentic loop. When the turn's classified intent demands a destructive workflow tool (memory_crystallize / dossier_link / workspace_write / skill_manage) but none executed successfully, the loop either injects a contract nudge + retries (Option A) or returns an honest user-facing error instead of the tools=[] silent fallback (Option B). The escape valve is preserved for non-workflow turns and clarification cases.  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agentic_loop.cot_emission`** · _experimental_ · since 2026-05-22 — Phase 1 PR 1.8 — when OPENALICE_COT_TRACE=on, the agentic loop appends a CoT-trace instruction block to the system message, parses the LLM's <cot_trace>…</cot_trace> JSON output, strips it from the user-facing reply, and persists it into TurnRecord.meta["cot_trace"] via the storage-v2 dual-write path. Default OFF.  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agentic_loop.deterministic_summary`** · _experimental_ · since 2026-04-27 — Layer-2 deterministic fallback for silent-finish recovery: when the forced-summary LLM call also returns empty, the agentic loop synthesises a short user-language summary from the recorded `ExecutedTool` history (workspace_read/write, memory_*, web_search, …) so users always see what work was done.  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agentic_loop.silent_finish_recovery`** · _experimental_ · since 2026-04-27 — Two-layer silent-finish recovery: when an LLM ends a tool-using turn with empty content (gpt-5.5 silent-finish bug), the agentic loop (Layer 1) issues one bounded forced-summary call with `tools=[]` using the same conversation history so the model summarises what it accomplished without calling more tools.  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agentic_loop.stale_cancel_selfheal`** · _beta_ · since 2026-05-19 — Phase 8OOO — when the agentic loop's iteration-0 cancel-mailbox poll finds a `CoalesceRestart` cancel AND the same iteration already drained the steer mailbox into the conversation, the cancel is provably stale (its only job was to surface those exact steers). The loop swallows the cancel instead of silencing the turn. `CancelRestart` (REDIRECT) and `Operator` (alice-cli steer cancel) are NEVER swallowed. Bumps `oa_steer_cancel_swallowed_total{reason=coalesce_restart}`. Prevents prod-silence race observed 2026-05-19; see docs/phase-8ooo-coalesce-cancel-race-rca-2026-05-19.md.  
  *openalice_api_handlers::http::routes::chat_tools::agentic_loop:0*
- **`transport.agent_protocol_route`** · _experimental_ · since 0.1.0 — /v1/agent/* — canonical openalice-agent-protocol contract surface. Skeleton AgentRuntime impl + ConnectorEvent ingestion endpoint. K11 P0 gap, K13 adoption (wave-k13-agent-protocol-adoption-audit-2026-05-02.md).  
  *openalice_api_handlers::http::routes::agent_protocol:0*
- **`transport.bench.chat_prompt`** · _experimental_ · since 2026-04-25 — Wave G6 — criterion benchmark for the system-prompt assembly path (safety_preamble + resolve_essential_tool_schemas + PromptAssembler::build). Empty (skeleton only) and full (30 tools + persona + history-slot + active-chars) cases. Audit gap: claim was sub-ms — first measurement. Wave G7 added the post-cache row. Wave G8 added the `_arc` variant case + `essential_tool_schemas_arc` sub-bench.  
  *openalice_api_handlers::benches::chat_prompt_perf:0*
- **`transport.chat_approve`** · _experimental_ · since 2026-06-16 — POST /v1/chat/approve — #489 Phase B2 approval-decision endpoint. Routes the client's allow/allow_always/deny back to a suspended agentic turn via the per-turn oneshot registry on AppState. B2.1 infra: additive + dormant (nothing suspends yet); the suspend/resume wiring lands in B2.2.  
  *openalice_api_handlers::http::routes::approvals::approve:0*
- **`transport.chat_cancel`** · _experimental_ · since 0.1.0 — POST /v1/chat/cancel — Wave K8.5 stream cancellation endpoint. Trips an atomic flag the chat_stream task polls between chunks so Ctrl+C in `alice tui` (and any future MC stop button) terminates the streaming response server-side instead of just dropping the SSE socket client-side.  
  *openalice_api_handlers::http::routes::chat::chat_cancel:0*
- **`transport.chat.post_turn_last_user_prefers_merged_text`** · _beta_ · since 2026-05-16 — Phase 8EE-0 — when computing `last_user_text` for the post-turn memory pipeline (`fire_post_turn_workers` → Scribe), the chat handler prefers the coalesce-merged text (`merged_user_text`) when present, falling back to the body's last user message. Fixes a race introduced by lab harness Phase 8DD-4 concurrent multi-turn POSTs: when the recall turn wins the buffer-insert race, the Holder's own body has no pin signal, but the merged text always carries the pin half — so Scribe fires regardless of which turn became the Holder. Solo single-turn requests (`merged_user_text = None`) keep the prior body-fallback path byte-identical.  
  *openalice_api_handlers::http::routes::chat:0*
- **`transport.chat_prompt.arc_tool_schemas`** · _experimental_ · since 2026-04-26 — Wave G8 — `ToolSchemaFunction.parameters` is `Arc<serde_json::Value>` end-to-end; provider adapters and `PromptAssembler` mirror the type. New `add_tools_shared(Arc<Vec<ToolSchema>>)` API on `PromptAssembler` lets the essential-tool-schema cache fan in without a per-call deep Vec clone. The legacy `resolve_essential_tool_schemas() -> Vec<ToolSchema>` is `#[deprecated]` but kept for backwards compat. Bench result: chat_prompt/full drops 48 µs → <15 µs (audit's projected target).  
  *openalice_api_handlers::http::routes::chat_prompt:0*
- **`transport.chat_route`** · _stable_ · since 0.1.0 — /v1/chat endpoints — SSE streaming, tool calling, conversation CRUD, auto-title generation. The user-facing entry point for Alice.  
  *openalice_api_handlers::http::routes::chat:0*
- **`transport.chat_tools_dispatch`** · _stable_ · since 0.1.0 — Agentic tool execution layer — LLM → tool_calls → execute → repeat, streaming tool-call accumulation, per-request `ConvContext` to keep chat/user identity threaded through the loop.  
  *openalice_api_handlers::http::routes::chat_tools:0*
- **`transport.federation`** · _beta_ · since 0.1.0 — /federation endpoints — peer CRUD, replication stream control, discovery handshake for multi-instance OpenAlice deployments.  
  *openalice_api_handlers::http::routes::federation:0*
- **`transport.grpc_sidecar`** · _stable_ · since 0.1.0 — gRPC sidecar (tonic) — AgentService contract: Syscall, StreamChat, SubmitToolResult, GetTask, UpdateTask, EmitEvent, WatchEvents.  
  *openalice_api_router::grpc::server:0*
- **`transport.http_server`** · _stable_ · since 0.1.0 — Axum HTTP server — middleware chain wiring, route module registry, TLS, CORS, IP allowlist, correlation IDs, health + metrics.  
  *openalice_api_router::http::server:0*
- **`transport.openapi.docs_viewer`** · _stable_ · since 0.1.0 — GET /public/docs — minimal HTML landing page that links to the JSON/YAML OpenAPI spec. Intentionally simple (no JS bundle) so it ships without adding a Swagger-UI / Redoc dependency.  
  *openalice_api_handlers::http::routes::openapi:0*
- **`transport.openapi.spec_json`** · _stable_ · since 0.1.0 — GET /public/openapi.json — embedded OpenAPI 3.0.3 specification describing every HTTP route Alice exposes. Reachable without authentication; the contract-tests crate asserts runtime bytes match the committed file.  
  *openalice_api_handlers::http::routes::openapi:0*
- **`transport.openapi.spec_yaml`** · _stable_ · since 0.1.0 — GET /public/openapi.yaml — YAML variant of the embedded OpenAPI spec. Consumable by Swagger UI, Redoc, and CLI tooling.  
  *openalice_api_handlers::http::routes::openapi:0*
- **`transport.routes.v1_agents_steer`** · _experimental_ · since 2026-04-26 — POST /v1/agents/{id}/steer — push a mid-run user steer into the (agent, conv) mailbox; the agentic loop drains it at the next LLM-call boundary. Auth-gated by AuthLayer alongside the rest of /v1/agents.  
  *openalice_api_handlers::http::routes::steer:0*
- **`transport.routes.v1_agents_steer_cancel`** · _experimental_ · since 2026-05-07 — POST /v1/agents/{id}/steer/cancel — Wave R2 operator-driven cancel. Sets the cancel mailbox flag with reason=operator; the agentic loop aborts the current turn at the next safe injection point. Auth-gated by AuthLayer.  
  *openalice_api_handlers::http::routes::steer:0*
- **`transport.routes.v1_agents_steer_status`** · _experimental_ · since 2026-05-07 — GET /v1/agents/{id}/steer/status?conv_id=... — Wave R2 read-only introspection. Returns the pending steer count, the pending `pending_after_current` count, and whether a cancel signal is pending. Auth-gated by AuthLayer.  
  *openalice_api_handlers::http::routes::steer:0*
- **`transport.setup`** · _stable_ · since 0.1.0 — First-run setup wizard — status, environment, providers, preset, database, admin, complete. Guided config without editing files.  
  *openalice_api_handlers::http::routes::setup:0*
- **`transport.sops`** · _stable_ · since 0.1.0 — SOP endpoints — CRUD for Standard Operating Procedures plus execution management; backs FS store `sops/` and user TOML files.  
  *openalice_api_handlers::http::routes::sops:0*
- **`transport.system_prompt.autonomous_doctrine`** · _experimental_ · since 2026-04-27 — System prompt section bringing Alice up to SOTA autonomous-agent behavior: plan-first cognition, autonomous execution loop, continuous progress reporting, self-verification, tool sharpness, resource budgeting, explicit blocked signal, file-handling discipline, plan/{label} memory hygiene, honest self-assessment. Eliminates the 'wait for user to say продолжай' anti-pattern.  
  *openalice_api_handlers::http::routes::chat_prompt:0*
- **`transport.system_prompt.bootstrap_defaults`** · _experimental_ · since 2026-04-27 — Wave I Step 4 — per-agent AGENTS/IDENTITY/USER.md defaults seeded into ~/.openalice/data/agents/{agent_id}/bootstrap/ on first install. Idempotent: existing files are never clobbered so Alice's edits survive re-init / lazy bootstrap.  
  *openalice_agents_soul::bootstrap_defaults:0*
- **`transport.system_prompt.bootstrap_files`** · _experimental_ · since 2026-04-27 — Wave I Step 4 — BootstrapLoader: mtime-cached reader for per-agent AGENTS/IDENTITY/USER.md plus claw-code-style dir-walk discovery of AGENTS.md / CLAUDE.md / .openalice/instructions.md from cwd upward. Dedupes by content hash so inherited parent files don't double-inject. Per-file cap 4K chars, total cap 12K with truncation notice. Feeds PromptCtx.bootstrap_files which WorkspaceFilesSection renders in Full mode (priority 180).  
  *openalice_agents_soul::bootstrap_loader:0*
- **`transport.system_prompt.cap_discovery`** · _experimental_ · since 2026-06-20 — Minimal-tools W1 — gated `## Capability Discovery` prompt block. When OPENALICE_MINIMAL_TOOLS=1 the agent is taught to run `alice-cli cap` to find capabilities instead of relying on a large LLM tool array. Default OFF (block absent = byte-identical prompt). Part of the Minimal Tools + Bash-Discoverable Capability Registry design (2026-06-20).  
  *openalice_agents_soul::sections::cap_discovery:0*
- **`transport.system_prompt.frozen_snapshot`** · _beta_ · since 2026-05-02 — Phase 2 Week 5 — frozen cache-stable prefix snapshot per chat session. Splits the assembled system prompt into D-stable (priority < 230, persisted) and D-volatile (rebuilt per turn). Drops prompt-assembly p50 from 250-700ms to ≤50ms on cache hit and reduces Codex billed prompt_tokens by ~30% via prefix-cache.  
  *openalice_agents_soul::snapshot:0*
- **`transport.system_prompt.git_context`** · _experimental_ · since 2026-04-27 — Wave I Step 5b — auto-inject git status/diff/recent commits into the system prompt (Full mode only). Mirrors claw-code's project-context renderer; helps Alice see uncommitted work without explicit tool calls.  
  *openalice_agents_soul::sections::git_context:0*
- **`transport.system_prompt.image_gen_skill_seeds`** · _experimental_ · since 2026-05-15 — Phase 8TT — 12 image-generation SKILL.md templates pre-seeded on `alice init`. Generate-mode (photoreal portrait, anime, painting, landscape, fantasy character, game sprite, UI mockup, infographic) + edit-mode (stylize, compose, bg-swap, character-swap). Each carries Codex-optimized prompt strategy + 3-5 bilingual user-input → tool-call examples for the SkillCurator.  
  *openalice_agents_soul::skill_defaults:0*
- **`transport.system_prompt.prompt_mode_tiering`** · _experimental_ · since 2026-04-27 — Wave I — PromptMode (Full | Minimal | None) tiering driven by EffortLevel. Max/High → Full, Medium/Low → Minimal, Micro → None. Lets cheap-effort tiers ship a smaller system prompt without losing safety or identity.  
  *openalice_agents_soul::prompt_ctx:0*
- **`transport.system_prompt.section_builder`** · _experimental_ · since 2026-04-27 — Wave I — composable PromptSection trait + SectionBuilder. Each section of the system prompt is a separate impl ordered by priority. Replaces the monolithic DEFAULT_SYSTEM_PROMPT_TEMPLATE and lets PromptMode (Full | Minimal | None) skip heavy sections per effort tier without losing identity or safety.  
  *openalice_agents_soul::section_builder:0*
- **`transport.system_prompt.skill_library`** · _experimental_ · since 2026-04-27 — Wave I — folder-based SKILL.md library at ~/.openalice/skills/{name}/. Eager-loads metadata into the SkillsSection of the system prompt; lazy-loads bodies via the skill_read tool. Self-evolution layer: Alice creates, patches, edits, deletes skills via the skill_manage tool. Three seed skills are written on alice init: skill-creator (meta), coding (TDD+git), memory-curator (taxonomy+conflict rules).  
  *openalice_agents_soul::skill_defaults:0*
- **`transport.tunnels`** · _beta_ · since 0.1.0 — Tunnel provider endpoints — manage Tailscale Funnel / Cloudflare Tunnel subprocesses for remote access without opening host ports.  
  *openalice_api_handlers::http::routes::tunnels:0*
- **`transport.worker_hooks.correction_signal_pin`** · _beta_ · since 2026-05-15 — Phase 8DD-2 — `detect_explicit_user_pin` accepts correction / update phrases (`кстати`, `поправка`, `наоборот`, `actually,`, `correction:`, `update:`) as soft pins so Scribe re-fires on every contradicting turn. The Q5 conflict pipeline relies on Scribe firing to walk candidate observations + append journal events; without this, multi-turn contradiction cascades never reached the threshold. Memory-pin phrases (`запомни`, `remember that`, …) continue to fire as before — additive.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`transport.worker_hooks.curator`** · _beta_ · since 2026-05-07 — Phase 8W-5 — explicit per-turn Curator invocation on the /v1/chat path. Mirrors the connector_bridge prompt_assembly hook so HTTP probes see the same `oa_curator_score{slug}` + `oa_curator_top_k_paste_total` traffic as Telegram/Discord turns.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`transport.worker_hooks.entity_stop_words`** · _beta_ · since 2026-05-15 — Phase 8DD-2 — `extract_primary_entity` now discards a richer set of sentence-initial connectors / particles / pronouns in Russian and English (`Кстати`, `Поправка`, `Так`, `Actually`, `Correction`, …) so the proper noun further into the sentence wins. Pre-8DD-2 the first capitalised token was always taken, which routed Alice to write `person/кстати.md` / `person/поправка.md` instead of the real entity slug.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`transport.worker_hooks.entity_translit`** · _beta_ · since 2026-05-15 — Phase 8DD-2 — `extract_primary_entity` transliterates Cyrillic entity names to Latin (table mirrors agents_memory::entity_resolution) and applies a small foreign-brand alias map so well-known names like `Мерседес` collapse to the canonical Latin spelling `mercedes`. Latin input is unchanged. Without this the dossier basename stayed in Cyrillic and probes that glob for the Latin spelling (`dossiers/person/*mercedes*.md`) silently missed.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`transport.worker_hooks.reflection`** · _beta_ · since 2026-05-07 — Phase 8W-5 — on-demand Reflection runner via the `force_reflection` field on the /v1/chat request body. Tests + ops probes set this flag to exercise `run_reflection` without a cron hop. Disabled by default; production chat turns never carry the flag.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`transport.worker_hooks.scribe`** · _beta_ · since 2026-05-07 — Phase 8W-5 — inline Scribe on-trigger after each `/v1/chat` turn. Builds an `ObservationRef` from the last user message + executed-tool signals (memory_pin → importance; «запомни …» / «remember …» → explicit user pin; task_execute success → post-action reflection) and runs `ScribeRunner::run` if any trigger fires. Audit row (`actor=scribe, action=promote`) appended on success.  
  *openalice_api_handlers::http::routes::chat_tools::worker_hooks:0*
- **`turn_bundle.metrics.counter`** · _beta_ · since 2026-05-07 — Wave R4 — `oa_turn_bundle_total{n_speakers}` counter. Labels are normalised to `2`, `3`, or `4+` so the cardinality stays bounded no matter how chaotic a group chat gets. Master plan §12.1.  
  *openalice_agents_soul::sections::turn_bundle:0*
- **`turn_bundle.metrics.histogram`** · _beta_ · since 2026-05-07 — Wave R4 — `oa_turn_bundle_render_ms` histogram. The renderer is pure string formatting and should sit comfortably below 1ms; the histogram is the smoke alarm if a future change ever regresses that.  
  *openalice_agents_soul::sections::turn_bundle:0*
- **`turn_bundle.render`** · _beta_ · since 2026-05-07 — Wave R4 — `render_turn_bundle` deterministic renderer. Pure string formatting (no LLM call), <1ms target. Honours the priority rules from master plan §8.4: most-recent message wins, tie-break via curator `always_include`, then first message.  
  *openalice_agents_soul::sections::turn_bundle:0*
- **`turn_bundle.section`** · _beta_ · since 2026-05-07 — Wave R4 — TurnBundleSection renders the per-turn multi-speaker `=== TURN BUNDLE ===` envelope when the coalescing window groups messages from ≥2 distinct speakers. Lives in the unstable suffix at priority 236 (right after PerTurnBlockSection).  
  *openalice_agents_soul::sections::turn_bundle:0*
- **`turn_bundle.tone_hint`** · _beta_ · since 2026-05-07 — Wave R4 — when ≥1 speaker carries a `tone_preference` (Q-frontmatter additive field), the bundle footer appends per-speaker hints (`@nao: direct, @katya: warm`). Omitted when every speaker's tone_preference resolves to None — zero footer churn for legacy dossiers.  
  *openalice_agents_soul::sections::turn_bundle:0*

### transport/agentic_loop
- **`transport.agentic_loop.phase_d_extraction`** — [doc(hidden)]  
  *crates/api-handlers/src/http/routes/chat_tools/agentic_loop/mod.rs:359*

### tui
- **`tui.alice_tui`** · _experimental_ · since 0.1.0 — alice tui — terminal Mission Control, chat-first with ratatui + crossterm. Ships an in-process event loop, ChatClient that speaks the local /v1/chat endpoint, and a three-pane UI (history / composer / status). M1 baseline for the 5-milestone MC+TUI plan.  
  *openalice_tui:0*
- **`tui.cockpit.agents`** · _experimental_ · since 0.1.0 — B5 — agents pane: AgentSummary + load_agents (global + chat-scoped AgentLayout) rendered as a depth-indented List with status glyphs (▶/⏸/✓/✗/⟳/○), heartbeat badges, token pills. 3-pane layout (25% agents / 30% sessions / 45% trace); numeric keys 1/2/3 focus.  
  *openalice_tui::cockpit::panes::agents:0*
- **`tui.cockpit.controls`** · _beta_ · since 0.1.0 — C5 — TUI control keys when agents pane focused: c→ConfirmCancel modal (y=confirm→cancel cmd, n/Esc=dismiss); p→pause; r→resume. Modal::ConfirmCancel overlay rendered centered over all panes. dispatch_control() builds+signs ControlCommand and appends to command_queue.jsonl via control_queue.  
  *openalice_tui::cockpit::screen:0*
- **`tui.cockpit.filter`** · _experimental_ · since 0.1.0 — B6 — filter mode: '/' enters filter mode (status row shows [filter:…]), typing narrows the focused pane (sessions by chat_id / agents by agent_id or task_preview), Esc clears the query.  
  *openalice_tui::cockpit::screen:0*
- **`tui.cockpit.live`** · _experimental_ · since 0.1.0 — B3 — notify v7 watcher on sessions/ + agents/ directories drives live refresh of the cockpit TUI; 500 ms fallback tick fires when no notify event arrives so the display never goes more than 500 ms stale. RefreshEvent::SessionsChanged / AgentsChanged / TraceChanged are forwarded to the tokio::select! event loop in screen.rs.  
  *openalice_tui::cockpit::refresh:0*
- **`tui.cockpit.rich_trace`** · _experimental_ · since 0.1.0 — B7 — rich trace meta: TraceRow.meta_model / meta_cost_usd / meta_latency_ms + cot_reasoning_steps (up to 3 + '+N more') + cot_context_sources + cot_uncertainty (green ≤ 0.3 / yellow ≤ 0.6 / red > 0.6). Populated from turn.meta by load_trace.  
  *openalice_tui::cockpit::data:0*
- **`tui.cockpit.static`** · _experimental_ · since 0.1.0 — alice cockpit — read-only three-pane terminal mission cockpit (ratatui). Phase A: sessions + trace. Phase B: agents tree (B5), live refresh via notify (B3), '/' filter (B6), rich trace meta + CoT (B7). Navigation: 1/2/3 pane, ↑↓/jk, Tab, Enter/l open trace, g/G, '/' filter, Ctrl+R reload, q/Esc quit.  
  *openalice_tui::cockpit:0*
- **`tui.context_picker`** · _experimental_ · since 0.1.0 — @-context picker — typing `@` opens a 3-tab overlay (File / Memory / Worker). File tab fuzzy-matches `git ls-files`, supports `path#L10-L20` ranges. Memory and Worker tabs read /v1/memory and /v1/workers.  
  *openalice_tui::picker:0*
- **`tui.hermes_layout`** · _experimental_ · since 0.1.0 — Wave K8 — Hermes-style multi-pane layout: sessions sidebar (left top, chat-scope list from ~/.openalice/data/chat), memory panel (left bottom, agent profile + recent + shortcuts), chat panel (centre), and tool execution feed (right bottom). Toggles via Ctrl+S / Ctrl+M / Ctrl+T; @<skill-name> activates a skill for the next turn.  
  *openalice_tui:0*
- **`tui.slash_palette`** · _experimental_ · since 0.1.0 — Slash-command palette — typing `/` opens an overlay listing /help, /clear, /new, /quit, /mode, /endpoint. Tab autocompletes; Enter runs (or queues if Alice is responding, Codex-style).  
  *openalice_tui::commands:0*
- **`tui.streaming`** · _experimental_ · since 0.1.0 — Incremental token streaming from /v1/chat/stream — the assistant reply renders chunk-by-chunk into the chat pane. Falls back to blocking /v1/chat when --no-stream is passed.  
  *openalice_tui::stream:0*

### voice
- **`intelligence.voice_module`** · _beta_ · since 0.1.0 — Voice manager — TTS/STT provider registry with HTTP transport, format negotiation, and a uniform API across Qwen3-ASR/TTS, Whisper, OpenAI TTS, and friends.  
  *openalice_modules::intelligence::voice_module:0*
- **`intelligence.voice_wake_adapter`** · _beta_ · since 0.1.0 — Bridge between `openalice-voice-wake` and `VoiceManager` — implements `WakeStt` so a `WakeEngine` transcribes through whichever STT provider is currently configured.  
  *openalice_modules::intelligence::voice_wake_adapter:0*
- **`voice_wake.silero_vad`** · _beta_ · since 0.1.0 — Silero-VAD ONNX adapter — ~2 MB model, ~15 ms CPU latency per 32 ms window at 16 kHz, dramatically more robust than energy VAD in noisy environments. Opt-in via the `silero` cargo feature.  
  *openalice_voice_wake::silero:0*

---

*Generated by [openalice-atlas](https://atlas.blal.pro) — single source of truth for the openalicelabs ecosystem.*
