Charter — eight lenses × seven feature families¶
The full, populated companion to the constitution skeleton in CLAUDE.md (§ Constitution).
Where the constitution states each lens's one-line pass-line, this page grounds every
lens against reyn's actual implemented features — the canonical inventory is
docs/feature-map.md, and every non-empty cell below cites a
feature-map file:line as its exemplar.
How to read this table¶
- Rows = the eight engineering lenses (see
CLAUDE.mdfor each lens's pass-line). - Columns = seven feature families, each a grouping of
feature-map.md's###sections (see Family → feature-map section map below). - Each cell = that family's exemplar implementation of that lens, with a
feature-map.mdfile:line citation. An empty cell is written as "—" — a lens genuinely does not manifest in that specific family. "—" is not "this lens is covered better elsewhere" — a lens can (and should) have a different exemplar in every family it genuinely shows up in; check the family's own feature-map section before writing "—", don't reach for a cross-family analogy or a same-word-different-meaning cousin (e.g. the Retrieval lens, about context, is not theretrievaltool-use scheme, about tool-surface scaling — don't conflate them). Cells are never invented to fill a gap; a lens that is honestly thin (Retrieval, Evaluation) will show mostly "—" across most families, and that sparseness is itself informative, not a defect in the table. - Don't conflate a band member with the lens that names it as a discipline.
cost/budget (bounding)is a cross-cutting band member — hard caps, refuse-on-exceed, the universal spend guard every feature respects. Product Think is a lens about legibility and predictability for the operator — cost reporting, warnings, and reduction (e.g.present's ~0-token routing), never the bounding mechanism itself. The owner drew this line explicitly (bounding ≠ reduction/legibility); a Product Think cell that cites a refuse-on-exceed cap is citing the band, not the lens — find the family's actual reporting/warning/reduction exemplar instead. The same discipline applies to the other two band↔lens pairs (Security↔permission, Reliability↔crash-recovery (WAL)): the band member is the mechanism every feature must obey; the lens is the discipline of doing that mechanism well for its own purpose, which usually has its own, narrower exemplar. - A single feature can legitimately exemplify more than one lens if it has more
than one facet. e.g. the inline CUI's audit chips are both an Observability
exemplar (the audit-trace-surface facet — the same operator-visible trace the P6
event log records, surfaced live rather than replayed after the fact) and a
Product Think exemplar (the operator-legibility facet — predictable, at-a-glance
cost/agent/permission state). This is not the band↔lens conflation above (one
mechanism, one true owner) — it's one feature with two genuinely distinct facets,
each independently satisfying a different lens's pass-line. Don't force a single
citation to pick one lens when the constitution's own pass-line (
CLAUDE.md) names the mechanism for both. - Authoring proceeds family-by-family (one PR per column). Not-yet-authored columns are marked "(pending)", distinct from a deliberately-empty "—" cell within an authored column.
The 8×7 grid¶
| Lens | Decision & Tool-Use | Chat & Session | Context & Retrieval | Orchestration | External surfaces | Safety & Config | Product surface |
|---|---|---|---|---|---|---|---|
| System Design | The agent loop is an OS-enforced contract: every side effect is a schema-validated, typed Control IR op, never a free-form string (feature-map.md: "every side effect the LLM emits is a schema-validated, typed Control IR op") | Human-in-the-loop is a first-class, surface-agnostic primitive — a permission ask or ask_user routes to the operator identically whether the agent runs in the inline CUI, CLI, web/A2A, or MCP (feature-map.md: "a permission ask or ask_user routes to the operator identically whether the agent runs in the inline CUI, CLI, web / A2A, or MCP") |
Skills' three-layer exposure (L1 system-prompt menu → L2 on-demand SKILL.md read → L3 bundled-asset file-read) delivers context progressively at the layer that needs it, never stuffed unconditionally into the prompt (feature-map.md: "L2 on-demand SKILL.md load (the dedicated load_skill op, FP-0066 P0/#3247)") |
Pipeline is a deterministic, Turing-incomplete control-plane DSL, not another agent loop — composition primitives are structurally closed (no nested launch, no arbitrary recursion) (feature-map.md: "a pipeline is a deterministic, Turing-incomplete control-plane DSL, not another agent loop") | EnvironmentBackend abstracts repo-FS read/write/exec away from the OS + permission layer — the same governance layer applies whether the repo lives on the host (production) or in a container (⚗ Stage 2, experimental) (feature-map.md: "Abstracts repo-FS read / write / exec away from the OS + permission layer") |
Config hot-reload's IN-set/OUT-set file-split is the structural write-gate: hot-reloadable config lives in one set, security/budget/loop-valve config is restart-only in another — right layer decides what can change live (feature-map.md: "OUT-set (reyn.yaml: security / budget / loop valve) is restart-only — the file-split is the structural write-gate") |
Each CLI subcommand owns exactly its own subsystem's operator surface (agent/topology/memory/permissions/events/mcp/config/…) — no cross-cutting mega-command, e.g. reyn mcp alone owns serve/search/install/manage for MCP (feature-map.md: "Serve, search, install, and manage MCP servers") |
| Tool Contract | Op kinds mirror OP_KIND_MODEL_MAP 1:1 in schemas/models.py, one typed schema per kind (feature-map.md: "The op kinds below mirror OP_KIND_MODEL_MAP in schemas/models.py"); every tool-use scheme dispatches through the same exclude → permission → dispatch gate regardless of presentation (feature-map.md: "every scheme dispatches through the same exclude → permission → dispatch_tool gate") |
— | semantic_search (FP-0057 Phase 2a; renamed from recall) is a typed, schema-validated Control IR op (SemanticSearchIROp), never a free-form retrieval string (feature-map.md: "renamed from recall — clean-break, fixes the recall/search_actions/memory naming collision") |
A Pipeline tool/agent step's result is validated against a SchemaRegistry-backed nested schema (verify: schema) — never an untyped free-form return (feature-map.md: "SchemaRegistry-backed schema documents a tool/agent step's result is validated against") |
MCP resource reads (mcp_read_resource) are a typed Control IR op gated by the negotiated resources capability on the same axis as mcp itself — no bespoke per-server protocol bypasses the typed dispatch gate (feature-map.md: "Read one MCP resource by URI (permission-gated, same axis as mcp)") |
SandboxPolicy is a typed envelope every backend receives — network / write_paths / read_deny_paths / write_deny_paths / deny_subprocess / allow_env_names / env_deny_names / timeout_seconds (#3901 PR-B ④; the SandboxedExecIROp op carries no policy fields of its own — #3907 deleted the 5 it used to have, measured to have zero real producers), never a bare shell string (feature-map.md: "the dataclass backends actually receive") |
— |
| Retrieval | semantic_search (renamed from recall): per-source-model embed query → index_query per source → merge top-K (feature-map.md: "per-source-model embed query → index_query per source → merge top-K") — context-retrieval, not to be confused with the retrieval tool-use scheme (feature-map.md: "RAG-over-tools — present a search tool, the LLM searches, the OS re-presents matched tools as callable"), which retrieves tools, not context |
— | search_actions over the tool/mcp/pipeline catalog; the FP-0066 P3b repo-knowledge index (knowledge_repo_doc/knowledge_repo_src) as a third, OS-internal thing distinct from both search_actions and the FP-0063 plugin — same substrate as search_actions but a repo-size-proportional population, gated separately via embedding.index.repo_knowledge (#4156, default off — the split exists because bundling it with search_actions under one embedding.enabled switch let an operator wanting the ~10-entry action catalog silently trigger a TPM-scale repo-wide embed); the FP-0063 user-RAG plugin's bundled ingest/query pipelines for agent-facing document search — the in-core IndexBackend substrate is OS-internal only, with no agent-callable entry point of its own (feature-map.md: "Reyn ships a RAG framework — the index_update op (add/update/remove/skip reconcile) over a pluggable IndexBackend") |
— | — | — | — |
| Reliability | Crash Recovery: .reyn/ recovery-core classification, WAL state log, generation-based restore (feature-map.md: "the recovery-core write-gate (mutate config via dedicated ops, never raw file.write)") |
Multi-session crash recovery: on restart the full name → {sid → Session} structure is reconstructed from the WAL + snapshots, not just one conversation (feature-map.md: "On restart the full name → {sid → Session} structure is reconstructed from the WAL + snapshots, not just one conversation") | skill_install_local/install_source are threat-scanned and permission-gated, with config-generation recorded for crash-recovery — the reliability facet of the same install path (feature-map.md: "threat-scanned, permission-gated, config-generation recorded for crash-recovery") |
Pipeline crash recovery: a per-run work-order persisted before step 0, step-boundary generation snapshots give exactly-once, truncation-surviving resume (including mid-call/fold/for_each state) (feature-map.md: "Per-run work-order (invocation.json) persisted before step 0; step-boundary generation snapshots give exactly-once, truncation-surviving resume") |
MCP resource subscriptions: the runtime-only subscribed-URI set survives a transport-death reconnect, re-subscribing with a synthetic resync per URI rather than silently dropping state (feature-map.md: "runtime-only subscribed-URI set survives a transport-death reconnect") |
Force-close wrap-up: a denied limit gets the LLM one final tool-less turn to summarise what was accomplished rather than hard-stopping or looping unbounded (feature-map.md: "On a denied limit the LLM gets one final tool-less turn to summarise what was accomplished") | Crash-durable cap counters: every cap counter is reconstructed on startup from the fsync-per-append ledger — the ledger, not the best-effort state-file cache, wins on recovery (feature-map.md: "reconstructed on startup from the fsync-per-append ledger") |
| Security | present's data_ref read authority resolves identically to file.read (feature-map.md: "data_ref read authority == file.read"); sandboxed_exec runs under a declared SandboxPolicy (feature-map.md: "argv under SandboxPolicy via platform-selected backend") |
— | skill_install_local/install_source are threat-scanned and permission-gated before a skill directory is registered — no external skill source reaches the registry without passing the gatekeeper (feature-map.md: "threat-scanned, permission-gated, config-generation recorded for crash-recovery") |
⊆-parent capability model: a spawned agent's effective capability = parent's live effective ∩ assigned profile, recursively no-escalation-via-spawn, closed across four stale-lineage axes (feature-map.md: "Spawned agent effective capability = parent's live effective ∩ assigned profile; recursive no-escalation-via-spawn; closed across four stale-lineage axes") | OAuth 2.1 tokens are cached outside the rewind bucket (mode 0600, per-server, never rewound), and a headless run with no cached token fails clearly instead of hanging — external auth material never re-enters a replayed state (feature-map.md: "tokens cached in ~/.reyn/oauth_tokens.json (outside bucket, mode 0600, per-server, never rewound") |
Tier 2/3 capabilities (exec — renamed from shell #3226 Phase 3 / mcp / file out-of-zone / python) require declaration + 4-layer just-in-time approval (config pre-approval → saved → session → interactive prompt) — no capability reaches the world without passing the gatekeeper (feature-map.md: "Tier 2/3 — declaration + 4-layer approval") |
— |
| Evaluation | Scoring an output against a rubric is a pipeline agent step + schema — the OS's contribution is the typed schema (constrained generation + validation) and the cost tracking it already provides for every agent step, not a bespoke scorer op (the prior judge_output op was removed as a clean-break: it was an LLM call with a rubric the OS never interpreted, i.e. agent work wearing an OS-op costume) (feature-map.md: "Self-review composes from the agent + schema primitives, with the threshold comparison done by a plain transform step") |
— | — | — | — | — | — |
| Observability | Event System (P6): 171 event types, append-only JSONL, reyn events replay (feature-map.md: "reyn events <path> streams events for audit and debug"); present's own presented audit event (feature-map.md: "Audit event carries refs + stats, never content bytes") |
Status chips (Agents / Cost / Model / Tools / MCP / Skills / Hooks / Pipes / Cron) are the chat surface's own live audit-trace facet, each expandable in place — the same operator-visible trace the P6 event log records, surfaced inline rather than replayed after the fact (feature-map.md: "a focusable tab row that expands a drawer downward — Model / Agent") | — | chain_id propagation traces multi-hop delegation chains in P6 events (feature-map.md: "Trace multi-hop chains in P6 events") |
The MCP resource-subscription push lands as a P6 mcp_resource_updated audit-event — the observability trace of the same subscription mechanism whose resync-on-reconnect is the Reliability exemplar above (that push is also wired as an external-event hook-point, but that's a reactivity trigger, not an observability facet — the events triad keeps audit-event/hook-event distinct) (feature-map.md: "push lands as an mcp_resource_updated EventLog event and is also wired into the hook dispatcher as an external-event hook-point") |
limit_denied is a P6 audit event on every deny path (max_iterations / router_cap) (feature-map.md: "P6 audit event on every deny path (max_iterations / router_cap)") |
reyn events replays event JSONL files for audit and debug — the CLI-side entry point into the P6 audit trail (feature-map.md: "Replay event JSONL files or purge old files by date") |
| Product Think | present routes bulk data to the surface at ~0 output tokens instead of reproducing it as LLM output (feature-map.md: "display costs ~0 output tokens") |
Reyn's chat surface is a local, inspectable CLI with live audit chips (agents / cost / permissions) beside the conversation — the operator sees what the agent is doing and spending in real time (feature-map.md: "Reyn's chat surface is a local, inspectable CLI with a live audit drawer (agents / cost / context / permissions) beneath the conversation") | Hot-reload: .reyn/config/skills.yaml edits apply at the next turn boundary via the "skills" reload seam — predictable, config-selectable operator control without a restart (feature-map.md: ".reyn/config/skills.yaml edits apply at the next turn boundary via the") |
Agent hops cap (safety.loop.max_agent_hops) gives the operator a predictable, config-selectable bound on delegation depth — legible orchestration, not an unbounded chain (feature-map.md: "Max delegation depth via safety.loop.max_agent_hops") |
Reyn keeps external connectivity to standard protocols (MCP client+server, A2A sync+async, REST/AG-UI SSE gateway) rather than a sprawling per-app integration catalog — a disciplined, legible surface set instead of endless bespoke connectors (feature-map.md: "Reyn keeps connectivity to standard protocols — MCP (client + server), A2A (sync + async tasks with webhook push), and a REST / AG-UI SSE gateway") | On-limit modes (interactive / auto_extend / unattended) give the operator predictable, config-selectable control over every loop/timeout/budget checkpoint uniformly (feature-map.md: "interactive (ask) / auto_extend (budgeted N times) / unattended (abort) via safety.on_limit.mode") |
High-cost model warn (cost_warn): a pre-selection warning to the operator when the resolved model's cost-per-1M-tokens exceeds a threshold, de-duped once per model per session — legibility, distinct from the token/USD bounding caps themselves (the cross-cutting band's cost/budget member, not a Product Think exemplar) (feature-map.md: "emits a model_cost_warn audit-event + inline conv-pane marker when the resolved model's input cost per 1M tokens exceeds") |
Family → feature-map section map¶
Every one of feature-map.md's 23 live ### sections falls into exactly one family —
this table is the lossless appendix; keep it in sync if a ### section is added,
renamed, or removed in feature-map.md.
| # | feature-map section | family |
|---|---|---|
| 1 | OS Core | Decision & Tool-Use |
| 2 | Chat Engine | Chat & Session |
| 3 | Control IR Ops | Decision & Tool-Use |
| 4 | Present layer | Decision & Tool-Use |
| 5 | Tool-Use Schemes | Decision & Tool-Use |
| 6 | CLI | Product surface |
| 7 | Config | Safety & Config |
| 8 | Permissions | Safety & Config |
| 9 | Safety / limit-handling | Safety & Config |
| 10 | Content-layer defense | Safety & Config |
| 11 | Budget & Cost | Product surface |
| 12 | Memory & RAG | Context & Retrieval |
| 13 | MCP | External surfaces |
| 14 | Skills | Context & Retrieval |
| 15 | Pipeline | Orchestration |
| 16 | Web & Protocol | External surfaces |
| 17 | Inline CUI | Chat & Session |
| 18 | Intervention | Chat & Session |
| 19 | Sessions and identity | Chat & Session |
| 20 | Multi-Agent | Orchestration |
| 21 | LLM org-design (runtime spawn primitives) | Orchestration |
| 22 | Sandbox | Safety & Config |
| 23 | Environment — ⚗ Stage 2 | External surfaces |
Totals: Chat & Session 4 · Decision & Tool-Use 4 · Context & Retrieval 2 · Orchestration 3 · External surfaces 3 · Safety & Config 5 · Product surface 2 = 23/23, each section in exactly one family. (#2839 Phase 2/3: the internal Task system section was removed — LLM task-decomposition moves external, MCP + hooks + pipelines.)
See also¶
CLAUDE.md— the constitution skeleton (eight lenses' pass-lines + the cross-cutting band) this table populatesdocs/feature-map.md— the canonical, impl-extracted feature inventory every cell cites