# Architecture This file is the **live-tree map** for the TypeScript Distilly Plugin. The former `dot-skill` implementation remains on its own maintenance branch and is not copied into this tree. New work must land on the design in [design/system-v3.md](design/system-v3.md). Do not implement from this page alone. Load [design/README.md](design/README.md) and the chapter that owns the change. ## What exists now This section describes the current product tree. Workspace experiments outside the governed product diff are not shipped evidence. - The root `pnpm` workspace pins Node `^22.19 || ^24`, its package manager and dependencies in `pnpm-lock.yaml`, and real format, lint, typecheck, Vitest, coverage, snapshot, build, built-entry, export-map, type-resolution, and dependency-hygiene commands. - `packages/protocol/` provides the V3 §29.1 Protocol slice: branded ids and value families, wire/error envelopes, trusted-session and private-capture values, fact-record shapes, all 35 EngineMethodMap schemas, EngineClient/Event contracts, the separate root-owner `EngineAdministrationClient` backup/restore schema pair, strict purge/GC diagnostics, the exact five MCP tool descriptors with runtime and draft-2020-12 schemas, strict runtime boundary schemas, and a built ESM entry. The administration pair is not part of EngineMethodMap, Panel RPC, or MCP. - `packages/adapters/` owns the source and deterministic-parser boundary. It exports the direct/delegated `SourceAdapter` union, adapter-owned resource-parser contracts, public configuration plus opaque secret references, a content-free source registry snapshot, strict runtime schemas for the separate four-method direct-user collection table, `MaterialParser` contracts, an exact-media-type parser registry, and built-in UTF-8 TXT, Markdown, stable JSON, SRT, and VTT parsers. It contains no built-in provider ids, secret resolution, network/filesystem collection, collection service, runtime, CLI, or EngineMethodMap/MCP extension. - `packages/engine/` now provides the package-private SQLite/WAL create, ingest, file-ingest, pending, brief, renew, release, commit, active-review query, promote, reject, rollback, correction, and Preview verified-read slice. Its exact nineteen-table canonical private schema v1 additionally owns content-addressed raw material identities and subject-to-raw provenance relations alongside spaces, subjects, aliases and identity hints, current material membership, authoritative pending jobs and optional leases, immutable versions, version-scoped claims/evidence/material membership, independent version status and current/suspended pointers, stable operations, blob-backed operation-result references, and audit events. Immutable raw bytes, normalized bodies, and complete canonical briefing templates live in the SHA-256 content-addressed blob store. Every mutation commits its structured effects in one transaction and replays RequestIds exactly. - The SQLite briefing path verifies the complete first-version material snapshot under one blob access lease, pins `source-groups-v1` and the packaged prompt contract, and refuses silent capacity truncation before publishing a fixed-width placeholder template. The write transaction takes a fresh acquisition time, grants the full 30-minute lease, and stores a small canonical envelope that binds RequestId, input checksum, subject, template pointer, and exact final lease. Replay verifies both authorities and overlays only the fixed-width lease fields, preserving the capacity fixed point while reconstructing the exact original `HostDistillBriefing` without consulting the current job or prompt. Duplicate ingest preserves a same-generation lease, while a changed generation replaces the pending job and cascades its prior lease. - SQLite commit rebuilds evidence context from verified pending, lease, current-version and material rows, validates referenced blob bytes, applies the claim-only patch with pinned algorithms, and derives claims, quality, mechanical review reasons, `VersionId`, Profile and prompt deterministically. Its one write transaction rechecks RequestId, job, generation, lease, pointers, material membership and subject identity; writes the complete immutable version authority; moves current or suspended status/pointers; removes pending/lease; and appends the stable result plus two events. A later ingest can therefore brief against a verified current baseline. The accepted-patch digest is part of a sealed private authority record; current/suspended uniqueness and same-subject lineage are constrained by schema and verified on direct reads. - The SQLite review query reads active subject pointers and only the directly needed immutable current/candidate rows inside one consistent snapshot, reconstructs their canonical profiles, and returns stable current-versus-candidate diffs without consulting pending work or full history. Promote and reject use active-candidate CAS in one write transaction; promote makes the previous current historical and rebases remaining material work, while reject preserves the pending row and lease byte-for-byte. Rollback accepts one same-subject historical target and creates a new immutable current descendant that copies its semantic snapshot while recording the new parent, actor, time, source, and `VersionId`. Promote and rollback replace any remaining pending work with a fresh JobId, mutation-time queue timestamp, recomputed delta, and no lease. All three store exact operation results plus reason/lineage-bearing events in the same transaction and use SQLite/WAL rather than mutation journals for crash recovery. - SQLite correction binds direct-user or relayed provenance to the trusted actor, stores its normalized private body through the shared blob store, and creates one full-body `user_asserted` replacement claim. One transaction writes material membership, immutable current or suspended version, optional candidate replacement lineage, pointers/statuses, fresh no-lease pending work, the stable operation result, and fixed events. A current correction intentionally permits a zero-delta pending job. Real pre/post-COMMIT process kills prove that reopen observes only the old world or the complete correction; there is no correction journal, staging, or recovery path. - The package-private SQLite read service supplies subject list/resolution, Profile get/prompt/status, material list/get, version list/diff/lineage, and direct Library list from one root authority. Ordinary reads verify the subject rows, immutable versions, events, and content blobs used by the requested result; current material rows are rebound to the subject material-set hash and pending total before material or Library delivery. Material reads acquire shared blob access before taking their SQLite snapshot and retain it through digest-verified delivery, including the raw blob behind `raw_extract` before reporting `rawAvailable=true`. The Library is a direct SQLite aggregate for this Preview, not a second stored authority or a generic projection framework. - An explicit `legacy-file-engine.test.fixture.ts` keeps the superseded package-internal material/profile/version/Library read pipeline executable without entering the SQLite composition. Supporting test-only files retain the former file-backed commit, immutable-version staging, lease/commit recovery, and a copied legacy review query solely as regression setup for those reads. The former file review/rollback mutation service and its recovery branches are removed; none of these fixtures is a compatibility fallback or production-package entry. - The retained package-internal file read slice and checksummed JSON Library projection remain executable only as uncomposed regression surfaces for the earlier fact tree. They continue to prove their historical cursor, snapshot, and corruption behavior while the Developer Preview uses neither path. - The retired file-backed commit writer, immutable-version staging and lease/commit recovery survive only through explicitly named test fixtures and are excluded from the production package. The superseded file-backed verified reads, JSON Library projection, their fact stores, and their read coordination remain packaged but uncomposed until post-Preview cleanup. A source-graph gate proves the live SQLite composition has no transitive dependency on that authority, locks, recovery, queue, or projection; it creates no queue database, version-staging directory, or dirty marker. The stable Engine package root intentionally exports no partial production API. - SQLite is therefore current authority for create, text ingest, local file ingest, pending, brief, renew, release, commit, active-review listing, promote, reject, rollback, correction, the three host-projection operation records, and the subject/Profile/material/version/lineage/Library reads required by the first Preview. File ingest stores explicit raw bytes and any deterministic text extraction under one operation, permits only one canonical text tuple per `RawId`, retains parser failures as raw-only without changing generation or enqueueing, and never persists the selected absolute path. Host install/export/uninstall store exact RequestId results and conflicts in the same operation ledger; uninstall authorization proves the supplied install reference came from a canonical prior install result before any filesystem effect. Other product methods still require feature-by-feature implementation before a complete root-scoped Engine writer exists. - `@distilly/engine/preview` now exposes an explicitly incomplete in-process EngineRuntime over that live SQLite composition. Each connection validates its trusted actor and optional capacity, receives a fresh engine-owned lease owner, parses exact Protocol params/context/results, and owns only its session watches. Runtime close stops new work, drains accepted calls, closes SQLite, and releases normalized in-process root ownership. Six deferred core keys fail with `schema_unsupported`; a separate package-private host-mutation authority owns replay, conflict, provenance, and completion for the three Runtime projections. The subpath does not claim daemon, RPC, cross-process takeover, doctor, maintenance, parser, or filesystem projection behavior. - `packages/runtime/` adds the empty stable `@distilly/runtime` root and opt-in `@distilly/runtime/preview` LocalRuntime. It wraps the Preview core as an `EngineClient`, reads only explicit user-selected regular files, maps the five initial extensions to exact media types, and composes the built-in parsers before handing raw bytes and parser drafts to Engine. When opened with one verified full host binding and trusted host context, it creates that binding's injector and serializes Profile install/export/uninstall through Engine replay authority, verified Profile reads, idempotent filesystem projection, and stable operation completion; missing or mismatched bindings fail closed. `system.doctor` remains unavailable. Runtime depends on Protocol, Adapters, Bindings, and Engine; it does not compose CLI, MCP, or Panel. - `packages/distilly/` is the browser-safe Step 8 facade. Its root exports `Distilly`, `Person`, `DistillyError`, and the reviewed Protocol type surface; it accepts a caller-supplied complete `EngineClient`, maps every public query and mutation without filesystem or Node imports, preserves the complete `PurgeResult`, keeps each `Person` bound to its subject, and delegates `close()` only to that injected client. It has no `openInProcess`, `distilly/node`, or local runtime constructor. - `packages/mcp/` is the Step 8 MCP adapter. Its transport-neutral root exports `createMcpServer` plus the narrow server and `ReviewPresenter` types, registers exactly the five Protocol descriptors, maps them to a caller-supplied complete `EngineClient`, normalizes every product outcome to a Protocol-parsed output, and presents only suspended review references. The Node-only `@distilly/mcp/stdio` subpath owns bounded stdio teardown; neither entry owns the injected client or presenter. - `packages/bindings/` is the host-specific leaf. Codex, Claude Code, OpenClaw, and Hermes capability factories remain filesystem/process-free and validate trusted net-capacity evidence against the exact host/environment/release/wire/skill tuple while forcing private UI capture unavailable. Separate full factories reuse that preflight and add concrete form renderers, prompt injection, digest-owned self-contained person-Skill install/export, narrow doctor, and host lifecycle. Codex installs through the personal marketplace plus the checked `codex plugin add/remove` command; Claude Code installs as an auto-discovered skills-directory plugin. OpenClaw consumes the Claude-compatible bundle in an owned `~/.openclaw/extensions/distilly` tree and receives a generated absolute-launcher `.mcp.json`; it does not take ownership of a pre-existing global MCP entry. Hermes consumes the canonical Skill from managed `~/.hermes/skills/distilly`, registers the same stdio server through a Distilly-owned wrapper and `~/.hermes/config.yaml`, and disables the auxiliary `resources` / `prompts` surfaces so exactly five Distilly tools remain visible. All four generate install-time configuration directly instead of reading the source sentinel template, reject source skill-digest drift, preserve unrelated files/data, and do not construct Runtime or access `DISTILLY_ROOT`. OpenClaw `2026.3.24` and Hermes `v0.9.0` now have separate real-host capacity fixtures (65,536 and 49,752 serialized-byte net budgets respectively); unknown versions and changed release/tool tuples still fail closed. Preflight completes before the MCP server starts and remains internal to binding/runtime composition; the canonical Skill treats the exact five model-visible tools as its entry gate instead of requiring an impossible model-visible `HostPreflight` object. - `packages/panel/` is the Step 10 injected-client Panel leaf with no root barrel. Its `@distilly/panel/server` subpath owns a literal-`127.0.0.1` server, exact Bearer/Host/Origin checks, fixed assets and CSP, bounded request/response/header/SSE handling, all-mutation one-use nonces, and a single-flight `ReviewPresenter` launcher; its browser-safe `@distilly/panel/web` subpath owns the complete EngineMethodMap HTTP client, authenticated `POST /events` re-read stream, and Library, Subject, Review, and Settings/Doctor rendering. It enables real reads plus promote/reject/rollback over a borrowed full client, never reads Engine stores, and gives unsupported production features no fake success. Review recovery suppresses only the non-retryable `schema_unsupported` response carrying the explicit `preview_method_deferred` / `system.doctor` detail pair, while Settings states that limitation and every other Doctor failure remains visible. - `packages/cli/` keeps an empty stable library root and an explicit private `@distilly/cli/preview` outer composition, plus the `distilly` binary. The binary exposes the real Preview commands: setup, narrow doctor, explicit `install --host `, uninstall, and plugin-owned `mcp --host ` for hosts with a matching fixture. Setup probes the exact executable version and parses the immutable `0.1.0-preview.1` host/version/environment/release/wire/Skill net-capacity record before writing; unknown versions and hosts without equivalent real-host evidence fail closed. A request for an unsupported host reports the explicit external Legacy Skill guide and confirms that no mode switch occurred. Every Codex probe uses the recorded absolute executable, restores the installed Codex home, and puts the manifest-verified Node directory first on `PATH`, including when Codex has removed `CODEX_HOME` from an MCP child's environment. In an assembled package it first verifies the complete runtime file manifest, copies those production bytes atomically into `~/.distilly/runtime/0.1.0-preview.1/`, writes an absolute launcher to the copied entry, invokes the selected full binding from that copy, and records the installed host. The MCP entry rechecks the executable version and evidence, reconstructs that full binding, and owns one Preview LocalRuntime, separate host and direct-user clients, the `Distilly` facade, exact five-tool server, and lazily started Panel. An automatic Panel port is selected inside each lazy start attempt rather than retained from MCP startup. The explicit install command uses the same verified composition and existing `Person.install` path; it does not add a sixth model-facing tool. Doctor verifies the runtime tree and plugin ownership before uninstall; last-host uninstall removes only those verified projections and preserves the SQLite/person root and separately installed person Skills. Cross-process attach, upgrade, and deep doctor remain deferred. - `plugins/shared/skills/distilly/` is the one canonical skill tree; the Codex and Claude Code copies are byte-identical generated mirrors. Its chat-first intake starts from pasted text, explicitly selected readable local paths/directories, and public URLs already in the request without a person-type form or connector setup. The host reads only that selected scope, keeps each traceable source separate, batches the existing text-ingest tool when necessary, and briefs only the final generation; the five-tool path does not claim raw-file storage or hidden background access. The repository assembler hashes every regular file and the sorted recursive tree, synchronizes platform manifest versions with `@distilly/mcp`, writes `plugins/release-manifest.json`, and rejects symlinks and stale targets. Both MCP templates remain source-only. The Codex package assembler copies only the release manifest, Codex platform manifest, canonical Skill mirror, Panel assets, prompt, and code-split production CLI graph; it rejects source inputs, symlinks, workspace dependencies, tests/fakes, sentinel bytes, and checkout paths, then writes a digest manifest consumed by setup. Forced rebuild first assembles the replacement and removes only an existing output that still passes the complete runtime manifest and digest check. Full bindings verify the matching Skill digest and directly generate a real absolute-launcher `.mcp.json` only in their owned install trees; OpenClaw reuses the Claude mirror at install time, while Hermes reuses the shared canonical Skill and does not require a Python plugin manifest. - The current internal dependency edges are `@distilly/adapters → @distilly/protocol`, `@distilly/engine → @distilly/protocol`, `@distilly/runtime → @distilly/protocol + @distilly/adapters + @distilly/bindings + @distilly/engine`, `distilly → @distilly/protocol`, `@distilly/mcp → @distilly/protocol`, `@distilly/bindings → @distilly/protocol`, `@distilly/panel → @distilly/protocol + @distilly/mcp`, and outer `@distilly/cli → Protocol + Bindings + Runtime + Facade + MCP + Panel`; the Panel web graph itself reaches only Protocol. Packages have no upward or mutual edge beyond that allowlist; negative fixtures cover bare, subpath, workspace, link, file, and directory aliases. - The MCP package's built stdio conformance child still injects a full test-only EngineClient and presenter. The CLI source integration executes the complete local data/correction/reopen graph plus Codex person-Skill install/export/uninstall and exact replay. Separately, built CLI smokes run compiled package bytes over temporary homes: one starts the private stdio Preview composition and drives the built Panel in Chromium against the same SQLite authority to promote, reject, roll back, and verify the reopened result; another uses the real binary for Codex setup, rejects unknown/deferred host tuples, starts MCP through the installed launcher, lists exactly five tools with the official client, then uninstalls while preserving SQLite and person data. Compatibility binding smokes additionally exercise OpenClaw bundle inspection and Hermes managed-Skill/config discovery. The immutable host-capacity verifier runs the installed OpenClaw and Hermes executables in isolated homes, invokes each real host/model through a deterministic synthetic fixture server over the five-tool MCP transport, checks exact structured/text duplication and unseen tail markers, and writes only a normalized content-free evidence record; it proves transport capacity, not the product Engine or a complete host lifecycle. The Codex package verifier runs the actual self-contained artifact from a path containing spaces and non-ASCII characters, deletes that extraction, verifies the installed runtime through official Codex plugin/MCP listing and the official MCP client, initializes once with the host-like absence of `CODEX_HOME`, runs create/ingest/brief/commit/get/prompt/correction/Panel promote, installs a person Skill through the human CLI, proves both plugin and person-Skill discovery in fresh Codex processes without a model call, and verifies uninstall preserves SQLite and the person Skill byte-for-byte. The `0.1.0-preview.1` fixtures record Codex/OpenClaw at 65,536 serialized bytes and Hermes at 49,752, each with model-observed unseen tail markers. - No complete production Engine factory or cross-process LocalRuntime, remaining evolution services, built-in source provider, user collection service, upgrade/deep-doctor lifecycle, Claude/OpenClaw/Hermes packaged fresh-install/lifecycle closure, or tagged user release exists yet. The `0.1.0-preview.1` Codex package is self-contained and executable from the public Preview branch, while OpenClaw/Hermes exact transport-capacity fixtures can enter their recorded briefing path without claiming packaged closure; the branch is not an npm publication or tagged release. Host filesystem projection precedes SQLite operation completion; a retry converges when it resolves the same Profile and destination state, while current-version drift, orphan collection, and exhaustive projection crash injection remain post-Preview hardening rather than a claimed cross-boundary atomic transaction. - TypeScript tests live with their source under `packages/*/src/`; repository tests under `tests/` cover package boundaries, build artifacts, documentation generation, and Plugin assembly. Root Python scripts are repository tools, not product runtime code. - CI on `dot-skill`, `distilly`, `distilly-plugin`, and `main` checks documentation and whitespace, exercises the TypeScript workspace, Protocol and source-adapter contracts, package boundaries, Engine SQLite paths, Facade/MCP/bindings/Panel tests, built stdio conformance, real Chromium Panel behavior, and Plugin release assembly on Node 22.19 and 24 across Linux and macOS. A small Python lane validates repository scripts and assembly. - Generated design chapters, local Markdown links, and governed-diff Note ownership are checked by scripts under `scripts/`. - Required-check enforcement is external GitHub state; this tree only defines the checks themselves. ## What must be built The contract is the uncut design. Entry points: | If you are changing | Read | |---|---| | Any term used below | [design/v3/00-how-to-read.md](design/v3/00-how-to-read.md) | | Product promise and user journeys | [design/v3/01-product.md](design/v3/01-product.md), [design/v3/02-user-journeys.md](design/v3/02-user-journeys.md) | | A locked rule or superseded V2 decision | [design/v3/03-locked-and-superseded.md](design/v3/03-locked-and-superseded.md) | | LLM versus engine trust boundary | [design/v3/04-trust-and-principles.md](design/v3/04-trust-and-principles.md) | | Layers, processes, and state machines | [design/v3/05-architecture-and-state.md](design/v3/05-architecture-and-state.md) | | Target storage authority, transactions, and audit | [design/v3/06-storage-authority-and-transactions.md](design/v3/06-storage-authority-and-transactions.md) | | A field name that reaches disk or the wire | [design/v3/07-protocol-types.md](design/v3/07-protocol-types.md) | | The exact five MCP tools | [design/v3/08-mcp-tools.md](design/v3/08-mcp-tools.md) | | Research, adapters, and provenance | [design/v3/10-research-provenance.md](design/v3/10-research-provenance.md) | | Ingest, queue, briefing, and lease | [design/v3/11-ingest-and-queue.md](design/v3/11-ingest-and-queue.md), [design/v3/12-briefing-and-lease.md](design/v3/12-briefing-and-lease.md) | | Claims, rendering, commit, and review gates | [design/v3/13-profile-and-claims.md](design/v3/13-profile-and-claims.md), [design/v3/14-commit-and-quality.md](design/v3/14-commit-and-quality.md) | | Local Panel and its security boundary | [design/v3/15-local-panel.md](design/v3/15-local-panel.md) | | Recall, injection, and host bindings | [design/v3/16-recall-and-injection.md](design/v3/16-recall-and-injection.md), [design/v3/17-host-bindings.md](design/v3/17-host-bindings.md) | | `Distilly`, `Person`, EngineClient, and methods | [design/v3/18-public-sdk.md](design/v3/18-public-sdk.md) | | CLI, setup, MCP composition, and plugins | [design/v3/19-cli-and-plugins.md](design/v3/19-cli-and-plugins.md) | | Corrections and version evolution | [design/v3/20-corrections-and-evolution.md](design/v3/20-corrections-and-evolution.md) | | Relations and rebuildable indexes | [design/v3/22-relations.md](design/v3/22-relations.md), [design/v3/23-index-and-search.md](design/v3/23-index-and-search.md) | | Local bundles and future Profile Catalog | [design/v3/24-profile-catalog.md](design/v3/24-profile-catalog.md) | | Package cut and dependency direction | [design/v3/25-package-and-source-tree.md](design/v3/25-package-and-source-tree.md) | | Gates, CI, and what only review can judge | [design/v3/27-testing-and-governance.md](design/v3/27-testing-and-governance.md) | | Retiring Python and compatibility | [design/v3/28-migration-and-compatibility.md](design/v3/28-migration-and-compatibility.md) | | Order of work and release acceptance | [design/v3/29-landing-and-evolution.md](design/v3/29-landing-and-evolution.md) | ## Live data flow (today) ``` product protocol: packages/protocol/src → types + runtime schemas + ESM lib entry source/parsers: packages/adapters/src → source seams + TXT/Markdown/JSON/SRT/VTT; no providers internal engine: packages/engine/src → SQLite mutations/raw authority + Preview verified reads; legacy regression fixtures preview engine: @distilly/engine/preview → actor/owner/capacity-bound real SQLite core client preview runtime: @distilly/runtime/preview → local parsers + verified binding-backed person projections; doctor fails visibly stable roots: @distilly/engine + @distilly/runtime → intentionally empty; no production runtime yet injected facade: distilly → Distilly + Person over a caller-supplied EngineClient injected MCP: @distilly/mcp → five handlers + separate stdio transport over borrowed ports host integration: @distilly/bindings → verified preflight + full host lifecycle/projections injected Panel: @distilly/panel → loopback server + browser UI over a borrowed complete EngineClient preview app: @distilly/cli/preview → Runtime + Facade + five MCP tools + lazy real Panel plugin sources: plugins/shared → recursive canonical skill → exact Codex/Claude mirrors + release manifest; OpenClaw reuses Claude bundle, Hermes installs shared Skill at runtime stdio fixtures: MCP fake conformance + real local Preview child and reopen ``` ## Target data flow (design) ``` host LLM research / files → five MCP tools → claim patch surfaces Distilly + Person | local Panel | CLI/plugin │ EngineClient only runtime host binding + parser → actor-bound client │ engine ingest → pending → brief/lease → validate/apply/render → current|suspended │ │ ▼ ▼ authority SQLite/WAL metadata + immutable blobs LSN projections / exports / host files ``` Signatures, field lists, and host pitfalls stay in the design chapters. This page only orients.