Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 160 additions & 9 deletions architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ Existing documents and code get aligned to this section retroactively.
| 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 |
| run ID | an opaque stable identifier assigned to a workflow run; it associates the run's durable records and effects, remains unchanged for the life of the run, and supports equality only |
| base | the Git revision supplied to choose a workflow run's starting repository state |
| workflow definition | the immutable source repository, pinned commit and root document path executed by a workflow run; it is distinct from every Repository created inside the run's Workspace |
| 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 |
| definition base | the Git revision supplied to choose a workflow definition's pinned commit |
| Repository base | the optional Git revision from which one named Workspace Repository initializes its primary checkout |
| 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 |
| 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 |
Expand All @@ -37,6 +39,12 @@ Existing documents and code get aligned to this section retroactively.
| 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 |
| Workspace | the provider-neutral, run-owned environment that supplies retained filesystem, repository, process and working-directory capabilities to a workflow |
| 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 |
| 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 |
| 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 |

## Three axes
Expand All @@ -56,8 +64,8 @@ Determinism is two properties:
## Workflow runs

Core retains one document-execution entry point: `execute()`. A host that needs
workflow-run metadata installs `useWorkflow({ base })` in the child scope that
owns one document execution. The installation applies ordinary
workflow-run metadata installs `useWorkflow({ base })` with the definition base
in the child scope that owns one document execution. The installation applies ordinary
`Execution.document` middleware, so the durable journal is active before the
workflow run is created or restored and before the root document is imported.
A later document execution, including one that continues the same workflow
Expand All @@ -67,8 +75,9 @@ scope-owned.

Installing the middleware alone creates no workflow run. On the first live
document execution, the first durable operation installed by the middleware
allocates an opaque run ID using cryptographic randomness, resolves the supplied
base to a commit, and durably records one value:
uses the host-authorized requested run ID or allocates one using cryptographic
randomness, resolves the supplied base to a commit, and durably records one
value:

```ts
interface WorkflowRun {
Expand All @@ -82,6 +91,12 @@ 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.

`WorkflowRun.base` and `WorkflowRun.pinnedCommit` identify the source repository
state containing the workflow definition. They do not create or seed a
Workspace Repository. Each `<Repository>` 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.

Base resolution goes through the contextual Git capability:

```ts
Expand Down Expand Up @@ -114,10 +129,140 @@ The `@executablemd/workflow` package owns `WorkflowRun`, `useWorkflow()`,
`getWorkflowRun()` and the Git capability. It depends on `@executablemd/core`,
`@executablemd/durable-streams` and `@executablemd/runtime`, whose contextual
`exec()` and `cwd()` the Git provider invokes; core never imports workflow or
Git. The CLI adds the `xmd workflow run` and `xmd workflow continue` lifecycle
together with the durable lookup that continuation requires. Ordinary `xmd run`
Git. The CLI lifecycle is `xmd workflow start` and `xmd workflow resume`,
together with the durable lookup that resumption requires. Ordinary `xmd run`
remains unchanged.

## Workflow Workspace

The command selects the environment; the document describes the procedure.
`xmd run` uses the caller's current environment and makes no restoration
promise. `xmd workflow` creates a workflow run with one implicit root Workspace.
The same declarative components use contextual capabilities in both modes; the
workflow host supplies the stronger durability and authority boundary.

Workspace identity belongs to the workflow run. A document path locates an
immutable definition but does not identify a previous run. A host-generated or
caller-selected run ID addresses `start`, `resume`, `status`, `history`,
`cancel`, `fork` and `delete`. Reusing a caller-selected ID is idempotent only
when every immutable creation input agrees.

One workflow-run database is the physical retention boundary for logically
distinct data:

```text
WorkflowRun SQLite
├── filtered journal events and effect results
├── versioned filesystem roots and content
├── Repository and Worktree metadata
└── Agent-session mappings
```

Co-location does not turn arbitrary filesystem content into journal or training
data. The journal security policy filters a value before insertion. Training
ingestion deliberately selects retained filtered history; it never receives the
whole database merely because the database is retained.

Repository, filesystem, process, forge and Agent behavior reaches production
code through contextual APIs. A provider adapter installs host behavior; shared
modules neither detect a runtime nor fall back to the caller's host when a
workflow capability is absent.

## Replay and effect transactions

Replay rehydrates the Effection tree. A completed durable effect restores its
recorded result without executing again. Ephemeral operations run again only to
rebuild live structure: attach the Workspace, enter lexical working-directory
scopes, attach providers and re-register Agent directories. A completed root
result returns without attaching any provider.

The Workspace stores the current frontier state. The journal stores the
historical execution that reached it. Replay never asks current state to prove a
past effect: a file written and later deleted is absent at the frontier, while
both completed effects still restore in order.

Every Workspace-local expansion publishes one effect through one effect
transaction:

```text
BEGIN
apply the filesystem, Git or metadata mutation
publish the resulting logical Workspace root
append the filtered journal result
COMMIT
```

All three changes commit or none does. Nested effects finish their transactions
before their parent's effect begins. Declarative Git operations, including
staging, switching and committing, operate on the same transactional Workspace
rather than invoking an untracked native Git side effect.

An external provider cannot join that transaction. Prompt, Git push and pull
request effects derive a stable identity from the run and expansion, ask the
provider to perform or reconcile that identity, then append one local result
transaction. Replay adopts proven compatible completion, performs a proven
absence and refuses conflicting or permanently ambiguous state. Temporary
provider unavailability may be retried or suspended by explicit middleware; it
never authorizes a duplicate effect while completion is unknown.

Every committed journal event references the current logical Workspace root.
Only committed event boundaries are checkpoints. A history fork cheaply retains
or clones the selected root, replays the inherited prefix under a compatible
modified definition and appends new history under a new run ID. It never rewinds
external branches, pushes, pull requests or provider state.

## Agent authority and generated XMD

An Agent under `xmd workflow` is read-only. The host enforces that ceiling in
the permission bridge, the provider-native sandbox and the filesystem view; a
document cannot raise it. A provider that cannot enforce the boundary fails
before Prompt execution. `xmd run` keeps its caller-selected Agent permission
behavior.

Native Agent processes inspect disposable read-only materializations of the
current logical Workspace root. Those views have no write-back path. An Agent
proposes changes by returning XMD, and a constrained XMD evaluator performs the
admitted components as ordinary durable effects against the authoritative
Workspace.

Generated XMD is untrusted input. The evaluator preflights the complete fragment
before its first effect and admits only explicitly allowed, already-resolved
component identities. It initially refuses eval and exec blocks, imports,
native execution and arbitrary JavaScript expressions. It retains the exact
filtered generated source for replay, history and deliberate training
ingestion. Replay restores that source and expands it without invoking the Agent
again.

## Local Workspace topology

The local workflow host owns SQLite directly in Deno and reuses Cloudflare's
DOFS filesystem layer behind the provider-neutral Workspace boundary. The
journal and DOFS adapter share the operation-scoped transaction. One
authoritative host-owned DOFS connection serves each workflow database, and the
host serializes its Workspace-local effect transactions. A second long-lived
DOFS connection is not a coherent reader because provider caches may retain
negative entries across another connection's commit.

The initial topology requires neither writable FUSE nor native subprocess
access and does not bundle `workerd`. A Cloudflare-hosted or workerd-backed
provider may install the same contextual contract without changing documents or
lifecycle commands.

Worker JavaScript is outside the initial local capability set. Worker Shell is
inside it: one `just-bash` invocation runs in a Deno Worker through Cloudflare's
Workspace filesystem adapter. The host begins one immediate SQLite transaction
and one effect-local mutation savepoint. Success releases the savepoint, appends
the already-filtered result and commits. Failure, timeout, cancellation and
Worker termination roll the mutation savepoint back, append the failed result
and commit. A host crash rolls back the still-open transaction entirely.

Every Worker filesystem request carries the effect identity and a
per-invocation token. Missing, foreign, cancelled, completed and stale requests
are refused. Cancellation must be able to forcefully terminate a CPU-bound
interpreter; graceful Worker shutdown alone is insufficient. Worker Shell
exposes no native executable or host PATH and is not described as POSIX or
native Bash.

## Expansion identity

Core describes the executable element currently being expanded:
Expand Down Expand Up @@ -362,7 +507,13 @@ Status is measured against main.
| `Expansion` / `getExpansion()` | describes the current logical element expansion | built on main |
| `useWorkflow()` / `getWorkflowRun()` | associates one document execution with a workflow run | built on main |
| `Git.revParse()` | verifies and resolves one Git revision expression contextually | built on main |
| `xmd workflow run` / `xmd workflow continue` | starts or continues a workflow run from the CLI | defined, unbuilt; ships with durable lookup |
| `xmd workflow start` / `xmd workflow resume` | starts or resumes a workflow run from the CLI | defined in `specs/workflow-workspace-spec.md`, unbuilt; ships with durable lookup |
| implicit workflow Workspace | retains provider-neutral filesystem, repository and attachment state by run ID | defined in `specs/workflow-workspace-spec.md`, unbuilt (#218) |
| Repository / Worktree / transactional Git effects | compose named checkouts and publish local mutations with their journal result | defined in `specs/workflow-workspace-spec.md`, unbuilt |
| workflow inspection and history fork | reads status/history without advancing a run and creates a new run from a checkpoint | defined in `specs/workflow-workspace-spec.md`, unbuilt |
| read-only workflow Agent / generated XMD | lets an Agent inspect a derived view and propose constrained executable changes | defined in `specs/workflow-workspace-spec.md`, unbuilt |
| Deno-local DOFS provider | stores the authoritative local Workspace in SQLite | persistence POC complete; effect-transaction integration unbuilt |
| scoped Worker Shell | executes `just-bash` through the Workspace adapter inside a Deno Worker | containment and effect-transaction POCs complete (#351, #357); production integration unbuilt |
| `<Retry max timeout>` | retry a region until it completes | defined, unbuilt |
| suspension effect | suspend durably | defined, unbuilt |
| `<Result as>` | binds `{ok: true, value}` or `{ok: false, error}`; a failure becomes a bound value, not a raise | defined, unbuilt |
Expand Down
Loading
Loading