diff --git a/.reviews/ReviewPR.local.md b/.reviews/ReviewPR.local.md
index 6a4a21dad..053485895 100644
--- a/.reviews/ReviewPR.local.md
+++ b/.reviews/ReviewPR.local.md
@@ -23,11 +23,7 @@ const changedTsFiles = pr.files
as="rawDiagnostics"
/>
-```ts eval
-import { buildDiagnostics } from "@executablemd/code-review-agent";
-
-const diagnostics = buildDiagnostics(rawDiagnostics, pr, doctor);
-```
+
diff --git a/.reviews/ReviewPR.md b/.reviews/ReviewPR.md
index 7d8063fca..9b5dbe5fc 100644
--- a/.reviews/ReviewPR.md
+++ b/.reviews/ReviewPR.md
@@ -25,11 +25,7 @@ const changedTsFiles = pr.files
as="rawDiagnostics"
/>
-```ts eval
-import { buildDiagnostics } from "@executablemd/code-review-agent";
-
-const diagnostics = buildDiagnostics(rawDiagnostics, pr, doctor);
-```
+
diff --git a/AGENTS.md b/AGENTS.md
index 1be3b2f02..c900139bd 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -405,7 +405,9 @@ the corpus or enabling in-shard concurrency is not an answer to a miss.
## MUST READ
- https://github.com/thefrontside/effection/blob/v4/AGENTS.md
-- `architecture.md` — read fully
+- [`architecture.md`](architecture.md) — read fully. Its [reading map](architecture.md#reading-this-architecture)
+ locates current invariants and their feature-interface owners; it does not
+ replace the full reading.
- `specs/executable-mdx-spec.md` — read the sections your change touches
## Code Rules
diff --git a/README.md b/README.md
index 086c29400..b32222bf5 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,21 @@ Three documents own the rest:
- [`specs/executable-mdx-spec.md`](specs/executable-mdx-spec.md) — what the
product does, with the conformance matrix that pins it.
+Follow a question into the [architecture reading map](architecture.md#reading-this-architecture):
+
+- [Execution and diagnostic journals](architecture.md#a-document-running): what
+ runs, what a Plan produces, and which journal can continue a workflow.
+- [Partial and completed replay](architecture.md#replay-and-effect-transactions):
+ why a historical file read survives a later deletion.
+- [Native Agent ownership](architecture.md#native-agent-sessions): handoff,
+ release and executable compatibility.
+- [Installed structural regions](architecture.md#the-installed-structural-syntax-boundary):
+ demand, output and cancellation.
+- [Plan recovery](architecture.md#typed-candidate-recovery-around-evaluate): why
+ cleanup failure stops a candidate retry.
+- [Current rules and historical decisions](specs/decisions.md#finding-the-current-rule):
+ where the architecture, feature contracts and vision differ in authority.
+
Locate the package that owns the behavior you are about to change:
- `packages/core/` — the engine: the boundary scanner, component expansion,
@@ -33,7 +48,7 @@ Locate the package that owns the behavior you are about to change:
- `packages/durable-streams/` — the journal protocol, replay and divergence.
- `packages/workflow/` — workflow runs, run storage, and the Workspace.
- `packages/git/` — repository collaboration: ``, ``,
- ``, the `Git.*` operations, pull requests and issues, and the GitHub
+ the `Git.*` operations, pull requests and issues, and the GitHub
adapter behind them. It is the one Plugin `xmd` bundles, active by default for
the run-profile commands — `run`, `plan`, `syntax`, and `workflow start`,
`resume` and `fork`. The `xmd test` root is deliberately not one of them, so a
diff --git a/architecture.md b/architecture.md
index f2a72a543..72bada740 100644
--- a/architecture.md
+++ b/architecture.md
@@ -1,151 +1,63 @@
# Architecture guidelines
-Rules the engine's core mechanics must satisfy. The spec says what the
-language does; this file binds what any implementation may do. Rules are
-invariants; the inventory at the end says what is built.
+## Reading this architecture
-## Terminology
+Read this document to understand the rules every engine implementation preserves.
+Start with a document running, then follow its execution, failures and retained
+state. The detailed boundaries explain what an implementation may do; the
+terminology and construct inventory are references after those ideas are clear.
-Terms are locked here. Two rules:
+The documents have different jobs:
-1. Only use concepts and words described here or already defined in the spec
- and code.
-2. If a concept or term is missing, ask for permission before using it; using
- it requires adding it here first.
+- This architecture owns implementation invariants and resource lifetimes.
+- [The language specification](specs/executable-mdx-spec.md) owns authored syntax,
+ observable behavior and conformance. Feature specifications refine their own
+ interfaces; the route table below points to them.
+- [The vision](specs/markdown-agents-vision.md) explains product direction and is
+ non-normative. [Decisions](specs/decisions.md) preserve history and consequential
+ rationale, including changes to earlier decisions.
+- [The contribution guide](AGENTS.md) owns preparation, verification and review.
-Existing documents and code get aligned to this section retroactively.
+| Question | Start here | Interface and evidence |
+| --- | --- | --- |
+| What runs, and can a diagnostic journal continue it? | [A document running](#a-document-running) | [Plan diagnostic journal](specs/plan-command-spec.md#the---journal-file) and [workflow continuation](specs/workflow-workspace-spec.md#9-replay-and-continuation) |
+| What does partial or completed replay restore after a write, read and delete? | [Replay and effect transactions](#replay-and-effect-transactions) | [Workflow replay](specs/workflow-workspace-spec.md#9-replay-and-continuation) |
+| Who owns a native Agent handoff, and what if its executable changes? | [Native Agent sessions](#native-agent-sessions) | [Native ownership](specs/native-agent-session-launch-spec.md#ownership-and-concurrency) and [build binding](specs/native-agent-session-launch-spec.md#executable-build-binding) |
+| When does an installed structural region run, and who cancels it? | [Installed structural syntax](#the-installed-structural-syntax-boundary) | [Structural interfaces](specs/executable-mdx-spec.md#declared-structural-syntax) and [SR conformance](specs/executable-mdx-spec.md#tier-sr--expanding-installed-structural-syntax-53) |
+| Why can Plan retry a refused candidate but stop on cleanup failure? | [Typed candidate recovery](#typed-candidate-recovery-around-evaluate) | [Plan failures](specs/plan-command-spec.md#failures) |
+| Which rules are current, and which explain earlier choices? | [Changing these rules](#changing-these-rules) | [Decisions](specs/decisions.md) and [vision](specs/markdown-agents-vision.md) |
-"Authority" is not one of these terms. Each boundary it once covered is named
-for what it actually does: canonical resolution, admission, configured
-permission, ownership, coordination, publication, execution, or definitive
-settlement. Two serialized spellings keep the older word because their bytes are
-a compatibility contract, not a description: the durable `LaunchFailureClass`
-value `"directory-authority"`, which a retained launch record is parsed against
-by exact match, and the Files invariant category `"authority"`, which crosses
-loaded copies and is matched the same way. Renaming either would break replay
-and categorization rather than clarify them, so both stay exactly as written.
+## A document running
-| Term | Meaning |
-| --- | --- |
-| behavioral predictability | a plan as a program: ~80% deterministic, ~20% probabilistic |
-| replay determinism | the journal doesn't lose the execution chain: replaying arrives at the same state, where execution can continue |
-| replay | using the durable journal to restore the recorded portion of a document execution without repeating durable effects; after the recorded entries are consumed, execution may continue live |
-| divergence | reserved for replay: a replay that departs from the recorded journal |
-| REPL history | the immutable ordered execution records the REPL reads from the durable journal and projects into `ReplModel`; the History surface presents this read model and is not itself a journal |
-| middleware | applied by the lexical structure, used by runtime execution |
-| workflow run | a workflow being carried out with its progress and outcome recorded durably; document executions perform its work, while ongoing effects remain scoped to the document execution in which they run |
-| document execution | one evaluation of a root document initiated through `execute()`, producing one output stream and one completion result while reading and appending a durable journal; its ongoing effects belong to the Effection scope in which the evaluation runs |
-| workflow definition | what a workflow run is a run of: a closed versioned descriptor, in one of two versions. Version 1 names an immutable Git object — its format and object ID — together with the repository-relative path of the root document inside it. Version 2 is a **source bundle**: the exact bytes themselves, addressed by logical paths and retained with the run. Both optionally carry the exact canonical document target and the component bundle the root declares. A repository locator is not part of either, and neither is distinct from every Repository created inside the run's Workspace |
-| source bundle | the workflow definition: an entrypoint, a canonically ordered manifest of logical paths with each source's SHA-256 and byte length, and a bundle hash over that manifest. The bytes behind it are retained with the run, so a file outside a repository, an untracked file and a file edited since its last commit are all ordinary starts, and editing, moving or deleting the original afterwards changes nothing about the run |
-| logical path | a portable identity inside a source bundle, never a host filesystem path: NFC Unicode scalar values, `/`-separated, without leading or trailing separator, NUL, C0 control, DEL, backslash or `#`, and without an empty, `.` or `..` segment, compared case-sensitively by its UTF-8 bytes. The containing directory, the absolute path and the invocation working directory are retrieval facts and never identity |
-| workflow component bundle | the closed set of authored Markdown components a workflow root declares. A bundle maps each name onto a logical path the same source bundle retains. It is both definition identity and canonical resolution: the names it declares resolve to its exact retained sources and to nothing else |
-| declared Markdown component | exact first-party Markdown a trusted host declares to one document execution, read once and held by the invocation — schemas copied, not referenced — before any installation runs, as immutable data on an `ExecutionInstallation`: the public name, the reported origin, the bytes, the SHA-256 of those bytes, the accepted forms, the contract parsed from them, and any private component closure only those bytes may write. The host reserves the name rather than offering a default for it, so it resolves ahead of a repository file, a workflow component bundle and every registration; a second reservation on one name is a configuration failure. It is a composition mechanism and not a policy loader: no caller-facing option selects one, adds one, or names its source |
-| private component closure | the components one declared Markdown component carries that only its own bytes may write. Each is minted like any other invocation-identity component and registered nowhere, so it resolves while canonical core is expanding that declaration's body and nowhere else — not from the caller's root, the content the caller projected through it, a sibling declaration, an imported component, middleware, or an implementation kept past teardown. Eligibility is the authored occurrence rather than the name: what an import may invoke is what canonical core produced inside that exact ask; an implementation the closure built is refused for every other name, copy, later site and later execution, because a run that has ended admits nothing; and a private name written anywhere else resolves to nothing before any other tier can answer. It is lexical availability, not permission: every private component still takes its operation from the invocation that carries it |
-| retrieval metadata | replaceable, credential-free information about where a workflow definition can be fetched from now; it takes no part in run identity and is reauthorized by the host before use |
-| stop reason | why a workflow run or a document execution stopped: a categorical host code, or a reference to an already-filtered journal event |
-| run ID | an opaque stable public identifier generated by the host or selected by an authorized caller; it associates the run's durable records and effects, remains unchanged for the life of the run, and has no semantics beyond equality and lifecycle addressing |
-| Repository base | the optional Git revision from which one named Repository initializes its primary checkout |
-| Repository selection | plain structural composition data naming the repository one component invocation acts on: an opaque provider-minted selection identifier, the display name, the credential-free repository identity, and the selected checkout path. It carries no credential, provider handle, lock, database, run ID or permission — the installed provider authenticates every selection against private state before it touches Git or a service, so a copied, replaced or rebuilt one can misname a target and be refused but can never reach one |
-| ambient Repository | the repository an ordinary `xmd run` was started inside, discovered when the first element asks for one — never at installation — from the invocation's starting directory, and remembered for the rest of the execution including when there is none. Its identity is the canonical common Git directory and its selected checkout is the canonical checkout root, so starting in a linked worktree names the same repository as starting in the primary checkout while Git operations still act on the worktree. A workflow run has none |
-| managed checkout | a Repository or Worktree an ordinary `xmd run` created under the host root `~/.xmd/repositories`, addressed by a digest of its whole identity, described by a closed version 1 sidecar written beside it, and held for one document execution by an exclusive non-blocking advisory lock. It survives every execution: nothing deletes, resets, cleans, fetches or repairs one |
-| ordinary Git identity | the invoking user's effective Git author and committer name and email, read from the trusted host's own environment and configuration by the first `` that needs one — never at installation — and kept in the provider's closure for the rest of the execution, including when the host can name none. A run that commits nothing never asks. It is used for an ordinary `` and nothing else, because that commit lands in the caller's own checkout; a workflow run keeps its one fixed identity, whose whole purpose is that retained Git state does not depend on whose machine made it. It is not a prop, a Context value, a component result or a middleware answer, and nothing else about the environment is borrowed with it — hooks, file-system monitors, signing programs and repository-supplied credential helpers stay disabled by the same fixed command-line configuration. A host where Git can name no identity refuses `` with an actionable sentence rather than substituting the workflow one; every other component is unaffected |
-| ordinary invocation identity | a fresh opaque random value an ordinary document execution's repository provider mints for itself and keeps in its own closure. It is not a prop, a Context value, a component result, a middleware answer, a lifecycle ID or a retained record, and it is neither addressable nor reusable; live Issue and pull-request idempotency and reconciliation keys are derived from it together with the engine's own expansion identity |
-| pinned commit | the commit obtained by resolving a base once; it remains the workflow run's starting repository state even as the run creates descendant commits |
-| document target | an addressable static heading in a root document's own Markdown flow, named by the canonical path of heading labels that reaches it; selecting one executes the preamble, each ancestor's own content, and that heading's complete subtree |
-| Prompt | a person's original request, in ordinary natural language. `xmd plan` takes exactly one |
-| Plan | the executable program produced from a Prompt: an Executable Markdown document combining readable prose that expresses the Prompt's intent with the components that carry it out, each placed beside the prose describing what it does. It begins with one descriptive level-one heading. A Plan is what `xmd plan` approves and then delivers as source: printed to stdout by default, or written to an `--output` file. Plan produces a program; Run executes a program from the host or CLI; composition decides whether and when a planned program runs. It is not a synonym for a workflow, a policy document or any executable Markdown file |
-| plan command document | the one exact checked-in first-party Markdown value root `xmd plan` executes. It is the command's adapter and nothing else: it projects the request into ``, supplies the session, and returns the approved source. Its body is those two elements and no prose, because its rendered transcript is the progress the command writes to stderr. It is not itself a Plan. Internal: no command-line option selects another one, and no repository component search can answer for it |
-| packaged `` Component | the one exact checked-in first-party Markdown text component that converts a prompt into a Plan, `packages/cli/src/documents/Plan.md`, declared to every ordinary run as the public ``. It owns and implements the Plan authorship workflow — the Prompt wording, the draft and repair loops, the `` branches, human review, revision, approval, stopping, exhaustion and the automatic final explanation turn — and produces the exact approved Plan source as what it renders: written bare it emits those bytes, and `as` is ordinary text capture that binds them and emits nothing. Neither form evaluates the source. Every Plan-producing turn in it states the complete Plan requirements for itself, so a replacement may add or correct a title rather than only carry one forward. Both surfaces expand these exact bytes under one origin and one digest; there is no generated TypeScript copy and no second Markdown implementation. Its four phase components are private to it, and it is not itself a Plan |
-| Plan writer profile | the trusted-host assembly the packaged `` Component runs its authored turns under, installed by its own `` inside the invocation that owns it rather than around an execution — which is what makes it the same frame whether `xmd plan`, an ordinary document, or a configured `` run child asked. Which Agent context goes under it is a trusted-host capability the declaration carries — the production ACPX one built from the run's Agent stack, or the deterministic one a canonical `` child declaration produced — and a host that supplies none states the sentence a `` written there is refused with. The fixed policy is installed in one place for both, so a second provider cannot bring a weaker one: its fixed inputs, a constrained Agent provider, Elicitation, the fixed first-party components and the host-declared ``. It uses no repository component search and exposes no custom root, and the policy it installs is not readable from the command line. Its working directory is one host-owned directory dedicated to the logical session, keyed by the digest of that name, created empty and required to be empty on the way in. An explicitly named session's directory is durable, because continuation derives the same session identity from it; an invocation-unique default session's is scope-owned, registered for cleanup before it is created, and exactly one cleanup is attempted after profile teardown and before admission on every ending — the leaf removed non-recursively when it is still the empty directory that was handed over, and left as found with the command failing terminally when it has gained content or vanished. Where those directories live is a host dependency no caller or document selects |
-| upgrade command document | the one exact checked-in first-party Markdown streaming text root `xmd upgrade` executes to select and install a published release. It owns the exact-tag grammar, release selection, semantic-version comparison, consent, the status, already-current and installation branches, and the wording of every refusal and report; its rendered body is the command's output rather than a value it returns. Internal: no command-line option selects another one, and no repository component search can answer for it |
-| upgrade assembly | what one runtime-named entrypoint states about the `xmd` that is running: its provenance, reported version, invoked executable path, platform, architecture, release target when the release publishes one, and — for an eligible compiled macOS or Linux host alone — the factory for the four phases an installation needs. It describes how this `xmd` is running, never how its files arrived |
-| release identity | the invocation-local opaque identifier `` mints for each release it admits. Holding one is what authorizes downloading that release, and nothing outside that one invocation's private admission map can read, extend or forge it. A download mints an upgrade candidate identity in the same way, and that candidate advances `downloaded → verified → committed` exactly once |
-| expansion | one logical evaluation of an authored executable element within a document execution |
-| expansion ID | a deterministic identifier for one logical expansion; restoring or retrying that expansion preserves the ID, while a distinct evaluation requested by the document receives another |
-| Git capability | the contextual interface through which `@executablemd/git` queries the Git repository associated with the current working directory |
-| Git host | an external service that owns remote Git repositories and associated collaboration objects such as branches and pull requests. GitHub is one Git-host adapter. A Git host is distinct from the local Git capability and the trusted workflow host, and from an Issue provider |
-| Issue provider | an external service that owns a collection of issues. GitHub and Atlassian Cloud are Issue-provider adapters. It is a separate boundary from a Git host because an Issue provider need not own a Git repository, and one that does not cannot truthfully persist as a Git-host effect |
-| Issue tracker | what a lexical `` names: a credential-free URL for the container new issues are created in, together with an optional explicit provider discriminator. An upsert requires one and takes its discriminator only from it; a read needs none, because the URL it was given is the identity. It is replaceable composition data; it requests a destination and grants nothing |
-| canonical target URL | the normalized form of an Issue tracker's URL. One destination has one spelling, which is what durable identity, the natural key and every provider comparison use |
-| provider discriminator | the stable lower-case name of an Issue provider. Stated on a tracker, it names the only provider allowed to handle the request; omitted, each installed provider matches the URLs it recognizes |
-| printed error | an error printed into the document (`ErrorSegment`); data, not control flow |
-| failure | an error that propagates (`ComponentFailure`, `DocumentationError`) |
-| error mode | what an undecided error in a region becomes: `print` (printed into the document), `output` (fails the document execution; `` can print instead), `throw` (fails the document execution) |
-| attempt | one execution of a retried operation or region |
-| raise | where an error no middleware converted is decided: printed or failed, per the error mode; observed exactly once, where raised |
-| blocker | execution needs input (auth, a human answer); not a failure |
-| suspension | a durable wait: a crash restarts into the same wait |
-| suspension ID | an opaque stable identifier derived by the trusted workflow execution for one logical suspension request; replay preserves it and only equality and input correlation are public |
-| delivery | retaining one externally supplied value for an exact durable suspension request, without executing the workflow run or advancing its lifecycle: it takes no executor lock, begins no document execution, appends no journal event and changes no run status. It is distinct from resume, which is the execution that later reaches the wait; from answer publication, which is what that execution appends; and from answer consumption, which is what spends the retained value |
-| answer publication | appending the durable answer event that records what ended one durable wait; performed by the resuming document execution, never by a delivery |
-| answer consumption | marking a retained delivery spent; it commits in the same transaction as the answer publication it belongs to, so neither can be observed without the other |
-| workflow executor | the live host invocation that advances or settles one workflow run |
-| executor lock | the scope-owned, non-blocking exclusive host lock that permits at most one workflow executor for a run |
-| stale execution | an unfinished retained document execution found after acquiring the executor lock proves its previous workflow executor is gone |
-| inspection recovery coordination | provider-private cross-process exclusion between copying a crashed run's database-and-journal pair for inspection and opening the retained database write-capably for SQLite recovery; it grants no executor or lifecycle ownership |
-| recovered inspection snapshot | an immutable lifecycle snapshot read from a private scratch copy after SQLite rolls that copy's hot journal back to the retained store's last committed state; the retained database and journal are not changed |
-| XMD artifact | one immutable portable evidence file with the `.xmd` extension, containing one workflow run's committed retained state at one artifact frontier together with its workflow definition source closure; it is neither a live run store nor permission to continue the source run |
-| artifact frontier | the exact committed lifecycle snapshot, journal boundary and current Workspace root an XMD artifact records |
-| workflow definition source closure | the exact root Markdown source and every source in its declared workflow component bundle, the retained bytes re-derived from the run's own store. Retrieval metadata, provenance and a repository checkout are not part of either |
-| artifact manifest | the canonical versioned inventory of every semantic record and retained byte in one XMD artifact, excluding its own derived identity and physical container layout |
-| XMD artifact identity | the lowercase SHA-256 of an XMD artifact's artifact manifest; it identifies the evidence independently of its host path and physical encoding and is retained as the source identity of a history fork made from that artifact |
-| Agent session portability evidence | what one XMD artifact states about every logical workflow Agent session that contributed a retained Prompt: either complete portable evidence — the session and its compatibility attributes, the provider, the bundle kind and compatibility identifier, the source and bundled provider-session identities, the identity-allocation mode, the ordered provider checkpoint tokens, and the Agent session bundle's length, hash and bytes — or an explicit unavailable marker naming why. A session that retained no Prompt has none. It is detached retained evidence about a conversation, never a live provider session and never control over the host that produced it |
-| provider checkpoint token | one opaque value a provider issued for one completed Agent Prompt, retained in Agent session portability evidence beside the event it belongs to. It says where a conversation reached; it is not a credential, is never derived from event position, transcript text, another token or a provider head, and no ordinary presentation renders it |
-| Agent session bundle | the opaque bytes a provider captured one Agent session as, retained under that session's key in an XMD artifact. Nothing scans or scrubs them: a bundle may hold transcript text, tool state, secrets a conversation repeated and the exporting host's own paths, and it carries the confidentiality of the whole retained Workspace |
-| Workspace | the provider-neutral, run-owned environment that supplies retained filesystem, repository, process and working-directory capabilities to a workflow |
-| document filesystem | the files a document names in its own text, reached only through `API.Files`; distinct from the host paths the engine's own control plane reads |
-| Files provider | the installed implementation of `API.Files` for a document execution: the host provider under `xmd run`, a transaction-bound provider under a workflow run. There is no default, and no provider falls back to another |
-| stable host namespace | the condition the host Files provider's containment is stated under: no other process replaces a directory, symlink, junction or reparse point between the moment a path is observed and the moment it is used |
-| Files infrastructure failure | a Files provider that is absent, that refuses an operation, or that broke its own contract; fatal like a durability failure, and never a printed error |
-| ephemeral | a replay classification for an operation, context or attachment that runs again to reconstruct live execution; its result is not substituted from the journal and it owns no durable workflow state |
-| live binding | an execution-owned value reconstructed ephemerally for the current document execution; it is visible only to constructs that explicitly consume the live binding overlay and never enters interpolation or the journal |
-| attached service | a scoped host process that publishes its authenticated loopback endpoint through the XMD service handshake protocol and remains supervised for the lifetime of its service attachment |
-| effect transaction | the single atomic SQLite transaction that publishes one Workspace-local mutation together with that effect's journal result |
-| external effect | an effect whose provider-owned outcome cannot participate in the Workspace SQLite transaction and therefore requires a stable identity and provider reconciliation |
-| XMD-mediated HTTP read | one bounded, non-mutating HTTP request an authored document performs through the contextual Fetch capability, whose detached response is retained as an ordinary durable observation. It is distinct from an Agent's own network permission, which it does not grant, and from a reconciled mutating external effect: it performs no reconciliation, so an interruption before its record commits may repeat the read |
-| Git-host evidence read | one bounded, non-mutating read of a collection a Git host already holds about the pull request a canonical URL names — its reviews, its comments, or the checks on its head. It needs no Repository in scope: the URL is the identity, and the selected provider parses the repository and number out of it. It is authenticated with the host's own credential, bounded by the operator's `allowed` list, and paginated by the adapter, and it is *not* a reconciled external effect: it has no natural key, no pre-state and nothing to adopt, so it is an ordinary durable read whose interrupted attempt may repeat, whose completed record replays without contacting a provider, and which a fork inherits. It answers completely or not at all — an empty collection and a collection nobody could finish reading are different answers |
-| object-source attachment | adapter-private composition data the trusted host builds for exactly one external-effect reconciliation, giving the selected provider authorized live access to local state the frozen request cannot describe — the Git objects a push publishes, and the retained locator it is authorized to reach. It is authenticated against the durable identity it belongs to and proven contained before its first use — the local state behind one can name further state, so the graph a provider could traverse through it is validated rather than assumed — held in that provider's own closure, disposed with the invocation, and is never durable, never part of a natural key and never visible to routing middleware |
-| checkpoint | a completed journal boundary associated with the logical Workspace root visible after that effect |
-| history fork | a new workflow run that replays a compatible journal prefix and continues from its checkpoint and Workspace root under a new immutable document definition |
-| loaded copy | one independently evaluated instance of a package, such as the copy bundled into the binary or a separately installed dependency |
-| authoritative behavior | behavior that decides what an execution or effect *is* — whether it happens, what it may replay from, and what it settles to. Non-authoritative behavior may inspect, narrow, refuse or add a failure, but cannot bring an execution into being, substitute one, or rescue one |
-| testing harness | the testing-only construct through which one canonical `` invocation runs another document as a real document execution under a selected host profile; it is not component composition and is unavailable to any element core did not recognize as its own `` |
-| host profile | a named production assembly a trusted host offers a testing harness — `run` today — reused after argument parsing rather than restated; a host that cannot offer one refuses rather than approximating it |
-| execution outcome | what one nested document execution ended as, as the harness publishes it: a settlement carrying the exact completion `Result`, or, for a workflow attempt, a durable suspension carrying the run and suspension identities. A suspension is neither success nor failure |
-| trusted host | the code that decides what an execution is for — a CLI entrypoint or a workflow runner — as distinct from the document, the components it expands, and the middleware packages composed around it |
-| native session launch | preparing one durable coding-agent session from a document and then handing its provider's own interactive UI the terminal for that exact session. It is session construction followed by an ownership handoff, not a chat frontend: XMD proxies no native turn and journals no native conversation, and takes no model turn of its own beyond the one materialization turn an adapter may require to make a freshly created conversation resumable |
-| provider-native session identity | the identity an agent asserts for its own durable session state, distinct from the logical XMD session key and from the ACP/ACPX record identity. Only an asserted one crosses a handoff; XMD never infers that a string a native CLI would accept is one |
-| pending session placement | an exact provider-issued `Session` capability carrying where a logical session will live and which agent it is compatible with, and nothing more: no construction route, no provider handle, no resumable identity. A fresh `` produces one, and the first consuming operation chooses how the session is constructed |
-| session materialization | the transition that makes a placement's chosen route and its backend history resumable. ACP-first materialization happens only when the backend reports that it accepted the session's first turn; client-native materialization is the native launch's existing retained construction. Nothing else promotes a placement — not a returning ensure, a first output, a terminal result, a checkpoint token, an error code or a diagnostic |
-| established session | a placement whose immutable construction route and durable provider or native identity both already exist, and which is therefore validated eagerly: reattached, compared against its retained history, and refused when either is missing or names another conversation |
-| instruction layer | the provider-native session, system or developer instructions a launch installs before the native UI accepts its first user turn. It is not a user message, and it is not conversation history |
-| foreground-terminal lease | the one exclusive hold on a document execution's foreground experience. A root native launch holds it for one inherited terminal. A host with no terminal refuses it, and no second root launch can hold it concurrently |
-| native launcher | the host-owned seam that reserves the foreground terminal, flushes what that terminal has pending, starts one native UI there, and reports its terminal status and nothing else. It is not `exec`, whose children are piped, captured and journaled |
-| launch request | the frozen, one-use value public launch middleware routes. It carries the facts of one launch and `with()`, and nothing that can settle one. Identity is object identity: a rebuilt look-alike describes the same ask and is admitted nowhere |
-| agent launch coordinator | what core delivers to the provider factory it installs, as an argument that factory closes over. It validates the routed request, runs each absent phase once, cross-checks and retains what comes back, and derives the result. There is no reader for one, no context holding one, and no request member carrying one |
-| session coordinator | the host-built capability that answers who owns one logical agent session right now, across processes. It is passed directly into the provider that needs it and is deliberately not contextual: a decision document middleware could replace is not one. Acquisition never waits |
-| construction route | how one logical agent session was first constructed — through ACP, or under an identity XMD chose — as strict create-once durable state beside the coordinator's own records. It answers a different question from ownership and grants no right to act: the coordinator remains the one live owner. A route never converts, and a session ACP already established is recorded as ACP-first rather than reclassified. Two schemas are readable: the released `session-route.v1`, and `session-route.v2`, which exists only for `client-native` and adds a required executable build binding. New client-native construction publishes V2; a V1 client-native route stays legacy-unbound, is never upgraded in place, and admits native resume only |
-| executable build binding | which build of a provider executable accepted a client-allocated identity, as a schema, an adapter-canonical version and the lowercase SHA-256 of the canonical executable target. Equality is exact over all three, so a matching build reached at another path is the same build and a changed build at the same path is not. It contains no path: a path says where a build was, which stops being true, and names host layout besides |
-| executable observer | the host-built capability that resolves a launcher command through the host's real execution environment, canonicalizes the target, requires an executable regular file, hashes that target and asks that same file its version. Passed directly into the provider like the coordinator beside it, and deliberately not contextual: executable validation decides which retained history may be accepted, and a resolver document middleware could replace could point the observation at one binary while the run spawns another |
-| client-native attachment | joining a conversation a native process constructed, through ACP, under the identity the route already names. It is attachment, never conversion: the route stays client-native, `resumeSessionId` receives that exact identity, and the provider's canonical assertion must equal it before the first turn. Advertised separately from native launch, because handing a session to a native UI and later joining it prove different things |
-| identity provenance | who chose a provider-native session identity: the provider returned it, or the client allocated it before the provider existed. Retained rather than inferred, because after the fact both are just a string in the record. A released record written before the distinction existed reads as provider-returned, which is the only compatibility inference |
-| quiescence | the one-use acknowledgement an ownership body gives. It does not mean "I finished" — it means nothing this owner started can still act on the session, which is why a handoff that could not release its handle never gives it |
-| recovery tombstone | an ownership record left active because its owner never proved it stopped. A crash releases the kernel lock and not this, and no pid, elapsed time, released lock or empty transcript clears it |
-| provider partition | one complete, independently owned agent-provider state — runtime, store, managed sessions, queues, coordinator, teardown — selected by the one installed factory at each dispatch. Production is the single-partition case of the same path; holding a partition grants work, never permission |
-| `JournalProvenance` | a non-operational, equality-only witness that a live publication stream descends from the exact journal backend a provider selected for one workflow run; it grants no append, read, execution, publication or reconciliation capability, and is meaningful only because the provider retains the witness it established and later requires exact equality |
-| result object | the value a component binds instead of failing: `{ok: true, value}` or `{ok: false, …}`, whose failure members the component declares |
-| syntax symbols | the complete, versioned description of what a document may write in one directory under one host profile: every structural construct the engine reserves, and the one implementation selection chooses for every other name. It is observation — describing an environment installs no operational state, runs nothing and journals nothing — and it is produced once per request and projected, never rediscovered per format. `xmd syntax` prints one for an environment nobody is running; canonical `` renders one for the site an element was written at, from the same construction and the same Markdown renderer |
-| execution environment | the private bundle of services and records one execution supplies while its document expands: what resolves a name, what routes it to a retained implementation, what the execution declared, and the records it keeps about its own identities, forms, vocabulary and source output. The execution builds it from what it captured and admitted, owns it, and passes it by value through canonical expansion — never through a context, because a context resolves by name and a name is not a secret. An expansion driven directly is handed none at all, which is what "nothing is installed here" means; there is no partial one. Its shape is an architecture and product boundary, which is why the resolution an execution performs for one *import* is not on it: that terminal is handed to expansion by hand, as an internal argument beside this bundle, named by no entry point and reachable only by having been given it |
-| syntax reference | the engine-owned lexical answer to "what may a document write here", carried by value on canonical core's execution environment beside what resolves an import. The execution builds one at its root from the selection inputs it captured before any installation, middleware or document code ran, or from the one set of symbols a trusted host stated for its profile; a trusted canonical evaluation boundary replaces it for the subtree it evaluates. It answers with text and decides nothing: a component the symbols name is not a component anything may run |
-| run profile declarations | the component registrations a first-party package makes, held as plain values apart from the middleware, providers, activation and launchers its installer also arranges. The installer registers exactly those values and inspection reads exactly those values, so what a run installs and what the symbols report cannot drift |
-| Plugin | trusted code installed once before an execution imports a root document. XMD bundles exactly one — `@executablemd/git` — and activates it for the run-profile commands: `run`, `plan`, `syntax`, and `workflow start`, `resume` and `fork`. The `xmd test` root is not one of them, because a harness that quietly gained the repository vocabulary would be reserving names its children are entitled to shadow; a nested `` child assembles the profile for itself rather than inheriting what its parent declined. Everything else an operator selects with `--plugin`, and a package that happens to be installed stays inert until it is named. A plain structural value carrying a name and one optional `install`; what it contributes is the existing `ExecutionInstallation` members, and what it composes through are the three stable contextual APIs below. Selecting one runs its module, and selected Plugin code can execute whatever the surrounding runtime permits: it is trusted, and it is not sandboxed |
-| document envelope | the Markdown the `Document` Api composes for one run: the canonical `` placeholder wrapped by each Plugin's middleware, first Plugin outermost. Canonical core scans it once and splices the root's already parsed, already target-selected segments in at each placeholder, at their authored positions — so an unwrapped run is the run it always was, and an authored `` is an ordinary element that projects nothing |
-| active Plugins | the frozen ordered list of Plugin values installed for one command — the bundled Git Plugin first where the command's profile carries it, then the operator's own in the order they wrote them — published before the first `install()` runs so that every Plugin and every later consumer read the same list. It is a description of what is installed and grants nothing |
-| command declarations | everything one command declares, in one order and under one discriminant: the exact Markdown components *and* the structural syntax the selected Plugins declared, then whatever the calling surface declares for itself. Both arms, because both are what a name means here — a catalog holding only the Markdown half would let `xmd syntax` and ``'s validation describe a language a run does not have. Built once per command so that an ordinary run, a nested `host="run"` child, inspection and ``'s validation cannot describe four different vocabularies |
-| origin-only | the inspectability of a component whose contract could only be learned by loading it: a repository TypeScript module, whose schemas live on its exports and whose top level would run. Such an entry carries name, category, origin and source kind, and no contract field at all — an absent contract is stated, never rendered as an empty one |
-| definition-owned return state | which value body a `` selects for: one ephemeral state per execution of one value root or Markdown value component. Structural directives keep the ambient one, a component invocation hides it from the invoked body, a nested value body installs its own, and caller-projected content restores the caller's. It travels down the expansion call stack as a local rather than through a context, and no exported function accepts another body's, so nothing a document can read, replace, or import acts on a live one. The first reservation on it is atomic, so a second executed return fails the body rather than replacing its value, and it appends no durable event |
-
-## Three axes
+Consider a document that writes a file, reads its contents, then deletes it.
+Each step has an observable result. At the end the file is absent, but the read
+still describes the contents observed between the write and deletion.
+
+An ordinary `xmd run` uses the caller's environment. Its `--journal` is a new
+diagnostic trace, not input to a CLI continuation: another invocation starts a
+new execution. A Plan is source for a program; producing or approving it does
+not run it. The caller composes it with a run when execution is wanted.
+
+A workflow instead retains the definition bytes, props, journal and filesystem
+state under a run ID. Partial replay rebuilds the live resources needed to continue and restores
+completed effects from their records, then performs the first unrecorded work.
+It does not write or delete again merely because those steps are reached again.
+A completed root returns its retained output and result without expanding the
+document or attaching operational providers.
+
+The journal is historical; the Workspace is the current filesystem frontier.
+After the three steps above, replay restores the old read even though the file
+is now absent. It never refreshes an observation against today's filesystem to
+prove that the earlier effect happened. These distinctions govern
+[effect transactions](#replay-and-effect-transactions),
+[workflow lifecycle ownership](#workflow-lifecycle-ownership) and
+[ordinary command retention](#foreground-commands).
+
+## Shared rules
+
+Start with the properties every execution shares: predictable behavior, scoped ownership and composition across independently loaded package copies.
+
+### Three axes
The UX has 3 axes: determinism, resilience and debuggability. If we pull too
far in one direction, the others suffer. Errors are inevitable in a system
@@ -159,2905 +71,2727 @@ Determinism is two properties:
replaying the journal arrives at the same state, where execution can
continue.
-## Workflow runs
-
-Core retains one document-execution entry point: `execute()`. A host that needs
-workflow-run metadata passes an `ExecutionInstallation` to `executeInstalled()`
-for the one document execution it is preparing. The run is created or
-restored by that installation's preparation, which canonical core invokes
-inside the durable root — so the journal is active before the workflow run
-exists, and the run exists before any document policy observes it and before the
-root document is imported.
-A later document execution, including one that continues the same workflow
-run, gets a new child scope and a new middleware installation. Workflow
-metadata is durable; the middleware and every ongoing effect remain
-scope-owned.
+### State ownership
-Installing the middleware alone creates no workflow run. On the first live
-document execution, the first durable operation installed by the middleware
-uses the host-authorized requested run ID or allocates one using cryptographic
-randomness and durably records one value:
+All state is scoped to the operation that owns it, so it is torn down when
+the operation is torn down: created inside the operation it describes,
+provided via context. No module-scoped registries — not as collections, not
+hidden inside library objects that accumulate. One exception: metadata an
+author declares at module evaluation, about a value the author owns, may live
+on that value.
-```ts
-interface WorkflowRun {
- readonly runId: string;
- readonly bundleHash: string;
- readonly targetPath?: string;
-}
-```
+A callback registered with something outside the process — a listener on a
+socket, a child process, a stream or a DOM target — is state of exactly this
+kind, and the source it is attached to knows nothing about the operation that
+attached it. The event arriving is not teardown: a cancelled wait is precisely
+the case where it never arrives, and a losing race arm is one that will never
+be told. So the owner detaches its handlers, on completion, failure, halt and
+race loss alike, before it is considered closed, and an event delivered after
+that reaches nothing and changes nothing. `local/require-scope-bound-event-registration`
+holds source to it.
-The workflow run exists once that value is durably recorded. A document failure
-or cancellation after that point does not erase it. Failure before that point
-creates no workflow run and the root document does not expand.
+A Repository selection is composition data and is therefore replaceable: a
+document may bind one, render one, hand one to a child, and construct one that
+looks exactly like it. Nothing a repository provider does is authorized by the
+value it was handed. What stays provider-owned, in the provider's own closure
+for one document execution, is everything a selection is *not*: the advisory
+locks on managed checkouts, the canonical Git identity each selection resolves
+to, an ordinary run's live Push evidence, its invocation identity, and every
+reconciliation key derived from them. A selection that the provider did not
+mint, or one whose name, checkout path or identity was edited after it did, is
+refused before Git or a service is touched.
-`WorkflowRun` is one closed shape carrying `runId`, `bundleHash` and the exact
-target when it has one. It has no base and no pinned commit: a run starts from
-exact retained bytes rather than from a repository state, so a member naming one
-would be a statement about a repository the run never had. It neither creates nor
-seeds a Workspace Repository. Each `` inside the definition resolves
-and pins its own optional Repository base, so one workflow may compose
-repositories unrelated to the definition repository or to one another.
+### State across loaded copies
-Read-only Git questions go through the contextual Git capability, which the
-workflow run itself never asks:
+The binary bundles its own package code while components and integrations may
+load another copy of the same package. Those loaded copies must be able to
+compose: one can provide shared state that another reads.
-```ts
-interface GitQueryApi {
- resolve(revision: string): Operation;
-}
-```
+Shared composition has two replaceable forms:
-`GitQuery.resolve(revision)` has the semantics of
-`git rev-parse --verify --end-of-options ` in the contextual working
-directory. Its default provider invokes the Git CLI; another provider may
-replace it lexically. It lives in `@executablemd/git` with the rest of the
-capability, and the workflow package calls none of it. Ordinary `execute()`
-remains Git-independent, and so does starting, resuming, forking or exporting a
-run.
+- Composition data uses an Effection Context with a stable, namespaced string
+ name and a plain structural value. Independently constructed descriptors with
+ the same name intentionally address the same binding.
+- Contextual operations use a contextual Api with stable, namespaced operation
+ names. Lexical middleware replacement is part of their contract.
-**The workflow package imports no Git feature, and a retained run reaches no
-repository either.** The CLI establishes a candidate from filesystem bytes, and
-the retained lifecycle re-derives the source from the run's own store, so a run
-genuinely needs none: there is no definition whose Markdown lives anywhere but
-in the run that retained it, and therefore no source capability for a host to
-supply.
+Neither form is a permission boundary. Security enforcement, durable-effect
+identity, and reconciliation never trust a same-named binding merely because
+its value has the expected structure. They derive from execution-owned state
+established before untrusted work begins or from parsed durable records. A
+contextual observation may describe an execution; it cannot authorize it or
+name its durable effects.
-Replay restores the recorded `WorkflowRun` without allocating another run ID or
-invoking Git. The supplied bundle hash must equal the recorded one.
+A private context name is not an exception to this. A descriptor built under a
+name nobody else knows — a module-local one, a name carrying a fresh identifier
+— is still a context, and reaching a capability through one is still reading
+replaceable state to decide it. The same holds for a public answer that carries
+an unreadable value: a registry record whose contents a handler cannot read is
+still a record that handler can keep and hand back somewhere else, so what
+cannot be read can still be transferred. A capability that must not move is held by
+the execution and delivered as an argument, never looked up.
-A host that has already created the run's storage record passes
-`retainedWorkflowInstallation(run)` instead, with the exact frozen value.
-Nothing is left for the execution to decide: it records that value through the
-same `workflow_run` durable operation, allocates no identifier and resolves no
-base, and every journal state — live, truncated and completed — requires the
-recorded run to agree with the supplied one in every member of its own version:
-run ID, base and pinned commit for version 1; run ID, bundle hash and exact
-target for version 2. A journal that disagrees in any of them, or that records
-the other version, is not this run's journal, and the refusal names the fields
-rather than their values.
+Metadata covered by State ownership's module-evaluation exception uses a
+stable, namespaced string property when another loaded copy must read it. A
+module-local symbol is unreachable to another loaded copy. A registry symbol is
+reachable but unowned, and offers nothing a namespaced string does not.
-`getWorkflowRun()` returns the frozen `WorkflowRun` for the current document
-execution. Every call in one live execution returns the same object. It throws
-outside a document execution a workflow installation was passed to, and it
-exposes no journal, Git, workspace or continuation capability. Replay preserves
-the field values, not JavaScript object identity.
+A descendant may replace a same-named Context binding for its own descendants
+under ordinary lexical rules. Private fields, constructors, symbols,
+module-local identity, and private sentinels remain valid when no second loaded
+copy needs to read the value. String names and metadata keys that cross loaded
+copies are compatibility contracts; changing one is a breaking change.
-The `@executablemd/workflow` package owns `WorkflowRun`,
-`retainedWorkflowInstallation()`, `getWorkflowRun()` and the generic run,
-storage, replay and Workspace boundaries. It owns no Git: repository
-composition, the Git capability, issue and pull-request contracts and the
-Git-host engine are `@executablemd/git`'s, and that package imports Workflow's
-published extension boundaries rather than the other way round. It depends on
-`@executablemd/core`, `@executablemd/durable-streams` and
-`@executablemd/runtime`; core never imports workflow or Git. `xmd workflow
-start` and `xmd workflow resume` are the CLI lifecycle, and they resume through
-the run storage below. Ordinary `xmd run` carries the bundled Git Plugin, so
-the repository vocabulary is available there without an operator naming it.
+Unreachable to another loaded copy and unreachable to a holder of the object are
+different properties, and only the first is what a module-local symbol gives.
+A symbol-keyed property is an ordinary property: `Reflect.ownKeys()` returns it,
+a descriptor read returns its value, and `Object.getOwnPropertyDescriptors()`
+copies it onto a look-alike — non-enumerable and frozen change none of that. So
+a symbol names state safely and hides none. State a value must carry but its
+holder must not reach belongs in a private field, or in membership of a set the
+owner keeps; both are absent from every key list, descriptor, and copy. A
+capability boundary that a handler holding the object could read across is not
+one, whichever of the two properties it was reasoned from.
-Git publishes on three subpaths, and which one a consumer imports from says
-what kind of thing it is reaching for. `@executablemd/git/api` is the only
-route to the contextual Apis — `Repository`, `RepositoryContext`, `Git`,
-`GitQuery`, `PullRequestAPI`, `IssueApi`, `IssueTrackerContext` and `GitHost`
-— together with their named interfaces, the identity each was minted under,
-the base refusal each falls back to, the direct operations and accessors
-consumers call, and the types those interfaces are written in. Those are the
-seams: a consumer reaches one to call an operation and replaces one to answer
-it. The root publishes the Plugin and its profile predicate, the component
-registrations and definitions, the workflow installation, the durable effect
-identifiers, the errors and the record parsers — what was said, rather than
-who answers. `@executablemd/git/deno` publishes the host adapters that
-implement the seams, and `@executablemd/git/credential-helper` is the
-standalone program Git spawns as itself. An Api is published from exactly one
-of these, not re-exported from the others, because a seam reachable two ways
-is two contracts.
+## Executing a document
-**Each Api is named for the operations it answers, and every identity is under
-one `executablemd.git` prefix.** A consumer writes the vocabulary of the thing
-it is doing rather than of the machinery behind it:
+Execution first acquires and selects source, then expands it under lexical bindings and ownership. The rules here distinguish authored identity from runtime scheduling.
-| Api | Identity | Operations |
-| --- | --- | --- |
-| `Repository` | `executablemd.git.repository` | `select`, `worktree`, `ambient` |
-| `RepositoryContext` | `executablemd.git.repository.current` | `current` |
-| `Git` | `executablemd.git` | `switch`, `add`, `commit`, `push` |
-| `GitQuery` | `executablemd.git.query` | `resolve`, `root`, `format`, `read` |
-| `PullRequestAPI` | `executablemd.git.pull-request` | `read`, `upsert` |
-| `IssueApi` | `executablemd.git.issue` | `read`, `upsert` |
-| `IssueTrackerContext` | `executablemd.git.issue-tracker.current` | `current` |
-| `GitHost` | `executablemd.git.host` | `route` |
+### The root document a run is given
-`Git` and `GitQuery` are two seams and never one. `Git` performs the four
-authored durable transitions a document writes as ``,
-``, `` and ``, and what lifecycle they have is
-the installed provider's. `GitQuery` asks read-only questions of the checkout
-containing the contextual working directory and mutates nothing, so replacing
-it answers questions rather than becoming a route to a transition.
+An `xmd run` starts from exactly one root document, and it comes from one of
+three places: a path, standard input, or one `--eval` value. Which one is fixed
+grammar — decided from the command form the caller wrote, before anything is
+read — so a run never discovers its source part-way through preparation.
-These names and identities are a break from `@executablemd/workflow@0.12.1`,
-taken deliberately and without compatibility aliases. A provider compiled
-against an old identity intercepts nothing, and an import of an old name does
-not resolve: two vocabularies for one seam is the outcome an alias would
-guarantee, and a silent miss is what an old identity would produce. The
-package-internal names that still read `Composition` — the provider
-installers, the error classes and the serialized refusal names retained
-history holds — are not this layer and did not move.
+The command form is what separates the three, because a path and standard input
+can be written the same way. `-` is the one filename the option grammar leaves
+unwritable, so it reaches the reference grammar through the parser's own
+unconsumed tokens: bare `xmd -` names that file, `xmd run -#Section` selects a
+section of it, and only an invocation that explicitly names `run` with a
+document argument of exactly `-` means standard input instead.
-## Workflow run storage
+Standard input is the one of the three the shared CLI cannot reach for itself. A
+process's own stdin is host-specific state, so each runtime-named entrypoint
+supplies the operation that reads it, as a value passed into the CLI beside the
+service installer, the upgrade assembly and the repository installer. It is not
+a Context, a contextual Api, a public export, a syntax entry, a component or a
+document capability: nothing an authored document can name reaches it, replaces
+it, or asks it for a second read. The CLI calls it at most once per invocation,
+and only for the one command form that selected it.
-A workflow run recorded only in the journal of the document execution that
-created it can be found only by whoever already holds that journal. Retained
-storage is what makes a run addressable: another process opens it by public run
-ID and continues from durable data.
+The parsed path and recovered reference remain separate until the grammar is
+settled. Naming two roots refuses in either order before either candidate is
+inspected or standard input is read. A `-` consumed as another option's value is
+not a document argument; another command's `-` keeps that command's meaning,
+and `--eval -` keeps its refusal.
-Shared code reaches storage through a contextual Api that names no provider, so
-the lifecycle stays host-neutral. The Deno host installs its own from a
-runtime-named entrypoint, and that entrypoint is the only place SQLite, run-ID
-hashing, filesystem paths and host filesystem behavior appear. No shared module
-imports them or detects the active runtime. The absence of a provider is
-reported rather than answered with an empty store: a run that appears to start
-and retains nothing has not started.
+Core represents the supplied source as `retainedSource("", source)`.
-A storage handle is a lease owned by the scope that opened it. Lease teardown
-makes that handle unusable without closing the run's physical connection or
-invalidating another handle. The Deno provider owns the authoritative
-SQLite/DOFS connection for each canonical workflow-run database path and closes
-it at provider-scope teardown after its child scopes finish. The public handle
-contains no raw connection association; the provider owns an exact-object lease
-registration and refuses foreign, fabricated, closed, or stale handles before
-they can reach SQLite.
+What comes back is admitted through the existing supplied-source protocol rather
+than a form of its own. The origin `` and the exact text travel together,
+which is what source positions, diagnostics, the root binding and the durable
+root import all carry — so replay restores the retained source without reading
+anything, and two different programs are two different roots without a second
+identity field. `` is an origin and never a path: no file of that name is
+read or created, and every relative operation still resolves from the contextual
+working directory.
-### Identity is separate from retrieval
+Acquisition is the first thing the run does. The complete input is in hand
+before document inspection, target and property preparation, Agent-stack or
+provider setup, the secret-detection announcement, journal creation, root
+admission and execution — so a host that cannot deliver a whole document reports
+one fixed sentence, exits nonzero and has reached none of them. It happens
+inside the run's existing deadline rather than opening a lifecycle of its own,
+and a waiting read is cancellable: cancellation tears the reader down and stays
+cancellation, never a read failure.
-Identity is the run ID, the whole workflow definition, and the normalized props.
-Values are compared canonically, so props differing only in key order are the
-same props. The comparison covers the bundle hash, the entrypoint, the whole
-canonical source manifest, the component mapping and the exact target. The
-descriptor carries no version and no kind: one shape is the only shape, so there
-is nothing to dispatch on.
-Everything a run accumulates is excluded from that comparison: status, stop
-reason, retrieval metadata, timestamps, document executions and journal
-records. A completed run asked for again is found, not refused.
+### Document targets
-Creation is therefore also lookup. A request describing the stored run answers
-with it; a request differing in any immutable field is a different run wearing
-the same ID and is refused. That is what makes a caller-selected run ID usable
-twice without a separate idempotency concept. A refusal names the fields that
-differ and never the values behind them.
+A root document addresses its own sections. The outline is discovered from the
+document's static Markdown alone: only headings in the root flow are targets,
+and a heading is addressable only when its text is statically rendered — a
+heading generated inside a component, or one carrying an interpolation, has no
+stable address, and neither does anything beneath it. Discovery therefore
+parses a copy in which the scanner's top-level component spans are blanked,
+because a Markdown parser reading raw XMD cannot tell a component's children
+from the root flow.
-Where a definition can be fetched from is retrieval metadata, not identity, so
-a run that moves between hosts is the same run.
+A document's preamble is what precedes its outline — the source before the first
+root-flow heading, whatever its depth. A document may open at a deeper level than
+the one supplying its title, and an earlier section is a target in its own right
+rather than preamble every other target carries.
-### Discovery has one source of truth
+Selection resolves exactly once, before the document expands and before any
+authored effect runs. A selector may glob, but it must name exactly one catalog
+entry: naming none and naming several are both failures, and two sections that
+canonicalize to the same path stay two entries so the ambiguity is reported
+rather than resolved arbitrarily.
-A run's location is derived from its run ID, so discovery is arithmetic and no
-second registry exists that could disagree with what is stored. The storage
-root and the location it produces are host arrangement rather than durable
-identity, which is why the run ID is also stored inside the run and checked
-against the one requested. Storage holding a different run than its location
-implies is a collision or tampering: it is reported as its own condition and
-left unchanged.
+The selector and the target it resolves to are different things, and only one of
+them is identity.
-### What a run retains
+**The exact canonical target is definition identity.** It is what ran, so it is
+what a document execution records durably, what a targeted workflow definition
+carries, and what a resumed run is checked against.
-A run retains its immutable identity, one of six statuses — `running`,
-`suspended`, `interrupted`, `completed`, `failed`, `cancelled` — a nullable
-stop reason, replaceable retrieval metadata, one document-execution record per
-start and per resume, and the filtered journal. Document-execution records are
-not attempts: an attempt is one execution of a retried operation or region and
-remains in the journal.
+**A caller's glob is non-authoritative invocation metadata.** It describes what
+a caller asked for — two callers may spell one request differently — and it
+never substitutes for the exact target: it does not occupy the recorded
+exact-target field, it never enters a workflow definition, and it is never
+re-resolved against a newer checkout to decide what a resumed run means. A glob
+is retained in exactly one place, a failed selection's structural record, and
+only so that an ordinary failed execution can be reproduced.
-A stop reason is a categorical host code or a reference to an already-filtered
-journal event. Arbitrary exception text is never duplicated outside the journal
-that filtered it.
+The command line is the first consumer of that split. `xmd run` resolves a
+selector while inspecting the document, then asks execution for the exact target
+that resolved — so a file replaced between the two reads fails on the target the
+run chose, rather than silently running whatever the glob would name now.
-WorkflowRun schema version 1 is complete in place. It contains the run records,
-filtered journal, pinned Cloudflare DOFS version-5 structure, immutable
-Workspace-root tables, current-root state, a non-null Workspace-root
-association on every journal event, and the Repository and Worktree creation
-records #293 added to it. A fresh run starts with one
-content-addressed root manifest describing only the root directory, empty
-retained manifest and blob reference sets, and the corresponding root-only DOFS
-frontier.
+`xmd workflow start` is the second, and it is stricter because its answer is
+retained. It resolves the selector once, against the exact bytes it is about to
+retain, and stores only what core answered. A resume re-enters that section
+without resolving anything again: the glob is gone, and the bytes it was
+resolved against are the run's.
-`workflow_run` has **no `base` column**, and two tables hold the run's own
-source: content keyed by its SHA-256 with its byte length, and one manifest row
-per descriptor entry mapping a logical path to that hash. Content is retained as
-BLOB bytes rather than as text or re-encoded JSON, and two paths holding
-identical bytes reference one blob.
+The workflow definition is the second. It optionally carries that exact target,
+compares it with the rest of the descriptor, and validates it through core's own
+canonical-target predicate rather than a rule the workflow package restates —
+identity two packages define separately is identity they can disagree about. A
+run of one section, a run of another, and a run of the whole document are three
+different runs.
-A new run is written at `user_version = 1`, and initialization never upgrades an
-existing database. Recognition reads the application ID first, then the schema
-version, and holds the whole inventory to its one declaration. Version 0 under
-that inventory is corruption, any other version is unsupported, and an altered
-or extra object is corruption rather than a migration candidate — there is no
-earlier shape for a file to be recognized as.
+A resumed run re-resolves the current selector against the *recorded* content
+and refuses to continue unless the outcome is the one recorded. A failed
+selection is an outcome too, and is recorded and compared as one — otherwise a
+journal left by a selector that matched nothing would answer a later request for
+a section that does exist.
-Before a record is exposed, its retained source is re-derived in full:
-the manifest equals the descriptor's `sources`, every referenced blob exists,
-both retained lengths equal the content's own, recomputing each blob's hash
-produces its key, no blob is unreferenced, and recomputing the bundle hash from
-the retained manifest and mapping produces `bundleHash`. No reader returns a
-partial bundle, and nothing falls back to the original file or the provenance.
+Validating that identity is **execution-owned**. Replay guards are composable
+policy — a handler installed further out may decline to delegate — so identity,
+which must not be negotiable, is not decided there. The execution owns the
+journal it replays through and validates the recorded selection inside the read
+itself, ahead of public guard policy, of a retained terminal result being
+reused, of authored work, and of any append. The retained history it owns covers
+every event that takes part in that decision, a recorded completion included, so
+no event can present one identity to the validation and another to the run.
-A Workspace root is a complete, immutable filesystem checkpoint. Its canonical
-format-1 JSON includes `/` and every reachable absolute POSIX path in UTF-8 byte
-order, with kind, mode, observable mtime, file size and DOFS manifest identity,
-symbolic-link target, and deterministic file-hardlink groups. The root ID is
-the lowercase SHA-256 of `xmd-workspace-root\0v1\0` followed by those exact
-canonical bytes. Mutable inode numbers, revisions, tombstones and cache state
-do not participate in the identity.
+Three views of that history stay distinct. The **authoritative** one is what
+admission validated and replay consumes, and it is immutable to policy.
+Replaceable public policy reads an **isolated observation** of it, so a handler
+composes freely without acquiring the enforcement the gate exists to withhold.
+What a document receives is a **fresh mutable copy**, because a resumed binding
+is ordinary data its own continuation writes to. Reusing a terminal result also
+requires exactly one recognizable root import belonging to the coroutine whose
+result is being reused.
-The root tables are authoritative checkpoints; the DOFS node, dirent and chunk
-tables are the live materialization of the current root. Files remain solely in
-DOFS content-addressed blobs. Normalized root-to-manifest and root-to-blob rows
-equal the root's transitive content exactly and prevent retained content from
-being deleted. Opening a run validates every root and referenced manifest and
-blob, then snapshots the live frontier read-only and requires it to equal
-`current_root`. The schema structure, retained content, live/current comparison
-and run row are read through one explicit SQLite snapshot. This recognition
-transaction is not a caller-owned Workspace transaction and enables no DOFS
-savepoints.
+Every public path validates in one order: parse the source, resolve the target,
+compile schemas, then build the projected definition. A caller who named a
+section the document does not offer hears that, rather than a complaint about a
+schema they never reached.
-Recognition also requires every file entry in every retained root, including a
-historical root, to declare the size held by its referenced DOFS manifest. A
-root whose XMD identity and reference rows are internally consistent but whose
-file size disagrees with DOFS is corrupt and not restorable.
+A recorded selection is a closed protocol, and a record that does not satisfy it
+is refused rather than delegated. "This event is not the root import" and "the
+root import, malformed" are different answers: one continues, the other fails
+before the recorded terminal result can be reused, without executing authored
+work or appending history. The record carries the content it was taken from, so
+the selection is verified against that content rather than merely parsed, and
+reading it is total — every way journal-controlled data can refuse to be read is
+the same refusal, carrying nothing the record supplied.
-Which status transitions are legal, and what a caller may do to a run in each
-of them, is lifecycle policy applied above storage.
+### The ordinary component prop boundary
-### The journal is stored, not re-encoded
+An ordinary component's props are JSON, and one resolver decides that for both
+Markdown and function components — before validation, and before anything
+durable is written.
-Journal events reach storage already filtered, through the existing
-pre-persistence gate. Storage adds no second filtering policy: a rejected or
-cancelled gate leaves nothing behind. A record is retained in the
-representation the protocol produced and parsed back through the matching
-reader, so replay reads what was written rather than a re-encoding of it.
-Events replay in append order. An event's opaque identity is retained
-separately from its physical position; the position orders replay and is not a
-public identifier.
+- **A successful `undefined` means the prop is absent.** The resolver leaves it
+ out rather than giving it a value, so the schema answers it: an optional prop
+ stays unset, a declared default is supplied, and a required one fails as a
+ missing property with no body run. That is how one authored invocation can
+ carry an optional identity a preceding result supplies later.
+- **`null` is a value the author wrote.** It crosses the boundary as itself, and
+ only a schema that accepts it accepts it. Absence is never widened to it, and
+ never widened to a root a JSON round trip cannot describe: a function, a
+ symbol and a serialization that threw stay the failure they were, as do an
+ expression that threw and a name that is not bound.
+- **The rule stops at the root.** Everything under it is the same native
+ `JSON.stringify` round trip as before — an `undefined` object member is
+ dropped, an `undefined` array entry becomes `null` — and no recursive
+ normalizer of ours replaces it.
+- **Deliberate bypasses stay bypasses.** A capture is separated before this
+ resolver runs and receives the exact operand, `undefined` included; `` binds by reference; a construct that evaluates an arbitrary operand
+ keeps its own contract.
+- **Absence is not durable state.** Prop resolution records nothing of its own.
+ No resolved prop, validated prop, retained event or replay-restored prop holds
+ `undefined`, and a replay reconstructs the same validated prop set through
+ ordinary expansion.
-### One database at a time, and a transaction a caller can hold
+### Expansion identity
-Operations on one run's storage are serialized, and each runs inside a
-transaction. The Deno provider's per-path entry owns the one physical SQLite
-connection, the one Cloudflare DOFS wrapper and Workspace filesystem, the
-cooperative connection queue, and the savepoint allocator. Turns belong to that
-entry rather than to a handle, so two leases for one run take turns instead of
-contending — a host whose storage is reached synchronously would otherwise stop
-while a second handle waited for a transaction the first one cannot resume to
-finish. Different workflow-run paths have independent entries.
+Core describes the executable element currently being expanded:
-Each entry has an opaque generation identity created with the physical
-connection. Reopening the same path after provider teardown creates a different
-generation. Each top-level transaction has its own opaque identity and exact
-active record, including its path, generation, authorized lease and public
-transaction handle. Finishing invalidates that record before commit or rollback
-can expose the connection to later work. Retained transaction handles and
-tokens stay invalid across a later transaction on the same connection and
-across a later provider generation.
+```ts
+interface Expansion {
+ readonly id: string;
+ readonly name: string;
+ readonly position?: Readonly;
+}
+```
-A caller that must publish several changes together holds the transaction
-itself and receives a handle for taking part in it. Enlistment travels with
-that handle rather than with the storage, so work that never received one
-cannot join by accident: an unrelated append waits for its turn and commits on
-its own rather than being rolled back with a failure it had nothing to do with.
+`getExpansion()` returns the same frozen snapshot throughout one live
+expansion. `name` is the authored tag name, independent of which repository,
+registered or built-in component resolves it. `position` is the opening tag's
+source position, including its workspace-relative path when known; dynamically
+rendered markup may have no position. A nested expansion temporarily replaces
+the contextual expansion and returning restores the enclosing one. Calling the
+operation outside an executable element expansion throws. The snapshot exposes
+no props, bindings, projected content, selected component definition or live
+scope.
-A transaction commits only once the work inside it has finished, including work
-that is still unwinding when the body returns. Cleanup belonging to that work
-appends through the same transaction, and a commit that happened first would
-leave those appends to publish themselves outside it. Failure and cancellation
-roll back everything the transaction did. Adapter-private Workspace work also
-waits for its supplied scope to finish teardown before it performs the final
-live/current validation.
+An expansion ID is derived from the root document and structural expansion
+path. It uses no process-global counter, time, randomness or scheduling order.
+Replay, continuation, retry attempts and restoration of the same loop
+iteration preserve it. Different authored elements, loop iterations,
+projections, component expansions and root documents receive different IDs.
+The ID is opaque and supports equality only. Two workflow runs may contain the
+same expansion ID; a durable effect that needs workflow-wide identity uses the
+run ID and expansion ID together. Replay preserves the snapshot's fields, not
+JavaScript object identity.
-A transaction opened inside another on the same storage is refused rather than
-nested, as is an ordinary operation called from inside a transaction body.
-The active-path context chain only detects and refuses that accidental nesting;
-it never authorizes transaction or savepoint use. Authorization comes from the
-provider-owned identities behind an adapter-private contextual operation, which
-validates exact handle possession each time.
+`Expansion` and `getExpansion()` belong to `@executablemd/core`, so ordinary
+document execution receives expansion identity without installing workflow
+middleware.
-One monotonically unique allocator serves both synchronous Cloudflare DOFS
-savepoints and Effection operation savepoints. The operation form receives an
-`Operation`, runs it in a child scope, waits for every child and resource to
-finish teardown, and only then releases. Ordinary failure rolls back to and
-releases that savepoint while leaving the outer transaction usable. Synchronous
-cleanup rolls an open savepoint back on cancellation or halt. A failure to
-create, roll back, or release poisons the active transaction, so its top-level
-owner cannot commit it.
+Selecting a document target does not disturb any of this. Projection retains
+the original source ranges and scans each one under its own origin, so a
+retained element keeps the offset and line it was authored at, and with them
+its expansion ID. Two runs of the same document under different targets
+therefore agree on the ID of every element they both retain, and may share IDs
+without sharing effects — run identity and workflow-definition identity are
+what tell those runs apart.
-Serialization is not a single-executor policy. Which executor may advance a run
-is decided above storage.
+### Definition-owned return state
-### Damaged storage is described, never replaced
+A value body — a value root, or a Markdown component that declares `returns` —
+selects its value with a `` its own flow reaches, rather than with a
+direct top-level child. What decides whose declaration an element satisfies is
+the body it was written in, which is the ownership `` already establishes
+for the loop it exits.
-Storage is parsed, never trusted, and every condition a caller can act on
-differently is reported as itself: absent, conflicting, holding another run,
-not this kind of storage at all, a schema version this build does not
-implement, damaged, holding a record that does not parse, asked for with a
-value that describes nothing, or unable to transact. Collapsing them would
-leave a host guessing whether to create, refuse, or report damage.
+One state exists per execution of one value body. ``, ``, ``,
+`` and `` keep the ambient one; a component invocation hides the caller's from the
+invoked body, so a component's own `` satisfies its own declaration; a
+`` passes none either, and the shared rule refuses the `` that
+would have reached for one, so concurrent children cannot race to reserve a value
+owned outside their ``; a
+nested value body installs a separate one, and both executions stand; and
+content the caller projected restores the caller's, through a Markdown
+`` and a function component's `content()` alike, with every
+projection of one authored element restoring the same state. Dynamically scanned
+Markdown and a foreign body receive none, so a `` there stays reserved
+and never resolves a component named `Return`.
-Recognizing storage means holding its structure to the one this build writes,
-not reading the names of its parts. Storage whose own header reports a version
-it is not shaped like is damage rather than a version this build has not
-learned. Storage is initialized only when it is pristine: something that merely
-looks unused is not.
+The first executed `` reserves the state before evaluating its expression,
+so two returns racing through one body cannot both believe they were first. The
+second fails the body, evaluates nothing, and the first value is not published —
+there is no first-wins or last-wins fallback. A body that executes none settles
+as a missing selection: the body ran and its flow reached no ``, which is
+a structural outcome and carries nothing about what the author concluded. A
+document that deliberately aborts, or that exhausted a bounded search, expresses
+that as authored control flow with `` and the sentence its author wrote.
-Complete version 1 is the first XMD schema. A database carrying the XMD
-application identity with schema version zero is a partial initialization and
-therefore damage, not a supported historical version.
+**Selection is not a decision a document makes about itself.** A document's own
+eval block reaches further than it looks: a named context by name, because
+`createContext(name)` names the slot the engine would publish on, and an internal
+module by file URL, because an eval block's imports are hoisted and resolved like
+any other module's. Anything published contextually is therefore readable, and
+any exported function acting on what was published is callable — a sealed carrier
+in a context plus an exported `claim(carrier)` is forgeable however carefully the
+carrier itself is sealed, because the document calls the engine's own helper with
+the engine's own carrier.
-Records are held to what they mean and not only to the types they are stored
-in. A retained timestamp is an instant, a retained identity is not empty, and
-normalized props are an object.
+So selection uses neither. The body that owns a value is a plain object whose
+reservation, selection and settlement are closures over state nothing else holds, and
+it reaches the `` that reserves it as an ordinary parameter of expansion —
+down the call stack, which document code cannot read or replace. Ownership is
+explicit at every site rather than ambient: a component invocation passes none,
+so an invoked body is isolated; caller projection passes the caller's, so
+projected content still satisfies the declaration its author could see; and
+dynamically scanned markdown and generated fragments pass none. Both settlement
+sites read the body their own expansion created and held as a local. Importing
+the module that defines one gains a document nothing — it gets a body of its own,
+connected to no execution — so a value still crosses its declared schema on the
+way out.
-Nothing initializes, migrates, truncates, deletes or replaces incompatible or
-damaged storage, and a lookup that finds nothing creates nothing. Messages
-describe what failed without repeating retained props or journal payloads —
-including their member *names*, which can carry a credential as readily as a
-member value can.
+Selection is not a permission and not durable state: it appends no journal event, a
+partial replay reconstructs it while completed effects replay, and a completed
+document replay reuses the retained result without expanding the body. ``
+does not end the body, so later documentation runs and a later failure,
+cancellation or teardown failure keeps its existing precedence.
-## The workflow lifecycle
+### Structural branch selection
-`xmd workflow start [--id=] [--props-*=…] ` and
-`xmd workflow resume ` are the two commands. Both run in the foreground,
-stream the document's own output to standard output, and report identity and
-outcome on standard error as two stable lines — `workflow run: ` once
-the run has been created or found, and `workflow status: ` once the
-execution settles. Only a completed run exits zero: failed exits 1, suspended 2,
-cancelled 3 and interrupted 130, so shell automation cannot mistake an
-incomplete workflow for a finished one. A request the command refuses — bad
-grammar, a missing run, an incompatible reuse, damaged storage, an unsupported
-host — exits 1.
+`` and `` are the engine's own syntax, not components, so
+core owns what they mean and no repository file, registration or bundle can
+supply either name.
-`start` establishes an immutable definition from **the bytes the caller named**.
-Its argument is a document reference — a path, optionally followed by `#` and one
-target selector — so the reference is taken apart before anything is resolved as
-a path. It reads the supplied file once, derives the logical entrypoint from that
-file's own NFC-normalized final segment, decodes it strictly, parses it, resolves
-any selector through core against those exact bytes to the one canonical target,
-reads the declared bundle from the root's own directory, and builds and verifies
-version 2 of the descriptor — all before storage exists.
+A switch decides its whole structure from source before it evaluates anything.
+Which props were written, that every substantive direct child is a paired
+``, that each case carries exactly one of a matcher or the bare `default`
+word, and that at most one default is written and written last — all of it is one
+shared rule that expansion and non-executing validation read. A malformed branch
+therefore stops the selector too, including a branch no comparison would have
+reached.
-**The bytes that execute are the bytes the file held**, so a file outside a
-repository starts, an untracked file starts, and a file edited since its last
-commit runs what it says. Where the file sat is never identity: the containing
-directory, the absolute path and the invocation working directory are retrieval
-facts. Git is optional provenance, recorded as replaceable metadata when it is
-cheaply available; failing to obtain it cannot fail a start, and nothing reads it
-back to find the source.
+Only then does selection run. The selector is evaluated once, each non-default
+matcher at most once in source order, and the first `===` match wins. Operands
+are arbitrary JavaScript values evaluated through the expression evaluator rather
+than through prop resolution, so `undefined` stays `undefined`, `NaN` matches no
+case including one written `NaN`, `0` and `-0` are one value, and two objects
+match only when they are the same object. With no match and no default, the
+switch renders nothing and reports nothing.
-`resume` executes the closure the lifecycle authenticated from the run's own
-store and never rereads the candidate path. A file that is unreadable, not
-well-formed UTF-8, not Markdown, whose selector resolves to nothing, or that
-declares a component this command cannot read fails explicitly and before
-storage exists; none of them creates a replacement run or an empty definition. A
-workflow definition is one closed set of retained bytes, so the component search
-path is empty and a repository component fails to resolve rather than resolving
-to content beside the definition in a mutable checkout.
+The selected case is transparent. It expands inline into the region that holds
+the switch, opening no binding scope, no observation boundary, no error mode and
+no loop boundary: a `` it creates stays available after ``, a
+`` reserves the value body that owns the switch, a `` exits the
+loop that lexically encloses it, and an error inside it is observed exactly where
+inline content would be. Fallthrough does not exist, because expansion enters one
+child list once.
-A root may close itself over a **component bundle** by declaring one in its own
-frontmatter — `workflow.components`, a non-empty mapping from a component name
-to a relative POSIX Markdown path beside the root. `start` normalizes that
-declaration against the root's own directory, reads every member from beside the
-root as exact bytes, takes each source's own domain-separated content hash as
-its source hash,
-parses each component before the run exists, and stores the bundle on the
-definition as a `components` array in canonical order — so each declared path is
-both the logical path the run retains and the file this host happened to find it
-at. A root that declares nothing writes no `components` member at all, which
-means "closed over no components"; an explicitly empty declaration is refused
-rather than becoming a second spelling of it. A declaration may not declare structural syntax, a component the
-engine supplies, or a name the host reserved, and the refusal names a component
-only once the name has passed the grammar a document writes.
+The selected `` contributes its own expansion frame even though the
+`` consumed it, so corresponding children of two branches cannot share
+one identity. Neither construct is durable state: they append no journal event, a
+partial replay rebuilds the selection through ordinary expansion while completed
+effects in the chosen branch replay from their own records, and a completed
+document replay reuses the retained result without expanding anything.
-The bundle is identity, so compatible reuse compares the whole array: a changed
-name, canonical path, source hash, or component set conflicts as `definition`,
-and a run closed over a bundle is never the same run as one closed over none.
-`resume` obtains the bundle under the executor lock and before the lifecycle
-advances. It re-derives the bundle from the run's own retained BLOBs,
-recomputing every source hash and the bundle hash from the bytes it holds;
-nothing is read from a repository or from the files the run was started beside.
-A component that changed, went missing, or became unreachable leaves the run's
-records exactly as they are.
+### Concurrent spawned children
-The bundle is also canonical resolution. It reaches canonical core as plain
-immutable data on the `ExecutionInstallation` that already carries the run's
-admission and preparation, captured by value before any installation, middleware
-or document code exists. Resolution places it between reserved registrations and
-ordinary registered defaults, so core's own components stay available and no
-name they own can be taken back. Every selected member records one
-`import_component` result of exactly `{ kind: "workflow", path, sourceHash,
-content }`, and the installation contributes a journal admission that holds every
-retained component import to that exact bundle before public document policy or
-the root import. While a bundle is installed, `Component.importComponent`
-middleware may observe, delegate, and refuse an import but cannot answer one:
-canonical core keeps its own copy of the definition it produced and invokes that
-copy, then compares the returned answer against it by own property descriptor —
-never by serialization — so a synthetic answer, a replacement, and a mutation
-each fail before the component is invoked, including one masked by a `toJSON()`
-or by an accessor that answers twice.
+`` and `` are the engine's own syntax, not components, so core owns
+what they mean and no repository file, registration, bundle or Plugin can supply
+either name. `` runs its direct `` children at the same time and
+waits for all of them. It takes no props, produces no value, and requires at
+least two spawns — one alone is the sequential document it was already written
+as.
-Every actual execution opens or creates the run's database, begins a
-document-execution record, installs the exact retained WorkflowRun, installs the
-service denial before the root is imported, and — for a live or partial
-execution — installs the logical working directory `/`, the transaction-bound
-Files provider and that database's Workspace effect coordinator. It executes
-against the database's own journal with the retained props and secret detection,
-then finishes the execution record and publishes the run's status. A completed
-run still replays, so its retained output and result are emitted, but it
-attaches no Workspace provider or coordinator and performs no filesystem
-mutation.
+The whole structure is decided from source before a child is constructed: the
+paired forms, the absent props, the two-spawn minimum, that only blank text sits
+between the spawns, that no `` is written outside its direct ``, and
+that no `` or `` inside a spawn reaches for an owner outside it.
+One shared rule states all of it, and expansion, non-executing validation and
+the generated-fragment preflight read the same result — so a malformed construct
+starts no child anywhere, including in a fragment an Agent generated.
-A failure retains `failed` and uses a journal stop reason when a retained event
-identifies it, and a categorical host code otherwise; no exception text is
-retained beside the journal that filtered it. Graceful foreground interruption
-finishes the execution `interrupted` and exits 130. `suspended` is resumable;
-`failed` and `cancelled` are refused by `resume`, and `completed` replays under
-either command.
+**Concurrent expansion shares immutable inputs and nothing else.** Every child
+gets a binding environment and live overlay snapshotted from the one that
+reached the ``, an eval scope of its own, a fresh block counter, a private
+output buffer, its own checked-failure ledger, a copied hide set and an
+expansion path extended by its authored ordinal. Nothing merges back, so a name
+one child binds or rebinds is invisible to its siblings and to the work after
+``, and a resource it retains is released when it ends. The outer
+`` and `` owners are cleared at the boundary; a loop or value
+component created wholly inside a child establishes its own.
-The initial host is Deno-local. The Deno entrypoints — source and the compiled
-binary — install the local run store, beneath `~/.xmd/runs` unless
-`XMD_WORKFLOW_RUNS` names another absolute directory. Node and Bun expose the
-same grammar and refuse before creating or executing anything. The shared CLI
-module imports no SQLite, no DOFS and no runtime detection: it asks a host
-adapter to open storage and to attach a run's Workspace, and the entrypoints
-decide which adapter exists.
+**Durable identity comes from the source, never from the schedule.** The
+existing durable structured-concurrency substrate is the implementation: in
+source order, before any child starts, each `` receives one child
+coroutine of the one that reached the ``, and nesting produces the existing
+hierarchical identity. Effects inside a child keep their ordinary descriptions
+under that coroutine, so two children may derive the same local block id without
+colliding, and work after `` continues on the parent counter it would have
+had without any child. Each successful child closes with the ordered `{ text, exact }` runs it
+rendered. Exact presentation is a provenance recorded against the segment
+objects expansion marked, and those segments do not cross the join — so the runs
+are what carries it, live and on replay alike, and a retained close that does
+not read as that shape fails the run instead of rebuilding part of a document.
-The start/resume slice predated single-executor enforcement. Issue #367
-replaced its opportunistic orphan closure with the lifecycle ownership below,
-and no supported host advances a retained run without it.
+**Output is authored order; the journal is completion order.** A child emits
+into its private buffer, and `` appends the renderings to its caller's
+region only after every child has succeeded. Which child finished first may
+decide when its records append and never what the document renders. A complete
+replay reads the child closes and runs no spawned work; a partial replay
+restores the children that closed and resumes only the unrecorded ones under the
+same identities. Inserting, removing or reordering spawns is a definition change
+and takes the existing divergence path rather than being reassigned by position
+or completion time.
-## Workflow lifecycle ownership
+**Failure is the existing fail-fast join.** The first child failure fails the
+``, cancels every unfinished sibling and does not return until all of them
+have finished tearing down. No private buffer is emitted, records acknowledged
+before the failure stay durable, and interrupted work is never recorded as
+complete. Cancelling the parent takes the same ownership path, and no task,
+subscription, retained resource or buffer survives its spawn. No scheduler, no
+new record family and no document-visible concurrency control is introduced.
-Storage serialization decides who uses one connection next. It does not decide
-who may advance a workflow run. A workflow executor must acquire one executor
-lock before stale recovery, a document-execution begin, Workspace attachment,
-journal replay, root import or authored work.
+## Errors, output and commands
-The provider-neutral lifecycle API routes acquisition and management requests
-to a host. Routing through a contextual Api selects a provider and grants no
-permission. Acquisition gives the workflow executor an opaque exact
-`ExecutorLock` object registered by that provider for one run and one
-acquisition. The provider checks the same object, its open scope, its run and
-the expected retained lifecycle state inside every mutating transaction. A run
-ID, database handle, structural look-alike, same-named context value or retained
-token is admitted nowhere. Releasing or tearing down the executor lock
-invalidates that object before another acquisition can mutate the run.
+A document decides recovery through its structure. Output routing, retained evidence and process failure remain separate decisions.
-The executor lock is not a time lease. It has no duration, expiry, renewal,
-heartbeat, watcher, generation record or liveness poll. The operating system
-releases the local lock when the workflow executor exits.
+### Two layers
-The shared surface names outcomes and retained data, not a transport:
+Error handling has two layers:
-```ts
-interface ExecutorLock {
- readonly runId: string;
-}
+1. **Lexical structure** — the document applies context, in two forms:
+ context values (`